Skip to content

Themes

The system has one palette and two readings of it. The dark theme changes which palette colours the semantic tokens point at, and nothing else; the palette itself never changes.

tokens.css writes the light values on :root and on [data-theme="light"], and the dark theme as one [data-theme="dark"] block that holds only the tokens it changes. The light block on the attribute lets a light section sit inside a dark page. In the token files, the dark theme is theme-dark.tokens.json, applied by the resolver’s theme modifier.

Two rules keep the dark theme coherent:

  • The dark surface stays emphasis. In the dark theme --surface-dark is one step above the canvas rather than equal to it, so a dark card, a dark band and every tone="dark" component still stand apart from the page.
  • Coral does not move. --color-primary, --color-on-primary and --focus-ring are the same in both themes. The brand colour is the one thing a theme may not reinterpret.

They are separate. A component’s tone names a surface within the page, such as a dark card; the theme names the page’s own floor. A component never takes a theme prop: it reads the tokens, and the tokens follow the theme.

The CSS reads only the data-theme attribute; there is no prefers-color-scheme query. A page sets data-theme="light" or data-theme="dark" on <html> with a short script in <head>, before the first paint, so a page never flashes the wrong theme. “Follow the system” is a stored preference that the script turns into light or dark with matchMedia, which is what lets a page force light against a dark operating system. The switch itself has no transition: a crossfade would put every surface in motion at once.

TokenLightDarkDescription
--color-primary-disabledcolor.primary-disabled#e6dfd8Points to --cream-500#3a3833Primary fill when disabled.
--text-inktext.ink#141413Points to --ink-900#faf9f5Points to --cream-50Headlines and the strongest text.
--text-body-strongtext.body-strong#252523Points to --ink-800#f5f0e8Points to --cream-100Emphasized body text.
--text-bodytext.body#3d3d3aPoints to --ink-700#e8e0d2Points to --cream-300Running text.
--text-mutedtext.muted#6c6a64Points to --ink-500#a09d96Points to --ink-300Secondary text such as dates and metadata.
--text-muted-softtext.muted-soft#8e8b82Points to --ink-400#7f7c74The quietest text: hints and micro-labels.
--surface-canvassurface.canvas#faf9f5Points to --cream-50#181715Points to --night-900The page floor.
--surface-softsurface.soft#f5f0e8Points to --cream-100#1f1e1bPoints to --night-850A soft band one step above the canvas.
--surface-cardsurface.card#efe9dePoints to --cream-200#252320Points to --night-800Cards on the canvas.
--surface-cream-strongsurface.cream-strong#e8e0d2Points to --cream-300#2b2925The strongest cream, for emphasis inside cards.
--surface-darksurface.dark#181715Points to --night-900#2b2925The emphasis surface: dark cards, code windows, the footer.
--surface-dark-softsurface.dark-soft#1f1e1bPoints to --night-850#322f2aOne step above the dark surface, such as code inside a dark card.
--surface-dark-elevatedsurface.dark-elevated#252320Points to --night-800#393631Raised elements on dark surfaces.
--surface-blur-creamsurface.blur-creamrgb(250 249 245 / 72%)rgb(24 23 21 / 72%)Translucent cream behind a 12px backdrop blur, such as the scrolled top bar.
--surface-blur-cream-opaquesurface.blur-cream-opaquergb(250 249 245 / 94%)rgb(24 23 21 / 94%)Near-opaque cream for when the blur is not supported.
--hairlinehairline#e6dfd8Points to --cream-500#35332fBorders. They read as one elevation step, not as ink lines.
--hairline-softhairline-soft#ebe6dfPoints to --cream-400#2a2823Fainter borders inside cards.
--hairline-on-darkhairline-on-dark#31302c#43413bBorders on dark surfaces.
--marker-coralmarker.coral#f4e2d9#4d352bPoints to --marker-coral-on-dark
--marker-tealmarker.teal#deede7#2e453fPoints to --marker-teal-on-dark
--marker-ambermarker.amber#f7ead9#52412cPoints to --marker-amber-on-dark
--marker-redmarker.red#f1d9d5#492826Points to --marker-red-on-dark
--marker-coral-on-darkmarker.coral-on-dark#422c24#4d352b
--marker-teal-on-darkmarker.teal-on-dark#273a35#2e453f
--marker-amber-on-darkmarker.amber-on-dark#463624#52412c
--marker-red-on-darkmarker.red-on-dark#3e2120#492826
--border-hairlineborder.hairline1px solid #e6dfd81px solid #35332fDividers and card outlines.
--border-hairline-softborder.hairline-soft1px solid #ebe6df1px solid #2a2823Fainter dividers inside cards.
--border-hairline-darkborder.hairline-dark1px solid #31302c1px solid #43413bBorders on dark surfaces.