Theming
Three layers: primitives hold the raw palette, semantic tokens name a role, and components only ever reference the roles.
The three layers
Primitives are the palette — --color-blue-400, --color-neutral-950. Semantic tokens name what a color is for — --color-text-primary, --color-background-full — and point at a primitive. Components reference only the semantic layer.
That indirection is what makes theming cheap: change what a role points at and every component follows, in both light and dark, with no component edits.
Changing the accent
Interactive surfaces — the primary button gradient, ghost and link buttons, checkbox, radio, switch, slider, tabs, sidebar selection, and the focus ring — reference --color-accent-* rather than a raw hue. Override those eleven variables and the whole system re-tints.
Overriding a single role
Any semantic token can be redefined the same way. Because @theme inlinere-exports each one, Tailwind reads the live value — so an override applies at runtime without a rebuild.
The Colors page lists every token, generated from the stylesheet itself.
Typography
The ramp is defined as composite utilities: text-body-medium carries size, line height, letter spacing, and weight together. To change the family, override the font stack once — the ramp inherits it. See Typography for the full scale.
A note on cx
BoardCN's cx helper wraps tailwind-merge and is taught about every composite text utility. If you add your own text-* style via @theme, register it in utils/cx.ts too — otherwise tailwind-merge reads it as a text-color utility and will drop your color classes.