Foundations
Design tokens
Two layers. tokens.css holds raw values — palette, type ramp, space, radius, motion. theme.css maps them to semantic names, and components only ever read those. Light and
dark are the same semantic names with different values, resolved from a single data-theme attribute on <html>.
Two names in that map do the accessibility heavy lifting: the interactive colour is --an-accent (ink, not a hue), and control boundaries use --an-border-control rather than the decorative hairline. Both are measured on the accessibility page.
Colour
Surfaces
--an-bg--an-surface--an-surface-raised--an-surface-sunken--an-surface-hover--an-surface-inverseContent & lines
--an-text--an-text-muted--an-text-faint--an-border--an-border-strong--an-border-controlInteractive, brand & status
--an-accent--an-accent-emphasis--an-accent-soft--an-brand--an-brand-strong--an-success--an-warning--an-danger--an-infoTypography
The ramp, the two families and every canonical pairing live on their own page — Typography — because type is where most of the day-to-day decisions get made, and a swatch grid is the wrong place to answer them.
Space, radius, elevation
Space
Radius
xssmmdlgxl2xlElevation
Surfaces are flat by default: a card shares the page's colour and is found by its
hairline, in both themes. Only two things break the plane — something recessed goes down a
step (sunken, the nav rail), and something genuinely floating over the page
casts a shadow. Nothing rises by getting lighter, except in dark, where a shadow over
near-black is invisible and raised has to lift with tone instead.
xssmmdlgxlMotion
Material 3's duration and easing scales, mirrored in tokens.css and motion/tokens.ts — so a CSS transition and a Svelte transition run the identical
curve. Press replay and watch the difference between the standard and emphasized families.
Easing
Duration
--an-duration-short-2 100ms--an-duration-short-4 200ms--an-duration-medium-2 300ms--an-duration-medium-4 400ms--an-duration-long-2 500msTheming an app
/* Rebrand by redefining the semantic layer — never by
overriding component selectors. */
:root {
--an-accent: #0a84ff;
--an-accent-soft: #dceafd;
--an-radius-md: 6px; /* squarer controls */
--an-press-scale: 1; /* opt out of the press squish */
}