Design tokens
The published CSS custom properties every theme is built on
Every color in the white-label dashboard resolves through a closed set of CSS custom properties — the published token list. Custom themes set them, CSS rules reference them via var(--token), and the theme contract endpoint publishes the same list machine-readably.
Tokens come in two tiers. Core tokens are required in a custom theme (all 11, per mode). Extended tokens are optional refinements — when you don't set one, its value is derived from the core tokens or falls back to the stock stylesheet default.
Core tokens (11)
| Token | What it controls |
|---|---|
--bg-canvas | The page gutter/canvas behind everything |
--bg-base | The base app surface |
--bg-raised | Cards and raised panels |
--bg-overlay | Popovers, dropdowns, dialogs |
--bg-inset | Inset wells and input backgrounds |
--text-heading | Headings |
--text-primary | Body text |
--text-secondary | Secondary text |
--text-tertiary | Muted text and captions |
--brand | The brand/action color (buttons, links, highlights) |
--accent | The secondary accent color |
A custom theme carries a full light map and a full dark map. Your single accent color is written into --brand and --accent in both modes when you save.
Extended tokens (26)
Optional. Set any of these to override the derived value; unset ones show through from the derivation or the stock defaults.
| Group | Tokens | Derived from (when unset) |
|---|---|---|
| Lines | --line-subtle, --line-weak, --line-strong | Translucent alphas of --text-primary (6% / 8% / 12%) |
| Fills | --fill-subtle, --fill-muted, --fill-default | Translucent alphas of --text-primary (3% / 6% / 10%) |
| Text extras | --text-disabled, --text-faint | Alphas of --text-primary (56% / 31%) |
| Brand | --brand-hover | --brand darkened 10% |
| Sections | --bg-section-alt, --bg-section-strong | --bg-raised |
| Semantic hues | --vitesse-green, --vitesse-red, --vitesse-orange, --vitesse-blue, --vitesse-cyan, --vitesse-magenta, --vitesse-yellow | Stock defaults |
| Status | --status-success, --status-warning, --status-danger, --status-info | Stock defaults |
| Charts | --chart-1 through --chart-5 | Stock series palette |
The semantic and status hues are deliberately left alone by the built-in presets — an error should still read as an error whatever the skin. Override them only with equally legible colors.
How the cascade works
You set solid values for the core tokens; the platform derives everything else so a theme always reads consistently:
- Hairlines and subtle fills are computed as translucent layers of your
--text-primary, so they inherit your theme's temperature automatically. Override the--line-*tokens with solid colors when you want drawn strokes instead of translucency (the Unstyled and Boardroom presets do this). - Hover/glow shades of
--brandand--accentare derived by lightening or darkening. - The shadcn-style component layer (dialogs, dropdowns, popovers) is bridged from the same tokens, so overlay surfaces follow your theme too.
Accepted color formats
Token values accept #hex (3, 6, or 8 digits), rgb() / rgba() with numbers or percentages, and hsl() / hsla(). Named colors are not accepted.
Dark and light
Every custom theme defines both modes. Which one a customer sees follows their preference unless you set a mode lock in Branding basics. When authoring, check both — a --line-strong that reads well on paper can vanish on a dark base.