Color contract
Every component takes a primary and a secondary Radix scale, and colors its parts only through the --primaryN, --secondaryN and --role-* variables those scales publish.
Two props on every component
primarytakes a scale from the primary roster: the neutralsolive,sage,slate,sand,grayandmauve, plusbrown,bronze,gold,red,ruby,crimson,tomato,pink,plum,indigo,iris,violetandpurple. The greens, yellows, oranges,blue,skyandcyanare secondary only.secondarytakes any of the 31 standard Radix scales. Alpha and custom scales are type errors.
Neither prop has a default. An omitted prop adds no class, so the value resolves in order:
- the prop;
- the nearest Ground scope's defaults, inherited as custom properties;
- the system defaults: primary
olive, secondarygreen, actionamber.
Primary drives almost everything: text, muted text, rules, hairlines, control edges, the focus ring, faces and soft fills. Secondary drives accents only: section heads on light grounds, link underlines and meaningful icons, selection, the action fill, and static category fills such as status.
Scale variables
A component never names a Radix scale, and never a mode. It reads the scope's steps, which keep the same names in light and dark mode:
| Variable | Holds |
|---|---|
--primary1 … --primary12 | The primary scale's 12 steps |
--secondary1 … --secondary12 | The secondary scale's 12 steps |
--action1 … --action12 | The scope's action scale, published by Ground; the solid Button reads it as its secondary |
--primary-contrast, --secondary-contrast, --action-contrast | The ink for a label on step 9 or 10 |
--primary-hover, --secondary-hover, --action-hover | The step a contained fill moves to on hover: step 9's lighter neighbour in a light scope (step 8 for most scales, --amber6, step 5 for yellow, lime, mint and sky), step 10 for purple, indigo, iris, violet and plum, and step 10 in every dark scope |
Role variables
Roles name a job, not a step, and resolve per ground and mode.
| Role | Used for |
|---|---|
--role-heading | Section heads only |
--role-muted | Secondary text, at 4.5:1 or better |
--role-rule | Any boundary a user must identify: field, table and card borders |
--role-hairline | Rules where whitespace and type also carry structure |
--role-tint | Decorative pattern color, never meaning |
--role-accent | Link underlines, meaningful icons, trails |
--role-select, -mark, -edge | Checked and selected states of value controls |
--role-select-text, -label, -edge, -hover | Selected states that carry words, such as option pills and labelled filter chips |
--role-action, -label, -edge | Every primary button and submit |
--role-action-pressed, -pressed-label | The pressed primary action: the inverse pair (the ink pill presses to a --primary1 face) |
--role-inverse | The label of an ink fill |
--role-halo | Paper-colored clearance and knockouts |
--role-glyph | Chevrons, arrows and text-button glyphs |
--role-status, --role-status-fill, --role-status-text | Status glyph, edge and bar; its fill; the status word |
--role-pill, -label, -edge | A solid badge's fill; the ink pill on saturated fields |
--role-disabled-edge | The dotted edge of a disabled control |
--role-series-odd | The odd chart series slots: --secondary11 on paper and white, --primary12 elsewhere |
--role-ground | The scope's ground color |
--role-edge | The container edge of a card, face or panel, published by Ground: --role-rule on a band, --primary10 on a face on a page ground, --primary12 on a field or light island |
--role-seam | A band's top and bottom rule: invisible, except on the night band in dark mode |
Hover
Hover follows the Land Trust Alliance model [D181]: it changes a fill or an ink, never an edge, a transform or a shadow. It runs for --ds-duration-quick with --ease-out-3, is instant under reduced motion, and never applies to a disabled control.
- Contained buttons lighten. A solid Button's fill moves to
--role-action-hover, and a contained selection fill to--role-select-hover. Label and edge stay, with no underline. - Outline buttons tint to
--role-soft-hover; where soft fills drop, the label underlines instead. - Chevron links change color. A
standaloneLink and atextButton take--role-link-hover, and the glyph swaps to its next weight. - Body links (
inline) keep their underline, take--role-link-hoverand thicken the underline to--border-size-2. - Bare text underlines. A
navLink (bar and utility items, page numbers, toolbar links) and a tab take a--border-size-2--role-accentunderline. - List links change color only.
kind="nav" list(navigation panels, footers, drawers),mutedbreadcrumb ancestors and cardtitlelinks take--role-link-hover.
| Role | Holds |
|---|---|
--role-action-hover | The action's lighter neighbour: --amber6 in light scopes, --amber10 in dark ones, --primary11 for the ink pill |
--role-select-hover | A selected fill on hover; --primary11 where selection is the inverse pair |
--role-link-hover | The secondary's step 12 on light grounds, step 9 on dark grounds where it is text-safe, and --primary12 on the solid fields and on dark rose and heather |
--role-soft-hover | The outline button's --primary3 fill, or the ground where soft fills drop (the pastels, forest, the solid fields) |
--role-soft-hover-face | The same hover for a part whose face is --role-halo, such as the slider thumb: --primary3, or the unchanged face where soft fills drop |
Wherever --role-link-hover is --primary12, an ink-only hover also underlines (--ds-link-hover-line); where soft fills drop, --ds-soft-hover-line underlines the outline button's label. Under forced colors, hover adds an underline to links and text and an outline to buttons.
Text is always --primary12, and the focus ring is a 2 px --primary12 line. Every fill has an edge [D12].
The 16 ground presets
v1 has 16 presets: eight page grounds, the night band and seven fields [D180]. Ground's kind decides where each may go: band (default, full-bleed) takes a page ground or night; field (inset, with a radius and its own --primary12 edge) takes a field; face (a card face, plate or panel) takes a page ground, and night only for the onMedia Button.
| Preset | Family | Ground | Primary × secondary; action | Mode |
|---|---|---|---|---|
paper (default) | page ground | light base (--orange2) | olive × green; amber | follows the page |
white | page ground | light base (--olive1) | olive × green; amber | follows the page |
tide | page ground | pastel (--blue3) | slate × blue; amber | follows the page |
meadow | page ground | pastel (--green3) | sage × green; amber | follows the page |
pollen | page ground | pastel (--yellow3) | sand × yellow; amber | follows the page |
apricot | page ground | pastel (--orange3) | sand × orange; amber | follows the page |
rose | page ground | pastel (--red3) | mauve × red; amber | follows the page |
heather | page ground | pastel (--purple3) | mauve × purple; amber | follows the page |
night | band (footer and media hero only) | deep base | slate × green; amber | always dark |
forest | field | deep tinted | sage × amber; amber | always dark |
leaf | field | solid | olive × green; ink | always light |
amber | field | solid | olive × amber; ink | always light |
clay | field | solid | olive × orange; ink | always light |
pink | field | solid | olive × pink; ink | always light |
royal | field | solid | slate × indigo; amber | always dark |
brick | field | solid | mauve × red; amber | always dark |
Page grounds paint the same step in both modes, so a pastel is very light in light mode and a rich near-black in dark mode. They hold reading and data; a page takes at most one pastel, with paper and white as its secondary bands. Fields hold media, actions and short content, inset with page ground around them, so two fields never touch. The solid fields carry one ink and no muted tier. Each page ground has a companion field for inverse placements: forest for paper, white, meadow and pollen; royal for tide and heather; brick for apricot and rose. Inside tinted or solid scopes, override primary and secondary only with a pairing the §2 matrix verifies.
sand, spruce and soil are deferred and lichen is retired; none is a preset, and passing one is a type error.
Full specification: DESIGN-SYSTEM.md §1.4 (the ink and ground model), §1.5.3 (role map) and §2.2 (presets and pairings), decisions D176–D181; companion guide §C.