CSS custom properties (theme variables)

Colour variables live in two standalone stylesheets, split so a theme swap touches only the first:

  1. colors.css — the 16 --base00--base0F base16 slots. This is the entire theme swap contract. A generator (e.g. one fed a stylix base16 scheme, which is natively base00–base0F) replaces only this file.
  2. theme.css — the semantic layer: --bg, --fg, --purple, … derived from the base16 slots (--bg: var(--base00) etc.). This is what the app references and it never changes on a swap.

Both files live in frontend/packages/shared/src/. Per-page stylesheets (common.css, dashboard.css, flow.css, logs.css, agent.css) reference the semantic names and must not redeclare them or reach for the raw --baseNN slots directly. (base.css holds only the shared body typography — it references the palette but no longer defines it.)

Both are deliberately standalone, not @imported into the page bundles: each package re-exports them (src/{colors,theme}.css@import "@hive/shared/…") so esbuild emits its own dist/static/colors.css + dist/static/theme.css, and every page links them first (colors.css then theme.css) ahead of the page CSS. Note theme.css does not @import colors.css — that would bake the slots back into it; they're two separate output files so a swap replaces just colors.css. (Load order doesn't actually affect resolution — custom properties resolve at computed-value time — but colors.css is linked first for clarity.)

Semantic palette (theme.css)

Each semantic var derives from a base16 slot (or, for the three that have no clean slot, a color-mix() over base16 — pixel-identical under the default palette). Default hexes shown are Catppuccin Mocha.

Variable Derives from Default hex Use
--bg base00 #1e1e2e page background
--bg-elev base01 #181825 elevated surfaces: floating dropdowns, popovers
--border base02 #313244 general borders, hover/active backgrounds
--purple-dim base03 #45475a subtle borders, terminal chrome, badge backgrounds
--fg base05 #cdd6f4 primary text colour
--red base08 #f38ba8 errors, fail state
--amber base09 #fab387 warnings, pending / running state
--yellow base0A #f9e2af flash messages, mild warnings
--green base0B #a6e3a1 success, ok state
--cyan base0C #89dceb tool-use events, info accents
--blue base0D #89b4fa links, interactive accent (distinct from cyan)
--purple base0E #cba6f7 accent — active tabs, links, highlights
--pink base0F #f5c2e7 thinking events
--crust mix(base00 58%, #000) #11111b terminal / code block background (below --bg)
--muted mix(base05 55.5%, base00) #7f849c secondary / dimmed text
--subtext0 mix(base05 77.7%, base00) #a6adc8 toolbar/status text; dimmer than --fg, lighter than --muted

Common mistakes

The Catppuccin colour names do not map 1:1 to the variable names. Variables to avoid (undefined — they will silently resolve to transparent / inherited):

Wrong Correct
--text --fg
--mauve --purple
--surface0 --bg-elev (float bg) or --border (border/hover)
--surface1 --border
--surface2 --purple-dim
--overlay0, --overlay1 --muted
--base, --mantle --bg, --bg-elev

Usage guide

Floating menus and dropdowns (e.g. agent context menu, tabbar overflow):

background: var(--bg-elev);
border: 1px solid var(--purple-dim);

Hover / active state backgrounds:

background: var(--border);

Active tab text / accent elements:

color: var(--purple);

Muted / meta text:

color: var(--muted);

Error / warning / success badges:

color: var(--red);    /* error */
color: var(--amber);  /* warning / running */
color: var(--green);  /* ok */

Theme swapping — the base16 contract

The swap interface is colors.css — the 16 base16 slots, not our semantic names. A theme generator (e.g. one reading a stylix base16 scheme) overrides only colors.css; the semantic layer in theme.css derives everything else, so the whole UI re-themes with nothing else to template or regenerate. The base16 slot → semantic mapping is internal to theme.css (the "Derives from" column above) — a generator never needs to know our var names, and theme.css + the page bundles stay untouched.

colors.css base16 slot defaults (Catppuccin Mocha):

Slot Default Standard base16 role Mapped to
base00 #1e1e2e default bg --bg, (darkened) --crust
base01 #181825 lighter bg --bg-elev
base02 #313244 selection/surface --border
base03 #45475a comments/dim surface --purple-dim
base04 #585b70 dark foreground (unused; kept for completeness)
base05 #cdd6f4 default foreground --fg, (blended) --muted/--subtext0
base06 #f5e0dc light foreground (unused)
base07 #b4befe lightest (unused)
base08 #f38ba8 red --red
base09 #fab387 orange --amber
base0A #f9e2af yellow --yellow
base0B #a6e3a1 green --green
base0C #89dceb cyan --cyan (our sky; Catppuccin's base0C is teal)
base0D #89b4fa blue --blue
base0E #cba6f7 magenta --purple
base0F #f5c2e7 extra accent --pink

Notes for theme authors: