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