Color tokens
A full primitive ramp, semantic tokens for light and dark mode, an allowed-pairing contrast matrix, and approved Headline + Body + Icon + Button compositions — every pairing meets WCAG AA.
Primitive ramps
The raw palette. Three families, ten steps each. Semantics below reference these — never hardcode a hex in a component.
Single-value tokens that sit outside the ramps. The semantics reference these by name — so slate, cream, and the warm surfaces are real primitives, not labels invented in the table below.
Semantic tokens — light & dark
One token name, two resolved values. Build with these and the page themes itself when data-theme flips.
| Token | Light | Dark |
|---|---|---|
--color-bg | neutral-100 · #f6f2ea | navy-900 · #0a1729 |
--color-surface | ivory-card · #fffdf8 | navy-800 · #10243d |
--color-surface-raised | neutral-0 · #ffffff | navy-700 · #142d49 |
--color-text | navy-800 · #10243d | neutral-0 · #ffffff |
--color-text-muted | slate · #3f4f63 | navy-200 · #a9c0d8 |
--color-text-accent | gold-600 · #8a6a2e | gold-300 · #d4b876 |
--color-border | neutral-300 · #d8d0c2 | navy-600 · #1d3a55 |
--color-action | gold-400 · #c2a15a | gold-400 · #c2a15a |
--color-action-text | navy-900 · #0a1729 | navy-900 · #0a1729 |
--color-focus | gold-400 · #c2a15a | gold-300 · #d4b876 |
--text-on-media | neutral-0 + shadow · #ffffff | neutral-0 + shadow · #ffffff |
Combination tokens — .combination-*
The usable mechanism behind the approved compositions. A .combination-* class on any section or card sets the contextual --c-* tokens; everything inside reads only those. Move a component between combos and it recolors itself — and every card below is rendered with the real classes, so flip dark mode (top right) to watch the remapping rules: light surfaces turn dark, dark surfaces turn darker, and the gold inverse stays gold.
| Contextual token | Role |
|---|---|
--c-bg | Section / surface background (with --c-bg-2 gradient partner) |
--c-text | Default copy |
--c-heading | Headlines |
--c-muted | Secondary copy |
--c-accent | Eyebrows, icons, hairline flourishes |
--c-line | Hairlines & borders (with --c-line-strong) |
--c-action | Button fill (with --c-action-hover) |
--c-on-action | Button label |
src/styles/ds/marketing.css (expressive, art-directed per mode) and src/styles/ds/brand.css (.combination-gold, shared with Utility). Utility's functional combos live in src/styles/ds/utility.css and derive from semantic tokens, so they follow theme and mode automatically.Allowed pairings — contrast matrix
Foreground token × surface. Green cells pass WCAG AA for normal text (≥ 4.5:1) and are approved; red cells fall below AA — don't use them for text or icons.
| Foreground ↓ / Surface → | neutral-0 #fff | neutral-100 #f6f2ea | navy-800 #10243d | navy-900 #0a1729 |
|---|---|---|---|---|
| navy-900 #0a1729 | 18.0:1AA ✓ | 16.1:1AA ✓ | 1.1:1✗ | 1.0:1✗ |
| navy-800 #10243d | 15.6:1AA ✓ | 14.0:1AA ✓ | 1.0:1✗ | 1.1:1✗ |
| slate #3f4f63 | 8.4:1AA ✓ | 7.5:1AA ✓ | 1.9:1✗ | 2.2:1✗ |
| gold-600 #8a6a2e | 5.0:1AA ✓ | 4.5:1AA ✓ | 3.1:1✗ | 3.6:1✗ |
| gold-400 #c2a15a | 2.5:1✗ | 2.2:1✗ | 6.4:1AA ✓ | 7.3:1AA ✓ |
| gold-300 #d4b876 | 1.9:1✗ | 1.7:1✗ | 8.1:1AA ✓ | 9.3:1AA ✓ |
| cream #f4efe4 | 1.1:1✗ | 1.1:1✗ | 13.6:1AA ✓ | 15.7:1AA ✓ |
| neutral-0 #ffffff | 1.1:1✗ | 1.1:1✗ | 15.6:1AA ✓ | 18.0:1AA ✓ |
Approved compositions
Headline + Body + Icon + Button realized on light and dark surfaces. Each card lists the measured contrast ratio for every element — all AA or better, in both modes — and an attention score that guides where to spend it.
Each card composes the same semantic roles — --surface · --text · --text-accent · --action — onto a richer surface. Swap the surface, repoint the role tokens, contrast holds.
Pair the engraved motifs two ways. A high-contrast foreground turns the illustration into a focal accent; a low-contrast watermark at ~8% opacity adds texture behind text without stealing from it. Same motif, opposite jobs — and opposite attention scores.
When type sits directly on a photo, it's always white with a shadow — in light and dark mode — so legibility never depends on the image behind it. That recipe is a token: --text-on-media (the colour) + --shadow-text (the drop shadow), applied here via the .on-media helper.
--text-on-media #ffffff · both modes
--shadow-text 0 1px 2px rgba(10,23,41,.6),
0 2px 14px rgba(10,23,41,.45)
Skip the scrim only when the photo has a dark, calm area. Over busy or bright imagery, add a navy gradient scrim and keep the shadow.
--text-on-media + --shadow-text tokens rather than a contrast ratio, since the backdrop varies per photo.