# Foundations — the brief fixed doctrine

Cross-cutting decisions every build makes once, stated at the length they deserve and no longer (the obviousness rule: what competent intelligence already knows gets nothing). Load the touched entry at the step that decides it, never the file whole.

## The five status palettes

Pick **one** per project at intake and hold it everywhere — status colors are semantics, not decoration, and deltas color by *meaning* (down is green when down is good):

| Palette | success | warning | danger | info | neutral | Feel |
| --- | --- | --- | --- | --- | --- | --- |
| `signal` | `oklch(0.64 0.15 150)` | `oklch(0.75 0.15 80)` | `oklch(0.58 0.20 25)` | `oklch(0.60 0.14 250)` | `oklch(0.65 0.02 260)` | the default — clear, saturated, unmistakable |
| `muted-pro` | `oklch(0.60 0.09 155)` | `oklch(0.68 0.10 75)` | `oklch(0.55 0.13 25)` | `oklch(0.58 0.08 250)` | `oklch(0.62 0.015 260)` | desaturated for dense dashboards — readable without shouting |
| `warm-ledger` | `oklch(0.62 0.11 140)` | `oklch(0.70 0.13 60)` | `oklch(0.56 0.17 30)` | `oklch(0.60 0.10 230)` | `oklch(0.64 0.02 80)` | warm-neutral products (finance, ops review) |
| `cool-console` | `oklch(0.66 0.12 165)` | `oklch(0.74 0.12 85)` | `oklch(0.60 0.18 15)` | `oklch(0.62 0.12 265)` | `oklch(0.66 0.02 250)` | cool/dark consoles — holds up on deep backgrounds |
| `high-contrast` | `oklch(0.55 0.17 150)` | `oklch(0.60 0.16 70)` | `oklch(0.50 0.21 27)` | `oklch(0.50 0.16 255)` | `oklch(0.50 0.02 260)` | accessibility-first; every value ≥4.5:1 on white |

Each value is the light-theme anchor; derive the dark-theme sibling by raising lightness ~0.08 and trimming chroma ~0.02. Severity ladders (P0–P3 and kin) map onto danger → warning → info → neutral, never onto new hues.

## Data-viz palettes

No database — three constraints, values yours: **categorical** series need distinguishable hues that survive colorblind simulation (rotate hue ≥40° apart, vary lightness too, ≤8 series then facet); **sequential** ramps run light→dark in one hue for magnitude; **diverging** ramps put two hues around a *meaningful* zero, neutral at the middle. Validate every ramp in both themes; charts consume package tokens, never raw hex.

## Number, date, unit formatting

Tabular figures in tables and KPIs; thousands separators; unit or currency attached to the number; consistent decimals per column; large values truncate meaningfully (`1.2M`, never `1,200,000` in a tile); timestamps show relative when recent and absolute on hover (under `nurix`, that is `<Timestamp format="auto">`, never a hand-rolled formatter); timezones explicit anywhere ambiguity costs money.

## Spacing & density

The 2/4/6/8 scale, period. Density is a per-project decision made once, not a per-surface mood — recorded as the `density` trait: **compact** for operator surfaces that scan (controls and data rows land at 32px), `regular` or `airy` only when `product.md` says reading. Under `nurix` the trait reaches controls and collection surfaces through the library's `--density-*` tokens, never through per-surface `p-*` literals.

## Radius & stroke

Radius is identity — sharp (0–2px), soft (4–6px), or round (10px+) — chosen by the package and applied consistently; mixing radii on one surface reads as templated. One border weight per surface; elevation *or* borders separate layers, never both at full strength.

## Loading, skeleton, progress

Skeletons for layout-known loads, spinners only for unknowable ones, optimistic updates for high-frequency mutations with undo. Skeletons mirror the real layout's bones (no generic gray blocks). Nothing pulses faster than 1.2s; under `nurix` a status pulse is `<Chip prefix="dot" pulse>`, never `animate-pulse` (a hardcoded keyframe neither `pace` nor the inline clamp can reach), and loaders keep breathing inside inline collections by design.

## Empty states

The three empties (first-use, no-results, cleared-filter) each say what happened and what to do next, in the project voice. Art direction follows the package's restraint: an icon or nothing for dense tools; illustration only where the package's feel says warm. Never a bare "No data".

## Keyboard

The operator vocabulary: `⌘K` command palette, `j/k` traversal where lists dominate, `esc` closes the topmost layer only, `enter` commits, focus visible always. Declare shortcuts in a discoverable surface (palette footer or `?` overlay).

## Dark mode physics

Elevation becomes lightness (surfaces lighten as they rise — shadows barely read); desaturate fills ~15%; never pure black (`oklch(0.13–0.18 …)` floors); borders drop to low-alpha white; charts re-derive from dark-theme tokens, never inherit light values.

## Code, log, terminal surfaces

Mono face with `tabular-nums`; a shiki theme paired to the package (dark identity → dark code surface even in light theme is legitimate); log levels use the status palette; wrap off by default with horizontal scroll.

## Polish

Focus rings on-brand (2px, offset, the accent — never browser default blue on a styled app); selection color derived from the accent at low alpha; scrollbars styled thin on dense panes; cursor changes only where affordance is real.
