Design tokens

Three layers. The theme-independent foundation supplies type, spacing, borders, and radii. A theme authors 30 palette values; 28 feed the 69 semantic names components actually use, while --tone-8 and --tone-9 are reserved to preserve the public 12-step neutral ramp and support future deep-ink roles. The init command adds all three layers to your CSS file — after that you own them. Values shown are Solace (default). See Themes for other presets.

Background

SwatchTokenValueUsage
--color-bg#fdfcfaPage background
--color-bg-raised#f4f3f2Cards, panels
--color-bg-overlay#ecebeaDialogs, menus, popovers
--color-bg-input#fdfcfaForm controls
--color-bg-hover#dbdadaHover surface
--color-bg-active#bcbcbcActive / selected surface
--color-bg-disabled#dbdadaDisabled surface
--color-bg-emphasis#16151dPrimary buttons, checked, tooltips, pagination current
--color-bg-emphasis-hovercolor-mix(in oklab, #2657d0 24%, #16151d)Emphasis surface, hovered (accent-warmed)
--color-bg-emphasis-activecolor-mix(in oklab, #2657d0 14%, #16151d)Emphasis surface, pressed (accent-warmed)

Use as Tailwind utilities: bg-bg, bg-bg-raised, bg-bg-emphasis, etc.

Foreground

SwatchTokenValueUsage
--color-fg#24232aPrimary text
--color-fg-muted#525257Secondary text, descriptions
--color-fg-subtle#636367Placeholders, decorative text
--color-fg-disabled#747477Disabled text
--color-fg-on-emphasis#fdfcfaText on bg-emphasis
--color-fg-link#2657d0Links

Use as text-fg, text-fg-muted, text-fg-link, etc.

Border

SwatchTokenValueUsage
--color-border#868688Default borders
--color-border-muted#a1a0a2Dividers, disabled borders
--color-border-strong#16151dInputs, overlays, emphasis
--color-border-focus#2657d0Focus outline

Use as border-border, divide-border-muted, outline-border-focus, etc.

Contrast guarantees

Beaket tests supported semantic combinations in Chromium after CSS variables and color-mix() expressions resolve. Normal-sized primary, muted, subtle, link, emphasis, and role text combinations meet at least 4.5:1. Default, strong, focus, and invalid interactive boundaries meet at least 3:1 against their supported surfaces.

These are guarantees for the documented semantic pairings, not an all-against-all promise. Decorative surfaces are intentionally excluded. Disabled text and boundaries are measured and reported to theme authors, but they are not presented as WCAG failures because inactive controls are exempt from the corresponding WCAG contrast requirements. Run pnpm test:contrast from the repository root to audit every shipped light and dark palette.

Solace signal distinguishability

Solace additionally tests every pair of its six semantic roles as a solid, foreground, tint, 1px border, hover, and active color under normal vision and simulated protanopia, deuteranopia, and tritanopia. The simulation applies the 100% severity matrices from Machado, Oliveira, and Fernandes (2009) to linear-light sRGB. Distances are then measured as Euclidean ΔE in OKLab.

The undiluted solid, hover, and active forms require ΔE ≥ 0.04. Derived forms scale that floor by the semantic layer's authored OKLab mixture: foreground 50% requires 0.02, tint 17% requires 0.007, and border 60% requires 0.025 (rounded up). The base floor is a Beaket safety margin for small marks, not a WCAG rule or a universal perception boundary. Tints remain supporting surfaces; shipped status examples retain readable labels or distinct icon shapes so color is never the only cue.

Roles

Six roles — danger, success, warning, info, info-alt, accent — each with seven slots. Values below show the danger role. The accent role alone carries one extra slot, -bg-subtle.

SwatchTokenValueUsage
--color-{role}-solid#961733Solid fill (buttons, badges)
--color-{role}-fg-on-solid#fdfcfaType on the solid — the knockout
--color-{role}-solid-hovercolor-mix( in oklab, #961733 90%, contrast-color(#fdfcfa) )Solid, hovered
--color-{role}-solid-activecolor-mix( in oklab, #961733 80%, contrast-color(#fdfcfa) )Solid, pressed
--color-{role}-fgcolor-mix(in oklab, #961733 50%, #16151d)Role-colored text on the page
--color-{role}-bgcolor-mix(in oklab, #961733 17%, #fdfcfa)Tinted background
--color-{role}-bordercolor-mix(in oklab, #961733 60%, #fdfcfa)Border on tinted background
--color-accent-bg-subtlecolor-mix(in oklab, #2657d0 8%, #fdfcfa)Accent only — faintest wash (the lens fill — navigation, tabs)

Use as bg-danger-solid, text-danger-fg-on-solid, text-success-fg, bg-info-bg, border-warning-border, etc.

Shadows

TokenValueUsage
--shadow-offset2px 2px 0 0 #bfbdb9Surfaces (cards, panels)
--shadow-offset-overlay2px 2px 0 0 #a19e98Overlays
--shadow-offset-action2px 2px 0 0 #2657d0Thin action edge — pressable hover or field focus
--shadow-offset-action-hovercalc(2px + 1px) calc(2px + 1px) 0 0 #2657d0Grown action edge — open owner
--shadow-offset-action-danger2px 2px 0 0 #961733Invalid writing field, focused

Surfaces use shadow-offset; overlays use shadow-offset-overlay. Pressables are neutral at rest: edged controls reveal shadow-offset-action on hover, and open owners hold shadow-offset-action-hover. Writing fields engage the thin edge only on focus, swapping to shadow-offset-action-danger when invalid. Size and color vary by theme.

Palette — authored by the theme

The layer a theme supplies. Components never reference these directly; the semantic names above point at them.

TokenValueUsage
--surface-0 … --surface-2#fdfcfaThe page and what sits on it
--tone-0 … --tone-7, --tone-11#525257Functional neutral ramp: paper through deepest ink
--tone-8 … --tone-10#323239Reserved: 12-step ramp compatibility and future deep-ink roles
--signal-{role}#961733One ink per meaning; only the accent is vivid
--signal-{role}-on#fdfcfaWhich ramp end carries type on each solid
--shadow-size / -color / -color-overlay#bfbdb9Shadow geometry and ink

Customization

To restyle an app, override palette values in the generated stub after beaket:theme:end — the semantic layer follows. Keep the stub's light, system-dark and forced-dark selectors so generated defaults cannot outrank your brand. The marked block is regenerated by theme; preview with theme --diff. Spacing uses Tailwind's existing 4px scale. See Themes for ownership and preference details, and the Changelog when updating.