apps/client/src/theme
The game's design tokens, one source of truth for how every interface looks: a Material-like theme in theme.ts, typed, without React or the DOM but for the one call that puts it in a page.
| Token group | In theme.ts | CSS custom properties | What |
|---|---|---|---|
| Palette | PALETTE | --foi-color-<role> (primary, on-primary, primary-container, surface-high, text-medium…) | The primary (the main menu's orange) with its hover, deep shade, container and the colours on them; a secondary and a tertiary; the background and five surface levels; the panels over the game; text at high, medium and disabled emphasis (and the menus' warm text); outlines; error, warning, success, info with their containers |
| Type | TYPE | --foi-type-<step> (the font shorthand), -size, -line, -weight, -tracking | Display, headline, title (lg, md, sm), body (lg, md, sm), label (lg, md, sm), all in Changa (--foi-font-family) |
| Spacing | SPACE | --foi-space-0 … --foi-space-10 | 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64 px |
| Radii | RADIUS | --foi-radius-xs to --foi-radius-full | 4, 6, 10, 16, 24 px (xs, sm, md, lg, xl) and a pill (full) |
| Elevation | ELEVATION | --foi-elevation-0 … --foi-elevation-5 | Shadows on a dark ground, from flat to a dialog |
| Motion | MOTION | --foi-duration-<name> (instant, short, medium, long), --foi-easing-<name> (standard, emphasized, decelerate, accelerate) | How long a change takes and how it eases |
| Layers | LAYER | --foi-z-<layer> (base, sticky, menu, popover, dialog, toast, tooltip) | The z-index of each layer |
| Focus | --foi-focus-ring | The ring a control shows when the keyboard reaches it |
themeVariables() names every token, themeCss() writes them on :root, and installTheme(document) puts that style sheet first in the page; ui/mount.tsx calls it before any tree is drawn. Everything else derives from it:
- the web UI's components (
../ui/kit,kit.css) and the game pages (../ui/browse.css) use the--foi-*properties alone; - the overlay's tokens (
--ui-fg,--ui-accent… on#ui,../ui/overlay.css) and the menus' (--menu-hot,--menu-fg…,../ui/menu.css) are aliases of them, so older rules keep working; - the in-game GUI drawn in the scene (
../gui/theme.ts'COLOURS) takes the palette's values.
So a colour changed in PALETTE recolours the game pages, the overlay, the menus and the game's own panels at once (theme.test.ts holds the GUI to the palette). A new token is a field here first, then its use; never a colour written into a component's CSS.