Knowledge base of ~80+ markdown files across 14 domains (00-13), Logseq graph, hardware design files (KiCAD), infrastructure configs, and talas-wiki static site. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
32 KiB
SUMI v3 — Specification du Design System
Ce document est la specification technique complete de SUMI v3. Il definit les regles, contraintes et tokens a implementer pour obtenir une UI singuliere, vivante et econome en ressources. Toute modification de l'UI doit etre conforme a ce document.
Direction artistique : lavis japonais interactif (sumi-e numerique). Voir 05_EXPERIENCE_UTILISATEUR/DIRECTION_ARTISTIQUE_TALAS pour la philosophie complete.
1. Ce qui change entre SUMI v2 et v3
| SUMI v2 (actuel) | SUMI v3 (cible) |
|---|---|
| Palette indigo froide (#7c9dd6) | Palette cyan (#0098B5) — touche de couleur unique dans un lavis monochrome |
| Surfaces plates (flat design) | Surfaces = couches d'encre diluee sur papier washi |
| Themes statiques (dark/light) | Theme circadien (le lavis suit le soleil — papier chaud/froid/inverse) |
| Interface figee | Interface qui se patine (le papier vieillit, l'encre s'oxyde) |
| Animations generiques | Animations avec le poids de l'eau (goutte/trait/lavis/vague/maree) |
| Icones standard | Icones = gestes calligraphiques dessines a la main |
| Player = barre en bas | Player = suzuri (pierre a encre) — objet le plus dense de l'interface |
| Performance non budgetee | Budget strict par metrique |
| Bordures nettes (border CSS) | Bords diffus comme l'encre dans l'eau (box-shadow tres diffus) |
Ce qui est conserve :
- L'architecture tokens (CSS custom properties + TypeScript)
- Le nommage
--sumi-*pour toutes les variables - La grille de 4px
- Les composants existants (refactores, pas remplaces)
- Tailwind v4 CSS-first
- Les modes accessibilite (high contrast, reduced motion, density)
- Space Grotesk + Inter + JetBrains Mono (deja valides dans la direction artistique)
2. Palette — encre, papier et cyan
2.1 Accent principal : le cyan
Le cyan (#0098B5) est la seule couleur d'accent. Dans un lavis traditionnel, une seule touche de couleur suffit a tout transformer. Le cyan est cette touche. Il evoque l'eau — l'element qui transporte l'encre, qui donne vie au lavis. Il contraste avec le noir/blanc ambiant comme un eclat de ciel dans un paysage monochrome.
/* SUMI v3 — Pigment primaire (cyan) */
--sumi-accent: #0098B5;
--sumi-accent-hover: #00B4D8;
--sumi-accent-active: #007A94;
--sumi-accent-muted: rgba(0, 152, 181, 0.15);
--sumi-accent-subtle: rgba(0, 152, 181, 0.08);
--sumi-accent-emphasis: #006B7F;
/* Focus ring — cyan diffus dans l'eau */
--sumi-border-focus: rgba(0, 152, 181, 0.50);
--sumi-shadow-glow: 0 0 0 3px rgba(0, 152, 181, 0.25);
--sumi-shadow-glow-lg: 0 0 20px rgba(0, 152, 181, 0.12);
2.2 Pigments fonctionnels — pastel diffuse
Les couleurs fonctionnelles sont des pigments dilues dans beaucoup d'eau. Elles apparaissent rarement : en lignes fines, en micro-points, en halos subtils. Jamais en aplats. Elles ne rivalisent jamais avec le cyan.
--sumi-success: rgba(90, 140, 100, 0.60); /* Vert sauge dilue */
--sumi-error: rgba(180, 80, 70, 0.55); /* Rouge brique dilue */
--sumi-warning: rgba(190, 150, 60, 0.55); /* Ambre dilue */
--sumi-info: #0098B5; /* Le cyan lui-meme */
Regles des couleurs fonctionnelles :
- Jamais en aplat (pas de fond rouge plein pour une erreur)
- Toujours en ligne fine, point, bordure, ou halo diffus
- L'opacite ne depasse jamais 60% — elles sont toujours "diluees"
- Si le cyan est present au meme endroit, la couleur fonctionnelle passe en gris + icone
2.3 Fonds — papier washi et encre noire
Le fond est du papier. Jamais une surface lisse. Jamais du blanc pur. Jamais du noir pur. Le papier a une texture, une chaleur, une vie.
/* Jour (papier washi clair) */
--sumi-bg-void: #EBE5DD; /* Washi vieilli — le papier le plus expose */
--sumi-bg-base: #F2EDE6; /* Fond principal — papier washi */
--sumi-bg-raised: #F7F3EC; /* Surfaces posees sur le papier */
--sumi-bg-overlay: #FBF8F2; /* Dropdowns, overlays */
--sumi-bg-hover: rgba(26, 26, 30, 0.06); /* Encre tres diluee */
--sumi-bg-active: rgba(26, 26, 30, 0.10); /* Encre legerement plus dense */
/* Nuit (lavis inverse — papier sombre, encre claire) */
--sumi-bg-void: #09090B; /* Noir d'encre profond */
--sumi-bg-base: #0D0D0F; /* Fond principal — papier sombre */
--sumi-bg-raised: #141416; /* Surfaces : couche d'encre legerement plus claire */
--sumi-bg-overlay: #1A1A1E; /* Overlays */
--sumi-bg-hover: rgba(232, 227, 219, 0.06); /* Encre claire diluee */
--sumi-bg-active: rgba(232, 227, 219, 0.10); /* Encre claire plus dense */
2.4 Texte — encre sur papier
Le texte est de l'encre posee sur du papier. Noir profond le jour, blanc creme la nuit. Le texte secondaire est de l'encre diluee.
/* Jour */
--sumi-text-primary: #1A1A1E; /* Encre sumi — dense mais pas pur */
--sumi-text-secondary: #9A958D; /* Encre diluee — gris chaud */
--sumi-text-tertiary: #B5B0A8; /* Encre tres diluee — s'efface comme un lavis dilue */
--sumi-text-link: #0098B5; /* Liens = accent cyan */
/* Nuit (inversion) */
--sumi-text-primary: #E8E3DB; /* Encre claire sur papier sombre */
--sumi-text-secondary: #9A958D; /* Encre diluee — reste gris chaud */
--sumi-text-tertiary: #706B63; /* Encre tres diluee en mode nuit */
--sumi-text-link: #006B7F; /* Cyan profond la nuit */
3. Texture washi et couches d'encre
3.1 Principe
Les surfaces ne sont jamais parfaitement lisses. Le fond porte la texture du papier washi — grain subtil, fibres visibles, surface vivante. Les elements poses dessus sont des couches d'encre diluee a differentes concentrations.
3.2 Implementation technique — texture washi
Un seul fichier image : washi.png (512x512, ~8 Ko)
Photo d'un vrai papier washi, desaturee, grain visible. Applique sur le body en pseudo-element.
/* Pseudo-element sur le body — texture washi globale */
body::after {
content: '';
position: fixed;
inset: 0;
pointer-events: none;
z-index: var(--sumi-z-max);
background-image: url('/washi.png');
background-repeat: repeat;
opacity: var(--sumi-washi-opacity, 0.04);
mix-blend-mode: soft-light;
}
/* Variable de controle */
:root {
--sumi-washi-opacity: 0.04; /* Subtil — a peine perceptible */
}
/* Desactive en mode eco ou reduced-motion */
@media (prefers-reduced-motion: reduce) {
body::after { display: none; }
}
[data-eco="true"] body::after { display: none; }
Cout en performance : ~8 Ko au chargement, 0 impact en runtime (image statique,
GPU-composited via position: fixed). Negligeable.
3.3 Couches d'encre par surface
Les surfaces elevees sont des couches d'encre diluee posees sur le papier. Pas de box-shadow traditionnelle — des diffusions douces, comme l'encre qui s'etend dans du papier mouille.
/* Les cartes sont des voiles d'encre poses sur le washi */
.sumi-card {
background: rgba(26, 26, 30, 0.04);
backdrop-filter: blur(8px);
/* Pas de border — un bord diffus d'encre */
box-shadow: 0 0 8px rgba(26, 26, 30, 0.05);
border: none;
}
/* Overlays — encre plus concentree */
.sumi-overlay {
background: rgba(26, 26, 30, 0.08);
backdrop-filter: blur(16px);
box-shadow: 0 0 16px rgba(26, 26, 30, 0.08);
border: none;
}
/* Modales — couche la plus dense */
.sumi-modal {
background: rgba(26, 26, 30, 0.15);
backdrop-filter: blur(24px);
box-shadow: 0 0 24px rgba(26, 26, 30, 0.10);
border: none;
}
| Elevation | Opacite encre | Blur du backdrop | Effet |
|---|---|---|---|
| Fond (papier) | 0% | — | Le papier washi brut |
| Surface (carte) | 4-8% | 8px | Un voile d'encre tres leger |
| Overlay (dropdown) | 8-12% | 16px | Une couche plus dense |
| Modale | 12-20% | 24px | Une zone nettement marquee |
| Player (suzuri) | 20-30% | 32px | L'element le plus "encre" — le plus present |
3.4 Bordures = diffusion d'encre
Les bordures ne sont pas des lignes CSS nettes. Elles sont des bords diffus d'encre, comme le contour d'une tache d'eau sur du papier.
/* MAL — bordure nette, mecanique */
border: 1px solid rgba(0, 0, 0, 0.1);
/* BIEN — bord diffus d'encre */
box-shadow: 0 0 6px rgba(26, 26, 30, 0.06);
border: none;
Regle : jamais de border visible. Toujours un box-shadow diffus
(spread 0, blur 4-8px, opacite 3-8%).
4. Theme circadien — le lavis suit le soleil
4.1 Concept
La "temperature" du papier change avec l'heure, comme la lumiere naturelle sur un rouleau de papier pose pres d'une fenetre. Le matin, le papier est chaud. Le jour, il est neutre. Le soir, il se rechauffe. La nuit, le lavis s'inverse : papier sombre, encre claire, cyan profond.
4.2 Phases circadiennes
| Phase | Heures | Ambiance | Modification |
|---|---|---|---|
| Aube | 05h-08h | Papier rose/chaud, encre douce | Fonds legerement plus chauds, cyan tire vers le teal |
| Jour | 08h-17h | Papier neutre, contraste maximal | Palette standard — cyan vif |
| Crepuscule | 17h-20h | Papier qui se rechauffe, encre dense | Fonds plus chauds, cyan plus profond |
| Nuit | 20h-05h | Lavis inverse | Papier sombre (#0D0D0F), encre claire (#E8E3DB), cyan profond (#006B7F) |
4.3 Implementation technique
// circadian.ts — calcule les ajustements de palette
interface CircadianShift {
bgWarmth: number; // -5 to +5 (degres hue shift sur les fonds)
accentWarmth: number; // -3 to +3 (degres hue shift sur l'accent)
brightness: number; // 0.95 to 1.05 (multiplicateur de luminosite)
contrast: number; // 0.97 to 1.0 (multiplicateur de contraste)
}
function getCircadianShift(hour: number): CircadianShift {
if (hour >= 5 && hour < 8) {
// Aube — papier plus chaud, encre plus douce
return { bgWarmth: 3, accentWarmth: 2, brightness: 1.02, contrast: 0.98 };
}
if (hour >= 8 && hour < 17) {
// Jour — neutre, contraste maximal, cyan vif
return { bgWarmth: 0, accentWarmth: 0, brightness: 1.0, contrast: 1.0 };
}
if (hour >= 17 && hour < 20) {
// Crepuscule — papier qui se rechauffe, encre plus dense
return { bgWarmth: 4, accentWarmth: 3, brightness: 0.98, contrast: 0.99 };
}
// Nuit — le lavis s'inverse, cyan s'approfondit
return { bgWarmth: 1, accentWarmth: -1, brightness: 0.95, contrast: 0.97 };
}
4.4 Application aux tokens CSS
// Dans ThemeProvider, au montage + toutes les 30 minutes
function applyCircadianShift() {
const hour = new Date().getHours();
const shift = getCircadianShift(hour);
// Applique les shifts via des custom properties sur :root
document.documentElement.style.setProperty(
'--sumi-circadian-warmth', `${shift.bgWarmth}deg`
);
document.documentElement.style.setProperty(
'--sumi-circadian-brightness', `${shift.brightness}`
);
}
// Recalcul toutes les 30 min (pas besoin de plus frequent)
setInterval(applyCircadianShift, 30 * 60 * 1000);
/* Les fonds utilisent un filtre CSS plutot que de recalculer les couleurs */
:root {
--sumi-circadian-warmth: 0deg;
--sumi-circadian-brightness: 1;
}
/* Applique sur le conteneur principal, pas sur chaque element */
#app {
filter:
hue-rotate(var(--sumi-circadian-warmth))
brightness(var(--sumi-circadian-brightness));
transition: filter 300s linear; /* Transition de 5 min, imperceptible */
}
4.5 Contraintes
- Le changement est imperceptible en temps reel (transition de 5 min)
- L'utilisateur ne doit jamais "voir" le changement — il le ressent
- L'accent cyan reste toujours reconnaissable (shift max : +/- 3 degres de hue)
- Le mode circadien est optionnel : un toggle dans les settings pour le desactiver
- En mode jour (papier clair), le circadien ajuste la temperature mais ne passe jamais en nuit (papier sombre), et inversement
- La nuit est une inversion complete du lavis : papier sombre + encre claire + cyan profond
- La transition jour/nuit est un fondu de 30 minutes, imperceptible
- Cout CPU : un setInterval de 30 min + 2 CSS custom properties. Negligeable.
5. Systeme de patine
5.1 Concept
Avec le temps et l'usage, l'interface se patine comme un rouleau ancien. Le papier vieillit. L'encre s'oxyde et gagne en profondeur. Le grain du washi devient plus prononce. Le cyan prend des nuances plus profondes.
5.2 Tokens de patine
:root {
/* Calculees au login, basees sur le profil utilisateur */
--sumi-patina-level: 0; /* 0-4, entier */
--sumi-patina-warmth: 0; /* 0-10, degres de hue shift additionnel */
--sumi-patina-washi: 0.04; /* 0.04-0.08, opacite de la texture washi */
--sumi-patina-depth: 0; /* 0-3, diffusion d'encre additionnelle */
--sumi-patina-texture: none; /* none | subtle | rich | deep */
}
5.3 Calcul de la patine
interface UserPatinaData {
accountAgeDays: number;
totalPlayTimeHours: number;
totalUploads: number;
totalMessages: number;
totalExchanges: number;
}
function calculatePatina(data: UserPatinaData): PatinaTokens {
// Score composite (0-100)
const ageScore = Math.min(data.accountAgeDays / 365, 1) * 25;
const playScore = Math.min(data.totalPlayTimeHours / 500, 1) * 25;
const createScore = Math.min(data.totalUploads / 20, 1) * 25;
const socialScore = Math.min(
(data.totalMessages + data.totalExchanges * 5) / 200, 1
) * 25;
const score = ageScore + playScore + createScore + socialScore;
// Niveau discret (0-4)
let level = 0;
if (score >= 15) level = 1; // Rode
if (score >= 35) level = 2; // Vecu
if (score >= 60) level = 3; // Patine
if (score >= 85) level = 4; // Heritage
return {
level,
warmth: level * 2.5, // 0, 2.5, 5, 7.5, 10
washi: 0.04 + (level * 0.01), // 0.04, 0.05, 0.06, 0.07, 0.08
depth: level * 0.75, // 0, 0.75, 1.5, 2.25, 3
texture: ['none', 'subtle', 'subtle', 'rich', 'deep'][level],
};
}
5.4 Application visuelle par niveau
| Niveau | Texture washi | Chaleur | Diffusion encre | Effet visuel |
|---|---|---|---|---|
| 0 — Neuf | 0.04 | Aucune | Standard | Papier frais, encre nette |
| 1 — Rode | 0.05 | +2.5 hue | Legerement plus diffuse | Papier qui commence a jaunir |
| 2 — Vecu | 0.06 | +5 hue | Notablement plus riche | Fibres du washi plus visibles, encre plus chaude |
| 3 — Patine | 0.07 | +7.5 hue | Diffusion prononcee | Papier ancien, encre oxydee aux reflets bruns |
| 4 — Heritage | 0.08 | +10 hue | Profonde et chaleureuse | Rouleau ancien — texture riche, encre patinee, cyan profond |
5.5 CSS de la patine
/* Applique via data-attribute sur html */
[data-patina="1"] { --sumi-washi-opacity: 0.05; }
[data-patina="2"] { --sumi-washi-opacity: 0.06; }
[data-patina="3"] {
--sumi-washi-opacity: 0.07;
/* Bords d'encre legerement plus diffus — l'encre a eu le temps de s'oxyder */
--sumi-border-default: 0 0 8px rgba(26, 26, 30, 0.08);
}
[data-patina="4"] {
--sumi-washi-opacity: 0.08;
--sumi-border-default: 0 0 10px rgba(26, 26, 30, 0.12);
--sumi-shadow-sm: 0 2px 8px rgba(26, 26, 30, 0.10), 0 0 4px rgba(0, 152, 181, 0.06);
}
/* La patine se combine avec le circadien */
/* hue-rotate du circadien + hue-rotate de la patine = chaleur cumulee */
#app {
filter:
hue-rotate(calc(var(--sumi-circadian-warmth) + var(--sumi-patina-warmth, 0deg)))
brightness(var(--sumi-circadian-brightness));
}
5.6 Regles inviolables de la patine
- Invisible consciemment. Si quelqu'un remarque "tiens l'UI a change", c'est trop fort.
- Pas de notification. Jamais "Felicitations, vous avez atteint le niveau 3".
- Pas de badge. La patine n'est pas visible par les autres utilisateurs.
- Pas d'avantage fonctionnel. Zero feature debloquee par la patine.
- Irreversible et non-achetable. Seul le temps et l'usage la creent.
- Calculee au login, pas en temps reel. Un seul calcul, pas de polling.
6. Animations — le poids de l'eau
6.1 Principe physique
Chaque element de l'UI a le poids de ce qu'il represente dans le lavis. Les elements legers bougent comme des gouttes d'encre. Les elements lourds bougent comme des vagues. L'eau est la metaphore universelle du mouvement.
6.2 Classification des elements par masse
| Masse | Elements | Metaphore lavis | Duree | Easing |
|---|---|---|---|---|
| Goutte | Tooltips, badges, toggles | Goutte d'encre qui tombe | 100ms | ease-out |
| Trait | Boutons, icones, liens | Trait de pinceau rapide | 150ms | ease-out avec rebond leger |
| Lavis | Cards, dropdowns, tabs | Encre qui s'etend dans l'eau | 250ms | cubic-bezier(0.25, 0.8, 0.25, 1) |
| Vague | Modales, sidebar, panneaux | Vague lente sur papier mouille | 350ms | cubic-bezier(0.16, 1, 0.3, 1) |
| Maree | Navigation de page, player | Le mouvement de fond de l'ocean | 450ms | cubic-bezier(0.33, 1, 0.68, 1) |
6.3 Tokens de mouvement v3
:root {
/* Durees par masse */
--sumi-motion-goutte: 100ms;
--sumi-motion-trait: 150ms;
--sumi-motion-lavis: 250ms;
--sumi-motion-vague: 350ms;
--sumi-motion-maree: 450ms;
/* Easings par masse */
--sumi-ease-goutte: cubic-bezier(0.25, 0.1, 0.25, 1);
--sumi-ease-trait: cubic-bezier(0.33, 1, 0.68, 1);
--sumi-ease-lavis: cubic-bezier(0.25, 0.8, 0.25, 1);
--sumi-ease-vague: cubic-bezier(0.16, 1, 0.3, 1);
--sumi-ease-maree: cubic-bezier(0.33, 1, 0.68, 1);
--sumi-ease-rebond: cubic-bezier(0.34, 1.56, 0.64, 1); /* Pour les gouttes/traits */
}
6.4 Regle des 2 animations max
Jamais plus de 2 animations simultanees a l'ecran. Si un troisieme element doit s'animer, il attend que le premier termine. Implemente via un compteur CSS ou un gestionnaire JS leger.
6.5 Transitions de page
/* La page entrante apparait par couches — comme un lavis qui se revele */
.page-enter {
opacity: 0;
transform: translateY(6px);
}
.page-enter-active {
opacity: 1;
transform: translateY(0);
transition:
opacity var(--sumi-motion-lavis) var(--sumi-ease-trait),
transform var(--sumi-motion-lavis) var(--sumi-ease-vague);
}
/* La page sortante se dissout — comme l'encre qui seche */
.page-exit {
opacity: 1;
}
.page-exit-active {
opacity: 0;
transition: opacity 150ms ease-out;
}
6.6 Hover — l'encre s'etend
Les hover states font "s'etendre" l'element legerement, comme une goutte d'eau qui s'elargit sur le papier.
.sumi-interactive:hover {
transform: scale(1.01);
box-shadow: 0 0 12px rgba(26, 26, 30, 0.08);
transition:
transform var(--sumi-motion-trait) var(--sumi-ease-trait),
box-shadow var(--sumi-motion-trait) var(--sumi-ease-trait);
}
7. Budgets de performance
7.1 Budgets stricts
| Metrique | Budget | Actuel (SUMI v2) | Methode de mesure |
|---|---|---|---|
| Bundle JS initial (gzip) | < 120 Ko | ~150 Ko | vite build --report |
| Bundle CSS total (gzip) | < 15 Ko | ? | Idem |
| First Contentful Paint | < 1.2s | < 1.5s | Lighthouse |
| Largest Contentful Paint | < 2.0s | ? | Lighthouse |
| Time to Interactive | < 1.8s | < 2s | Lighthouse |
| Cumulative Layout Shift | < 0.05 | ? | Lighthouse |
| Total Blocking Time | < 150ms | ? | Lighthouse |
| Requetes au chargement initial | <= 5 | ? | Network tab |
| Polices chargees | <= 2 fichiers | 3-4 | Network tab |
| Images texture washi | <= 10 Ko total | 0 | Taille des assets |
| Animations simultanees max | 2 | Illimite | Audit visuel |
requestAnimationFrame actifs au repos |
0 | ? | Performance tab |
| Memoire JS heap (idle) | < 30 Mo | ? | Chrome DevTools |
7.2 Strategies d'optimisation
Polices :
- Inter : charger uniquement Regular (400) et Semi-Bold (600) en variable font
- Space Grotesk : charger uniquement Bold (700) en variable font
- JetBrains Mono : charger uniquement Regular (400) — utilise rarement
- Format :
woff2uniquement font-display: swapobligatoire- Preload les 2 polices principales dans
<head> - Budget total polices : < 80 Ko
Code splitting :
// Chaque page est un chunk separe
const Library = lazy(() => import('./pages/Library'));
const Discover = lazy(() => import('./pages/Discover'));
const Profile = lazy(() => import('./pages/Profile'));
const Settings = lazy(() => import('./pages/Settings'));
// Le player est dans le bundle initial (toujours visible)
Images :
- Format : WebP (fallback JPEG), AVIF si support
- Lazy loading :
loading="lazy"sur toutes les images hors viewport - Responsive :
srcsetavec 3 tailles (320w, 640w, 1280w) - Pochettes d'album : max 300x300 en liste, 600x600 en page artiste
- Avatars : max 128x128
Mode eco :
[data-eco="true"] {
/* Desactive les textures et animations */
body::after { display: none; } /* texture washi */
* { animation-duration: 0ms !important; }
#app { filter: none; } /* circadien + patine */
}
Prefetch intelligent :
- Prefetch la page la plus probable (ex: clic sur un artiste -> prefetch sa page)
- Ne PAS prefetch toutes les pages
- Utiliser
<link rel="prefetch">et nonpreload(priorite basse)
8. Iconographie — gestes calligraphiques
8.1 Principes
Les icones SUMI v3 sont des gestes dessines — comme des caracteres calligraphiques simplifies. Elles ne sont pas des SVG generes par ordinateur. L'irregularite du trace est volontaire et preservee.
8.2 Contraintes techniques
| Contrainte | Valeur |
|---|---|
| Format | SVG inline (pas de sprite, pas de font icon) |
| Taille de reference | 24x24 viewBox |
| Epaisseur de trait | 2px, variable (plus epaisse au debut du geste, plus fine a la fin) |
| Style | Stroke only (pas de fill), sauf exceptions |
| Couleur | currentColor (herite du texte parent) |
| Nombre max d'icones | 30 (pas plus — chaque icone est dessinee specifiquement) |
| Lignes | Irreguliere comme un vrai trait de pinceau (pas de Bezier parfaites) |
| Coins | Mix organique (pas uniformement arrondis) |
8.3 Correspondances icone -> metaphore
| Fonction | Metaphore | Description du geste |
|---|---|---|
| Play | Trait de pinceau diagonal | Un triangle forme par un seul trait rapide |
| Pause | Deux colonnes d'encre | Deux traits verticaux paralleles |
| Recherche | Enso (cercle zen) | Un cercle ouvert — non ferme, comme un enso |
| Profil | Capsule de micro | Forme ovale avec un trait de base |
| Chat / Messages | Onde sonore | Trois arcs concentriques |
| Upload | Trait ascendant | Un trait qui monte avec une goutte au sommet |
| Settings | Ensui (roue) | Cercle avec trait directionnel |
| Home | Montagne | Triangle inverse — symbole de montagne minimaliste |
| Notifications | Point d'encre | Cercle avec une onde de diffusion |
| Like / Favori | Trait croise | Deux traits qui se rencontrent en pointe |
| Volume | Ondes | Arc de cercle avec des ondes de diffusion |
| Menu | Trois traits | Trois traits horizontaux d'epaisseur variable |
| Close | Croix de pinceau | Deux traits croises d'un seul geste |
| Download | Trait descendant | Un trait qui descend vers une ligne de base |
| Share | Traces | Trois points relies par des traits de pinceau |
| Filter | Entonnoir de traits | Deux traits convergents vers le bas |
| Expand | Triangle ouvert | Symbole d'amplification — triangle de pinceau |
8.4 Production
Dessiner les icones a la main (papier ou tablette), puis vectoriser dans Inkscape. L'irregularite du trace est volontaire et ne doit pas etre "corrigee" par l'outil de vectorisation.
Les icones sont stockees comme composants React SVG individuels dans
apps/web/src/components/icons/.
9. Le Player — suzuri (pierre a encre)
9.1 Principe
Le player est la pierre a encre (suzuri) de l'interface — l'objet le plus lourd, le plus present, le plus ancre. C'est la surface la plus "encree", la plus opaque, la plus dense. Ce n'est pas une barre generique en bas de page. C'est le coeur de l'experience.
9.2 Contraintes de design
| Contrainte | Valeur |
|---|---|
| Position | Bas de page, pleine largeur, toujours visible |
| Hauteur collapsed | 80px (--sumi-player-height) |
| Hauteur expanded | Jusqu'a 60vh (vue immersive — le lavis s'intensifie) |
| Waveform | Traits de pinceau horizontaux — le son EST l'encre |
| Controle volume | Trait vertical avec un point (goutte de pinceau) — pas un slider classique |
| Patine | Le suzuri est l'element qui se patine le plus vite et le plus visiblement |
| Adaptabilite | Le player prend les couleurs de l'artiste en cours d'ecoute |
| Animation au repos | Micro-oscillation du VU-metre (respiration) — CSS uniquement |
| Transition expand/collapse | --sumi-motion-vague + --sumi-ease-vague |
| Touch | Swipe up pour expand, swipe down pour collapse |
9.3 Waveform
La waveform est pre-calculee cote serveur (tableau de 200 valeurs d'amplitude par morceau). Les barres ne sont pas rectangulaires — elles ont des bords arrondis et une opacite variable, comme des traits d'encre poses cote a cote.
.waveform-bar {
width: 2px;
margin: 0 1px;
background: var(--sumi-accent);
border-radius: 50%; /* Bords arrondis comme un trait de pinceau */
transition: height var(--sumi-motion-goutte) var(--sumi-ease-goutte);
}
.waveform-bar.played {
opacity: 1; /* Encre dense — la partie jouee */
}
.waveform-bar.unplayed {
opacity: 0.25; /* Lavis dilue — la partie a jouer */
}
Pas de canvas WebGL, pas de Three.js, pas de librairie audio-visualizer. 200 divs CSS = leger et suffisant.
9.4 Controle de volume
Le volume est un trait vertical avec un point — comme un trait de pinceau interrompu par une goutte. Implementation :
- SVG : un trait vertical (
<line>) avec un cercle (<circle>) positionne dessus - Evenements pointer (pointerdown/move/up) pour le drag vertical
- Le composant entier < 50 lignes de code
- Fallback accessibilite :
<input type="range">pour screen readers (visuellement cache)
9.5 Mode expanded
Quand le player est en mode expanded (vue immersive) :
- Le papier de fond s'assombrit (le lavis s'intensifie)
- L'encre de la waveform s'elargit et prend plus de place
- Le cyan s'illumine — il devient plus vif, comme un pigment concentre
- L'espace negatif augmente — le vide (ma) entoure les elements
10. Mode eco
10.1 Declenchement
Le mode eco est active :
- Manuellement par l'utilisateur (toggle dans les settings)
- Automatiquement si
prefers-reduced-motion: reduce - Automatiquement si
Save-Data: on(header HTTP) - Automatiquement si la batterie < 20% (
navigator.getBattery()si disponible)
10.2 Ce que le mode eco desactive
| Fonctionnalite | Etat en mode eco |
|---|---|
| Texture washi | Desactivee |
| Circadien | Desactive (palette statique) |
| Patine | Desactivee (palette standard) |
| Animations | Reduites a 0ms |
| Waveform player | Barre de progression simple |
| Controle volume | Slider lineaire classique |
| Prefetch | Desactive |
| Images pochettes | Taille reduite (160x160 max) |
| Diffusions d'encre (box-shadow) | Desactivees |
| Backdrop-filter (blur) | Desactive |
Le mode eco ne change PAS :
- La palette de couleurs de base (cyan, encre, papier)
- La typographie
- La disposition
- Les fonctionnalites
L'app reste complete et utilisable. Elle perd juste sa texture — comme un lavis sur papier lisse au lieu de papier washi.
11. Themes artistes
11.1 Concept
Quand l'utilisateur navigue sur le profil d'un artiste ou ecoute un de ses morceaux, l'interface s'adapte aux couleurs choisies par l'artiste.
11.2 Variables d'artiste
Chaque artiste peut definir :
/* Stocke dans le profil artiste, charge avec les donnees du profil */
--artist-hue: 220; /* Teinte principale (0-360) */
--artist-saturation: 0.6; /* Saturation (0-1) */
--artist-lightness: 0.5; /* Luminosite (0-1) */
11.3 Application
Quand un profil artiste est affiche ou qu'un morceau est en cours de lecture :
/* Le player et la page profil utilisent la couleur artiste */
.artist-context {
--sumi-accent: hsl(
var(--artist-hue),
calc(var(--artist-saturation) * 100%),
calc(var(--artist-lightness) * 100%)
);
}
Les autres elements (navigation, sidebar) restent en cyan standard. Seuls le player (suzuri) et la zone de contenu s'adaptent.
11.4 Contraintes
- La couleur artiste ne doit jamais nuire a la lisibilite (contraste WCAG AA)
- Si le contraste est insuffisant, fallback sur le cyan standard
- L'artiste ne controle QUE la teinte — pas les fonds, pas la typo, pas le layout
- En mode high contrast, les couleurs artistes sont ignorees
12. Regles inviolables de SUMI v3
-
Cyan partout. L'accent est toujours cyan (#0098B5), sauf dans un contexte artiste. Pas d'autre couleur primaire. Le cyan est la goutte de pigment dans l'eau noire — rare et precieux.
-
Texture washi toujours. Sauf en mode eco. Opacite max 0.08. Le fond n'est jamais une surface lisse.
-
2 animations max. Jamais 3 elements qui bougent en meme temps.
-
Pas de blanc pur (#FFFFFF). Le blanc le plus clair est #F2EDE6 (papier washi). Le blanc pur n'existe pas dans un lavis — le papier a toujours une teinte.
-
Pas de noir pur (#000000). Le noir le plus profond est #0D0D0F (noir d'encre). Le noir pur est plat et sans vie — l'encre sumi a toujours de la profondeur.
-
Pas d'icone generique. Chaque icone est un geste calligraphique dessine specifiquement. Si une icone n'existe pas dans le set, elle n'est pas utilisee.
-
Le suzuri (player) est sacre. C'est l'element le plus soigne, le plus teste, le plus patine. Ne jamais le traiter comme un composant secondaire.
-
Rien n'est lineaire. Pas de
transition: all 0.3s linear. Toute animation a un easing organique — le mouvement de l'eau, pas d'un mecanisme. -
Le mode eco doit etre beau aussi. L'app sans texture/animation/circadien doit rester coherente et agreable. C'est le lavis sur papier lisse — sobre mais pas pauvre.
-
Accessible d'abord. Chaque decision esthetique doit passer le test WCAG AA (4.5:1 pour le texte, 3:1 pour les grands elements). Si l'esthetique et l'accessibilite sont en conflit, l'accessibilite gagne.
-
Pas de bordures nettes. Jamais de
border: 1px solid. Les bords sont des diffusions d'encre —box-shadowdiffus, toujours. -
Le vide est un choix. L'espace negatif (ma) n'est pas du padding vide. C'est le papier qui respire entre les traits.
13. Checklist d'implementation
| Tache | Priorite | Complexite | Impact |
|---|---|---|---|
| Remplacer la palette indigo par cyan (#0098B5) | 1 | Faible | Fondamental |
| Ajouter la texture washi (washi.png + pseudo-element) | 1 | Faible | Texture immediate |
| Adapter les fonds (papier washi jour/nuit) | 1 | Faible | Ambiance |
| Remplacer les border par des box-shadow diffus | 1 | Moyenne | Langage visuel |
| Implementer les couches d'encre (backdrop-filter + opacites) | 1 | Moyenne | Profondeur |
| Renommer les tokens de mouvement (goutte/trait/lavis/vague/maree) | 1 | Faible | Coherence |
| Implementer les couleurs fonctionnelles pastel diffuse | 1 | Faible | Etats |
| Dessiner les 10 icones prioritaires (gestes calligraphiques) | 2 | Moyenne | Identite |
| Implementer le circadien (ThemeProvider + inversion nuit) | 2 | Moyenne | Vie |
| Refaire le player en suzuri (waveform pinceau + volume trait) | 2 | Elevee | Coeur de l'UX |
| Implementer la patine (niveau 0-2 d'abord) | 3 | Moyenne | Singularite |
| Ajouter le mode eco | 3 | Faible | Ethique |
| Implementer les couleurs artistes | 3 | Moyenne | Personnalisation |
| Patine niveaux 3-4 (encre oxydee, rouleau ancien) | 4 | Moyenne | Profondeur |
| Micro-mouvements du papier de fond (ondulation CSS) | 4 | Faible | Vie subtile |
| Variantes de texture washi pour la patine (2-3 fichiers) | 4 | Faible | Richesse |