Theming
The token system is small on purpose: a handful of physical variables drive everything else.
The five knobs
Every shadow, bevel, and glint in Emboss is computed from the light vector, scaled by depth, and clipped by the radius scale. Accent color rotates around a single oklch hue with lightness locked by contrast tests. Override any of them on :root — or on a subtree to re-light just one region.
:root {
/* Where light comes from (unit vector; screen y points down). */
--light-x: -0.45;
--light-y: -0.89;
/* Relief intensity: 0 = flat, 1 = default, 1.5 = deep. */
--depth: 1;
/* Accent hue in oklch degrees: 45 = signal orange, 152 = green, 252 = blue. */
--accent-h: 45;
/* Multiplies the whole radius scale: 0 = square, 1 = machined, 1.5 = soft. */
--radius-scale: 1;
}What the tokens generate
The theme exposes surfaces (bg-surface-0…3, bg-well), ink (text-ink, text-ink-muted), semantic colors, and the elevation recipes: shadow-deboss-2 through shadow-float-2. Use them in your own components and they will obey the same light.
<div className="bg-surface-2 shadow-emboss-1 rounded-md">Raised</div>
<div className="bg-well shadow-deboss-1 rounded-md">Recessed</div>
<div className="bg-surface-3 shadow-float-1 rounded-md">Floating</div>Dark mode
The .dark class swaps the material — in the dark, depth reads through lit edges more than cast shadows — while the geometry stays identical. Components never branch on the scheme; they reference the same tokens in both.
Fonts
The tokens map --font-sans to Instrument Sans and --font-mono to JetBrains Mono, with system fallbacks if the fonts are absent. Numeric readouts always use the mono face with tabular-numsso values don't jitter as they change.