Requirement
Each product anchors its primary actions and brand moments in its own primary brand colour and that colour's ramp. Do not import another product's primary for emphasis on a different product's surface. The active product is established in Phase 1 of the design-ui loop.
Per-product primary
Each product declares its primary in its own DESIGN.md: the brand colour, the token
that carries it, and its value. For example, a product might record a brand blue
#0064FF on its --primary token. A primary marked "(proposed)" in its DESIGN.md awaits
the design lead's settle.
Foreground pairing (A11Y-1)
A product's primary is a background for its label text, so the primary and its paired foreground must clear A11Y-1 together — this is not automatic, and a light or mid-luminance primary cannot carry white text.
- Radix orange-9
#F76B15takes a dark foreground, not white. White on#F76B15is 2.97:1 — it fails the 4.5:1 body floor (and the 3:1 large-text floor). Pair it with the scale's high-contrast dark step (Radix orange "contrast" / step-12, a near-black brown) → ~5.7:1. This is the Radix convention for the light-hue solids (orange, amber, lime, yellow): step-9 is a dark-text background, not a white-text one. - A brand blue such as
#0064FFand Radix indigo-9 take white text (both clear AA).
When a product adopts a light-hue primary, the brand variant's --primary-foreground
must be the dark contrast colour, and the evaluator re-checks label contrast.
Same-hue collision (A11Y-1)
Applying COL-1 can create an A11Y-1 failure: when the product primary would sit on a
same-hue field, the button's fill can lose the 3:1 boundary against its background.
The foreseeable case is an orange primary on an orange tint or splash
(orange-on-orange — e.g. a tag-*-50 topic tint or the login splash). Before
recolouring a primary onto a coloured field:
- change the container so the button sits on a neutral / near-white surface (the typical fix is moving a login CTA into a white card — orange-on-white clears AA), or
- keep the action neutral on that surface and record the deviation.
Never recolour a primary onto a same-hue field without re-checking the 3:1 UI-component boundary; a mechanical "make it brand" that ignores this ships an inaccessible control.
Rationale
The portfolio is independent products: one product's primary might be orange, another's indigo. A rule that pointed every product at a single shared blue would mark a correct orange CTA as a violation. Instead, each product's primary is its own brand colour. People recognise a product partly by its colour; forcing a single blue across the portfolio erases that identity and mis-grades correct work.
How to verify
Deterministic half: the active product's primary CTA and brand-moment colours
resolve to that product's primary token (not a raw hex bypassing the token layer).
The checks/token-audit allowlist already knows the product's --color-* names
from its CSS — see plan 011 for the project-token-aware mechanism.
Judgment half (why this control is hybrid, not deterministic): the colour
resolving to a valid token passes the mechanical half trivially — the real question
is whether the view's single primary action (per CMP-5) carries the product
primary, or a legitimately-tokenised neutral is sitting where the brand belongs. The
evaluator confirms: (1) the one primary action per view resolves to the product
primary; (2) its label/background pairing clears A11Y-1 (see Foreground pairing);
(3) no other product's primary appears for emphasis (an orange from one product on a
blue product's screen is a finding, and the reverse is too).