Design Tokens
All colours and surface values are defined as CSS custom properties in frontend/src/theme/tokens.css and exposed through the typed T object in frontend/src/theme/tokens.ts.
The system follows the Flowbite Mono semantic variable set with a VF violet brand override. Switching the html.dark class (toggled by the app or the Storybook toolbar) flips every variable automatically — components that use the tokens adapt without any dark-mode-specific code.
Importing tokens
import { T } from "../theme/tokens"; // pages/
import { T } from "../../theme/tokens"; // pages/operator/, components/, etc.OperatorLayout and ProfileLayout also re-export T for backwards compatibility with older pages.
Tailwind v4 semantic classes
Tailwind v4 allows referencing any CSS custom property directly as a utility value using parentheses syntax. Use this for inline-style-free class strings:
// Text
<p className="text-(--color-heading)">heading</p>
<p className="text-(--color-body)">body</p>
<p className="text-(--color-body-subtle)">muted</p>
// Backgrounds
<div className="bg-(--color-neutral-primary)">page bg</div>
<div className="bg-(--color-neutral-secondary)">card bg</div>
<div className="bg-(--color-brand-soft)">brand tint</div>
<div className="bg-(--color-success-soft)">green tint</div>
<div className="bg-(--color-warning-soft)">amber tint</div>
<div className="bg-(--color-danger-soft)">red tint</div>
// Borders
<div className="border border-(--color-default)">standard border</div>
<div className="border border-(--color-brand-subtle)">brand border</div>
// Foreground colours
<span className="text-(--color-fg-brand)">violet</span>
<span className="text-(--color-fg-success)">green</span>
<span className="text-(--color-fg-warning)">amber/orange</span>
<span className="text-(--color-fg-danger)">red</span>T.* token object
Use T.* when you need the value inside a style= prop (e.g. SVG fills, dynamic inline styles). Do not use T.* for class names — use Tailwind semantic classes instead.
Backgrounds
| Token | CSS variable | Usage |
|---|---|---|
T.bg | --color-neutral-primary | Page background |
T.card | --color-neutral-secondary | Elevated card surface |
T.rowEven | --color-neutral-secondary | Alternating table row |
Borders
| Token | CSS variable | Usage |
|---|---|---|
T.border | --color-default | Default dividers and outlines |
T.borderHover | --color-default-medium | Hover / focus border |
T.borderStrong | --color-default-strong | Emphasis border |
Text
| Token | CSS variable | Usage |
|---|---|---|
T.text | --color-heading | Primary / heading text |
T.textSoft | --color-body | Body text |
T.textMuted | --color-body-subtle | Secondary / muted text |
Accent — violet brand
| Token | CSS variable | Usage |
|---|---|---|
T.accent | --color-fg-brand | Primary brand colour |
T.accentSoft | --color-brand-soft | Brand tint background |
T.accentBorder | --color-brand-subtle | Brand border / ring |
Success — green
| Token | CSS variable | Usage |
|---|---|---|
T.green | --color-fg-success | Success foreground |
T.greenSoft | --color-success-soft | Success tint background |
T.greenBorder | --color-success-subtle | Success border |
T.greenBorderLight | --color-success-medium | Stronger success border |
Warning — amber / orange
| Token | CSS variable | Usage |
|---|---|---|
T.amber | --color-fg-warning | Warning foreground (dark) |
T.amber600 | --color-fg-warning-subtle | Orange-600 emphasis |
T.amberSoft | --color-warning-soft | Warning tint background |
T.amberBorder | --color-warning-subtle | Warning border |
T.amberSoftHexandT.amberBorderHexare aliases ofamberSoft/amberBorderkept for backward compatibility — prefer the non-Hex names.
Danger — red
| Token | CSS variable | Usage |
|---|---|---|
T.red | --color-fg-danger | Danger foreground |
T.red600 | --color-fg-danger-strong | Stronger red |
T.redSoft | --color-danger-soft | Danger tint background |
T.redBorder | --color-danger-subtle | Danger border |
T.red600Softis an alias ofT.redSoftkept for backward compatibility.
Info — sky / cyan
| Token | CSS variable | Usage |
|---|---|---|
T.sky | --color-fg-cyan | Cyan foreground |
T.skySoft | --color-sky-soft | Cyan tint background |
Dark tones
| Token | CSS variable | Usage |
|---|---|---|
T.dark | --color-dark | Dark chip fill, nav badge bg |
T.darkSoft | --color-dark-soft | Soft dark surface |
Light / dark mode values (reference)
The CSS variables are defined for both modes in tokens.css:
| Semantic role | Light | Dark |
|---|---|---|
| Page background | #ffffff | #111827 (neutral-900) |
| Card surface | #f9fafb (neutral-50) | #1f2937 (neutral-800) |
| Heading text | #111827 | #f9fafb |
| Body text | #4b5563 | #d1d5db |
| Muted text | #6b7280 | #9ca3af |
| Brand (violet) | #7c3aed | #8b5cf6 |
| Success (green) | #15803d | #4ade80 |
| Danger (red) | #b91c1c | #f87171 |
| Warning (amber) | #7c2d12 | #fbbf24 |
| Default border | rgba(0,0,0,0.08) | rgba(255,255,255,0.1) |
Typography
Font: Nunito Sans (loaded via CDN). Fallback: Inter, system-ui.
--font-sans: "Nunito Sans", Inter, system-ui, sans-serif;Tailwind classes: text-sm (13–14 px), text-base (16 px), font-semibold, font-bold.
Spacing
4 px base grid. Standard Tailwind spacing classes apply (p-4 = 16 px, gap-6 = 24 px, etc.).
Border radius
| Element | Tailwind |
|---|---|
| Cards / panels | rounded-xl or rounded-2xl |
| Buttons | Flowbite default (rounded-lg) |
| Badges / pills | rounded-full |
| Small chips | rounded-md |