Theme rotation as composition
Light and dark aren't a toggle. Used per section, the tonal shift carries an argument the layout alone can't make.
Design tokens stored as CSS custom properties — values you can read, override, and ship without a build step.
A design token is a decision with a name. --color-bg-default is the decision “this is the page background,” made once and referenced everywhere.
Plenty of systems store those decisions in a format only a build tool can read. Plus UI stores them as plain CSS custom properties. The difference matters more than it sounds.
Because tokens are CSS variables, they are live in the page. Open dev tools, inspect an element, and the token is right there:
:root {
--color-bg-default: #ffffff;
--color-text-default: #0a0a0a;
--space-4: 1rem;
}No source map back to a JSON file. No mental translation between a token name and the value it resolves to. What you read is what ships.
Theming is reassigning variables in a narrower scope:
[data-theme="dark"] {
--color-bg-default: #0a0a0a;
--color-text-default: #fafafa;
}Every component that reads --color-bg-default updates at once. No recompile, no runtime JavaScript, no flash of the wrong theme. The cascade does the work it was designed to do.
Tokens resolve in one direction, never sideways:
bg-default, text-caption.A component only ever names the semantic tier. It never reaches for a raw hex, so it stays correct in any theme without knowing the theme exists.
That is the whole trick: decisions you can read, in the language the browser already speaks.