# SUMI Design System — Source de Vérité **Version**: 2.0 — Merged (Visual truth: Web version) **Updated**: 2026-02-12 **Status**: Active — Single Source of Truth for ALL UI decisions **System Name**: SUMI (墨) — "L'encre et la lumiere" --- ## 1. Philosophy & Identity ### 1.1 Name: SUMI (墨) "Sumi" is the Japanese word for ink — the fundamental medium of sumi-e painting (ink wash). This design system takes its visual language from the encounter between **ink and paper**: depth without darkness, light without glare, expression without excess. The name replaces all previous system names (KODO, Spectre Astral, Neon Refined, Botanical). There is now ONE system. ### 1.2 Core Concept: "L'encre et la lumière" The visual identity of Veza/Talas is built on a single metaphor: **ink diluted in water, applied on washi paper**. This is not a decorative theme — it's a design grammar that unifies ALL user experiences. > *Encre sur papier. Chaque surface est une feuille, chaque accent un coup de pinceau délibéré. L'espace (間 ma) est sacré.* ### 1.3 Les 6 Règles Inviolables 1. **Encre, pas néon** — Les couleurs sont des pigments, pas des lumières. Quand tout brille, rien ne se distingue. Le glow est UNIQUEMENT pour les focus rings. 2. **Espace sacré (Ma 間)** — Spacing généreux, densité maîtrisée. Ce qui n'est pas là est aussi important que ce qui y est. Le vide n'est pas vide — il respire. 3. **Universalité** — Lisible pour tous (8 ans–80 ans, auditeur casual–label pro). Pas de dark pattern, pas de complexité gratuite. 4. **Wabi-sabi numérique** — Authenticité > perfection stérile. Personnalité dans les détails, pas dans les effets. Les textures sont subtiles, les formes légèrement organiques. 5. **Révélation progressive** — Simple pour l'auditeur, profond pour le label. Les fonctions avancées (stats, gestion multi-artistes, analytics) se révèlent au fur et à mesure. Jamais tout d'un coup. 6. **Thèmes comme épices** — Gaming (XP, achievements), cyber (monospace, terminal), graffiti (chips, tags) = 5% de l'UI, 100% de la personnalité. Ce sont des accents, pas le plat principal. ### 1.4 Thèmes Absorbés | Thème | Comment il se manifeste | Où dans l'UI | |---|---|---| | **Fusain / Lavis japonais** | Couleurs chaudes, tons d'encre, espace | **Partout** — c'est le langage visuel de base | | **Nature / Botanical** | Sauge comme couleur success, tons terreux | Badges, états online/success | | **Cybersec / Linux** | JetBrains Mono, terminal blocks, stats mono | Stats, analytics, terminal, durées | | **Jeux vidéo 2D** | XP bar, achievements, animation pop | Gamification, récompenses | | **Graffiti / Tag** | Chips genre, tags, énergie gestuelle | Tags musicaux, filtres, catégories | | **Musique indé** | Authenticité, imperfection, warmth | Ton général, pas de clinquant | ### 1.5 Mnemonic S.U.M.I. As a quick memory device, the system name also encodes its principles: - **S — Subtle**: 90% neutral ink tones. Accent ONLY where action or status demands it. - **U — Universal**: Grandmother and label manager see the same natural interface. - **M — Measured**: 4px grid, defined elevations, purposeful transitions. No ornament without function. - **I — Intentional**: Every visual decision answers "what does this help the user DO?" ### 1.6 Reference Products (Quality Benchmarks) The SUMI system targets the visual quality and polish of: - **Spotify**: Surface hierarchy, typography-driven hierarchy, minimal accent usage - **Discord**: Information density without clutter, dark mode excellence, community warmth - **Linear**: Precision, speed feel, glass effects done right - **Arc Browser**: Personality without sacrificing usability ### 1.7 What SUMI is NOT - NOT a neon/cyberpunk interface (no #00fff7 everywhere) - NOT a flat botanical/nature app (nature is a sub-theme, not the identity) - NOT a gaming UI (gaming elements appear only in gamification features) - NOT music-focused visually (music is the CONTENT; the UI is content-agnostic) - NOT anxious or overstimulating (calm > cool) --- ## 2. Color System — "Les 4 Pigments" The SUMI palette repose sur des neutres chauds (90% of the UI) and 4 intentional accent pigments. Pas 50 variables. Pas de neon. Think: charcoal on rice paper, not LED screens. ### 2.1 The 90/10 Rule **90% of every screen is ink tones** (warm neutrals). **10% is accent color** — reserved exclusively for primary actions, active states, status indicators, and navigation markers. This ratio is non-negotiable. ### 2.2 Backgrounds — Couches d'encre Like ink wash (墨絵): darkest = most ink, lightest = diluted wash. These are WARM darks — notice the slight warm undertone vs cold slate. **Dark mode** (default): | Token | Hex | Role | |---|---|---| | `--sumi-bg-void` | `#0c0c0f` | Deepest — app background behind everything | | `--sumi-bg-base` | `#121215` | Primary background — main content area | | `--sumi-bg-raised` | `#1a1a1f` | Cards, sidebar — one layer up | | `--sumi-bg-overlay` | `#222228` | Dropdowns, popovers, modals | | `--sumi-bg-hover` | `#2a2a31` | Hover state on surfaces | | `--sumi-bg-active` | `#32323a` | Active/pressed state | | `--sumi-bg-wash` | `#18181d` | Subtle tinted bg (like diluted ink wash) | **Light mode** ("Washi Paper" 和紙 — warm off-whites, like handmade Japanese paper. NOT cold clinical white): | Token | Hex | Role | |---|---|---| | `--sumi-bg-void` | `#f0ece4` | Warmest base — like aged washi | | `--sumi-bg-base` | `#f6f3ed` | Main content — fresh rice paper | | `--sumi-bg-raised` | `#ffffff` | Cards — pure white stands out on cream | | `--sumi-bg-overlay` | `#ffffff` | Modals, dropdowns | | `--sumi-bg-hover` | `#ede9e1` | Hover on light surfaces | | `--sumi-bg-active` | `#e4e0d8` | Pressed on light surfaces | | `--sumi-bg-wash` | `#f8f6f1` | Subtle tinted bg | ### 2.3 Surfaces For components that sit ON backgrounds (inputs, wells, insets): | Token | Dark | Light | Usage | |---|---|---|---| | `--sumi-surface-inset` | `#101013` | `#ebe7df` | Sunken — search bars, input fields | | `--sumi-surface-subtle` | `#1e1e24` | `#f2eee6` | Slightly raised — table rows alternate | | `--sumi-surface-card` | `#1a1a1f` | `#ffffff` | Standard card | | `--sumi-surface-elevated` | `#242430` | `#ffffff` | Floating — FAB, sticky headers | ### 2.4 Borders — Ink lines | Token | Dark | Light | Usage | |---|---|---|---| | `--sumi-border-faint` | `rgba(255,255,255, 0.06)` | `rgba(0,0,0, 0.05)` | Subtle separation | | `--sumi-border-default` | `rgba(255,255,255, 0.10)` | `rgba(0,0,0, 0.10)` | Standard borders | | `--sumi-border-strong` | `rgba(255,255,255, 0.16)` | `rgba(0,0,0, 0.18)` | Emphasized borders | | `--sumi-border-focus` | `rgba(139,170,220, 0.50)` | `rgba(80,110,170, 0.45)` | Focus rings | | `--sumi-border-accent` | `rgba(139,170,220, 0.30)` | `rgba(80,110,170, 0.25)` | Accent-colored borders | **Border width**: Always 1px. The only exception is the active sidebar indicator (3px left border) and focus rings (2px outline). ### 2.5 Text — Densités d'encre | Token | Dark | Light | Usage | |---|---|---|---| | `--sumi-text-primary` | `#f0ede8` (warm white) | `#1a1816` (deep charcoal) | Titles, main content | | `--sumi-text-secondary` | `#a8a4a0` | `#5c5854` | Descriptions, metadata | | `--sumi-text-tertiary` | `#706c68` | `#8a8580` | Timestamps, captions | | `--sumi-text-disabled` | `#4a4844` | `#b5b0aa` | Disabled state | | `--sumi-text-inverse` | `#121215` | `#f0ede8` | On accent backgrounds | | `--sumi-text-link` | `#8baade` | `#4a6fa5` | Links — soft blue | **Text hierarchy rule**: Info principale = `text-primary` (titles, names), info secondaire = `text-secondary` (artist under title, descriptions), info tertiaire = `text-tertiary` (timestamps, durations, captions). Données chiffrées = `font-mono` toujours (12,847 streams, 3:42, +23.4%). ### 2.6 Les 4 Pigments d'Accent | Pigment | Kanji | Variable | Hex (dark) | Hex (light) | Usage | |---|---|---|---|---|---| | **Indigo Ink** | 藍墨 | `--sumi-accent` | `#7c9dd6` | `#4a6fa5` | Primaire — boutons, active, focus, navigation | | **Vermillion Seal** | 朱印 | `--sumi-vermillion` | `#d4634a` | `#b84a35` | Danger — erreurs, destructif, notifications, live | | **Sage** | 草墨 | `--sumi-sage` | `#7a9e6c` | `#5a7e4e` | Success — online, validé, nature | | **Gold Leaf** | 金墨 | `--sumi-gold` | `#c9a84c` | `#9a7d2e` | Reward — XP, achievements, premium, warnings | Each pigment has 3 variants: | Variant | Indigo | Vermillion | Sage | Gold | |---|---|---|---|---| | `base` | `#7c9dd6` | `#d4634a` | `#7a9e6c` | `#c9a84c` | | `hover` | `#93afe0` | `#de7a64` | `#8eb280` | `#d6b860` | | `subtle` | `rgba(124,157,214, 0.12)` | `rgba(212,99,74, 0.12)` | `rgba(122,158,108, 0.12)` | `rgba(201,168,76, 0.12)` | Additional accent variants (Indigo only): `--sumi-accent-active: #6b8dc6`, `--sumi-accent-muted: rgba(124,157,214, 0.20)`, `--sumi-accent-emphasis: #5a7fba`. **Usage rules for primary (Indigo):** - Primary buttons: `--sumi-accent` background, `--sumi-text-inverse` text - Links: `--sumi-text-link` - Active nav item: `--sumi-accent-subtle` background tint + `--sumi-accent` text - Focus ring: `--sumi-shadow-glow` - Progress bars, sliders: `--sumi-accent` - NEVER as background for cards, sections, or large areas ### 2.7 Semantic Mapping ```css --sumi-success: var(--sumi-sage); --sumi-warning: var(--sumi-gold); --sumi-error: var(--sumi-vermillion); --sumi-info: var(--sumi-accent); --sumi-live: #e05a5a; /* Brighter red for live indicators */ --sumi-online: var(--sumi-sage); ``` Each semantic color has a `*-subtle` variant for tinted backgrounds (e.g. `--sumi-success-subtle: var(--sumi-sage-subtle)`). ### 2.8 Contextual Accents — Feature-Specific Colors These colors appear ONLY in their specific feature contexts. They are NOT part of the general UI palette. | Token | Hex | Feature Context | |---|---|---| | `--graffiti-magenta` | `#c840a0` | Creative expression: artist profiles, cover art badges | | `--gaming-gold` | `#d4b040` | XP, achievements, leaderboards, level badges | | `--terminal-green` | `#3eaa5e` | Admin panel, dev tools, API status | | `--sakura` | `#e0a0b8` | Delicate moments: welcome, onboarding, empty states | **Strict usage rule**: If you cannot justify which FEATURE requires the contextual color, use `--sumi-accent` or `--sumi-vermillion` instead. ### 2.9 Color Architecture Summary ``` ┌───────────────────────────────────────────────────────┐ │ SUMI COLOR MODEL │ ├───────────────────────────────────────────────────────┤ │ │ │ ████████████████████████████████████████ 90% │ │ Sumi Neutrals (--sumi-bg-*, --sumi-text-*) │ │ Backgrounds, surfaces, text, borders │ │ │ │ ██████ 7% │ │ Indigo Ink 藍墨 (--sumi-accent) │ │ Buttons, links, active states, focus │ │ │ │ ███ 2% │ │ Vermillion 朱印 + Sage 草墨 + Gold 金墨 │ │ Errors, success, warnings, achievements │ │ │ │ █ 1% │ │ Contextual (magenta, gold, green, sakura) │ │ Feature-specific moments only │ │ │ └───────────────────────────────────────────────────────┘ ``` --- ## 3. Typography — "The Brush & The Grid" ### 3.1 Font Stack 3 fonts + 1 decorative. That's it. No Orbitron. No display fonts that scream. | Role | Font | Variable | Fallbacks | Weight Range | Why | |---|---|---|---|---|---| | **Body** | Inter | `--sumi-font-body` | -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif | 300–700 | Universal readability. Google/Apple-tier. | | **Headings** | Space Grotesk | `--sumi-font-heading` | 'Inter', sans-serif | 400–700 | Geometric but warm. Has personality without being aggressive. Nods to tech/cyber subtly. | | **Mono** | JetBrains Mono | `--sumi-font-mono` | 'SF Mono', 'Consolas', monospace | 400–600 | Code, terminal UI, stats. The cybersec/linux accent. | | **Decorative** | Noto Serif JP | `--sumi-font-serif` | Georgia, serif | 400, 600 | Easter eggs, citations japonaises (rare). | **Fonts removed** (and why): - Orbitron: Too sci-fi/gaming. Makes the app look like a cyberpunk game, alienates non-tech users. - Rajdhani: Too niche/specific. Doesn't add readability. - Barlow / DM Sans: Good but Inter is the industry standard body font with better feature support. - Source Serif 4 / Instrument Serif: Serif fonts don't belong in a streaming app primary stack. - Bebas Neue: Display-only font, Space Grotesk at bold weights covers this. **Loading strategy:** ```html ``` **Font feature settings** (Inter): `font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';` — stylistic alternates for cleaner glyphs. ### 3.2 Type Scale (Major Third — 1.250) | Class | Token | Size | Font | Weight | Line Height | Spacing | Usage | |---|---|---|---|---|---|---|---| | `.sumi-display` | `--sumi-text-4xl` | 2.25rem (36px) | Heading | 700 | `--sumi-leading-tight` (1.25) | `--sumi-tracking-tighter` (-0.03em) | Hero, landing | | `.sumi-h1` | `--sumi-text-3xl` | 1.875rem (30px) | Heading | 600 | `--sumi-leading-tight` | `--sumi-tracking-tight` (-0.015em) | Titre de page | | `.sumi-h2` | `--sumi-text-2xl` | 1.5rem (24px) | Heading | 600 | `--sumi-leading-snug` (1.375) | `--sumi-tracking-tight` | Section | | `.sumi-h3` | `--sumi-text-xl` | 1.25rem (20px) | Heading | 500 | `--sumi-leading-snug` | Normal | Sous-section | | `.sumi-h4` | `--sumi-text-lg` | 1.125rem (18px) | Heading | 500 | `--sumi-leading-snug` | Normal | Sous-titre | | `.sumi-body-lg` | `--sumi-text-md` | 1rem (16px) | Body | 400 | `--sumi-leading-relaxed` (1.625) | Normal | Texte important | | `.sumi-body` | `--sumi-text-base` | 0.875rem (14px) | Body | 400 | `--sumi-leading-normal` (1.5) | Normal | **Texte standard** | | `.sumi-body-sm` | `--sumi-text-sm` | 0.8125rem (13px) | Body | 400 | `--sumi-leading-normal` | Normal | Texte compact | | `.sumi-caption` | `--sumi-text-xs` | 0.75rem (12px) | Body | 400 | `--sumi-leading-normal` | Normal | Timestamps, captions | | `.sumi-label` | `--sumi-text-xs` | 0.75rem (12px) | Body | 500 | `--sumi-leading-normal` | `--sumi-tracking-wider` (0.05em) | Labels uppercase | | `.sumi-mono` | `--sumi-text-sm` | 0.8125rem (13px) | Mono | 400 | — | — | Stats, durées | ### 3.3 Typography Tokens **Line Heights:** | Token | Value | |---|---| | `--sumi-leading-none` | 1 | | `--sumi-leading-tight` | 1.25 | | `--sumi-leading-snug` | 1.375 | | `--sumi-leading-normal` | 1.5 | | `--sumi-leading-relaxed` | 1.625 | | `--sumi-leading-loose` | 1.75 | **Letter Spacing:** | Token | Value | |---|---| | `--sumi-tracking-tighter` | -0.03em | | `--sumi-tracking-tight` | -0.015em | | `--sumi-tracking-normal` | 0 | | `--sumi-tracking-wide` | 0.025em | | `--sumi-tracking-wider` | 0.05em | | `--sumi-tracking-widest` | 0.1em | **Font Weights:** | Token | Value | |---|---| | `--sumi-weight-light` | 300 | | `--sumi-weight-regular` | 400 | | `--sumi-weight-medium` | 500 | | `--sumi-weight-semibold` | 600 | | `--sumi-weight-bold` | 700 | ### 3.4 Text Color Hierarchy On dark surfaces: | Priority | Token | Hex | Usage | |---|---|---|---| | **Primary** | `--sumi-text-primary` | `#f0ede8` | Headings, important text, interactive labels | | **Secondary** | `--sumi-text-secondary` | `#a8a4a0` | Body text, descriptions | | **Tertiary** | `--sumi-text-tertiary` | `#706c68` | Metadata, timestamps, helper text | | **Disabled** | `--sumi-text-disabled` | `#4a4844` | Disabled labels, placeholder | On light surfaces: | Priority | Token | Hex | Usage | |---|---|---|---| | **Primary** | `--sumi-text-primary` | `#1a1816` | Headings, important text | | **Secondary** | `--sumi-text-secondary` | `#5c5854` | Body text | | **Tertiary** | `--sumi-text-tertiary` | `#8a8580` | Metadata | | **Disabled** | `--sumi-text-disabled` | `#b5b0aa` | Disabled | ### 3.5 Typography Rules 1. **Never use more than 3 font weights on a single screen**: pick from 400, 500, 600, 700. 2. **Headings are always `font-heading` (Space Grotesk)**, never mono or body. 3. **Monospace is ONLY for**: BPM numbers, musical keys, code blocks, terminal output, timestamps in admin, file sizes, stream counts, durations. 4. **Maximum 4 type sizes per screen** to maintain hierarchy clarity. 5. **Line length**: Body text should not exceed `65ch` (~520px at 14px). Use `max-w-prose` or equivalent. 6. **Font feature settings**: Always enable Inter's stylistic alternates with `'cv02', 'cv03', 'cv04', 'cv11'`. --- ## 4. Spacing, Radius & Elevation ### 4.1 Spacing — 4px Base Grid All spacing uses the standard Tailwind scale built on a 4px base unit. NO arbitrary spacing values. | Token | Tailwind | Value | Typical Use | |---|---|---|---| | `1` | `p-1` / `gap-1` | 4px | Icon-to-text micro gap | | `1.5` | `p-1.5` / `gap-1.5` | 6px | Tight chip/badge padding | | `2` | `p-2` / `gap-2` | 8px | Internal component gap, icon button padding | | `3` | `p-3` / `gap-3` | 12px | Compact card padding, input horizontal padding | | `4` | `p-4` / `gap-4` | 16px | Standard card padding, list item spacing | | `5` | `p-5` / `gap-5` | 20px | Form group spacing | | `6` | `p-6` / `gap-6` | 24px | Generous card padding, section internal spacing | | `8` | `p-8` / `gap-8` | 32px | Section-to-section spacing | | `10` | `p-10` / `gap-10` | 40px | Large section spacing | | `12` | `p-12` / `gap-12` | 48px | Page-level section gaps | | `16` | `p-16` / `gap-16` | 64px | Hero sections top/bottom | | `20` | `p-20` / `gap-20` | 80px | Maximum content spacing | **Spacing rules:** 1. Card padding: `p-4` (compact) or `p-6` (standard). NOT `p-8` for cards (too much wasted space). 2. Section spacing: `gap-6` (tight) or `gap-8` (standard) between related sections. 3. Page-level spacing: `gap-10` or `gap-12` between major page sections. 4. Never use `space-y-*` when `gap-*` on a flex/grid parent achieves the same result. ### 4.2 Border Radius Inspired by ink brush curves — soft but not bubbly. The dominant shape language is "soft rectangle". | Token | Tailwind | Value | Usage | |---|---|---|---| | `none` | `rounded-none` | 0px | Table cells, inline code | | `sm` | `rounded-sm` | 4px | Chips inside inputs, micro elements | | `md` | `rounded-md` | 6px | Badges, small buttons, tags | | `DEFAULT` | `rounded` | 8px | Buttons, inputs, small cards | | `lg` | `rounded-lg` | 12px | Standard cards, dropdowns, popovers | | `xl` | `rounded-xl` | 16px | Modals, large feature cards | | `2xl` | `rounded-2xl` | 20px | Hero cards, full-page modals | | `full` | `rounded-full` | 9999px | Avatars, pills, circular buttons, sliders | **Radius rules:** 1. Default interactive elements (buttons, inputs): `rounded` (8px) 2. Cards: `rounded-lg` (12px) 3. Modals: `rounded-xl` (16px) 4. Avatars: Always `rounded-full` 5. NEVER mix different radii on the same component — children should use smaller or equal radius. ### 4.3 Elevation & Shadow System Shadows in SUMI are "ink pooling" — soft, warm-tinted, not harsh black. **Dark mode shadows:** | Token | CSS Value | Usage | |---|---|---| | `--sumi-shadow-xs` | `0 1px 2px rgba(0,0,0,0.30)` | Inputs, badges | | `--sumi-shadow-sm` | `0 2px 4px rgba(0,0,0,0.25), 0 1px 2px rgba(0,0,0,0.20)` | Cards at rest | | `--sumi-shadow-md` | `0 4px 12px rgba(0,0,0,0.30), 0 2px 4px rgba(0,0,0,0.15)` | Cards hover, tooltips | | `--sumi-shadow-lg` | `0 8px 24px rgba(0,0,0,0.35), 0 4px 8px rgba(0,0,0,0.20)` | Dropdowns, popovers | | `--sumi-shadow-xl` | `0 16px 48px rgba(0,0,0,0.40), 0 8px 16px rgba(0,0,0,0.20)` | Modals, drawers | | `--sumi-shadow-2xl` | `0 24px 64px rgba(0,0,0,0.50)` | Full-screen overlays | **Light mode shadows** (softer): | Token | CSS Value | |---|---| | `--sumi-shadow-xs` | `0 1px 2px rgba(0,0,0,0.05)` | | `--sumi-shadow-sm` | `0 2px 4px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)` | | `--sumi-shadow-md` | `0 4px 12px rgba(0,0,0,0.08), 0 2px 4px rgba(0,0,0,0.04)` | | `--sumi-shadow-lg` | `0 8px 24px rgba(0,0,0,0.10), 0 4px 8px rgba(0,0,0,0.05)` | | `--sumi-shadow-xl` | `0 16px 48px rgba(0,0,0,0.12), 0 8px 16px rgba(0,0,0,0.06)` | | `--sumi-shadow-2xl` | `0 24px 64px rgba(0,0,0,0.15)` | **Glow** — used ONLY for focus states and primary CTA. Never decorative: | Token | CSS Value | When to use | |---|---|---| | `--sumi-shadow-glow` | `0 0 0 3px rgba(124,157,214,0.25)` | Focus rings on interactive elements | | `--sumi-shadow-glow-lg` | `0 0 20px rgba(124,157,214,0.15)` | "Now playing", active live stream | **Glow rules:** 1. Glows are ANIMATED, never static (they pulse or appear then fade) 2. Maximum 1 glowing element visible at a time on any screen 3. Respect `prefers-reduced-motion`: no glow animations ### 4.4 Glass Panel Frosted ink paper — for player bar, header, floating panels. NOT for regular cards. ```css .sumi-glass { background: var(--sumi-glass-bg); backdrop-filter: blur(var(--sumi-glass-blur)); -webkit-backdrop-filter: blur(var(--sumi-glass-blur)); border: 1px solid var(--sumi-glass-border); } ``` | Token | Dark | Light | |---|---|---| | `--sumi-glass-bg` | `rgba(18,18,21, 0.80)` | `rgba(255,255,255, 0.85)` | | `--sumi-glass-border` | `rgba(255,255,255, 0.08)` | `rgba(0,0,0, 0.06)` | | `--sumi-glass-blur` | `12px` | `12px` | ### 4.5 Scrollbar | Token | Dark | Light | |---|---|---| | `--sumi-scrollbar-track` | `transparent` | `transparent` | | `--sumi-scrollbar-thumb` | `rgba(255,255,255, 0.10)` | `rgba(0,0,0, 0.12)` | | `--sumi-scrollbar-hover` | `rgba(255,255,255, 0.18)` | `rgba(0,0,0, 0.22)` | Width: 6px. Border-radius: `--sumi-radius-full`. ### 4.6 Z-Index Scale | Token | Value | Usage | |---|---|---| | `--sumi-z-base` | 0 | Default | | `--sumi-z-raised` | 10 | Slightly elevated | | `--sumi-z-dropdown` | 100 | Dropdown menus | | `--sumi-z-sticky` | 200 | Sidebar, header, 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 | Emergency override | ### 4.7 Layout Tokens | Token | Value | Usage | |---|---|---| | `--sumi-max-width` | 1400px | Overall page max | | `--sumi-max-width-content` | 1200px | Content area | | `--sumi-max-width-narrow` | 800px | Narrow layouts (settings, forms) | | `--sumi-max-width-prose` | 65ch | Body text maximum line length | | `--sumi-sidebar-width` | 240px | Sidebar expanded | | `--sumi-sidebar-collapsed` | 64px | Sidebar collapsed | | `--sumi-header-height` | 56px | Header bar | | `--sumi-player-height` | 80px | Player bar | ### 4.8 Surface Hierarchy The surface system creates depth through background color, not shadows. This is the Spotify/Discord approach. ``` ┌─ Layer 0: Canvas ──────────────────────────────────────┐ │ --sumi-bg-void (dark) / washi (light) │ │ The page background. Nothing sits below this. │ │ │ │ ┌─ Layer 1: Surface ──────────────────────────────┐ │ │ │ --sumi-bg-raised / --sumi-surface-card │ │ │ │ Cards, panels, sidebar content area │ │ │ │ │ │ │ │ ┌─ Layer 2: Elevated ──────────────────────┐ │ │ │ │ │ --sumi-surface-elevated / glass panels │ │ │ │ │ │ Dropdowns, popovers, floating player │ │ │ │ │ │ │ │ │ │ │ │ ┌─ Layer 3: Overlay ────────────────┐ │ │ │ │ │ │ │ --sumi-bg-overlay │ │ │ │ │ │ │ │ Modals, dialogs, command palette │ │ │ │ │ │ │ └───────────────────────────────────┘ │ │ │ │ │ └──────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` **Rules:** 1. Cards do NOT have shadows in dark mode — they rely on background color difference. 2. Cards in light mode get `shadow-sm` for subtle lift. 3. Floating elements (player, dropdowns) get `shadow-lg` in light mode, `shadow-md` in dark mode. 4. Modals always have `shadow-xl` + backdrop overlay (`rgba(0,0,0,0.60)` + `backdrop-filter: blur(4px)`). 5. The sidebar is Layer 1 (raised) — it uses `--sumi-bg-raised`. --- ## 5. Motion & Texture ### 5.1 Animation Principles Motion in SUMI follows the movement of ink on paper: **fluid arrival, calm rest, gentle exit**. Never mechanical. Never bouncy unless celebrating (achievement unlocked). **Rules:** 1. Every animation must have a purpose: feedback, orientation, or celebration. 2. If you can't explain what the animation TELLS the user — remove it. 3. Hover effects are limited to: background change, opacity change, border change. NO scale transforms on cards. 4. Respect `prefers-reduced-motion`: disable decorative motion, keep functional feedback (opacity changes OK, position changes not). ### 5.2 Duration Scale | Token | Value | Usage | |---|---|---| | `--sumi-duration-instant` | 75ms | Button press feedback, keyboard response | | `--sumi-duration-fast` | 150ms | Hover in/out, focus ring appear, tooltip show | | `--sumi-duration-normal` | 200ms | Panel open/close, sidebar toggle, dropdown appear | | `--sumi-duration-slow` | 300ms | Modal entrance, sidebar transition | | `--sumi-duration-slower` | 500ms | Achievement animation only | ### 5.3 Easing Curves | Token | Value | Usage | |---|---|---| | `--sumi-ease-default` | `cubic-bezier(0.25, 0.1, 0.25, 1)` | Standard for everything | | `--sumi-ease-out` | `cubic-bezier(0.33, 1, 0.68, 1)` | Decelerate — entries, elements appearing | | `--sumi-ease-in` | `cubic-bezier(0.32, 0, 0.67, 0)` | Accelerate — exits, elements disappearing | | `--sumi-ease-in-out` | `cubic-bezier(0.65, 0, 0.35, 1)` | Symmetric — toggles, smooth both ways | | `--sumi-ease-bounce` | `cubic-bezier(0.34, 1.56, 0.64, 1)` | Playful — achievements ONLY, never elsewhere | | `--sumi-ease-spring` | `cubic-bezier(0.175, 0.885, 0.32, 1.1)` | Natural spring — toast notifications | ### 5.4 Transition Presets (CSS Variables) Composable transition presets for consistency: ```css --sumi-transition-colors: color var(--sumi-duration-fast) var(--sumi-ease-default), background-color var(--sumi-duration-fast) var(--sumi-ease-default), border-color var(--sumi-duration-fast) var(--sumi-ease-default); --sumi-transition-opacity: opacity var(--sumi-duration-fast) var(--sumi-ease-default); --sumi-transition-transform: transform var(--sumi-duration-normal) var(--sumi-ease-out); --sumi-transition-shadow: box-shadow var(--sumi-duration-fast) var(--sumi-ease-default); --sumi-transition-all: all var(--sumi-duration-normal) var(--sumi-ease-default); ``` ### 5.5 Hover States — The Complete List What hovering DOES in SUMI: | Element | Hover Effect | Transition | |---|---|---| | **Button (primary)** | Lighten background 10% | `background 150ms ease-out` | | **Button (ghost)** | Show `sumi-800` background | `background 150ms ease-out` | | **Card** | Show `white/5%` overlay OR lighten surface | `background 150ms ease-out` | | **Link** | Underline + slightly dim | `color 150ms ease-out` | | **Nav item** | Background tint + text brighten | `background 150ms ease-out, color 150ms ease-out` | | **Table row** | Lighten background | `background 100ms ease-out` | | **Icon button** | Background tint circle | `background 150ms ease-out` | What hovering does NOT do: - NO `scale()` transforms on any element - NO shadow changes on hover (shadows are static by elevation) - NO border-color changes (except on inputs going to focus) - NO glow effects on hover (glows are for status, not interaction) ### 5.6 Keyframe Animations ```css /* Essential animations — only these are allowed */ @keyframes sumi-fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes sumi-fade-out { from { opacity: 1; } to { opacity: 0; } } @keyframes sumi-slide-up { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } @keyframes sumi-slide-down { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: translateY(0); } } @keyframes sumi-scale-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } @keyframes sumi-scale-out { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.95); } } /* Achievement pop — the ONE playful animation (gaming touch) */ @keyframes sumi-pop { 0% { opacity: 0; transform: scale(0.8); } 60% { opacity: 1; transform: scale(1.05); } 100% { transform: scale(1); } } /* Subtle pulse for live indicators */ @keyframes sumi-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } /* Ink brush stroke reveal — for page transitions (signature SUMI touch) */ @keyframes sumi-brush-reveal { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } } /* Skeleton shimmer (loading) */ @keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } /* EQ bars — for "now playing" indicator */ @keyframes eq-bar { 0%, 100% { transform: scaleY(0.3); } 50% { transform: scaleY(1); } } ``` ### 5.7 Texture — The Sumi Layer The visual signature that makes SUMI unique. These textures are SUBTLE — they create atmosphere, not noise. #### 5.7.1 Paper Grain (Global) A barely perceptible noise texture on the body background. Gives the feeling of looking at washi paper on a screen. ```css body::after { content: ''; position: fixed; inset: 0; background: url("data:image/svg+xml,...noise-svg..."); opacity: 0.012; /* Almost invisible — you feel it, don't see it */ pointer-events: none; z-index: 9999; mix-blend-mode: overlay; } ``` Opacity: 1.2% in dark mode, 2% in light mode. If users set `prefers-reduced-motion`, disable it entirely. #### 5.7.2 Ink Wash Gradients (Hero/Feature Sections) For hero sections, featured content, or onboarding screens — a soft, asymmetric gradient that feels like diluted ink spreading on wet paper. ```css .sumi-wash-texture { position: relative; } .sumi-wash-texture::after { content: ''; position: absolute; inset: 0; background: radial-gradient(ellipse at 20% 50%, var(--sumi-accent-subtle) 0%, transparent 60%), radial-gradient(ellipse at 80% 20%, rgba(201,168,76,0.04) 0%, transparent 50%); pointer-events: none; } ``` Key characteristics: - Asymmetric (never centered or symmetrical) - Very low opacity (4-8%) - Uses primary and warm colors - Organic ellipse shapes, not circles #### 5.7.3 Brush Stroke Accents (Special Moments) For empty states, achievement cards, artist profile headers — SVG brush strokes as decorative elements. These are NOT used in general UI. Usage contexts: - Empty state illustrations: A single brush stroke as background - Achievement card borders: Ink splash frame - Artist profile hero: Calligraphic flourish behind artist name - 404 page: Sumi-e landscape sketch **Rules:** 1. Maximum 1 brush stroke element per screen 2. Always `opacity: 0.1` to `0.3` — they're atmosphere, not content 3. Never compete with text for attention 4. Color: `sumi-400` or `primary-400` only --- ## 6. Component Specifications Every component below uses `--sumi-*` CSS custom properties. The CSS class definitions below are the definitive implementations. ### 6.1 Card ```css .sumi-card { background: var(--sumi-surface-card); border: 1px solid var(--sumi-border-faint); border-radius: var(--sumi-radius-lg); padding: var(--sumi-space-4); transition: var(--sumi-transition-shadow), var(--sumi-transition-colors); } .sumi-card:hover { border-color: var(--sumi-border-default); box-shadow: var(--sumi-shadow-sm); } .sumi-card--interactive { cursor: pointer; } .sumi-card--interactive:hover { background: var(--sumi-bg-hover); box-shadow: var(--sumi-shadow-md); } .sumi-card--elevated { background: var(--sumi-surface-elevated); box-shadow: var(--sumi-shadow-md); } ``` **Card variants** (prose specs): | Variant | Details | |---|---| | **Media Card** (Track, Album, Playlist) | Cover `aspect-square`, `rounded-lg`. Title `text-sm font-medium`, truncated. Subtitle `text-xs text-secondary`, truncated. Play overlay on hover. | | **Stat Card** | Icon container 40px `rounded-lg`, value `sumi-h2`, label `sumi-label`, trend indicator mono ±%. | | **Profile Card** | Avatar `rounded-full`, name `sumi-h4`, role badge pill. | ### 6.2 Buttons ```css .sumi-btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--sumi-space-2); font-family: var(--sumi-font-body); font-size: var(--sumi-text-sm); font-weight: var(--sumi-weight-medium); line-height: 1; padding: var(--sumi-space-2) var(--sumi-space-4); border-radius: var(--sumi-radius-md); border: 1px solid transparent; cursor: pointer; transition: var(--sumi-transition-colors), var(--sumi-transition-shadow); user-select: none; white-space: nowrap; } .sumi-btn:focus-visible { box-shadow: var(--sumi-shadow-glow); } .sumi-btn:disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; } /* Primary — THE action */ .sumi-btn--primary { background: var(--sumi-accent); color: var(--sumi-text-inverse); border-color: var(--sumi-accent); } .sumi-btn--primary:hover { background: var(--sumi-accent-hover); border-color: var(--sumi-accent-hover); } .sumi-btn--primary:active { background: var(--sumi-accent-active); } /* Secondary — bordered, subtle */ .sumi-btn--secondary { background: transparent; color: var(--sumi-text-primary); border-color: var(--sumi-border-strong); } .sumi-btn--secondary:hover { background: var(--sumi-bg-hover); border-color: var(--sumi-accent); color: var(--sumi-accent); } /* Ghost — no border, minimal */ .sumi-btn--ghost { background: transparent; color: var(--sumi-text-secondary); border-color: transparent; } .sumi-btn--ghost:hover { background: var(--sumi-bg-hover); color: var(--sumi-text-primary); } /* Danger */ .sumi-btn--danger { background: var(--sumi-vermillion); color: white; border-color: var(--sumi-vermillion); } .sumi-btn--danger:hover { background: var(--sumi-vermillion-hover); } /* Sizes */ .sumi-btn--xs { padding: var(--sumi-space-1) var(--sumi-space-2); font-size: var(--sumi-text-xs); } .sumi-btn--sm { padding: var(--sumi-space-1-5) var(--sumi-space-3); font-size: var(--sumi-text-sm); } .sumi-btn--lg { padding: var(--sumi-space-3) var(--sumi-space-6); font-size: var(--sumi-text-md); } .sumi-btn--icon { padding: var(--sumi-space-2); width: 36px; height: 36px; } .sumi-btn--icon-sm { padding: var(--sumi-space-1-5); width: 28px; height: 28px; } ``` ### 6.3 Input ```css .sumi-input { display: block; width: 100%; font-family: var(--sumi-font-body); font-size: var(--sumi-text-base); color: var(--sumi-text-primary); background: var(--sumi-surface-inset); border: 1px solid var(--sumi-border-default); border-radius: var(--sumi-radius-md); padding: var(--sumi-space-2) var(--sumi-space-3); transition: var(--sumi-transition-colors), var(--sumi-transition-shadow); } .sumi-input::placeholder { color: var(--sumi-text-tertiary); } .sumi-input:hover { border-color: var(--sumi-border-strong); } .sumi-input:focus { outline: none; border-color: var(--sumi-accent); box-shadow: var(--sumi-shadow-glow); } ``` Additional form elements (prose specs): - **Checkbox/Radio**: 18px, 2px border, checked = `--sumi-accent` fill + white check. - **Toggle**: See `.sumi-toggle` below. ### 6.4 Badge / Tag ```css .sumi-badge { display: inline-flex; align-items: center; gap: var(--sumi-space-1); font-family: var(--sumi-font-body); font-size: var(--sumi-text-xs); font-weight: var(--sumi-weight-medium); padding: var(--sumi-space-0-5) var(--sumi-space-2); border-radius: var(--sumi-radius-full); line-height: var(--sumi-leading-normal); } .sumi-badge--default { background: var(--sumi-bg-hover); color: var(--sumi-text-secondary); } .sumi-badge--accent { background: var(--sumi-accent-subtle); color: var(--sumi-accent); } .sumi-badge--success { background: var(--sumi-success-subtle); color: var(--sumi-success); } .sumi-badge--warning { background: var(--sumi-warning-subtle); color: var(--sumi-warning); } .sumi-badge--error { background: var(--sumi-error-subtle); color: var(--sumi-error); } .sumi-badge--live { background: rgba(224,90,90,0.15); color: var(--sumi-live); } ``` ### 6.5 Chip (Graffiti touch) ```css .sumi-chip { display: inline-flex; align-items: center; gap: var(--sumi-space-1); font-size: var(--sumi-text-xs); font-weight: var(--sumi-weight-semibold); padding: var(--sumi-space-1) var(--sumi-space-2-5); border-radius: var(--sumi-radius-sm); background: var(--sumi-bg-hover); color: var(--sumi-text-secondary); border: 1px solid var(--sumi-border-faint); transition: var(--sumi-transition-colors); cursor: pointer; } .sumi-chip:hover { background: var(--sumi-accent-subtle); color: var(--sumi-accent); border-color: var(--sumi-border-accent); } .sumi-chip--selected { background: var(--sumi-accent-subtle); color: var(--sumi-accent); border-color: var(--sumi-accent); } ``` ### 6.6 Avatar ```css .sumi-avatar { display: inline-flex; align-items: center; justify-content: center; border-radius: var(--sumi-radius-full); overflow: hidden; background: var(--sumi-bg-hover); color: var(--sumi-text-secondary); font-weight: var(--sumi-weight-medium); flex-shrink: 0; } .sumi-avatar--xs { width: 24px; height: 24px; font-size: 10px; } .sumi-avatar--sm { width: 32px; height: 32px; font-size: var(--sumi-text-xs); } .sumi-avatar--md { width: 40px; height: 40px; font-size: var(--sumi-text-sm); } .sumi-avatar--lg { width: 48px; height: 48px; font-size: var(--sumi-text-base); } .sumi-avatar--xl { width: 64px; height: 64px; font-size: var(--sumi-text-lg); } .sumi-avatar--2xl { width: 96px; height: 96px; font-size: var(--sumi-text-2xl); } .sumi-avatar img { width: 100%; height: 100%; object-fit: cover; } /* Online indicator (position: relative on parent required) */ .sumi-avatar__status { position: absolute; bottom: 0; right: 0; width: 10px; height: 10px; border-radius: var(--sumi-radius-full); border: 2px solid var(--sumi-bg-raised); } .sumi-avatar__status--online { background: var(--sumi-online); } .sumi-avatar__status--live { background: var(--sumi-live); animation: sumi-pulse 2s ease-in-out infinite; } ``` ### 6.7 Dropdown / Menu ```css .sumi-menu { background: var(--sumi-bg-overlay); border: 1px solid var(--sumi-border-default); border-radius: var(--sumi-radius-lg); box-shadow: var(--sumi-shadow-xl); padding: var(--sumi-space-1); z-index: var(--sumi-z-dropdown); min-width: 180px; animation: sumi-scale-in var(--sumi-duration-fast) var(--sumi-ease-out); } .sumi-menu__item { display: flex; align-items: center; gap: var(--sumi-space-2); padding: var(--sumi-space-2) var(--sumi-space-3); border-radius: var(--sumi-radius-sm); font-size: var(--sumi-text-sm); color: var(--sumi-text-secondary); cursor: pointer; transition: var(--sumi-transition-colors); } .sumi-menu__item:hover { background: var(--sumi-bg-hover); color: var(--sumi-text-primary); } .sumi-menu__item--active { background: var(--sumi-accent-subtle); color: var(--sumi-accent); } .sumi-menu__item--danger { color: var(--sumi-vermillion); } .sumi-menu__item--danger:hover { background: var(--sumi-vermillion-subtle); } .sumi-menu__separator { height: 1px; background: var(--sumi-border-faint); margin: var(--sumi-space-1) 0; } ``` ### 6.8 Modal ```css .sumi-modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.60); backdrop-filter: blur(4px); z-index: var(--sumi-z-modal); animation: sumi-fade-in var(--sumi-duration-fast) var(--sumi-ease-out); } .sumi-modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: var(--sumi-bg-overlay); border: 1px solid var(--sumi-border-default); border-radius: var(--sumi-radius-xl); box-shadow: var(--sumi-shadow-2xl); z-index: calc(var(--sumi-z-modal) + 1); max-width: 560px; width: 90vw; max-height: 85vh; overflow-y: auto; animation: sumi-scale-in var(--sumi-duration-normal) var(--sumi-ease-out); } .sumi-modal__header { padding: var(--sumi-space-5) var(--sumi-space-6) var(--sumi-space-3); } .sumi-modal__body { padding: var(--sumi-space-3) var(--sumi-space-6); } .sumi-modal__footer { padding: var(--sumi-space-3) var(--sumi-space-6) var(--sumi-space-5); display: flex; justify-content: flex-end; gap: var(--sumi-space-2); } ``` ### 6.9 Toast ```css .sumi-toast { display: flex; align-items: flex-start; gap: var(--sumi-space-3); background: var(--sumi-surface-elevated); border: 1px solid var(--sumi-border-default); border-radius: var(--sumi-radius-lg); padding: var(--sumi-space-3) var(--sumi-space-4); box-shadow: var(--sumi-shadow-xl); min-width: 300px; max-width: 420px; animation: sumi-slide-up var(--sumi-duration-slow) var(--sumi-ease-spring); } ``` ### 6.10 Tooltip ```css .sumi-tooltip { background: var(--sumi-bg-overlay); color: var(--sumi-text-primary); font-size: var(--sumi-text-xs); padding: var(--sumi-space-1-5) var(--sumi-space-2-5); border-radius: var(--sumi-radius-md); box-shadow: var(--sumi-shadow-lg); border: 1px solid var(--sumi-border-default); max-width: 240px; z-index: var(--sumi-z-tooltip); } ``` ### 6.11 Tabs ```css .sumi-tabs { display: flex; gap: var(--sumi-space-1); border-bottom: 1px solid var(--sumi-border-faint); } .sumi-tab { padding: var(--sumi-space-2) var(--sumi-space-4); font-size: var(--sumi-text-sm); font-weight: var(--sumi-weight-medium); color: var(--sumi-text-tertiary); cursor: pointer; border-bottom: 2px solid transparent; transition: var(--sumi-transition-colors); } .sumi-tab:hover { color: var(--sumi-text-primary); } .sumi-tab--active { color: var(--sumi-text-primary); border-bottom-color: var(--sumi-accent); } ``` ### 6.12 Toggle ```css .sumi-toggle { position: relative; width: 40px; height: 22px; background: var(--sumi-bg-active); border-radius: var(--sumi-radius-full); cursor: pointer; transition: var(--sumi-transition-colors); } .sumi-toggle--active { background: var(--sumi-accent); } .sumi-toggle__knob { position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: var(--sumi-radius-full); background: white; box-shadow: var(--sumi-shadow-xs); transition: transform var(--sumi-duration-fast) var(--sumi-ease-out); } .sumi-toggle--active .sumi-toggle__knob { transform: translateX(18px); } ``` ### 6.13 Divider ```css .sumi-divider { height: 1px; background: var(--sumi-border-faint); border: none; margin: var(--sumi-space-4) 0; } ``` ### 6.14 Sidebar ```css .sumi-sidebar { position: fixed; top: 0; left: 0; bottom: 0; width: var(--sumi-sidebar-width); background: var(--sumi-bg-raised); border-right: 1px solid var(--sumi-border-faint); z-index: var(--sumi-z-sticky); display: flex; flex-direction: column; transition: width var(--sumi-duration-slow) var(--sumi-ease-out); overflow: hidden; } .sumi-sidebar--collapsed { width: var(--sumi-sidebar-collapsed); } .sumi-sidebar__nav-item { display: flex; align-items: center; gap: var(--sumi-space-3); padding: var(--sumi-space-2) var(--sumi-space-3); border-radius: var(--sumi-radius-md); color: var(--sumi-text-secondary); font-size: var(--sumi-text-sm); font-weight: var(--sumi-weight-medium); cursor: pointer; transition: var(--sumi-transition-colors); text-decoration: none; } .sumi-sidebar__nav-item:hover { background: var(--sumi-bg-hover); color: var(--sumi-text-primary); } .sumi-sidebar__nav-item--active { background: var(--sumi-accent-subtle); color: var(--sumi-accent); } /* Active indicator — 3px left accent bar */ .sumi-sidebar__nav-item--active::before { content: ''; position: absolute; left: 0; top: 25%; bottom: 25%; width: 3px; background: var(--sumi-accent); border-radius: 0 var(--sumi-radius-full) var(--sumi-radius-full) 0; } .sumi-sidebar__section-label { font-size: var(--sumi-text-xs); font-weight: var(--sumi-weight-medium); letter-spacing: var(--sumi-tracking-wider); text-transform: uppercase; color: var(--sumi-text-tertiary); padding: var(--sumi-space-4) var(--sumi-space-3) var(--sumi-space-1); } ``` ### 6.15 Header ```css .sumi-header { position: fixed; top: 0; right: 0; height: var(--sumi-header-height); background: var(--sumi-glass-bg); backdrop-filter: blur(var(--sumi-glass-blur)); -webkit-backdrop-filter: blur(var(--sumi-glass-blur)); border-bottom: 1px solid var(--sumi-border-faint); z-index: var(--sumi-z-sticky); display: flex; align-items: center; padding: 0 var(--sumi-space-6); gap: var(--sumi-space-4); } ``` ### 6.16 Player Bar ```css .sumi-player { position: fixed; bottom: 0; left: 0; right: 0; height: var(--sumi-player-height); background: var(--sumi-glass-bg); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border-top: 1px solid var(--sumi-border-faint); z-index: var(--sumi-z-sticky); display: flex; align-items: center; padding: 0 var(--sumi-space-6); } ``` **Player variants** (prose specs — not in Web version CSS): | Component | Details | |---|---| | **Mini Player** | 3 columns: track info (left, 48px cover `rounded-md`), controls (center), volume/queue (right). Progress bar: 4px → 6px on hover, `--sumi-accent` fill. | | **Full Player** | Background: gradient from dominant album color at 15% opacity. Cover: 280px max, `rounded-xl`, `shadow-xl`. Time: `font-mono`. | | **Queue Drawer** | Slides up, max-height 60vh. Current track: `--sumi-accent-subtle` bg + left border. Drag handle: pill at top center. | ### 6.17 Data Display ```css /* Table */ .sumi-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--sumi-text-sm); } .sumi-table th { text-align: left; padding: var(--sumi-space-2) var(--sumi-space-3); font-size: var(--sumi-text-xs); font-weight: var(--sumi-weight-medium); letter-spacing: var(--sumi-tracking-wide); text-transform: uppercase; color: var(--sumi-text-tertiary); border-bottom: 1px solid var(--sumi-border-default); } .sumi-table td { padding: var(--sumi-space-3); border-bottom: 1px solid var(--sumi-border-faint); color: var(--sumi-text-secondary); } .sumi-table tr:hover td { background: var(--sumi-bg-hover); } .sumi-table .sumi-col-number { font-family: var(--sumi-font-mono); font-size: var(--sumi-text-xs); letter-spacing: var(--sumi-tracking-wide); } /* Track List Item */ .sumi-track { display: flex; align-items: center; gap: var(--sumi-space-3); padding: var(--sumi-space-2) var(--sumi-space-3); border-radius: var(--sumi-radius-md); transition: var(--sumi-transition-colors); cursor: pointer; } .sumi-track:hover { background: var(--sumi-bg-hover); } .sumi-track--playing { background: var(--sumi-accent-subtle); } .sumi-track__number { font-family: var(--sumi-font-mono); font-size: var(--sumi-text-xs); color: var(--sumi-text-tertiary); width: 24px; text-align: right; } .sumi-track__title { font-weight: var(--sumi-weight-medium); color: var(--sumi-text-primary); } .sumi-track__artist { font-size: var(--sumi-text-sm); color: var(--sumi-text-secondary); } .sumi-track__duration { font-family: var(--sumi-font-mono); font-size: var(--sumi-text-xs); color: var(--sumi-text-tertiary); margin-left: auto; } /* Stat Card */ .sumi-stat { display: flex; flex-direction: column; gap: var(--sumi-space-1); padding: var(--sumi-space-4); } .sumi-stat__label { font-size: var(--sumi-text-xs); font-weight: var(--sumi-weight-medium); letter-spacing: var(--sumi-tracking-wide); text-transform: uppercase; color: var(--sumi-text-tertiary); } .sumi-stat__value { font-family: var(--sumi-font-heading); font-size: var(--sumi-text-2xl); font-weight: var(--sumi-weight-bold); letter-spacing: var(--sumi-tracking-tight); color: var(--sumi-text-primary); } .sumi-stat__value--mono { font-family: var(--sumi-font-mono); } .sumi-stat__trend { font-family: var(--sumi-font-mono); font-size: var(--sumi-text-xs); } .sumi-stat__trend--up { color: var(--sumi-sage); } .sumi-stat__trend--down { color: var(--sumi-vermillion); } ``` ### 6.18 Specialty Components (Thematic Personality) ```css /* XP / Achievement Bar (Gaming touch 🎮) */ .sumi-xp-bar { display: flex; align-items: center; gap: var(--sumi-space-3); } .sumi-xp-bar__track { flex: 1; height: 6px; background: var(--sumi-bg-hover); border-radius: var(--sumi-radius-full); overflow: hidden; } .sumi-xp-bar__fill { height: 100%; background: var(--sumi-gold); border-radius: var(--sumi-radius-full); transition: width var(--sumi-duration-slower) var(--sumi-ease-out); } .sumi-xp-bar__label { font-family: var(--sumi-font-mono); font-size: var(--sumi-text-xs); font-weight: var(--sumi-weight-medium); color: var(--sumi-gold); } /* Achievement Toast (Gaming 🎮) */ .sumi-achievement { display: flex; align-items: center; gap: var(--sumi-space-3); background: var(--sumi-surface-elevated); border: 1px solid var(--sumi-gold-subtle); border-left: 3px solid var(--sumi-gold); border-radius: var(--sumi-radius-lg); padding: var(--sumi-space-3) var(--sumi-space-4); animation: sumi-pop var(--sumi-duration-slower) var(--sumi-ease-bounce); } .sumi-achievement__icon { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; background: var(--sumi-gold-subtle); border-radius: var(--sumi-radius-md); font-size: var(--sumi-text-lg); } /* Terminal Block (Cybersec/Linux 💻) */ .sumi-terminal { background: var(--sumi-bg-void); border: 1px solid var(--sumi-border-default); border-radius: var(--sumi-radius-lg); font-family: var(--sumi-font-mono); font-size: var(--sumi-text-sm); overflow: hidden; } .sumi-terminal__header { display: flex; align-items: center; gap: var(--sumi-space-2); padding: var(--sumi-space-2) var(--sumi-space-3); background: var(--sumi-bg-raised); border-bottom: 1px solid var(--sumi-border-faint); } .sumi-terminal__dot { width: 8px; height: 8px; border-radius: var(--sumi-radius-full); } .sumi-terminal__dot--red { background: var(--sumi-vermillion); } .sumi-terminal__dot--yellow { background: var(--sumi-gold); } .sumi-terminal__dot--green { background: var(--sumi-sage); } .sumi-terminal__body { padding: var(--sumi-space-4); color: var(--sumi-text-secondary); line-height: var(--sumi-leading-relaxed); } .sumi-terminal__prompt { color: var(--sumi-accent); } .sumi-terminal__output { color: var(--sumi-text-tertiary); } /* Live Indicator (📡 Stream) */ .sumi-live-dot { display: inline-flex; align-items: center; gap: var(--sumi-space-1-5); font-size: var(--sumi-text-xs); font-weight: var(--sumi-weight-semibold); text-transform: uppercase; letter-spacing: var(--sumi-tracking-wider); color: var(--sumi-live); } .sumi-live-dot::before { content: ''; width: 6px; height: 6px; border-radius: var(--sumi-radius-full); background: var(--sumi-live); animation: sumi-pulse 2s ease-in-out infinite; } /* Cover Art (🎵 Music) */ .sumi-cover { border-radius: var(--sumi-radius-md); overflow: hidden; background: var(--sumi-bg-hover); aspect-ratio: 1; position: relative; } .sumi-cover img { width: 100%; height: 100%; object-fit: cover; } .sumi-cover--sm { width: 40px; height: 40px; border-radius: var(--sumi-radius-sm); } .sumi-cover--md { width: 56px; height: 56px; } .sumi-cover--lg { width: 160px; height: 160px; border-radius: var(--sumi-radius-lg); } .sumi-cover--xl { width: 240px; height: 240px; border-radius: var(--sumi-radius-xl); } .sumi-cover--hero { width: 100%; max-width: 300px; box-shadow: var(--sumi-shadow-xl); } /* Progress Slider (🎧 Player) */ .sumi-slider { position: relative; width: 100%; height: 4px; background: var(--sumi-bg-hover); border-radius: var(--sumi-radius-full); cursor: pointer; } .sumi-slider:hover { height: 6px; } .sumi-slider__fill { height: 100%; background: var(--sumi-accent); border-radius: var(--sumi-radius-full); position: relative; } .sumi-slider__thumb { position: absolute; right: -6px; top: 50%; transform: translateY(-50%); width: 12px; height: 12px; border-radius: var(--sumi-radius-full); background: white; box-shadow: var(--sumi-shadow-sm); opacity: 0; transition: opacity var(--sumi-duration-fast); } .sumi-slider:hover .sumi-slider__thumb { opacity: 1; } ``` ### 6.19 Chat (Prose Spec) | Element | Spec | |---|---| | **Message Bubble** | Max-width 70%. Own: `--sumi-accent-subtle` bg, right-aligned. Others: `--sumi-bg-hover` bg, left-aligned. `rounded-xl` with squared corner on sender's side. | | **Timestamp** | `sumi-caption`, `text-tertiary`, below message. | | **Reactions** | Small pills, `--sumi-bg-active` bg, emoji + count. | | **Room List** | 48px items, 36px avatar, room name `sumi-body font-medium`, last message `sumi-caption text-secondary`, unread badge `--sumi-accent` pill with white text. | ### 6.20 Skeleton / Loading | Aspect | Spec | |---|---| | **Shape** | Matches the content it replaces (text line, avatar, card) | | **Background** | `--sumi-bg-hover` (dark) / `--sumi-bg-active` (light) | | **Animation** | `shimmer` sweep, 1.8s, ease-in-out, infinite | | **Shimmer highlight** | `rgba(255,255,255, 0.06)` (dark) / `rgba(255,255,255, 0.40)` (light) | | **Radius** | Matches the component being loaded | ### 6.21 Empty States Empty states use the sumi-e aesthetic most directly. They are the moments where the app's personality shines. - Container: centered, `max-w-sm`, `py-16` - Illustration: Simple brush stroke SVG, `--sumi-text-tertiary` color, 120px max - Title: `sumi-h4`, `text-primary` - Description: `sumi-body`, `text-secondary`, 2-3 lines max - CTA: `.sumi-btn--primary` below - Background: Optional `.sumi-wash-texture` --- ## 7. Anti-Patterns — INTERDIT | Ne JAMAIS faire | Faire a la place | |---|---| | Couleurs Tailwind par defaut (`slate`, `zinc`, `gray`) | Tokens `--sumi-*` exclusively | | Glow/neon decoratif | Glow UNIQUEMENT pour focus rings (`--sumi-shadow-glow`) | | Orbitron ou font gaming | Space Grotesk pour headings | | Clip-path manga/hex | `border-radius` standard (`--sumi-radius-*`) | | Plus de 4 couleurs d'accent | Indigo, Vermillon, Sauge, Or — c'est tout | | Gradient sur composants | Gradient uniquement hero/cover (`.sumi-wash-texture`) | | Box-shadow decoratif | Shadow = elevation fonctionnelle uniquement | | Animations > 300ms | Max 300ms sauf achievements (500ms) | | Valeurs CSS arbitraires (`w-[347px]`) | Tokens et echelle Tailwind/SUMI | | `!important` sauf utilitaires | Specificite CSS normale | | Neon flicker, matrix rain, terminal green text | Subtilite, discretion | --- ## 8. Component Checklist — Quality Gate Avant de merger un composant, verifier : - [ ] Utilise uniquement des tokens `--sumi-*` - [ ] Fonctionne en dark ET light theme - [ ] Responsive (teste a 320px, 768px, 1024px, 1280px) - [ ] Focus visible avec `--sumi-shadow-glow` - [ ] Pas plus de 2 fonts utilisees (body + heading, ou body + mono) - [ ] Pas d'animation > 300ms (sauf achievement) - [ ] Contrast ratio >= 4.5:1 pour le texte (WCAG AA) - [ ] Pas de valeur CSS arbitraire - [ ] States couverts : default, hover, active, focus, disabled - [ ] Donnees chiffrees en `font-mono` (`--sumi-font-mono`) --- ## 9. Theme Contexts & Accessibility ### 9.1 How Sub-Themes Surface Instead of applying ALL your interests equally across the UI (which creates visual chaos), each theme surfaces in a SPECIFIC context. The base SUMI aesthetic is always the foundation. #### Theme Map | Theme | Where It Appears | How It Manifests | Never Appears In | |---|---|---|---| | **Sumi-e / Lavis** | Everywhere (base) | Ink neutrals, paper textures, soft shadows, ink wash gradients, brush stroke decorative elements | — | | **Nature** | Empty states, onboarding, community features, settings backgrounds | Organic shapes in illustrations, leaf/branch motifs in empty state art, earthy warm accents, organic radius on feature cards | Navigation, data tables, admin | | **Graffiti / Tag** | Artist profiles, creative tools, release announcements, achievement badges | Bold uppercase type moments (display font at large size), manga clip-paths on special cards, splash/drip micro-texture on album art hover, high-contrast headlines | General cards, forms, settings | | **Gaming** | XP/levels, achievements, leaderboards, challenges, gamification UI | `--sumi-gold` accent, `.sumi-xp-bar`, `.sumi-achievement`, level numbers in bold | Chat, marketplace, analytics | | **Terminal / Linux** | Admin panel, developer API page, system status, file manager | `.sumi-terminal`, monospace font for data, `--terminal-green` for success status, `--sumi-bg-void` even in light mode | Player, social, onboarding | | **Music** | Player, waveforms, streaming page, track cards | Waveform visualizations, EQ bar animations, BPM/key in mono font — but these are FUNCTIONAL, not decorative. The player itself uses the base SUMI palette | Everywhere else looks the same whether it's a music app or not | #### Implementation Examples **Graffiti moment — Artist profile hero:** ```tsx
{description}
{description}