veza/veza-sumi-design-system.html
senke b103a09a25 chore: consolidate CI, E2E, backend and frontend updates
- CI: workflows updates (cd, ci), remove playwright.yml
- E2E: global-setup, auth/playlists/profile specs
- Remove playwright-report and test-results artifacts from tracking
- Backend: auth, handlers, services, workers, migrations
- Frontend: components, features, vite config
- Add e2e-results.json to gitignore
- Docs: REMEDIATION_PROGRESS, audit archive
- Rust: chat-server, stream-server updates
2026-02-17 16:43:21 +01:00

2680 lines
118 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="fr" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VEZA — SUMI Design System v1.0</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Noto+Serif+JP:wght@400;600&display=swap" rel="stylesheet">
<style>
/* ═══════════════════════════════════════════════════════════════════════
VEZA SUMI DESIGN SYSTEM v1.0
───────────────────────────────────────────────────────────────────────
Philosophy: Ink on paper. Every surface is a sheet, every accent
is a deliberate brush stroke. Space (ma 間) is sacred.
Themes absorbed:
- Fusain / Lavis japonais → Core visual language
- Graffiti / Tag → Gestural energy, spray textures, bold marks
- Nature / Botanical → Organic warmth, earthy tones, breathing space
- Cybersec / Linux → Monospace type, terminal patterns, subtle
- Jeux vidéo 2D → Pixel-precise interactions, achievement feel
- Musique indé → Authenticity, imperfection, handmade warmth
═══════════════════════════════════════════════════════════════════════ */
/* ─────────────────────────────────────────────────────────────────────
0. RESET
───────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; -webkit-font-smoothing: antialiased; scroll-behavior: smooth; }
/* ─────────────────────────────────────────────────────────────────────
1. DESIGN TOKENS — DARK THEME (DEFAULT)
─────────────────────────────────────────────────────────────────────
Naming convention:
--sumi-{category}-{variant}
Categories: bg, surface, border, text, accent, semantic, shadow
The palette is built on WARM neutrals (not cold slate/zinc).
Think: charcoal on rice paper, not LED screens.
───────────────────────────────────────────────────────────────────── */
:root, [data-theme="dark"] {
/* ── Color mode flag ── */
--sumi-mode: dark;
color-scheme: dark;
/* ── Background layers ──
Like ink wash (墨絵): darkest = most ink, lightest = diluted wash.
These are WARM darks — notice the slight warm undertone vs cold slate.
*/
--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) */
/* ── Surface ──
For components that sit ON backgrounds (inputs, wells, insets)
*/
--sumi-surface-inset: #101013; /* Sunken — search bars, input fields */
--sumi-surface-subtle: #1e1e24; /* Slightly raised — table rows alternate */
--sumi-surface-card: #1a1a1f; /* Standard card */
--sumi-surface-elevated: #242430; /* Floating — FAB, sticky headers */
/* ── Borders ──
Ink lines: from barely visible to structural
*/
--sumi-border-faint: rgba(255, 255, 255, 0.06); /* Subtle separation */
--sumi-border-default: rgba(255, 255, 255, 0.10); /* Standard borders */
--sumi-border-strong: rgba(255, 255, 255, 0.16); /* Emphasized borders */
--sumi-border-focus: rgba(139, 170, 220, 0.50); /* Focus rings */
--sumi-border-accent: rgba(139, 170, 220, 0.30); /* Accent-colored borders */
/* ── Text ──
Ink density: from full black (white in dark) to faintest wash
*/
--sumi-text-primary: #f0ede8; /* Warm white — main content */
--sumi-text-secondary: #a8a4a0; /* Diluted — descriptions, metadata */
--sumi-text-tertiary: #706c68; /* Faint wash — timestamps, captions */
--sumi-text-disabled: #4a4844; /* Ghost ink — disabled state */
--sumi-text-inverse: #121215; /* For use on light/accent backgrounds */
--sumi-text-link: #8baade; /* Links — soft blue */
/* ── Accent: INDIGO INK (藍墨) ──
Primary accent. Inspired by Japanese indigo ink (ai-zumi).
Feels like a pigment, not a neon light.
*/
--sumi-accent: #7c9dd6; /* Primary — buttons, active states */
--sumi-accent-hover: #93afe0; /* Hover — slightly lighter */
--sumi-accent-active: #6b8dc6; /* Pressed */
--sumi-accent-subtle: rgba(124, 157, 214, 0.12); /* Subtle bg tint */
--sumi-accent-muted: rgba(124, 157, 214, 0.20); /* Selected states */
--sumi-accent-emphasis: #5a7fba; /* Text on dark — higher contrast */
/* ── Vermillion Seal (朱印) ──
Secondary accent. The red seal stamp on Japanese calligraphy.
Used VERY sparingly — notifications, destructive actions, live indicators.
*/
--sumi-vermillion: #d4634a; /* The seal red */
--sumi-vermillion-hover: #de7a64;
--sumi-vermillion-subtle: rgba(212, 99, 74, 0.12);
/* ── Nature Ink (草墨) ──
Tertiary — success, online, nature accents.
Muted sage green, like ink mixed with plant pigment.
*/
--sumi-sage: #7a9e6c;
--sumi-sage-hover: #8eb280;
--sumi-sage-subtle: rgba(122, 158, 108, 0.12);
/* ── Warm Gold (金墨) ──
Quaternary — warnings, achievements, XP, premium.
Like gold leaf on lacquerware.
*/
--sumi-gold: #c9a84c;
--sumi-gold-hover: #d6b860;
--sumi-gold-subtle: rgba(201, 168, 76, 0.12);
/* ── Semantic Colors ── */
--sumi-success: var(--sumi-sage);
--sumi-success-subtle: var(--sumi-sage-subtle);
--sumi-warning: var(--sumi-gold);
--sumi-warning-subtle: var(--sumi-gold-subtle);
--sumi-error: var(--sumi-vermillion);
--sumi-error-subtle: var(--sumi-vermillion-subtle);
--sumi-info: var(--sumi-accent);
--sumi-info-subtle: var(--sumi-accent-subtle);
/* ── Live / Online / Streaming ── */
--sumi-live: #e05a5a;
--sumi-online: var(--sumi-sage);
/* ── Shadows ──
Ink pooling: soft, warm-tinted shadows (not harsh black)
*/
--sumi-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.30);
--sumi-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.20);
--sumi-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.30), 0 2px 4px rgba(0, 0, 0, 0.15);
--sumi-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.35), 0 4px 8px rgba(0, 0, 0, 0.20);
--sumi-shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.40), 0 8px 16px rgba(0, 0, 0, 0.20);
--sumi-shadow-2xl: 0 24px 64px rgba(0, 0, 0, 0.50);
/* Glow — used ONLY for focus states and primary CTA. Never decorative. */
--sumi-shadow-glow: 0 0 0 3px rgba(124, 157, 214, 0.25);
--sumi-shadow-glow-lg: 0 0 20px rgba(124, 157, 214, 0.15);
/* ── Backdrop / Glass ──
Frosted ink paper — subtle, not overdone
*/
--sumi-glass-bg: rgba(18, 18, 21, 0.80);
--sumi-glass-border: rgba(255, 255, 255, 0.08);
--sumi-glass-blur: 12px;
/* ── Scrollbar ── */
--sumi-scrollbar-track: transparent;
--sumi-scrollbar-thumb: rgba(255, 255, 255, 0.10);
--sumi-scrollbar-hover: rgba(255, 255, 255, 0.18);
}
/* ─────────────────────────────────────────────────────────────────────
2. DESIGN TOKENS — LIGHT THEME
─────────────────────────────────────────────────────────────────────
"Washi Paper" (和紙) — warm off-whites, like handmade Japanese paper.
NOT cold clinical white. Soft, inviting, high readability.
───────────────────────────────────────────────────────────────────── */
[data-theme="light"] {
--sumi-mode: light;
color-scheme: light;
/* ── Backgrounds — paper tones ── */
--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;
--sumi-bg-hover: #ede9e1;
--sumi-bg-active: #e4e0d8;
--sumi-bg-wash: #f8f6f1;
/* ── Surfaces ── */
--sumi-surface-inset: #ebe7df;
--sumi-surface-subtle: #f2eee6;
--sumi-surface-card: #ffffff;
--sumi-surface-elevated: #ffffff;
/* ── Borders ── */
--sumi-border-faint: rgba(0, 0, 0, 0.05);
--sumi-border-default: rgba(0, 0, 0, 0.10);
--sumi-border-strong: rgba(0, 0, 0, 0.18);
--sumi-border-focus: rgba(80, 110, 170, 0.45);
--sumi-border-accent: rgba(80, 110, 170, 0.25);
/* ── Text — ink tones ── */
--sumi-text-primary: #1a1816; /* Deep charcoal — warm, not pure black */
--sumi-text-secondary: #5c5854;
--sumi-text-tertiary: #8a8580;
--sumi-text-disabled: #b5b0aa;
--sumi-text-inverse: #f0ede8;
--sumi-text-link: #4a6fa5;
/* ── Accents — deeper pigments for light bg ── */
--sumi-accent: #4a6fa5;
--sumi-accent-hover: #3d5f92;
--sumi-accent-active: #355480;
--sumi-accent-subtle: rgba(74, 111, 165, 0.08);
--sumi-accent-muted: rgba(74, 111, 165, 0.14);
--sumi-accent-emphasis: #3d5f92;
--sumi-vermillion: #b84a35;
--sumi-vermillion-hover: #a43f2d;
--sumi-vermillion-subtle: rgba(184, 74, 53, 0.08);
--sumi-sage: #5a7e4e;
--sumi-sage-hover: #4d6e42;
--sumi-sage-subtle: rgba(90, 126, 78, 0.08);
--sumi-gold: #9a7d2e;
--sumi-gold-hover: #8a6e25;
--sumi-gold-subtle: rgba(154, 125, 46, 0.08);
--sumi-live: #c44040;
--sumi-online: var(--sumi-sage);
/* ── Shadows — softer, warm-tinted ── */
--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);
--sumi-shadow-glow: 0 0 0 3px rgba(74, 111, 165, 0.20);
--sumi-shadow-glow-lg: 0 0 20px rgba(74, 111, 165, 0.10);
/* ── Glass ── */
--sumi-glass-bg: rgba(255, 255, 255, 0.85);
--sumi-glass-border: rgba(0, 0, 0, 0.06);
--sumi-glass-blur: 12px;
/* ── Scrollbar ── */
--sumi-scrollbar-track: transparent;
--sumi-scrollbar-thumb: rgba(0, 0, 0, 0.12);
--sumi-scrollbar-hover: rgba(0, 0, 0, 0.22);
}
/* ─────────────────────────────────────────────────────────────────────
3. TYPOGRAPHY
─────────────────────────────────────────────────────────────────────
3 fonts. That's it. No Orbitron. No display fonts that scream.
- Inter: Body text. Universal readability. Google/Apple-tier.
- Space Grotesk: Headings. Geometric but warm. Has personality
without being aggressive. Nods to tech/cyber subtly.
- JetBrains Mono: Code, terminal UI, stats. The cybersec/linux accent.
Optional (loaded but used sparingly):
- Noto Serif JP: For decorative Japanese text, quotes, easter eggs.
───────────────────────────────────────────────────────────────────── */
:root {
--sumi-font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--sumi-font-heading: 'Space Grotesk', 'Inter', sans-serif;
--sumi-font-mono: 'JetBrains Mono', 'SF Mono', 'Consolas', monospace;
--sumi-font-serif: 'Noto Serif JP', Georgia, serif;
/* ── Type Scale (Major Third — 1.250) ── */
--sumi-text-xs: 0.75rem; /* 12px — captions, badges */
--sumi-text-sm: 0.8125rem; /* 13px — metadata, labels */
--sumi-text-base: 0.875rem; /* 14px — body default */
--sumi-text-md: 1rem; /* 16px — body large, nav items */
--sumi-text-lg: 1.125rem; /* 18px — card titles */
--sumi-text-xl: 1.25rem; /* 20px — section headings */
--sumi-text-2xl: 1.5rem; /* 24px — page headings */
--sumi-text-3xl: 1.875rem; /* 30px — hero headings */
--sumi-text-4xl: 2.25rem; /* 36px — display */
--sumi-text-5xl: 3rem; /* 48px — hero display */
/* ── Line Heights ── */
--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;
/* ── Tracking ── */
--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 ── */
--sumi-weight-light: 300;
--sumi-weight-regular: 400;
--sumi-weight-medium: 500;
--sumi-weight-semibold: 600;
--sumi-weight-bold: 700;
}
/* ─────────────────────────────────────────────────────────────────────
4. SPACING, RADIUS, LAYOUT
───────────────────────────────────────────────────────────────────── */
:root {
/* ── Spacing Scale (4px base) ── */
--sumi-space-0: 0;
--sumi-space-px: 1px;
--sumi-space-0-5: 0.125rem; /* 2px */
--sumi-space-1: 0.25rem; /* 4px */
--sumi-space-1-5: 0.375rem; /* 6px */
--sumi-space-2: 0.5rem; /* 8px */
--sumi-space-2-5: 0.625rem; /* 10px */
--sumi-space-3: 0.75rem; /* 12px */
--sumi-space-4: 1rem; /* 16px */
--sumi-space-5: 1.25rem; /* 20px */
--sumi-space-6: 1.5rem; /* 24px */
--sumi-space-8: 2rem; /* 32px */
--sumi-space-10: 2.5rem; /* 40px */
--sumi-space-12: 3rem; /* 48px */
--sumi-space-16: 4rem; /* 64px */
--sumi-space-20: 5rem; /* 80px */
--sumi-space-24: 6rem; /* 96px */
/* ── Border Radius ──
Slightly larger than typical — softer, more organic feel.
Avoids harsh sharp corners AND overdone full-round pills.
*/
--sumi-radius-xs: 4px;
--sumi-radius-sm: 6px;
--sumi-radius-md: 8px;
--sumi-radius-lg: 12px;
--sumi-radius-xl: 16px;
--sumi-radius-2xl: 20px;
--sumi-radius-full: 9999px;
/* ── Layout ── */
--sumi-max-width: 1400px;
--sumi-max-width-content: 1200px;
--sumi-max-width-narrow: 800px;
--sumi-max-width-prose: 65ch;
/* Shell (keep existing values — compatibility) */
--sumi-sidebar-width: 240px;
--sumi-sidebar-collapsed: 64px;
--sumi-header-height: 56px;
--sumi-player-height: 80px;
/* ── Z-Index Scale ── */
--sumi-z-base: 0;
--sumi-z-raised: 10;
--sumi-z-dropdown: 100;
--sumi-z-sticky: 200;
--sumi-z-overlay: 300;
--sumi-z-modal: 400;
--sumi-z-popover: 500;
--sumi-z-toast: 600;
--sumi-z-tooltip: 700;
--sumi-z-max: 999;
}
/* ─────────────────────────────────────────────────────────────────────
5. TRANSITIONS & ANIMATIONS
───────────────────────────────────────────────────────────────────── */
:root {
/* ── Durations ── */
--sumi-duration-instant: 75ms;
--sumi-duration-fast: 150ms;
--sumi-duration-normal: 200ms;
--sumi-duration-slow: 300ms;
--sumi-duration-slower: 500ms;
/* ── Easings ── */
--sumi-ease-default: cubic-bezier(0.25, 0.1, 0.25, 1); /* Standard */
--sumi-ease-out: cubic-bezier(0.33, 1, 0.68, 1); /* Decelerate — enter */
--sumi-ease-in: cubic-bezier(0.32, 0, 0.67, 0); /* Accelerate — exit */
--sumi-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1); /* Symmetric */
--sumi-ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); /* Playful — achievements */
--sumi-ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.1); /* Natural spring */
/* ── Presets ── */
--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);
}
/* Keyframes — only the essential ones */
@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 */
@keyframes sumi-brush-reveal {
from { clip-path: inset(0 100% 0 0); }
to { clip-path: inset(0 0 0 0); }
}
/* ─────────────────────────────────────────────────────────────────────
6. BASE STYLES
───────────────────────────────────────────────────────────────────── */
body {
font-family: var(--sumi-font-body);
font-size: var(--sumi-text-base);
line-height: var(--sumi-leading-normal);
color: var(--sumi-text-primary);
background-color: var(--sumi-bg-base);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11'; /* Inter stylistic alternates */
}
/* Scrollbar */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--sumi-scrollbar-track); }
::-webkit-scrollbar-thumb {
background: var(--sumi-scrollbar-thumb);
border-radius: var(--sumi-radius-full);
}
::-webkit-scrollbar-thumb:hover { background: var(--sumi-scrollbar-hover); }
/* Selection */
::selection {
background: var(--sumi-accent-muted);
color: var(--sumi-text-primary);
}
/* Focus visible — consistent focus ring everywhere */
:focus-visible {
outline: 2px solid var(--sumi-accent);
outline-offset: 2px;
border-radius: var(--sumi-radius-sm);
}
/* ─────────────────────────────────────────────────────────────────────
7. TYPOGRAPHY CLASSES
───────────────────────────────────────────────────────────────────── */
.sumi-display {
font-family: var(--sumi-font-heading);
font-size: var(--sumi-text-4xl);
font-weight: var(--sumi-weight-bold);
line-height: var(--sumi-leading-tight);
letter-spacing: var(--sumi-tracking-tighter);
color: var(--sumi-text-primary);
}
.sumi-h1 {
font-family: var(--sumi-font-heading);
font-size: var(--sumi-text-3xl);
font-weight: var(--sumi-weight-semibold);
line-height: var(--sumi-leading-tight);
letter-spacing: var(--sumi-tracking-tight);
}
.sumi-h2 {
font-family: var(--sumi-font-heading);
font-size: var(--sumi-text-2xl);
font-weight: var(--sumi-weight-semibold);
line-height: var(--sumi-leading-snug);
letter-spacing: var(--sumi-tracking-tight);
}
.sumi-h3 {
font-family: var(--sumi-font-heading);
font-size: var(--sumi-text-xl);
font-weight: var(--sumi-weight-medium);
line-height: var(--sumi-leading-snug);
}
.sumi-h4 {
font-family: var(--sumi-font-heading);
font-size: var(--sumi-text-lg);
font-weight: var(--sumi-weight-medium);
line-height: var(--sumi-leading-snug);
}
.sumi-body-lg {
font-size: var(--sumi-text-md);
line-height: var(--sumi-leading-relaxed);
}
.sumi-body {
font-size: var(--sumi-text-base);
line-height: var(--sumi-leading-normal);
}
.sumi-body-sm {
font-size: var(--sumi-text-sm);
line-height: var(--sumi-leading-normal);
}
.sumi-caption {
font-size: var(--sumi-text-xs);
line-height: var(--sumi-leading-normal);
color: var(--sumi-text-tertiary);
}
.sumi-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);
}
.sumi-mono {
font-family: var(--sumi-font-mono);
font-size: var(--sumi-text-sm);
font-feature-settings: 'liga' 0;
}
/* For decorative Japanese text — poetry quotes, easter eggs */
.sumi-serif-jp {
font-family: var(--sumi-font-serif);
font-style: normal;
}
/* ─────────────────────────────────────────────────────────────────────
8. COMPONENT PRIMITIVES
─────────────────────────────────────────────────────────────────────
These are the building blocks. Every component in the app
should be composed from these primitives.
───────────────────────────────────────────────────────────────────── */
/* ── Card ── */
.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);
}
/* ── Glass Panel (use sparingly — player, floating headers) ── */
.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);
}
/* ── Button ── */
.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. Filled accent. */
.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;
}
/* ── Input ── */
.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);
}
/* ── Badge / Tag ── */
.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);
}
/* ── Avatar ── */
.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 */
.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; }
/* ── Divider ── */
.sumi-divider {
height: 1px;
background: var(--sumi-border-faint);
border: none;
margin: var(--sumi-space-4) 0;
}
/* ── Tooltip ── */
.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);
}
/* ── Dropdown / Menu ── */
.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;
}
/* ── Modal ── */
.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);
}
/* ── Toast / Notification ── */
.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);
}
/* ─────────────────────────────────────────────────────────────────────
9. LAYOUT COMPONENTS
───────────────────────────────────────────────────────────────────── */
/* ── Sidebar ── */
.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__logo {
display: flex;
align-items: center;
gap: var(--sumi-space-3);
padding: var(--sumi-space-4);
height: var(--sumi-header-height);
flex-shrink: 0;
}
.sumi-sidebar__nav {
flex: 1;
overflow-y: auto;
padding: var(--sumi-space-2);
}
.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 — subtle left border, not a heavy glow */
.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);
}
/* ── Header ── */
.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);
}
/* ── Player Bar ── */
.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);
}
/* ── Main Content ── */
.sumi-main {
padding-top: calc(var(--sumi-header-height) + var(--sumi-space-6));
padding-bottom: calc(var(--sumi-player-height) + var(--sumi-space-6));
min-height: 100vh;
}
/* ─────────────────────────────────────────────────────────────────────
10. DATA DISPLAY COMPONENTS
───────────────────────────────────────────────────────────────────── */
/* ── 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);
}
/* Number column — mono for stats (cybersec touch) */
.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 (dashboard, analytics) ── */
.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); }
/* ─────────────────────────────────────────────────────────────────────
11. SPECIALTY COMPONENTS
─────────────────────────────────────────────────────────────────────
Where the thematic personality lives — but restrained and functional.
───────────────────────────────────────────────────────────────────── */
/* ── 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 touch) ── */
.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 ── */
.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 ── */
.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);
}
/* ── Tag / Genre Chip (Graffiti touch — slightly rougher feel) ── */
.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);
}
/* ── 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; }
/* ── Toggle / Switch ── */
.sumi-toggle {
position: relative;
width: 40px;
height: 22px;
background: var(--sumi-bg-active);
border-radius: var(--sumi-radius-full);
cursor: pointer;
transition: background var(--sumi-duration-fast);
}
.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);
}
/* ── Tabs ── */
.sumi-tabs {
display: flex;
gap: var(--sumi-space-1);
border-bottom: 1px solid var(--sumi-border-faint);
padding-bottom: 0;
}
.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;
margin-bottom: -1px;
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);
}
/* ─────────────────────────────────────────────────────────────────────
12. UTILITY CLASSES
───────────────────────────────────────────────────────────────────── */
/* Text colors */
.text-primary { color: var(--sumi-text-primary) !important; }
.text-secondary { color: var(--sumi-text-secondary) !important; }
.text-tertiary { color: var(--sumi-text-tertiary) !important; }
.text-accent { color: var(--sumi-accent) !important; }
.text-vermillion{ color: var(--sumi-vermillion) !important; }
.text-sage { color: var(--sumi-sage) !important; }
.text-gold { color: var(--sumi-gold) !important; }
/* Background */
.bg-void { background: var(--sumi-bg-void) !important; }
.bg-base { background: var(--sumi-bg-base) !important; }
.bg-raised { background: var(--sumi-bg-raised) !important; }
.bg-overlay { background: var(--sumi-bg-overlay) !important; }
/* Borders */
.border-faint { border-color: var(--sumi-border-faint) !important; }
.border-default { border-color: var(--sumi-border-default) !important; }
.border-strong { border-color: var(--sumi-border-strong) !important; }
.border-accent { border-color: var(--sumi-border-accent) !important; }
/* Ink wash texture — very subtle bg pattern for hero sections */
.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;
}
/* Truncate */
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Line clamp */
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.line-clamp-3 {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* ═══════════════════════════════════════════════════════════════════════
DESIGN SYSTEM PREVIEW — DOCUMENTATION STYLES
═══════════════════════════════════════════════════════════════════════ */
.ds-page {
max-width: 1200px;
margin: 0 auto;
padding: 48px 32px 120px;
}
.ds-section {
margin-bottom: 80px;
}
.ds-section__title {
font-family: var(--sumi-font-heading);
font-size: var(--sumi-text-3xl);
font-weight: var(--sumi-weight-bold);
letter-spacing: var(--sumi-tracking-tight);
margin-bottom: 8px;
color: var(--sumi-text-primary);
}
.ds-section__subtitle {
font-size: var(--sumi-text-md);
color: var(--sumi-text-tertiary);
margin-bottom: 40px;
max-width: 65ch;
line-height: var(--sumi-leading-relaxed);
}
.ds-subsection {
margin-bottom: 48px;
}
.ds-subsection__title {
font-family: var(--sumi-font-heading);
font-size: var(--sumi-text-xl);
font-weight: var(--sumi-weight-semibold);
margin-bottom: 20px;
color: var(--sumi-text-primary);
}
.ds-grid {
display: grid;
gap: 16px;
}
.ds-grid--2 { grid-template-columns: repeat(2, 1fr); }
.ds-grid--3 { grid-template-columns: repeat(3, 1fr); }
.ds-grid--4 { grid-template-columns: repeat(4, 1fr); }
.ds-grid--5 { grid-template-columns: repeat(5, 1fr); }
.ds-grid--auto { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
@media (max-width: 768px) {
.ds-grid--2, .ds-grid--3, .ds-grid--4, .ds-grid--5 { grid-template-columns: 1fr; }
}
.ds-swatch {
border-radius: var(--sumi-radius-lg);
overflow: hidden;
border: 1px solid var(--sumi-border-faint);
}
.ds-swatch__color {
height: 80px;
}
.ds-swatch__info {
padding: 10px 12px;
background: var(--sumi-bg-raised);
}
.ds-swatch__name {
font-size: var(--sumi-text-sm);
font-weight: var(--sumi-weight-medium);
color: var(--sumi-text-primary);
}
.ds-swatch__value {
font-family: var(--sumi-font-mono);
font-size: var(--sumi-text-xs);
color: var(--sumi-text-tertiary);
margin-top: 2px;
}
.ds-preview-row {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.ds-code {
font-family: var(--sumi-font-mono);
font-size: var(--sumi-text-xs);
color: var(--sumi-text-tertiary);
background: var(--sumi-surface-inset);
padding: 2px 6px;
border-radius: var(--sumi-radius-xs);
}
.ds-theme-toggle {
position: fixed;
top: 16px;
right: 16px;
z-index: 999;
}
.ds-showcase-box {
background: var(--sumi-bg-raised);
border: 1px solid var(--sumi-border-faint);
border-radius: var(--sumi-radius-lg);
padding: 24px;
}
.ds-hr {
border: none;
height: 1px;
background: var(--sumi-border-faint);
margin: 64px 0;
}
.ds-annotation {
font-size: var(--sumi-text-xs);
color: var(--sumi-text-tertiary);
font-style: italic;
margin-top: 8px;
}
/* Mini app mockup container */
.ds-app-mock {
border: 1px solid var(--sumi-border-default);
border-radius: var(--sumi-radius-xl);
overflow: hidden;
background: var(--sumi-bg-base);
box-shadow: var(--sumi-shadow-xl);
}
</style>
</head>
<body>
<!-- Theme Toggle -->
<div class="ds-theme-toggle">
<button class="sumi-btn sumi-btn--secondary" onclick="toggleTheme()" id="themeToggle">
☀ Light
</button>
</div>
<div class="ds-page">
<!-- ════════════════════════════════════════════════════════════════
HEADER
════════════════════════════════════════════════════════════════ -->
<header style="margin-bottom: 80px; padding-top: 20px;">
<div style="display: flex; align-items: center; gap: 16px; margin-bottom: 24px;">
<!-- Sumi brush stroke logo mark -->
<svg width="48" height="48" viewBox="0 0 48 48" fill="none">
<rect width="48" height="48" rx="12" fill="var(--sumi-bg-raised)"/>
<path d="M12 36C14 28 18 16 24 12C30 16 34 28 36 36" stroke="var(--sumi-accent)" stroke-width="2.5" stroke-linecap="round" fill="none" opacity="0.6"/>
<path d="M14 34C16 26 20 18 24 14C28 18 32 26 34 34" stroke="var(--sumi-text-primary)" stroke-width="2" stroke-linecap="round" fill="none"/>
<circle cx="24" cy="14" r="2" fill="var(--sumi-accent)"/>
</svg>
<div>
<h1 style="font-family: var(--sumi-font-heading); font-size: var(--sumi-text-4xl); font-weight: 700; letter-spacing: -0.03em; color: var(--sumi-text-primary);">
VEZA <span style="color: var(--sumi-text-tertiary); font-weight: 400;">SUMI</span>
</h1>
<p style="font-family: var(--sumi-font-mono); font-size: var(--sumi-text-xs); color: var(--sumi-text-tertiary); letter-spacing: 0.05em;">DESIGN SYSTEM v1.0 — SOURCE OF TRUTH</p>
</div>
</div>
<p style="font-size: var(--sumi-text-md); color: var(--sumi-text-secondary); max-width: 70ch; line-height: 1.7;">
Encre sur papier. Chaque surface est une feuille, chaque accent est un coup de pinceau délibéré.
L'espace (<span class="sumi-serif-jp" style="color: var(--sumi-accent);"></span> — ma) est sacré.
Ni néon, ni matrice, ni glow excessif. De l'authentique, du lisible, de l'universel.
</p>
</header>
<hr class="ds-hr" style="margin-top: 0;">
<!-- ════════════════════════════════════════════════════════════════
1. PHILOSOPHY & PRINCIPLES
════════════════════════════════════════════════════════════════ -->
<section class="ds-section">
<h2 class="ds-section__title">Principes fondamentaux</h2>
<p class="ds-section__subtitle">
Les 5 règles qui gouvernent chaque décision de design dans Veza.
</p>
<div class="ds-grid ds-grid--3" style="gap: 20px;">
<div class="sumi-card" style="padding: 24px;">
<div style="font-size: 24px; margin-bottom: 12px;"></div>
<h3 class="sumi-h4" style="margin-bottom: 8px;">Encre, pas néon</h3>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary);">
Les couleurs sont des pigments, pas des lumières. Chaque touche de couleur est délibérée comme un coup de pinceau. Quand tout brille, rien ne se distingue.
</p>
</div>
<div class="sumi-card" style="padding: 24px;">
<div style="font-size: 24px; margin-bottom: 12px;"></div>
<h3 class="sumi-h4" style="margin-bottom: 8px;">Espace sacré (Ma)</h3>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary);">
Le vide n'est pas vide — il respire. Spacing généreux, densité d'information maîtrisée. Ce qui n'est pas là est aussi important que ce qui y est.
</p>
</div>
<div class="sumi-card" style="padding: 24px;">
<div style="font-size: 24px; margin-bottom: 12px;"></div>
<h3 class="sumi-h4" style="margin-bottom: 8px;">Universalité</h3>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary);">
Lisible pour tous — 8 ans comme 80 ans, auditeur casual comme label pro. Pas de dark pattern, pas de complexité gratuite. Discord-tier accessibilité.
</p>
</div>
<div class="sumi-card" style="padding: 24px;">
<div style="font-size: 24px; margin-bottom: 12px;"></div>
<h3 class="sumi-h4" style="margin-bottom: 8px;">Wabi-sabi numérique</h3>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary);">
Authenticité > perfection stérile. Les textures sont subtiles, les formes légèrement organiques, la personnalité est dans les détails — pas dans les effets.
</p>
</div>
<div class="sumi-card" style="padding: 24px;">
<div style="font-size: 24px; margin-bottom: 12px;"></div>
<h3 class="sumi-h4" style="margin-bottom: 8px;">Révélation progressive</h3>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary);">
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.
</p>
</div>
<div class="sumi-card" style="padding: 24px;">
<div style="font-size: 24px; margin-bottom: 12px;">🎮</div>
<h3 class="sumi-h4" style="margin-bottom: 8px;">Touches thématiques</h3>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary);">
Le gaming (XP, achievements), le cyber (monospace, terminal), le graffiti (chips, tags) sont des épices — pas le plat principal. 5% de l'UI, 100% de la personnalité.
</p>
</div>
</div>
</section>
<hr class="ds-hr">
<!-- ════════════════════════════════════════════════════════════════
2. COLOR PALETTE
════════════════════════════════════════════════════════════════ -->
<section class="ds-section">
<h2 class="ds-section__title">Palette</h2>
<p class="ds-section__subtitle">
Palette réduite et intentionnelle. 4 couleurs d'accent maximum. Les neutres font 90% du travail — les accents sont des coups de pinceau.
</p>
<!-- Backgrounds -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Fonds — Couches d'encre</h3>
<div class="ds-grid ds-grid--5" style="gap: 12px;">
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-bg-void);"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Void</div>
<div class="ds-swatch__value">--sumi-bg-void</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-bg-base);"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Base</div>
<div class="ds-swatch__value">--sumi-bg-base</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-bg-raised);"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Raised</div>
<div class="ds-swatch__value">--sumi-bg-raised</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-bg-overlay);"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Overlay</div>
<div class="ds-swatch__value">--sumi-bg-overlay</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-bg-hover);"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Hover</div>
<div class="ds-swatch__value">--sumi-bg-hover</div>
</div>
</div>
</div>
</div>
<!-- Text -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Texte — Densités d'encre</h3>
<div class="ds-grid ds-grid--4" style="gap: 12px;">
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-bg-raised); display: flex; align-items: center; justify-content: center;">
<span style="font-size: 24px; font-weight: 600; color: var(--sumi-text-primary);">Aa</span>
</div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Primary</div>
<div class="ds-swatch__value">--sumi-text-primary</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-bg-raised); display: flex; align-items: center; justify-content: center;">
<span style="font-size: 24px; font-weight: 600; color: var(--sumi-text-secondary);">Aa</span>
</div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Secondary</div>
<div class="ds-swatch__value">--sumi-text-secondary</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-bg-raised); display: flex; align-items: center; justify-content: center;">
<span style="font-size: 24px; font-weight: 600; color: var(--sumi-text-tertiary);">Aa</span>
</div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Tertiary</div>
<div class="ds-swatch__value">--sumi-text-tertiary</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-bg-raised); display: flex; align-items: center; justify-content: center;">
<span style="font-size: 24px; font-weight: 600; color: var(--sumi-text-disabled);">Aa</span>
</div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Disabled</div>
<div class="ds-swatch__value">--sumi-text-disabled</div>
</div>
</div>
</div>
</div>
<!-- Accents -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Accents — Les 4 pigments</h3>
<p style="color: var(--sumi-text-tertiary); font-size: var(--sumi-text-sm); margin-bottom: 20px; max-width: 60ch;">
Indigo pour les actions, Vermillon pour l'urgence, Sauge pour le succès, Or pour les récompenses. C'est tout.
</p>
<div class="ds-grid ds-grid--4" style="gap: 12px;">
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-accent);"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Indigo Ink 藍墨</div>
<div class="ds-swatch__value">--sumi-accent</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-vermillion);"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Vermillion Seal 朱印</div>
<div class="ds-swatch__value">--sumi-vermillion</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-sage);"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Sage 草墨</div>
<div class="ds-swatch__value">--sumi-sage</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-gold);"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Gold Leaf 金墨</div>
<div class="ds-swatch__value">--sumi-gold</div>
</div>
</div>
</div>
<!-- Subtle variants -->
<div class="ds-grid ds-grid--4" style="gap: 12px; margin-top: 12px;">
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-accent-subtle); height: 40px;"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Accent Subtle</div>
<div class="ds-swatch__value">--sumi-accent-subtle</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-vermillion-subtle); height: 40px;"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Vermillion Subtle</div>
<div class="ds-swatch__value">--sumi-vermillion-subtle</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-sage-subtle); height: 40px;"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Sage Subtle</div>
<div class="ds-swatch__value">--sumi-sage-subtle</div>
</div>
</div>
<div class="ds-swatch">
<div class="ds-swatch__color" style="background: var(--sumi-gold-subtle); height: 40px;"></div>
<div class="ds-swatch__info">
<div class="ds-swatch__name">Gold Subtle</div>
<div class="ds-swatch__value">--sumi-gold-subtle</div>
</div>
</div>
</div>
</div>
<!-- Semantic -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Sémantique</h3>
<div class="ds-grid ds-grid--4" style="gap: 12px;">
<div style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--sumi-success-subtle); border-radius: var(--sumi-radius-md); border-left: 3px solid var(--sumi-success);">
<span style="color: var(--sumi-success); font-weight: 600;"></span>
<span style="color: var(--sumi-success); font-size: var(--sumi-text-sm);">Success / Online</span>
</div>
<div style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--sumi-warning-subtle); border-radius: var(--sumi-radius-md); border-left: 3px solid var(--sumi-warning);">
<span style="color: var(--sumi-warning); font-weight: 600;"></span>
<span style="color: var(--sumi-warning); font-size: var(--sumi-text-sm);">Warning</span>
</div>
<div style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--sumi-error-subtle); border-radius: var(--sumi-radius-md); border-left: 3px solid var(--sumi-error);">
<span style="color: var(--sumi-error); font-weight: 600;"></span>
<span style="color: var(--sumi-error); font-size: var(--sumi-text-sm);">Error / Danger</span>
</div>
<div style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--sumi-info-subtle); border-radius: var(--sumi-radius-md); border-left: 3px solid var(--sumi-info);">
<span style="color: var(--sumi-info); font-weight: 600;"></span>
<span style="color: var(--sumi-info); font-size: var(--sumi-text-sm);">Info</span>
</div>
</div>
</div>
</section>
<hr class="ds-hr">
<!-- ════════════════════════════════════════════════════════════════
3. TYPOGRAPHY
════════════════════════════════════════════════════════════════ -->
<section class="ds-section">
<h2 class="ds-section__title">Typographie</h2>
<p class="ds-section__subtitle">
3 polices, chacune avec un rôle clair. Inter pour le corps (universel), Space Grotesk pour les titres (personnalité sans agressivité), JetBrains Mono pour les stats et le terminal (touche cyber).
</p>
<div class="ds-subsection">
<h3 class="ds-subsection__title">Hiérarchie</h3>
<div style="display: flex; flex-direction: column; gap: 24px;">
<div style="display: flex; align-items: baseline; gap: 24px; border-bottom: 1px solid var(--sumi-border-faint); padding-bottom: 16px;">
<span class="ds-code" style="width: 100px; flex-shrink: 0;">Display</span>
<span class="sumi-display">Veza Music</span>
</div>
<div style="display: flex; align-items: baseline; gap: 24px; border-bottom: 1px solid var(--sumi-border-faint); padding-bottom: 16px;">
<span class="ds-code" style="width: 100px; flex-shrink: 0;">H1</span>
<span class="sumi-h1">Dashboard</span>
</div>
<div style="display: flex; align-items: baseline; gap: 24px; border-bottom: 1px solid var(--sumi-border-faint); padding-bottom: 16px;">
<span class="ds-code" style="width: 100px; flex-shrink: 0;">H2</span>
<span class="sumi-h2">Playlists récentes</span>
</div>
<div style="display: flex; align-items: baseline; gap: 24px; border-bottom: 1px solid var(--sumi-border-faint); padding-bottom: 16px;">
<span class="ds-code" style="width: 100px; flex-shrink: 0;">H3</span>
<span class="sumi-h3">Artistes suivis</span>
</div>
<div style="display: flex; align-items: baseline; gap: 24px; border-bottom: 1px solid var(--sumi-border-faint); padding-bottom: 16px;">
<span class="ds-code" style="width: 100px; flex-shrink: 0;">H4</span>
<span class="sumi-h4">Nouveautés</span>
</div>
<div style="display: flex; align-items: baseline; gap: 24px; border-bottom: 1px solid var(--sumi-border-faint); padding-bottom: 16px;">
<span class="ds-code" style="width: 100px; flex-shrink: 0;">Body Lg</span>
<span class="sumi-body-lg">Découvre les dernières sorties des artistes que tu suis et explore de nouveaux horizons musicaux.</span>
</div>
<div style="display: flex; align-items: baseline; gap: 24px; border-bottom: 1px solid var(--sumi-border-faint); padding-bottom: 16px;">
<span class="ds-code" style="width: 100px; flex-shrink: 0;">Body</span>
<span class="sumi-body">Un morceau publié hier · 3 min 42 · Hip-Hop Indépendant</span>
</div>
<div style="display: flex; align-items: baseline; gap: 24px; border-bottom: 1px solid var(--sumi-border-faint); padding-bottom: 16px;">
<span class="ds-code" style="width: 100px; flex-shrink: 0;">Caption</span>
<span class="sumi-caption">Ajouté le 15 mars 2025 · 1 240 écoutes</span>
</div>
<div style="display: flex; align-items: baseline; gap: 24px; border-bottom: 1px solid var(--sumi-border-faint); padding-bottom: 16px;">
<span class="ds-code" style="width: 100px; flex-shrink: 0;">Label</span>
<span class="sumi-label">Genre • Sortie</span>
</div>
<div style="display: flex; align-items: baseline; gap: 24px;">
<span class="ds-code" style="width: 100px; flex-shrink: 0;">Mono</span>
<span class="sumi-mono">12,847 streams · 03:42 · 320kbps</span>
</div>
</div>
</div>
</section>
<hr class="ds-hr">
<!-- ════════════════════════════════════════════════════════════════
4. COMPONENTS
════════════════════════════════════════════════════════════════ -->
<section class="ds-section">
<h2 class="ds-section__title">Composants</h2>
<p class="ds-section__subtitle">
Chaque composant est une primitive réutilisable. Composez, ne customisez pas.
</p>
<!-- Buttons -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Buttons</h3>
<div style="display: flex; flex-direction: column; gap: 20px;">
<div class="ds-preview-row">
<button class="sumi-btn sumi-btn--primary">Publier</button>
<button class="sumi-btn sumi-btn--secondary">Annuler</button>
<button class="sumi-btn sumi-btn--ghost">Plus d'options</button>
<button class="sumi-btn sumi-btn--danger">Supprimer</button>
</div>
<div class="ds-preview-row">
<button class="sumi-btn sumi-btn--primary sumi-btn--xs">XS</button>
<button class="sumi-btn sumi-btn--primary sumi-btn--sm">Small</button>
<button class="sumi-btn sumi-btn--primary">Default</button>
<button class="sumi-btn sumi-btn--primary sumi-btn--lg">Large</button>
</div>
<div class="ds-preview-row">
<button class="sumi-btn sumi-btn--primary" disabled>Disabled</button>
<button class="sumi-btn sumi-btn--secondary sumi-btn--icon" title="Menu"></button>
<button class="sumi-btn sumi-btn--ghost sumi-btn--icon-sm" title="Fermer"></button>
</div>
</div>
</div>
<!-- Inputs -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Inputs</h3>
<div style="max-width: 400px; display: flex; flex-direction: column; gap: 16px;">
<div>
<label class="sumi-label" style="display: block; margin-bottom: 6px;">Nom de l'artiste</label>
<input class="sumi-input" type="text" placeholder="Rechercher un artiste...">
</div>
<div>
<label class="sumi-label" style="display: block; margin-bottom: 6px;">Description</label>
<textarea class="sumi-input" rows="3" placeholder="Décris ton projet..." style="resize: vertical;"></textarea>
</div>
</div>
</div>
<!-- Badges -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Badges</h3>
<div class="ds-preview-row">
<span class="sumi-badge sumi-badge--default">Draft</span>
<span class="sumi-badge sumi-badge--accent">Published</span>
<span class="sumi-badge sumi-badge--success">Online</span>
<span class="sumi-badge sumi-badge--warning">Pending</span>
<span class="sumi-badge sumi-badge--error">Rejected</span>
<span class="sumi-badge sumi-badge--live">● LIVE</span>
</div>
</div>
<!-- Chips / Tags -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Chips — Genre tags (touche graffiti)</h3>
<div class="ds-preview-row">
<span class="sumi-chip">Hip-Hop</span>
<span class="sumi-chip sumi-chip--selected">Lo-Fi</span>
<span class="sumi-chip">Jazz</span>
<span class="sumi-chip">Electro</span>
<span class="sumi-chip">Ambient</span>
<span class="sumi-chip">Punk</span>
</div>
</div>
<!-- Avatars -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Avatars</h3>
<div class="ds-preview-row">
<div class="sumi-avatar sumi-avatar--xs">M</div>
<div class="sumi-avatar sumi-avatar--sm">MK</div>
<div class="sumi-avatar sumi-avatar--md" style="background: var(--sumi-accent-subtle); color: var(--sumi-accent);">MK</div>
<div class="sumi-avatar sumi-avatar--lg" style="background: var(--sumi-sage-subtle); color: var(--sumi-sage);">VZ</div>
<div class="sumi-avatar sumi-avatar--xl" style="background: var(--sumi-gold-subtle); color: var(--sumi-gold);">DJ</div>
</div>
</div>
<!-- Cards -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Cards</h3>
<div class="ds-grid ds-grid--3" style="gap: 16px;">
<div class="sumi-card">
<div style="width: 100%; aspect-ratio: 1; background: var(--sumi-bg-hover); border-radius: var(--sumi-radius-md); margin-bottom: 12px; display: flex; align-items: center; justify-content: center;">
<span style="font-size: 32px; opacity: 0.3;"></span>
</div>
<h4 class="sumi-h4" style="margin-bottom: 4px;">Nuits Urbaines</h4>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary);">Kōji · 2024</p>
<p class="sumi-caption" style="margin-top: 8px;">12 titres · 42 min</p>
</div>
<div class="sumi-card sumi-card--interactive">
<div style="width: 100%; aspect-ratio: 1; background: linear-gradient(135deg, var(--sumi-bg-hover), var(--sumi-bg-active)); border-radius: var(--sumi-radius-md); margin-bottom: 12px; display: flex; align-items: center; justify-content: center;">
<span style="font-size: 32px; opacity: 0.3;">🎤</span>
</div>
<h4 class="sumi-h4" style="margin-bottom: 4px;">Stream Session #12</h4>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary);">En direct</p>
<div style="margin-top: 8px;">
<span class="sumi-live-dot">Live</span>
</div>
</div>
<div class="sumi-card sumi-card--elevated">
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">
<div class="sumi-avatar sumi-avatar--lg" style="background: var(--sumi-accent-subtle); color: var(--sumi-accent);">AT</div>
<div>
<h4 class="sumi-h4">Atelier Records</h4>
<p class="sumi-caption">Label · 8 artistes</p>
</div>
</div>
<div style="display: flex; gap: 16px;">
<div>
<span class="sumi-mono" style="color: var(--sumi-text-primary); font-weight: 600;">24.8K</span>
<span class="sumi-caption" style="display: block;">Streams</span>
</div>
<div>
<span class="sumi-mono" style="color: var(--sumi-text-primary); font-weight: 600;">1.2K</span>
<span class="sumi-caption" style="display: block;">Followers</span>
</div>
</div>
</div>
</div>
</div>
<!-- Tabs -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Tabs</h3>
<div class="sumi-tabs" style="margin-bottom: 16px;">
<div class="sumi-tab sumi-tab--active">Morceaux</div>
<div class="sumi-tab">Albums</div>
<div class="sumi-tab">Playlists</div>
<div class="sumi-tab">À propos</div>
</div>
</div>
<!-- Toggle -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Toggle</h3>
<div class="ds-preview-row">
<div class="sumi-toggle" onclick="this.classList.toggle('sumi-toggle--active')">
<div class="sumi-toggle__knob"></div>
</div>
<div class="sumi-toggle sumi-toggle--active" onclick="this.classList.toggle('sumi-toggle--active')">
<div class="sumi-toggle__knob"></div>
</div>
<span class="sumi-body-sm" style="color: var(--sumi-text-secondary);">Mode public</span>
</div>
</div>
<!-- Menu / Dropdown -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Menu / Dropdown</h3>
<div style="max-width: 220px;">
<div class="sumi-menu" style="position: relative;">
<div class="sumi-menu__item">
<span></span> Lire maintenant
</div>
<div class="sumi-menu__item sumi-menu__item--active">
<span></span> Favoris
</div>
<div class="sumi-menu__item">
<span>+</span> Ajouter à une playlist
</div>
<div class="sumi-menu__item">
<span></span> Partager
</div>
<div class="sumi-menu__separator"></div>
<div class="sumi-menu__item sumi-menu__item--danger">
<span>🗑</span> Supprimer
</div>
</div>
</div>
</div>
<!-- Tooltip -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">Tooltip</h3>
<div style="display: inline-block; position: relative;">
<button class="sumi-btn sumi-btn--ghost">Hover me</button>
<div class="sumi-tooltip" style="position: absolute; top: -44px; left: 50%; transform: translateX(-50%); white-space: nowrap;">
Raccourci: Ctrl + P
</div>
</div>
</div>
</section>
<hr class="ds-hr">
<!-- ════════════════════════════════════════════════════════════════
5. SPECIALTY — THEMED COMPONENTS
════════════════════════════════════════════════════════════════ -->
<section class="ds-section">
<h2 class="ds-section__title">Spécialités thématiques</h2>
<p class="ds-section__subtitle">
Les composants qui portent la personnalité de Veza. Gaming, terminal, live — mais toujours fonctionnels d'abord.
</p>
<!-- XP Bar -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">🎮 XP / Progression</h3>
<div style="max-width: 400px;">
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
<span class="sumi-body-sm" style="font-weight: 500;">Niveau 7 — Explorateur</span>
<span class="sumi-mono" style="font-size: var(--sumi-text-xs); color: var(--sumi-gold);">2,840 / 4,000 XP</span>
</div>
<div class="sumi-xp-bar">
<div class="sumi-xp-bar__track">
<div class="sumi-xp-bar__fill" style="width: 71%;"></div>
</div>
</div>
</div>
</div>
<!-- Achievement -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">🏆 Achievement Toast</h3>
<div style="max-width: 360px;">
<div class="sumi-achievement">
<div class="sumi-achievement__icon">🎵</div>
<div>
<div style="font-weight: 600; font-size: var(--sumi-text-sm);">Premier Stream!</div>
<div class="sumi-caption">Tu as lancé ta première session de streaming en direct.</div>
</div>
</div>
</div>
</div>
<!-- Terminal -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">💻 Terminal Block</h3>
<div style="max-width: 500px;">
<div class="sumi-terminal">
<div class="sumi-terminal__header">
<div class="sumi-terminal__dot sumi-terminal__dot--red"></div>
<div class="sumi-terminal__dot sumi-terminal__dot--yellow"></div>
<div class="sumi-terminal__dot sumi-terminal__dot--green"></div>
<span style="font-size: var(--sumi-text-xs); color: var(--sumi-text-tertiary); margin-left: 8px;">veza-analytics</span>
</div>
<div class="sumi-terminal__body">
<div><span class="sumi-terminal__prompt">$</span> veza stats --artist kōji --period 30d</div>
<div class="sumi-terminal__output" style="margin-top: 8px;">
streams: 12,847 (+23.4%)<br>
listeners: 3,201 (+18.7%)<br>
saves: 847 (+31.2%)<br>
top_track: "Nuits Urbaines" (4,231 plays)
</div>
</div>
</div>
</div>
</div>
<!-- Track List -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">🎵 Track List</h3>
<div style="max-width: 600px; background: var(--sumi-surface-card); border-radius: var(--sumi-radius-lg); border: 1px solid var(--sumi-border-faint); padding: var(--sumi-space-2);">
<div class="sumi-track sumi-track--playing">
<span class="sumi-track__number" style="color: var(--sumi-accent);"></span>
<div class="sumi-cover sumi-cover--sm" style="background: linear-gradient(135deg, var(--sumi-bg-hover), var(--sumi-bg-active));"></div>
<div style="flex: 1; min-width: 0;">
<div class="sumi-track__title truncate">Nuits Urbaines</div>
<div class="sumi-track__artist truncate">Kōji</div>
</div>
<span class="sumi-track__duration">3:42</span>
</div>
<div class="sumi-track">
<span class="sumi-track__number">2</span>
<div class="sumi-cover sumi-cover--sm" style="background: var(--sumi-bg-hover);"></div>
<div style="flex: 1; min-width: 0;">
<div class="sumi-track__title truncate">Brume Matinale</div>
<div class="sumi-track__artist truncate">Kōji</div>
</div>
<span class="sumi-track__duration">4:15</span>
</div>
<div class="sumi-track">
<span class="sumi-track__number">3</span>
<div class="sumi-cover sumi-cover--sm" style="background: var(--sumi-bg-hover);"></div>
<div style="flex: 1; min-width: 0;">
<div class="sumi-track__title truncate">Fragments de Verre</div>
<div class="sumi-track__artist truncate">Kōji ft. Yūrei</div>
</div>
<span class="sumi-track__duration">5:01</span>
</div>
</div>
</div>
<!-- Stat Cards -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">📊 Stats Dashboard</h3>
<div class="ds-grid ds-grid--4" style="gap: 12px;">
<div class="sumi-card" style="padding: 0;">
<div class="sumi-stat">
<span class="sumi-stat__label">Streams</span>
<span class="sumi-stat__value sumi-stat__value--mono">12,847</span>
<span class="sumi-stat__trend sumi-stat__trend--up">↑ 23.4%</span>
</div>
</div>
<div class="sumi-card" style="padding: 0;">
<div class="sumi-stat">
<span class="sumi-stat__label">Auditeurs</span>
<span class="sumi-stat__value sumi-stat__value--mono">3,201</span>
<span class="sumi-stat__trend sumi-stat__trend--up">↑ 18.7%</span>
</div>
</div>
<div class="sumi-card" style="padding: 0;">
<div class="sumi-stat">
<span class="sumi-stat__label">Revenus</span>
<span class="sumi-stat__value sumi-stat__value--mono">€284</span>
<span class="sumi-stat__trend sumi-stat__trend--down">↓ 5.2%</span>
</div>
</div>
<div class="sumi-card" style="padding: 0;">
<div class="sumi-stat">
<span class="sumi-stat__label">Followers</span>
<span class="sumi-stat__value sumi-stat__value--mono">1,204</span>
<span class="sumi-stat__trend sumi-stat__trend--up">↑ 42.1%</span>
</div>
</div>
</div>
</div>
<!-- Player Slider -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">🎧 Player Controls</h3>
<div style="max-width: 500px; padding: 24px; background: var(--sumi-surface-card); border-radius: var(--sumi-radius-lg); border: 1px solid var(--sumi-border-faint);">
<div style="display: flex; align-items: center; gap: 16px; margin-bottom: 16px;">
<div class="sumi-cover sumi-cover--sm" style="background: linear-gradient(135deg, var(--sumi-bg-hover), var(--sumi-bg-active));"></div>
<div style="flex: 1;">
<div style="font-weight: 500; font-size: var(--sumi-text-sm);">Nuits Urbaines</div>
<div class="sumi-caption">Kōji</div>
</div>
<span style="color: var(--sumi-vermillion); cursor: pointer;"></span>
</div>
<div class="sumi-slider" style="margin-bottom: 8px;">
<div class="sumi-slider__fill" style="width: 35%;">
<div class="sumi-slider__thumb"></div>
</div>
</div>
<div style="display: flex; justify-content: space-between;">
<span class="sumi-mono" style="font-size: var(--sumi-text-xs); color: var(--sumi-text-tertiary);">1:18</span>
<span class="sumi-mono" style="font-size: var(--sumi-text-xs); color: var(--sumi-text-tertiary);">3:42</span>
</div>
<div style="display: flex; align-items: center; justify-content: center; gap: 24px; margin-top: 16px;">
<button class="sumi-btn sumi-btn--ghost sumi-btn--icon-sm"></button>
<button class="sumi-btn sumi-btn--ghost sumi-btn--icon-sm"></button>
<button class="sumi-btn sumi-btn--primary sumi-btn--icon" style="border-radius: var(--sumi-radius-full); width: 42px; height: 42px; font-size: 18px;"></button>
<button class="sumi-btn sumi-btn--ghost sumi-btn--icon-sm"></button>
<button class="sumi-btn sumi-btn--ghost sumi-btn--icon-sm"></button>
</div>
</div>
</div>
<!-- Live Indicator -->
<div class="ds-subsection">
<h3 class="ds-subsection__title">📡 Live Indicators</h3>
<div class="ds-preview-row">
<span class="sumi-live-dot">En direct</span>
<span class="sumi-badge sumi-badge--live">● LIVE</span>
</div>
</div>
</section>
<hr class="ds-hr">
<!-- ════════════════════════════════════════════════════════════════
6. SHADOWS & ELEVATION
════════════════════════════════════════════════════════════════ -->
<section class="ds-section">
<h2 class="ds-section__title">Ombres & Élévation</h2>
<p class="ds-section__subtitle">
6 niveaux d'ombre. Chaque couche correspond à un usage spécifique.
</p>
<div class="ds-grid ds-grid--3" style="gap: 20px;">
<div style="background: var(--sumi-surface-card); border-radius: var(--sumi-radius-lg); padding: 24px; box-shadow: var(--sumi-shadow-xs);">
<span class="sumi-label">XS</span>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary); margin-top: 8px;">Inputs, badges</p>
</div>
<div style="background: var(--sumi-surface-card); border-radius: var(--sumi-radius-lg); padding: 24px; box-shadow: var(--sumi-shadow-sm);">
<span class="sumi-label">SM</span>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary); margin-top: 8px;">Cards au repos</p>
</div>
<div style="background: var(--sumi-surface-card); border-radius: var(--sumi-radius-lg); padding: 24px; box-shadow: var(--sumi-shadow-md);">
<span class="sumi-label">MD</span>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary); margin-top: 8px;">Cards hover, tooltips</p>
</div>
<div style="background: var(--sumi-surface-card); border-radius: var(--sumi-radius-lg); padding: 24px; box-shadow: var(--sumi-shadow-lg);">
<span class="sumi-label">LG</span>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary); margin-top: 8px;">Dropdowns, popovers</p>
</div>
<div style="background: var(--sumi-surface-card); border-radius: var(--sumi-radius-lg); padding: 24px; box-shadow: var(--sumi-shadow-xl);">
<span class="sumi-label">XL</span>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary); margin-top: 8px;">Modales, drawers</p>
</div>
<div style="background: var(--sumi-surface-card); border-radius: var(--sumi-radius-lg); padding: 24px; box-shadow: var(--sumi-shadow-2xl);">
<span class="sumi-label">2XL</span>
<p class="sumi-body-sm" style="color: var(--sumi-text-secondary); margin-top: 8px;">Full-screen overlays</p>
</div>
</div>
</section>
<hr class="ds-hr">
<!-- ════════════════════════════════════════════════════════════════
7. SPACING & RADIUS
════════════════════════════════════════════════════════════════ -->
<section class="ds-section">
<h2 class="ds-section__title">Spacing & Radius</h2>
<div class="ds-subsection">
<h3 class="ds-subsection__title">Échelle de spacing (base 4px)</h3>
<div style="display: flex; flex-direction: column; gap: 8px;">
<div style="display: flex; align-items: center; gap: 16px;" class="sumi-body-sm">
<span class="ds-code" style="width: 80px;">space-1</span>
<div style="width: 4px; height: 16px; background: var(--sumi-accent); border-radius: 2px;"></div>
<span style="color: var(--sumi-text-tertiary);">4px — Micro gaps</span>
</div>
<div style="display: flex; align-items: center; gap: 16px;" class="sumi-body-sm">
<span class="ds-code" style="width: 80px;">space-2</span>
<div style="width: 8px; height: 16px; background: var(--sumi-accent); border-radius: 2px;"></div>
<span style="color: var(--sumi-text-tertiary);">8px — Icon gaps, tight padding</span>
</div>
<div style="display: flex; align-items: center; gap: 16px;" class="sumi-body-sm">
<span class="ds-code" style="width: 80px;">space-3</span>
<div style="width: 12px; height: 16px; background: var(--sumi-accent); border-radius: 2px;"></div>
<span style="color: var(--sumi-text-tertiary);">12px — Input padding, small gaps</span>
</div>
<div style="display: flex; align-items: center; gap: 16px;" class="sumi-body-sm">
<span class="ds-code" style="width: 80px;">space-4</span>
<div style="width: 16px; height: 16px; background: var(--sumi-accent); border-radius: 2px;"></div>
<span style="color: var(--sumi-text-tertiary);">16px — Card padding, standard gap</span>
</div>
<div style="display: flex; align-items: center; gap: 16px;" class="sumi-body-sm">
<span class="ds-code" style="width: 80px;">space-6</span>
<div style="width: 24px; height: 16px; background: var(--sumi-accent); border-radius: 2px;"></div>
<span style="color: var(--sumi-text-tertiary);">24px — Section padding</span>
</div>
<div style="display: flex; align-items: center; gap: 16px;" class="sumi-body-sm">
<span class="ds-code" style="width: 80px;">space-8</span>
<div style="width: 32px; height: 16px; background: var(--sumi-accent); border-radius: 2px;"></div>
<span style="color: var(--sumi-text-tertiary);">32px — Section margins</span>
</div>
<div style="display: flex; align-items: center; gap: 16px;" class="sumi-body-sm">
<span class="ds-code" style="width: 80px;">space-12</span>
<div style="width: 48px; height: 16px; background: var(--sumi-accent); border-radius: 2px;"></div>
<span style="color: var(--sumi-text-tertiary);">48px — Page sections</span>
</div>
<div style="display: flex; align-items: center; gap: 16px;" class="sumi-body-sm">
<span class="ds-code" style="width: 80px;">space-16</span>
<div style="width: 64px; height: 16px; background: var(--sumi-accent); border-radius: 2px;"></div>
<span style="color: var(--sumi-text-tertiary);">64px — Major page gaps</span>
</div>
</div>
</div>
<div class="ds-subsection">
<h3 class="ds-subsection__title">Border Radius</h3>
<div class="ds-preview-row" style="gap: 20px;">
<div style="text-align: center;">
<div style="width: 48px; height: 48px; background: var(--sumi-accent-subtle); border: 1px solid var(--sumi-accent); border-radius: var(--sumi-radius-xs);"></div>
<span class="ds-code" style="margin-top: 8px; display: block;">xs (4px)</span>
</div>
<div style="text-align: center;">
<div style="width: 48px; height: 48px; background: var(--sumi-accent-subtle); border: 1px solid var(--sumi-accent); border-radius: var(--sumi-radius-sm);"></div>
<span class="ds-code" style="margin-top: 8px; display: block;">sm (6px)</span>
</div>
<div style="text-align: center;">
<div style="width: 48px; height: 48px; background: var(--sumi-accent-subtle); border: 1px solid var(--sumi-accent); border-radius: var(--sumi-radius-md);"></div>
<span class="ds-code" style="margin-top: 8px; display: block;">md (8px)</span>
</div>
<div style="text-align: center;">
<div style="width: 48px; height: 48px; background: var(--sumi-accent-subtle); border: 1px solid var(--sumi-accent); border-radius: var(--sumi-radius-lg);"></div>
<span class="ds-code" style="margin-top: 8px; display: block;">lg (12px)</span>
</div>
<div style="text-align: center;">
<div style="width: 48px; height: 48px; background: var(--sumi-accent-subtle); border: 1px solid var(--sumi-accent); border-radius: var(--sumi-radius-xl);"></div>
<span class="ds-code" style="margin-top: 8px; display: block;">xl (16px)</span>
</div>
<div style="text-align: center;">
<div style="width: 48px; height: 48px; background: var(--sumi-accent-subtle); border: 1px solid var(--sumi-accent); border-radius: var(--sumi-radius-full);"></div>
<span class="ds-code" style="margin-top: 8px; display: block;">full</span>
</div>
</div>
</div>
</section>
<hr class="ds-hr">
<!-- ════════════════════════════════════════════════════════════════
8. MINI APP MOCKUP
════════════════════════════════════════════════════════════════ -->
<section class="ds-section">
<h2 class="ds-section__title">Aperçu — App Mockup</h2>
<p class="ds-section__subtitle">
Composition réelle avec les composants du système. C'est ce à quoi l'app doit ressembler.
</p>
<div class="ds-app-mock" style="max-width: 900px; height: 560px; display: grid; grid-template-columns: 200px 1fr; grid-template-rows: 48px 1fr 64px; overflow: hidden;">
<!-- Sidebar -->
<div style="grid-row: 1 / -1; background: var(--sumi-bg-raised); border-right: 1px solid var(--sumi-border-faint); padding: 12px; display: flex; flex-direction: column; overflow: hidden;">
<!-- Logo -->
<div style="display: flex; align-items: center; gap: 8px; padding: 8px 4px; margin-bottom: 16px;">
<svg width="24" height="24" viewBox="0 0 48 48" fill="none">
<path d="M14 34C16 26 20 18 24 14C28 18 32 26 34 34" stroke="var(--sumi-text-primary)" stroke-width="3" stroke-linecap="round" fill="none"/>
<circle cx="24" cy="14" r="2.5" fill="var(--sumi-accent)"/>
</svg>
<span style="font-family: var(--sumi-font-heading); font-weight: 700; font-size: var(--sumi-text-md);">Veza</span>
</div>
<!-- Nav -->
<div style="display: flex; flex-direction: column; gap: 2px; flex: 1;">
<div class="sumi-sidebar__nav-item sumi-sidebar__nav-item--active" style="font-size: var(--sumi-text-xs); padding: 8px; position: relative;">
<span></span> Accueil
</div>
<div class="sumi-sidebar__nav-item" style="font-size: var(--sumi-text-xs); padding: 8px;">
<span>🔍</span> Explorer
</div>
<div class="sumi-sidebar__nav-item" style="font-size: var(--sumi-text-xs); padding: 8px;">
<span>📚</span> Bibliothèque
</div>
<div class="sumi-sidebar__nav-item" style="font-size: var(--sumi-text-xs); padding: 8px;">
<span>📡</span> Streams
</div>
<div class="sumi-sidebar__nav-item" style="font-size: var(--sumi-text-xs); padding: 8px;">
<span>💬</span> Messages
</div>
<div class="sumi-sidebar__section-label" style="padding: 12px 4px 4px; font-size: 9px;">Mes Playlists</div>
<div class="sumi-sidebar__nav-item" style="font-size: var(--sumi-text-xs); padding: 6px 8px;">
<span style="opacity: 0.4;"></span> Lo-Fi Sessions
</div>
<div class="sumi-sidebar__nav-item" style="font-size: var(--sumi-text-xs); padding: 6px 8px;">
<span style="opacity: 0.4;"></span> Workout Mix
</div>
</div>
<!-- User -->
<div style="display: flex; align-items: center; gap: 8px; padding: 8px 4px; border-top: 1px solid var(--sumi-border-faint);">
<div class="sumi-avatar sumi-avatar--xs" style="background: var(--sumi-accent-subtle); color: var(--sumi-accent); font-size: 8px;">MK</div>
<span style="font-size: 11px; font-weight: 500; color: var(--sumi-text-secondary);">Marko</span>
</div>
</div>
<!-- Header -->
<div style="background: var(--sumi-glass-bg); backdrop-filter: blur(12px); border-bottom: 1px solid var(--sumi-border-faint); display: flex; align-items: center; padding: 0 16px; gap: 12px;">
<div style="flex: 1; display: flex; align-items: center; gap: 8px; background: var(--sumi-surface-inset); border-radius: var(--sumi-radius-md); padding: 5px 10px;">
<span style="color: var(--sumi-text-tertiary); font-size: 12px;">🔍</span>
<span style="color: var(--sumi-text-tertiary); font-size: var(--sumi-text-xs);">Rechercher artistes, morceaux, playlists...</span>
</div>
<div class="sumi-avatar sumi-avatar--xs" style="background: var(--sumi-accent-subtle); color: var(--sumi-accent); font-size: 8px;">MK</div>
</div>
<!-- Main Content -->
<div style="overflow-y: auto; padding: 20px; background: var(--sumi-bg-base);">
<h1 style="font-family: var(--sumi-font-heading); font-size: var(--sumi-text-xl); font-weight: 600; margin-bottom: 4px;">Bon retour, Marko</h1>
<p style="font-size: var(--sumi-text-xs); color: var(--sumi-text-tertiary); margin-bottom: 20px;">Mercredi 11 février 2026</p>
<!-- Stats row -->
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 20px;">
<div style="background: var(--sumi-surface-card); border: 1px solid var(--sumi-border-faint); border-radius: var(--sumi-radius-md); padding: 12px;">
<span style="font-size: 9px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--sumi-text-tertiary); font-weight: 500;">Streams</span>
<div style="font-family: var(--sumi-font-mono); font-size: var(--sumi-text-lg); font-weight: 700; margin-top: 4px;">12.8K</div>
<span style="font-family: var(--sumi-font-mono); font-size: 10px; color: var(--sumi-sage);">↑ 23%</span>
</div>
<div style="background: var(--sumi-surface-card); border: 1px solid var(--sumi-border-faint); border-radius: var(--sumi-radius-md); padding: 12px;">
<span style="font-size: 9px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--sumi-text-tertiary); font-weight: 500;">Followers</span>
<div style="font-family: var(--sumi-font-mono); font-size: var(--sumi-text-lg); font-weight: 700; margin-top: 4px;">1.2K</div>
<span style="font-family: var(--sumi-font-mono); font-size: 10px; color: var(--sumi-sage);">↑ 42%</span>
</div>
<div style="background: var(--sumi-surface-card); border: 1px solid var(--sumi-border-faint); border-radius: var(--sumi-radius-md); padding: 12px;">
<span style="font-size: 9px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--sumi-text-tertiary); font-weight: 500;">XP</span>
<div style="font-family: var(--sumi-font-mono); font-size: var(--sumi-text-lg); font-weight: 700; margin-top: 4px; color: var(--sumi-gold);">Lv.7</div>
<div style="height: 3px; background: var(--sumi-bg-hover); border-radius: 2px; margin-top: 6px;">
<div style="height: 100%; width: 71%; background: var(--sumi-gold); border-radius: 2px;"></div>
</div>
</div>
</div>
<!-- Recent tracks -->
<h2 style="font-family: var(--sumi-font-heading); font-size: var(--sumi-text-base); font-weight: 600; margin-bottom: 10px;">Récemment joués</h2>
<div style="display: flex; flex-direction: column; gap: 2px; background: var(--sumi-surface-card); border: 1px solid var(--sumi-border-faint); border-radius: var(--sumi-radius-md); padding: 4px;">
<div style="display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 4px; background: var(--sumi-accent-subtle);">
<span style="font-family: var(--sumi-font-mono); font-size: 10px; color: var(--sumi-accent); width: 16px; text-align: right;"></span>
<div style="width: 28px; height: 28px; background: linear-gradient(135deg, var(--sumi-bg-hover), var(--sumi-bg-active)); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 1; min-width: 0;">
<div style="font-size: 12px; font-weight: 500;" class="truncate">Nuits Urbaines</div>
<div style="font-size: 10px; color: var(--sumi-text-secondary);" class="truncate">Kōji</div>
</div>
<span style="font-family: var(--sumi-font-mono); font-size: 10px; color: var(--sumi-text-tertiary);">3:42</span>
</div>
<div style="display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 4px;">
<span style="font-family: var(--sumi-font-mono); font-size: 10px; color: var(--sumi-text-tertiary); width: 16px; text-align: right;">2</span>
<div style="width: 28px; height: 28px; background: var(--sumi-bg-hover); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 1; min-width: 0;">
<div style="font-size: 12px; font-weight: 500;" class="truncate">Brume Matinale</div>
<div style="font-size: 10px; color: var(--sumi-text-secondary);" class="truncate">Kōji</div>
</div>
<span style="font-family: var(--sumi-font-mono); font-size: 10px; color: var(--sumi-text-tertiary);">4:15</span>
</div>
<div style="display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 4px;">
<span style="font-family: var(--sumi-font-mono); font-size: 10px; color: var(--sumi-text-tertiary); width: 16px; text-align: right;">3</span>
<div style="width: 28px; height: 28px; background: var(--sumi-bg-hover); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 1; min-width: 0;">
<div style="font-size: 12px; font-weight: 500;" class="truncate">Encre &amp; Silence</div>
<div style="font-size: 10px; color: var(--sumi-text-secondary);" class="truncate">Yūrei</div>
</div>
<span style="font-family: var(--sumi-font-mono); font-size: 10px; color: var(--sumi-text-tertiary);">5:01</span>
</div>
</div>
</div>
<!-- Player -->
<div style="grid-column: 1 / -1; background: var(--sumi-glass-bg); backdrop-filter: blur(16px); border-top: 1px solid var(--sumi-border-faint); display: flex; align-items: center; padding: 0 16px; gap: 12px;">
<div style="width: 36px; height: 36px; background: linear-gradient(135deg, var(--sumi-bg-hover), var(--sumi-bg-active)); border-radius: 4px; flex-shrink: 0;"></div>
<div style="flex: 0 0 120px;">
<div style="font-size: 11px; font-weight: 500;">Nuits Urbaines</div>
<div style="font-size: 10px; color: var(--sumi-text-secondary);">Kōji</div>
</div>
<div style="flex: 1; display: flex; flex-direction: column; gap: 4px; align-items: center;">
<div style="display: flex; gap: 16px; align-items: center;">
<span style="color: var(--sumi-text-tertiary); font-size: 12px; cursor: pointer;"></span>
<div style="width: 28px; height: 28px; background: var(--sumi-accent); border-radius: var(--sumi-radius-full); display: flex; align-items: center; justify-content: center; color: var(--sumi-text-inverse); font-size: 10px; cursor: pointer;"></div>
<span style="color: var(--sumi-text-tertiary); font-size: 12px; cursor: pointer;"></span>
</div>
<div style="width: 100%; max-width: 300px; display: flex; align-items: center; gap: 8px;">
<span style="font-family: var(--sumi-font-mono); font-size: 9px; color: var(--sumi-text-tertiary);">1:18</span>
<div style="flex: 1; height: 3px; background: var(--sumi-bg-hover); border-radius: 2px; overflow: hidden;">
<div style="width: 35%; height: 100%; background: var(--sumi-accent); border-radius: 2px;"></div>
</div>
<span style="font-family: var(--sumi-font-mono); font-size: 9px; color: var(--sumi-text-tertiary);">3:42</span>
</div>
</div>
<div style="display: flex; align-items: center; gap: 8px;">
<span style="font-size: 12px; color: var(--sumi-text-tertiary); cursor: pointer;">🔊</span>
<div style="width: 60px; height: 3px; background: var(--sumi-bg-hover); border-radius: 2px; overflow: hidden;">
<div style="width: 65%; height: 100%; background: var(--sumi-text-tertiary); border-radius: 2px;"></div>
</div>
</div>
</div>
</div>
</section>
<hr class="ds-hr">
<!-- ════════════════════════════════════════════════════════════════
9. RULES & ANTI-PATTERNS
════════════════════════════════════════════════════════════════ -->
<section class="ds-section">
<h2 class="ds-section__title">Règles & Anti-patterns</h2>
<p class="ds-section__subtitle">
Ce qu'il faut absolument suivre — et ce qu'il faut absolument éviter.
</p>
<div class="ds-grid ds-grid--2" style="gap: 20px;">
<!-- DO -->
<div class="sumi-card" style="border-left: 3px solid var(--sumi-sage); padding: 24px;">
<h3 class="sumi-h4" style="color: var(--sumi-sage); margin-bottom: 16px;">✓ FAIRE</h3>
<div style="display: flex; flex-direction: column; gap: 10px; font-size: var(--sumi-text-sm); color: var(--sumi-text-secondary);">
<p>Utiliser les tokens <code class="ds-code">--sumi-*</code> pour TOUTE valeur visuelle</p>
<p>Laisser respirer — padding généreux, margins explicites</p>
<p>JetBrains Mono pour les chiffres, stats, durées</p>
<p>Un seul accent par section — jamais 2 couleurs en compétition</p>
<p>Borders subtiles <code class="ds-code">border-faint</code> comme séparation principale</p>
<p>Le thème gaming (XP, achievements) comme récompense, pas comme déco</p>
<p>Tester en light ET dark — chaque composant doit marcher dans les deux</p>
<p>Responsive : mobile-first, sidebar overlay sous lg</p>
</div>
</div>
<!-- DON'T -->
<div class="sumi-card" style="border-left: 3px solid var(--sumi-vermillion); padding: 24px;">
<h3 class="sumi-h4" style="color: var(--sumi-vermillion); margin-bottom: 16px;">✕ NE PAS FAIRE</h3>
<div style="display: flex; flex-direction: column; gap: 10px; font-size: var(--sumi-text-sm); color: var(--sumi-text-secondary);">
<p>Utiliser des couleurs Tailwind par défaut (slate, zinc, gray)</p>
<p>Ajouter des glow/neon décoratifs — le glow est UNIQUEMENT pour le focus</p>
<p>Orbitron ou toute font "gaming" agressive en heading</p>
<p>Clip-path manga/hex — c'est gimmick, pas fonctionnel</p>
<p>Plus de 4 couleurs d'accent — indigo, vermillon, sauge, or. C'est TOUT</p>
<p>Gradient comme fond de composant — réservé aux hero/cover uniquement</p>
<p>Box-shadow décoratif — les ombres servent l'élévation, pas la déco</p>
<p>Animations au-delà de 300ms sauf pour les achievements</p>
<p>Plus de 2 fonts dans un même composant</p>
<p>Des valeurs CSS arbitraires (text-[14px], w-[237px])</p>
</div>
</div>
</div>
</section>
<hr class="ds-hr">
<!-- ════════════════════════════════════════════════════════════════
10. TOKEN MAPPING — TAILWIND
════════════════════════════════════════════════════════════════ -->
<section class="ds-section">
<h2 class="ds-section__title">Mapping Tailwind</h2>
<p class="ds-section__subtitle">
Comment traduire ce design system en classes Tailwind dans ton projet React. Chaque token SUMI a son équivalent Tailwind via le fichier de config.
</p>
<div class="sumi-terminal" style="max-width: 700px;">
<div class="sumi-terminal__header">
<div class="sumi-terminal__dot sumi-terminal__dot--red"></div>
<div class="sumi-terminal__dot sumi-terminal__dot--yellow"></div>
<div class="sumi-terminal__dot sumi-terminal__dot--green"></div>
<span style="font-size: var(--sumi-text-xs); color: var(--sumi-text-tertiary); margin-left: 8px;">tailwind.config — token mapping</span>
</div>
<div class="sumi-terminal__body" style="font-size: 11px; line-height: 1.7;">
<span style="color: var(--sumi-text-tertiary);">// Colors</span>
<span style="color: var(--sumi-accent);">bg-sumi-void</span> → var(--sumi-bg-void)
<span style="color: var(--sumi-accent);">bg-sumi-base</span> → var(--sumi-bg-base)
<span style="color: var(--sumi-accent);">bg-sumi-raised</span> → var(--sumi-bg-raised)
<span style="color: var(--sumi-accent);">text-sumi-primary</span> → var(--sumi-text-primary)
<span style="color: var(--sumi-accent);">text-sumi-secondary</span>→ var(--sumi-text-secondary)
<span style="color: var(--sumi-accent);">text-sumi-accent</span> → var(--sumi-accent)
<span style="color: var(--sumi-accent);">border-sumi-faint</span> → var(--sumi-border-faint)
<span style="color: var(--sumi-text-tertiary);">// Fonts</span>
<span style="color: var(--sumi-accent);">font-body</span> → var(--sumi-font-body)
<span style="color: var(--sumi-accent);">font-heading</span> → var(--sumi-font-heading)
<span style="color: var(--sumi-accent);">font-mono</span> → var(--sumi-font-mono)
<span style="color: var(--sumi-text-tertiary);">// Shadows</span>
<span style="color: var(--sumi-accent);">shadow-sumi-sm</span> → var(--sumi-shadow-sm)
<span style="color: var(--sumi-accent);">shadow-sumi-md</span> → var(--sumi-shadow-md)
<span style="color: var(--sumi-accent);">shadow-sumi-glow</span> → var(--sumi-shadow-glow)
</div>
</div>
</section>
<hr class="ds-hr">
<!-- Footer -->
<footer style="text-align: center; padding: 32px 0;">
<p class="sumi-caption">VEZA SUMI Design System v1.0 — Source de vérité</p>
<p class="sumi-caption" style="margin-top: 4px;">
<span class="sumi-serif-jp" style="font-size: var(--sumi-text-base); color: var(--sumi-accent);">墨は心の鏡</span>
<span style="display: block; margin-top: 4px;">L'encre est le miroir du cœur</span>
</p>
</footer>
</div>
<script>
function toggleTheme() {
const html = document.documentElement;
const btn = document.getElementById('themeToggle');
if (html.dataset.theme === 'dark') {
html.dataset.theme = 'light';
btn.textContent = '☾ Dark';
} else {
html.dataset.theme = 'dark';
btn.textContent = '☀ Light';
}
}
</script>
</body>
</html>