--- title: "Colour" subtitle: "The palette as web tokens" description: "How BlackDoctor's palette maps onto the design system's semantic colour tokens for the web, with the light and dark value of every token the site uses." author: "Studio" section: "Website" subsection: "Foundations" order: 1 status: "published" --- The web palette is the [brand palette](/brand/color.html) expressed as design-system tokens. Page and component code uses the semantic tokens on this page and nothing else — never a hex value, never a primitive such as a neutral or gold step. Each token resolves to a brand colour in light mode and to its counterpart in dark mode; a component written against the tokens gets both for free. ## Semantic tokens | Token | Light | Dark | Use | | --- | --- | --- | --- | | `--text-primary` | `#000000` | `#ffffff` | Body text, headings | | `--text-secondary` | `#494847` | `#e2dcd6` | Supporting text | | `--text-faded` | 60 % black | 50 % white | Captions, disabled text | | `--text-accent` | `#83550c` | `#efb14d` | Accented words, the link underline and the link hover colour; `--text-link` follows it. Link text at rest is `--text-plain` | | `--text-inverted` | `#f9f8f6` | `#1a1a1a` | Text on an ink-coloured surface | | `--background-primary` | `#f4f1ed` | `#181818` | The page | | `--background-secondary` | `#e8e5e1` | `#242424` | Secondary surfaces | | `--background-plain` | `#ffffff` | `#2f2f2f` | Cards and fields on a tinted ground | | `--background-faded` | 5 % black | 6 % white | Hover washes, inputs | | `--background-accent` | `#efb14d` | `#efb14d` | Accent fills | | `--dropdown-background` | `#f9f8f6` | `#2f2f2f` | Menus and panels that open over the page | | `--border-primary` | `#000000` | `#ffffff` | Structural rules | | `--border-secondary` | `#aba9a6` | `#62605f` | Decorative rules | | `--border-faded` | 10 % black | 20 % white | Hairlines | | `--border-control` | `#7a7977` | `#92918e` | The boundary of a pressable control | | `--input-border` | `#7a7977` | `#92918e` | Form field borders | | `--input-placeholder` | 60 % black | 50 % white | Placeholder text | | `--checkbox-selected` | `#83550c` | `#efb14d` | A checked box | | `--selection-background` / `--selection-text` | `#efb14d` / `#000000` | same | Text selection | The primitive scales behind these — `--neutral-50` to `--neutral-990` and `--gold-50` to `--gold-950` — are listed on the brand page. They exist so the semantic tokens have something to resolve through; reaching past a semantic token to a primitive is a sign the semantic layer is missing a token, and the fix is to add one, not to use the primitive. ## Where the web differs from the design file Four Figma values are not used as written, because they fail WCAG AA where the design file puts them: - **Text Accent** `#efb14d` is 1.68:1 on paper. Accented words, link underlines and hover states use the gold scale's 800 step, `#83550c`, in light mode; the true gold is the dark-mode accent. - **Text Faded** at 40 % black is 2.79:1. The site keeps 60 %. - **Input Placeholder** at 50 % black is 3.86:1. The site keeps 60 %. - **Text Tertiary** `#9d9488` is 2.65:1 and is not a text colour on the web. Two further defaults were raised for the same reason: the boundary of a control and of a form field takes the neutral 600 step (3.86:1 on paper), because the engine's default landed below the 3:1 a control boundary needs on this ramp. Two brand surfaces have no web token yet. The peach highlighter `#fae6cc` is what `` paints, through the engine's `--yellow-light`; the mint highlighter `#c0e2d2` has no slot at all and is recorded as an engine gap, so nothing on the site renders it. ## Dark mode Dark mode is opt-in through `data-theme="dark"` on the document, and follows the operating system's preference when no choice is stored. Every token above re-resolves; a component never carries its own dark colours. ## Checking a pairing Every text-on-background pairing must clear WCAG 2.1 AA. Use the [Colour Pairing](/tools/color-pairing.html) tool to measure any two palette colours before a pairing ships.