# Design Tokens — SUMI Design System Source of truth: [`src/index.css`](../src/index.css). All `--sumi-*` variables are defined there. Do not create competing token files. Theme switching uses `[data-theme="dark"]` (default, applied on `:root`) and `[data-theme="light"]` attributes. --- ## 1. Colors ### Backgrounds | Token | Dark | Light | Role | |-------|------|-------|------| | `--sumi-bg-void` | `#0c0c0f` | `#f0ece4` | Deepest background | | `--sumi-bg-base` | `#121215` | `#f6f3ed` | App background | | `--sumi-bg-raised` | `#1a1a1f` | `#ffffff` | Cards, sidebar | | `--sumi-bg-overlay` | `#222228` | `#ffffff` | Popovers, dropdowns | | `--sumi-bg-hover` | `#2a2a31` | `#ede9e1` | Hover state | | `--sumi-bg-active` | `#32323a` | `#e4e0d8` | Active/pressed state | | `--sumi-bg-wash` | `#18181d` | `#f8f6f1` | Subtle wash area | ### Surfaces | Token | Role | |-------|------| | `--sumi-surface-inset` | Inset/recessed areas | | `--sumi-surface-subtle` | Subtle differentiation | | `--sumi-surface-card` | Card backgrounds | | `--sumi-surface-elevated` | Elevated panels | ### Text — Warm neutrals | Token | Dark | Light | Role | |-------|------|-------|------| | `--sumi-text-primary` | `#f0ede8` | `#1a1816` | Primary content | | `--sumi-text-secondary` | `#a8a4a0` | `#5c5854` | Secondary content | | `--sumi-text-tertiary` | `#706c68` | `#8a8580` | Tertiary/hints | | `--sumi-text-disabled` | `#4a4844` | `#b5b0aa` | Disabled state | | `--sumi-text-inverse` | `#121215` | `#f0ede8` | Inverse (on accent bg) | | `--sumi-text-link` | `#8baade` | `#4a6fa5` | Links | ### Borders | Token | Role | |-------|------| | `--sumi-border-faint` | Barely visible dividers | | `--sumi-border-default` | Standard borders | | `--sumi-border-strong` | Emphasized borders | | `--sumi-border-focus` | Focus rings | | `--sumi-border-accent` | Accent-tinted borders | ### Pigments (accent colors) 4 pigments provide all accent color needs: | Pigment | Token | Dark hex | Role | |---------|-------|----------|------| | **Indigo** | `--sumi-accent` | `#7c9dd6` | Primary accent, links, focus | | **Vermillion** | `--sumi-vermillion` | `#d4634a` | Destructive, errors, live | | **Sage** | `--sumi-sage` | `#7a9e6c` | Success, online, positive | | **Gold** | `--sumi-gold` | `#c9a84c` | Warnings, achievements | Each pigment has `-hover` and `-subtle` variants. Indigo also has `-active`, `-muted`, and `-emphasis`. ### Semantic aliases | Token | Maps to | |-------|---------| | `--sumi-success` | `--sumi-sage` | | `--sumi-warning` | `--sumi-gold` | | `--sumi-error` | `--sumi-vermillion` | | `--sumi-info` | `--sumi-accent` | ### shadcn/Radix mapping Standard `--background`, `--foreground`, `--primary`, `--muted`, `--border`, etc. are all aliased to `--sumi-*` tokens in `index.css`. Use Tailwind classes (`bg-background`, `text-foreground`, `text-primary`, `text-muted-foreground`) as usual — they resolve to SUMI values. **Do not** use raw Tailwind color palettes (slate, gray, zinc, etc.). Always use the semantic tokens. --- ## 2. Typography ### Font stacks | Token | Font | Usage | |-------|------|-------| | `--sumi-font-body` | Inter | Body text (Tailwind `font-sans`) | | `--sumi-font-heading` | Space Grotesk | Headings (Tailwind `font-heading`) | | `--sumi-font-mono` | JetBrains Mono | Code (Tailwind `font-mono`) | | `--sumi-font-serif` | Noto Serif JP | Decorative (Tailwind `font-serif`) | ### Type scale (`--sumi-text-*`) | Token | Size | Tailwind class | |-------|------|----------------| | `--sumi-text-4xl` | 2.25rem | `text-4xl` | | `--sumi-text-3xl` | 1.875rem | `text-3xl` | | `--sumi-text-2xl` | 1.5rem | `text-2xl` | | `--sumi-text-xl` | 1.25rem | `text-xl` | | `--sumi-text-lg` | 1.125rem | `text-lg` | | `--sumi-text-md` | 1rem | — | | `--sumi-text-base` | 0.875rem | `text-sm` | | `--sumi-text-sm` | 0.8125rem | — | | `--sumi-text-xs` | 0.75rem | `text-xs` | ### Utility classes (Tailwind-friendly) | Class | Definition | |-------|------------| | `.text-display` | `text-4xl font-bold tracking-tight` | | `.text-heading-1` | `text-3xl font-semibold tracking-tight` | | `.text-heading-2` | `text-2xl font-semibold` | | `.text-heading-3` | `text-xl font-medium` | | `.text-heading-4` | `text-lg font-medium` | | `.text-body-lg` | `text-base leading-relaxed` | | `.text-body` | `text-sm leading-relaxed` | | `.text-caption` | `text-xs text-muted-foreground` | | `.text-label` | `text-xs font-medium uppercase tracking-wider text-muted-foreground` | ### SUMI typography classes (token-driven) `.sumi-display`, `.sumi-h1` through `.sumi-h4`, `.sumi-body-lg`, `.sumi-body`, `.sumi-body-sm`, `.sumi-caption`, `.sumi-label`, `.sumi-mono` — these use `--sumi-*` variables directly for font-size, weight, line-height, and letter-spacing. Use these for finer control over the SUMI type scale. ### Visual hierarchy (recommended usage) | Role | Class | Context | |------|-------|---------| | Page title | `.text-heading-1` / `.text-display` | H1 | | Section title | `.text-heading-2` / `.text-heading-3` | H2, H3 | | Label / metadata | `.text-label` / `text-sm` | Field labels | | Body | `.text-body-lg` / `.text-body` | Running text | | Caption | `.text-caption` | Timestamps, legends | Use `text-foreground` for primary info, `text-muted-foreground` for secondary. --- ## 3. Spacing **Base grid: 4px.** Use the standard Tailwind spacing scale (`gap-*`, `p-*`, `m-*`, `space-*`). SUMI spacing tokens in `index.css` (for reference — prefer Tailwind classes): | Token | Value | |-------|-------| | `--sumi-space-0-5` | 2px | | `--sumi-space-1` | 4px | | `--sumi-space-1-5` | 6px | | `--sumi-space-2` | 8px | | `--sumi-space-3` | 12px | | `--sumi-space-4` | 16px | | `--sumi-space-5` | 20px | | `--sumi-space-6` | 24px | | `--sumi-space-8` | 32px | | `--sumi-space-10` | 40px | | `--sumi-space-12` | 48px | | `--sumi-space-16` | 64px | | `--sumi-space-20` | 80px | Layout gaps: `--layout-gap` (16px), `--layout-gap-sm` (12px), `--layout-gap-lg` (24px). --- ## 4. Radius | Token | Value | Usage | |-------|-------|-------| | `--sumi-radius-xs` | 2px | Badges, tags | | `--sumi-radius-sm` | 4px | Buttons, inputs | | `--sumi-radius-md` | 6px | Cards (default `--radius`) | | `--sumi-radius-lg` | 12px | Panels, dialogs | | `--sumi-radius-xl` | 16px | Large cards | | `--sumi-radius-2xl` | 20px | Hero sections | | `--sumi-radius-full` | 9999px | Pills, avatars | Tailwind mapping: `rounded-sm` → `--sumi-radius-sm`, `rounded-md` → `--sumi-radius-md`, etc. --- ## 5. Shadows Defined in `:root` and overridden in `[data-theme="light"]`. | Token | Role | |-------|------| | `--sumi-shadow-xs` | Subtle elevation | | `--sumi-shadow-sm` | Buttons, small cards | | `--sumi-shadow-md` | Tooltips, dropdowns | | `--sumi-shadow-lg` | Cards, panels | | `--sumi-shadow-xl` | Modals, dialogs | | `--sumi-shadow-2xl` | Full overlays | | `--sumi-shadow-glow` | Focus ring glow (Indigo-tinted) | | `--sumi-shadow-glow-lg` | Large ambient glow | ### Glass effect | Token | Value | |-------|-------| | `--sumi-glass-bg` | Semi-transparent bg | | `--sumi-glass-border` | Subtle glass border | | `--sumi-glass-blur` | 12px blur | Classes: `.glass` / `.sumi-glass` apply all three properties + `backdrop-filter`. --- ## 6. Z-Index | Token | Value | Usage | |-------|-------|-------| | `--sumi-z-base` | 0 | Default layer | | `--sumi-z-raised` | 10 | Raised content | | `--sumi-z-dropdown` | 100 | Dropdown menus | | `--sumi-z-sticky` | 200 | Sticky headers, player | | `--sumi-z-overlay` | 300 | Overlays | | `--sumi-z-modal` | 400 | Modals | | `--sumi-z-popover` | 500 | Popovers | | `--sumi-z-toast` | 600 | Toast notifications | | `--sumi-z-tooltip` | 700 | Tooltips | | `--sumi-z-max` | 999 | Absolute top layer | --- ## 7. Motion ### Durations | Token | Value | Usage | |-------|-------|-------| | `--sumi-duration-instant` | 75ms | Immediate feedback | | `--sumi-duration-fast` | 150ms | Hover, focus, color changes | | `--sumi-duration-normal` | 200ms | Sidebar, modals, transforms | | `--sumi-duration-slow` | 300ms | Complex transitions | | `--sumi-duration-slower` | 500ms | Page-level transitions | ### Easings | Token | Curve | Usage | |-------|-------|-------| | `--sumi-ease-default` | `cubic-bezier(0.25, 0.1, 0.25, 1)` | General purpose | | `--sumi-ease-out` | `cubic-bezier(0.33, 1, 0.68, 1)` | Enter / appear | | `--sumi-ease-in` | `cubic-bezier(0.32, 0, 0.67, 0)` | Exit / leave | | `--sumi-ease-in-out` | `cubic-bezier(0.65, 0, 0.35, 1)` | Symmetric transitions | | `--sumi-ease-bounce` | `cubic-bezier(0.34, 1.56, 0.64, 1)` | Playful bounce | | `--sumi-ease-spring` | `cubic-bezier(0.175, 0.885, 0.32, 1.1)` | Spring feel | ### Composite transition tokens | Token | Animates | |-------|----------| | `--sumi-transition-colors` | color, background-color, border-color | | `--sumi-transition-opacity` | opacity | | `--sumi-transition-transform` | transform | | `--sumi-transition-shadow` | box-shadow | `prefers-reduced-motion: reduce` is respected globally — all durations collapse to near-zero. --- ## 8. Layout Shell Full reference: [APP_SHELL.md](APP_SHELL.md). | Token | Value | Role | |-------|-------|------| | `--sumi-header-height` | 56px | Header height | | `--sumi-sidebar-width` | 240px | Sidebar expanded | | `--sumi-sidebar-collapsed` | 64px | Sidebar collapsed | | `--sumi-player-height` | 80px | Player bar | | `--sumi-max-width` | 1400px | App max width | | `--sumi-max-width-content` | 1200px | Content max width | | `--sumi-max-width-narrow` | 800px | Narrow content | | `--sumi-max-width-prose` | 65ch | Prose text width | ### Layout primitives (utility classes) | Class | Token | Value | |-------|-------|-------| | `.max-w-layout-content` | `--layout-content-max-width` | 100rem | | `.min-h-layout-main` | `--layout-main-min-height` | calc(100vh - 4rem) | | `.min-h-layout-page` | `--layout-page-min-height` | 37.5rem | | `.min-h-layout-page-sm` | `--layout-page-min-height-sm` | 25rem | | `.min-h-layout-story` | `--layout-story-decorator-min-height` | 12rem | Modal/drawer height constraints, lyrics, chat, and stream heights — all defined in `index.css` with matching utility classes (`.max-h-layout-modal`, `.h-layout-chat`, etc.). See `index.css` `@layer utilities` section for the full list. --- ## 9. Exceptions (arbitrary values) Arbitrary Tailwind values (`w-[...]`, `h-[...]`, `rounded-[...]`, `shadow-[...]`) are **forbidden** unless: - SVG/canvas rendering (e.g., `text-[2px]` for chart axes) - Third-party component markup you don't control - Documented here or in a PR with justification Add `eslint-disable` comment when an exception is necessary. See also: [.cursorrules](../.cursorrules) for layout primitives and spacing rules.