# Canvas Design System v1 — VERIFIED > **Status:** VERIFIED — Cross-referenced against molecule-core/canvas/src/ (2026-05-09, updated 2026-05-10 evening) > **Authors:** Core-FE (draft), Core-UIUX (verification + updates) > **Source files verified:** > - `canvas/src/app/globals.css` > - `canvas/src/styles/theme-tokens.css` > - `canvas/src/lib/design-tokens.ts` > - `canvas/src/components/Tooltip.tsx` > - `canvas/src/components/ContextMenu.tsx` > - `canvas/src/components/Canvas.tsx` > - `canvas/src/components/__tests__/Canvas.a11y.test.tsx` > - `canvas/src/components/__tests__/ContextMenu.keyboard.test.tsx` > - `canvas/src/components/__tests__/MissingKeysModal.a11y.test.tsx` > - `canvas/src/components/__tests__/ConversationTraceModal.a11y.test.tsx` --- ## 1. Color Palette — Three-Mode Theme System Canvas supports **three themes**: System (follows OS), Light, Dark. Controlled via `ThemeProvider` in `theme-provider.tsx` with preference persisted in `mol_theme` cookie. **Key principle: Use semantic tokens, NOT raw zinc values for surfaces.** ### 1.1 Theme-Mutable Tokens (use these for surfaces) Defined in `globals.css` via Tailwind v4 `@theme` block. Automatically flip between light/dark. **Light theme (warm paper):** | Token | Tailwind Class | Hex | Usage | |-------|--------------|-----|-------| | `--color-surface` | `bg-surface` | `#fafaf7` | Page background | | `--color-surface-elevated` | `bg-surface-elevated` | `#ffffff` | Elevated cards, modals | | `--color-surface-sunken` | `bg-surface-sunken` | `#f3f1ec` | Input fields, recessed areas | | `--color-surface-card` | `bg-surface-card` | `#efece4` | Node cards, chips | | `--color-line` | `border-line` | `#e6e2d8` | Dividers, borders | | `--color-line-soft` | `border-line-soft` | `#efece4` | Subtle dividers | | `--color-ink` | `text-ink` | `#15181c` | Primary text | | `--color-ink-mid` | `text-ink-mid` | `#5a5e66` | Secondary text | | `--color-ink-soft` | `text-ink-soft` | `#8b8e95` | Tertiary text, placeholders | | `--color-accent` | `text-accent` | `#3b5bdb` | Links, primary actions | | `--color-accent-strong` | `text-accent-strong` | `#1a2f99` | Emphasized accent | | `--color-warm` | `text-warm` | `#c0532b` | Warnings | | `--color-good` | `text-good` | `#2f7a4d` | Success states | | `--color-bad` | `text-bad` | `#b94e4a` | Error states | **Dark theme:** | Token | Hex | Usage | |-------|-----|-------| | `--color-surface` | `#0e1014` | Page background | | `--color-surface-elevated` | `#15181c` | Elevated cards | | `--color-surface-sunken` | `#0a0b0e` | Input fields | | `--color-surface-card` | `#1a1d23` | Node cards | | `--color-line` | `#2a2f3a` | Dividers | | `--color-ink` | `#f4f1e9` | Primary text | | `--color-ink-mid` | `#c8c2b4` | Secondary text | | `--color-ink-soft` | `#8d92a0` | Tertiary text | | `--color-accent` | `#6883e8` | Links (brighter for AA contrast) | | `--color-accent-strong` | `#8aa1ee` | Emphasized accent | | `--color-warm` | `#d96f48` | Warnings | | `--color-good` | `#4ca06e` | Success | | `--color-bad` | `#d27773` | Errors | ### 1.2 Always-Dark Tokens (terminal surfaces) Terminals, console modal, log streams **stay dark** in all themes — readable green-on-black doesn't translate to light. | Token | Tailwind Class | Hex | Usage | |-------|--------------|-----|-------| | `--color-bg` | `bg-bg` | `rgb(9 9 11)` / zinc-950 | Terminal background | | `--color-bg-elev` | `bg-bg-elev` | `rgb(24 24 27)` / zinc-900 | Elevated terminal surfaces | | `--color-bg-card` | `bg-bg-card` | `rgb(39 39 42)` / zinc-800 | Terminal cards | | `--color-line-strong` | `border-line-strong` | `rgb(63 63 70)` / zinc-700 | Strong borders | | `--color-ink-mute` | `text-ink-mute` | `rgb(161 161 170)` / zinc-400 | Muted text | | `--color-ink-dim` | `text-ink-dim` | `rgb(113 113 122)` / zinc-500 | Dim text | ### 1.3 Raw Zinc Usage Rules **Use raw zinc for:** - Borders: `border-zinc-700`, `border-zinc-800` - Disabled states: `text-zinc-600`, `bg-zinc-800` - Code highlighting: `bg-zinc-900`, `text-zinc-300` - Terminal surfaces: `bg-zinc-950` (always-dark) **NEVER use for surfaces:** - `bg-zinc-900` or `bg-zinc-950` as page/card backgrounds — use `bg-surface` - `text-zinc-50` or `text-zinc-100` as primary text — use `text-ink` - `bg-white`, `bg-gray-50/100` for surfaces — use semantic tokens ### 1.4 Accessibility Contrast | Pair | Ratio | WCAG | |------|-------|------| | `text-ink` on `bg-surface` (light) | ~14.5:1 | AAA | | `text-ink` on `bg-surface` (dark) | ~15.8:1 | AAA | | `text-ink-mid` on `bg-surface` (light) | ~5.2:1 | AA | | `text-ink-mid` on `bg-surface` (dark) | ~5.9:1 | AA | | `text-accent` on `bg-surface` (light) | ~4.8:1 | AA | | `text-accent` on `bg-surface` (dark) | ~4.6:1 | AA | --- ## 2. Typography Scale **Actual font stack** (from `globals.css`): ``` -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif ``` No custom fonts loaded — uses OS-native system stack. | Size Token | Tailwind | Usage | |------------|----------|-------| | `text-[10px]` | 10px | Micro badges, tier labels | | `text-[11px]` | 11px | Tooltip text | | `text-xs` / `text-[12px]` | 12px | Badges, timestamps | | `text-sm` / `text-[13px]` | 13–14px | Secondary labels, node titles | | `text-base` / `text-[16px]` | 16px | Body text | | `text-lg` | 18px | Section headers | | `text-xl` | 20px | Modal titles | **Line height:** `leading-tight` (1.25) for headings, `leading-relaxed` (1.625) for body/tooltips. --- ## 3. Animation / Motion Tokens **Defined in `canvas/src/styles/theme-tokens.css`** — use these, don't hardcode ms values. | Token | Value | Usage | |-------|-------|-------| | `--mol-duration-fast` | 150ms | Hover states, button feedback | | `--mol-duration-base` | 300ms | Standard transitions | | `--mol-duration-spawn` | 350ms | Node spawn animation | | `--mol-duration-root-complete` | 700ms | Org-deploy root glow | | `--mol-duration-fit-view` | 800ms | Canvas fit-viewport | | Token | Value | Usage | |-------|-------|-------| | `--mol-easing-standard` | `cubic-bezier(0.2, 0, 0, 1)` | Default ease | | `--mol-easing-bounce-out` | `cubic-bezier(0.2, 0.8, 0.2, 1.05)` | Node spawn bounce | | `--mol-easing-emphasize` | `cubic-bezier(0.3, 0, 0, 1)` | Modal/drawer enter | **CSS usage:** ```css /* Good — reference the token */ transition: all var(--mol-duration-fast) ease; /* Bad — hardcoded value */ transition: all 150ms ease; ``` --- ## 4. Component Patterns (Verified) ### 4.1 Buttons ```tsx // Primary — accent background, ink text // Secondary — surface-card background, border-line // Ghost — no background, hover surface // Danger — bad color, requires confirmation dialog ``` **States:** default, hover, active (`scale-95`), focus (`ring-2 ring-blue-500 ring-offset-2 ring-offset-zinc-900`), disabled (`opacity-50 cursor-not-allowed`). ### 4.2 Inputs ```tsx // Text input — use semantic tokens for surfaces // Error state ``` **Label:** `text-sm font-medium text-ink mb-1` **Error:** `text-xs text-bad mt-1` ### 4.3 Cards ```tsx // Workspace node card (from WorkspaceNode.tsx)