Skip to content

CaseSolo UI design system

Living record of what is true in code. MASTER freeze: planning/design/MASTER.md. Visual primitives: docs/dev/dashboard-visual-system.md.

Tokens stay the single source of truth. Components consume names, never hex.

T0 — tokens

Source: src/app/globals.css (:root, .dark, @theme) and public/brand/brand-tokens.css.

| Token | Role | |---|---| | --cs-navy | Ground, ink, shell | | --cs-amber | One-match accent, gold CTA fill | | --cs-amber-600 | Amber text on light | | --cs-blue | Links, focus, in-app primary | | --cs-font-display | Page titles (alias of branded Inter) | | --font-sans / --font-heading | Inter UI | | --font-mono | Data / code | | --background --foreground --card --primary --muted --border --ring --destructive | Semantic shadcn roles | | --shell-bg --shell-rail --shell-panel --shell-flyout | App chrome (always navy) | | --elevation-1..4 | Layered navy-tinted shadows | | --radius | 0.625rem base; sm/md/lg/xl derived | | --motion-ease --motion-fast --motion-base | Spring ease, 180ms / 220ms |

Raw palette lives only here. Components use bg-background, text-primary, variant="gold", .ds-eyebrow, .dashboard-card-chrome.

T1 — primitives (src/components/ui)

| Primitive | Variants | Required states | |---|---|---| | Button | default (Counsel Blue), gold (Signal Amber), outline, secondary, ghost, destructive, link | default / hover / focus-visible / active / disabled / loading | | Card | default, sm | hover bloom only when the card is a control (via dashboard-border-motion) | | Input Select Textarea | default | focus-visible, disabled, aria-invalid | | Badge | default, secondary, destructive, outline, ghost, link, gold | focus-visible | | EmptyState | empty, error, loading × sm/default/lg | role=status on loading, role=alert on error | | Skeleton | .dashboard-skeleton-line | reduced-motion: no shimmer |

Gold CTA: navy type on amber (color: #0b1b34). Never white on amber.

T2 — page kit (src/components/page)

| Pattern | Rule | |---|---| | PageShell | Only page root. Width full \| medium \| narrow. Layout owns padding. | | PageHeader | Exactly one per page. Branded Inter h1. Optional eyebrow. Actions right. One gold button max. | | Eyebrow | Mission label: 0.65rem, 600, tracking 0.16em, amber. | | StatCard / StatGrid | Tabular stat-figure. Semantic trend color only. | | Toolbar | Search grows, filters, actions. |

Chrome

Usage rules

  1. No page-local hex, text-gray-*, or bg-white on dashboard surfaces.
  2. No second page wrapper (container, mx-auto max-w-*) — PageShell width prop.
  3. Empty, loading, and error are three treatments (EmptyState variants).
  4. Hover only on actual controls.
  5. One primary CTA per view. Gold is that CTA. Everything else is outline/ghost/blue.
  6. Numbers use .tabular / .stat-figure.
  7. Page titles use font-display (the PageHeader default).

Drift ratchet (manual until CI)

Grep for: #0b0b16, #7c3aed, from-blue-500 to-cyan, violet-500, conic-gradient, text-gray-. Each hit is a named migration onto a token that already exists.

Source: docs/dev/UI_DESIGN_SYSTEM.md