# Design System The single written standard for Orla Numis's web UI. Every new or changed view in `src/web` must follow it, including the status tones, shared primitives and tables. Enforcement lives in `src/web/src/__tests__/design-tokens.test.ts`. Budgets in that suite are ratchets: they may only decrease. ## 1. Tokens All CSS values must come from `src/web/src/assets/styles/variables.css` and the global classes in `main.css`. Never hardcode a raw value when a token exists. | Token | Value | Use for | |---|---|---| | `--radius-sm` | `8px` | Cards, inputs, buttons | | `--radius-md` | `12px` | Larger containers, modals | | `--radius-lg` | `16px` | Hero sections | | `--radius-full` | `9999px` | Pills, chips, badges | | `--border-subtle` | gold 15% | Default borders | | `--border-accent` | gold 40% | Hover / active borders | | `--accent-gold` | `#c9a84c` | Primary accent, active states, links | | `--accent-bronze` | `#b08d57` | Secondary accent | | `--accent-gold-dim` | gold 30% | Active chip / pill / toggle backgrounds | | `--accent-gold-glow` | gold 15% | Focus rings, subtle backgrounds | | `--bg-card` | theme | Card backgrounds | | `--bg-input` | theme | Input, textarea and toggle track backgrounds | | `--text-primary` | theme | Body text | | `--text-secondary` | theme | Secondary text, toggle knobs | | `--text-muted` | theme | Labels, hints, placeholders | | `--text-heading` | theme | Headings (h1–h4) | | `--transition-fast` | `0.2s ease` | Hover, focus | | `--transition-med` | `0.3s ease` | Layout changes | Gold (`--accent-gold`) is reserved for active states, values and prices, links, and section accents. ## 2. Typography One scale. Every font size in the app is a step on it — `text-[0.82rem]` and friends are a test failure. Steps are defined in the `@theme` block of `src/web/src/assets/styles/main.css`. | Utility | Size | Use for | |---|---|---| | `text-2xs` | `0.55rem` | Dense data grids at phone widths only | | `text-micro` | `0.65rem` | Dense data grids, micro-chips | | `text-label` | `0.7rem` | Section labels, table headers, uppercase tiny | | `text-sm` | `0.75rem` | Badges, `.chip-sm` | | `text-chip` | `0.8rem` | Standard chip text, field hints | | `text-body` | `0.85rem` | Form labels, secondary body | | `text-base` | `0.9rem` | Primary body, h4 | | `text-md` | `1.1rem` | Card and modal titles | | `text-lg` | `1.2rem` | h3 | | `text-xl` | `1.5rem` | h2 | | `text-2xl` | `2rem` | h1, stat numerals | | `text-3xl` | `2.5rem` | Hero numerals | | `text-4xl` | `3rem` | Single headline numeral | Headings also carry a font: h1–h4 use Cinzel (`font-display`) at weights 600 / 500 / 500 / 500; body copy uses Inter (`font-sans`). The only permitted arbitrary size is an `em` value inside rendered markdown (`[&_code]:text-[0.88em]`), because that is a ratio to its container rather than a scale step. ### What the guards do and do not catch `design-tokens.test.ts` forbids `text-[Nrem|px|pt]` and `text-[var(--…)]`, but it is a regex over the `