Color
Semantic color tokens, interaction states, status colors, and the primitive palettes they reference.
Color tokens define the visual identity across all BDS themes. The system separates primitive color scales (raw hex values) from semantic color roles (purpose-bound aliases). Components reference the semantic roles only.
Never use a token outside its semantic category. --text-* is for text. --background-* is for backgrounds. --border-* is for borders. No --text-primary on a background-color. The cascade is a contract — bypassing it leaks brand drift everywhere it isn't caught.
Click any swatch to copy var(--token-name) to your clipboard.
Page and surface
Background
Text
Border
Interaction states
Hover, press, and disabled. These replace filter: brightness() and opacity hacks — the proper tokens compose with the rest of the cascade.
Status
Canonical Figma tokens for positive, negative, and warning states. Background variants are saturated; surface variants are subtle tints.
The info signal — blue, and one of the five valence values. It came from Figma under the status- segment until #1959 freed the name: the gray family that used to hold --*-info is now --*-neutral, so info means blue and only blue. The --*-status-info* spellings still resolve as deprecated aliases for one minor (#1958 deletes them). There is no --border-info — the gray one retired with the rename and blue has no border counterpart.
The neutral intent family — gray, Figma-sourced across all four purposes since #1959. Note the purpose split the rename made honest: --background-neutral is the saturated charcoal, --surface-neutral the subtle tint. A gray Badge or Tag chip wants --surface-neutral.
Hues with no valence — purple and orange are hue names, not valence values, so ADR-033 § 1's five words have no slot for them. They belong to the hue-source scope documented under Accent below and are Figma-sourced there, so #1958 retired the --background-status-{purple,orange} spellings into it rather than amending the ADR.
Accent
The scope-stable accent — one brand highlight that stays fixed regardless of [data-audience] scope (brik fills it from tan; each Brand Kit fills its own). Use it for audience-independent affordances such as an active carousel dot or an eyebrow rule.
It is distinct from two neighbours it is easy to confuse:
--*-brand-primaryre-tints per audience scope (Vale: land → gold, healthcare → olive). The accent must not shift, so it is its own role — not a brand-tier token.- The per-color status accents (
--background-accent-blue,--text-accent-green, …) encode state/category, not the brand highlight.
Brand Kits fill --*-accent per client (brik → tan, Vale Partners → gold). Because the audience scopes re-bind only the brand-primary tier, the accent stays constant across every [data-audience] — that scope-stability is the whole point of the role.
Presence
Online/offline indicator tokens used by Avatar and Dot components.
The 11-step scale
Every family is an 11-step numeric ramp — 50, 100, 200, … 900, 950, lightest to darkest. 50 and 950 bracket the ends; the middle nine carry the working values. The scale is generated, not hand-tuned per family: scripts/generate-color-ramps.mjs pins the six historical swatches as anchors and interpolates the other five stops as OKLCh midpoints, writing design-tokens/color-ramps.generated.json (#1737). Shipped in v0.152.0.
Reach for a stop by its number. --color-{family}-{stop} is the Primitive-tier name; components still consume Semantic tokens only.
Deprecated 6-step aliases
The old ladder (lightest → lighter → light → dark → darker → darkest) still resolves — #1739 aliased each name onto its stop so nothing broke on upgrade. The aliases are deprecated and land at these positions in every family:
| Deprecated alias | Resolves to | Anchor? |
|---|---|---|
--color-{family}-lightest | 100 | anchor |
--color-{family}-lighter | 300 | anchor |
--color-{family}-light | 500 | anchor |
--color-{family}-dark | 700 | anchor |
--color-{family}-darker | 800 | anchor |
--color-{family}-darkest | 950 | anchor |
Note the ladder was never evenly spaced: dark and darker sit one stop apart (700/800) while darker to darkest skips 900. Prose that said "one step deeper" under the 6-step names does not translate to one numeric stop — count stops, don't translate names.
Don't write a deprecated alias into new code. npm run lint-mdx-tokens fails the build on one in a docs code block or table, and lint-tokens Rule 12 covers component CSS. Consumer migration is tracked in #1740; the aliases are removed only once it closes.
The two new stops that matter
Five stops per family are new. Two of them close specific, filed gaps:
| Stop | Value | Why it exists |
|---|---|---|
--color-poppy-600 | #c94428 | 4.84:1 on white — clears AA (4.5:1). The near-Poppy step ADR-015/ADR-016 said did not exist, unblocking #479 |
--color-grayscale-400 | #b0b0b0 | Fills the #828282 → #e0e0e0 gap from #1726. It is not #bdbdbd — no even OKLCh ramp lands there, so consumers that hand-pinned #bdbdbd are migrating to this value, not matching it |
Primitives
Raw color scales from the Figma Brand Kit, rendered from color-ramps.generated.json. Components reference these via semantic tokens — never directly. The primitives change rarely; the semantic mappings change per theme.
Grayscale
Poppy (brand primary)
Tan
Orange
Yellow
Green
Blue
Purple
Pink
Related
- Color Pairings — which text token is WCAG-safe on which surface (brand + service tiers, both themes), the contrast matrix, and the CI gate
- Color primitive tier — the closed
tiervocabulary, tonal-scale emission rules, and the deprecated suffix-alias migration - Client Themes → Per-audience scope binding — multi-brand scope-based token re-binding for sites like Vale Partners and brikdesigns.com
- Cascade rules — the three-layer architecture every consumer follows
- Atmospheres — the mood overlay layer that sits on top of theme tokens
- Storybook → Color contrast compliance
Token Anatomy
The six disambiguated concepts that describe every BDS token — Anatomy, Tier, Library, Layer, Mode, Tenet — and the four-tier abstraction stack every token belongs to.
Color Pairings
The accessible foreground/background pairing system — which text token is WCAG-safe on which surface, for brand and service-tier colors, in both themes, enforced by a CI gate and portable to client themes.