# Design System Gachanime

La marque associe un **G propriétaire à une étoile à quatre branches**. Le G est d'abord dessiné comme un contour complet, massif, arrondi et coupé en biais. L'étoile verticale se superpose ensuite à droite. Un masque vectoriel transparent détoure sa jonction, sans contour blanc imposé. Le wordmark utilise ce même G seul ; son premier A reçoit exactement le même tracé d'étoile, simplement réduit. Ses lettres sont des contours construits et éditables, pas une simple composition de caractères Montserrat. `GACH` est blanc sur fond sombre, noir sur fond clair ; `ANIME` reste rose.

Le logo horizontal ajoute le petit `ガチャ` vertical, sans signature sous le wordmark. `COLLECTIONNE · DÉCOUVRE · PARTAGE` sert séparément aux campagnes. Le logo secondaire place le symbole au-dessus du wordmark ; l'interface compacte utilise le wordmark seul. Les fiches Storybook « Modèle et tracés corrigés » et « G seul et étoile commune » montrent les références fournies, la reconstruction et ses couches séparées.

Le symbole G + étoile est toujours bicolore : les deux tracés doivent rester distincts. Sur fond rose, utiliser G noir et étoile blanche ; sur fond noir, G blanc et étoile rose, ou G rose et étoile blanche ; sur fond blanc, G noir et étoile rose. La variante G blanc sur rose utilise une étoile noire. Cette règle s'applique aux symboles transparents, logos secondaires et App Icons. Les wordmarks monochromes restent disponibles séparément.

Un seul master d'étoile, dans `scripts/build-brand.py`, alimente le symbole, le A, les étoiles seules et les motifs. Le module généré `src/design-system/brand-geometry.json` fournit ce même tracé à l'icône UI de marque. Ne pas lui appliquer de rotation ou d'étirement indépendant. Les masques et les transformations uniformes conservent le dessin d'origine.

Le portail statique `apps/asset-portal/` complète Storybook : charte publique, construction, catalogue filtrable, variantes, résolutions et pack ZIP. Son build reprend les fichiers réels, avec manifeste SHA-256, licences et documentation ; il vise `asset.gachanime.yazene.com`. Voir son README pour la construction et la publication indépendante du jeu.

La collection est le sujet principal. La navigation et les panneaux utilisent des surfaces neutres ; le rose signale une action, une sélection ou la marque. Les couleurs de rareté, de type de combat et de finition restent des informations de jeu distinctes.

## Sources et architecture

- `src/design-system/tokens.json` : source des couleurs, thèmes, typographie, espaces, rayons, ombres, durées, plans et breakpoints.
- `scripts/build-design-tokens.mjs` : génère `src/design-system/tokens.css` et `public/assets/brand/design-tokens.css`. Lancer `npm run brand:tokens` après une modification.
- `src/design-system/components.css` : contrats communs, états, focus, formulaires et overlays.
- `src/design-system/application.css` : composition de l'application, navigation, cartes et surfaces des pages.
- `src/design-system/ui.tsx` : primitives React natives ; `Icon.tsx` : une seule famille UI de pictogrammes à trait.
- `public/assets/brand/marketing.css` : vitrine FR/EN/ES avec les mêmes tokens.
- `/design-system` : showcase disponible avec `npm run dev`, exclu du build de production.

Les feuilles de fonctionnalités conservent leurs layouts et effets de jeu. Les anciennes feuilles globales `light-theme.css` et `contrast-theme.css` ont été retirées. Les alias historiques encore nécessaires pointent vers les tokens actuels : ils ne constituent pas une deuxième palette.

## Couleurs et thèmes

| Rôle de marque | Couleur |
| --- | --- |
| Rose officiel / brand-500 | #FF2D55 |
| Noir principal | #0B0B0F |
| Surface Dark | #1F1F24 |
| Texte secondaire Dark | #E5E7EB |
| Fond Light | #F8FAFC |
| Blanc | #FFFFFF |
| Rose doux / brand-200 | #FFD6DE |

L'échelle brand va de 50 à 950 ; les neutres de 0 à 950. Les deux thèmes exposent les mêmes rôles `--page`, `--surface`, `--surface-raised`, `--surface-soft`, `--text`, `--text-secondary`, `--muted`, `--border`, `--control-border`, `--primary`, `--primary-text`, `--accent`, `--focus`.

**Dark** : CTA rose officiel avec texte noir ; liens rose clair brand-400. **Light** : CTA brand-600 avec texte blanc ; liens brand-700. Le rose officiel ne sert pas aux petits liens sur blanc ni à un bouton contenant un petit texte blanc.

`success`, `warning`, `danger`, `info` possèdent chacun un texte et un fond dédiés. Un statut comporte aussi un libellé : la couleur seule ne transmet jamais son sens. Les couleurs de jeu sont conservées dans `shared/` ; sur une surface Light, un libellé neutre et une pastille permettent de garder leur identité sans sacrifier la lecture.

## Contraste et accessibilité

Les tests calculent la luminance relative sRGB et le ratio WCAG. Tous les textes principaux, secondaires et atténués sont vérifiés sur les quatre surfaces des deux thèmes ; les CTA et états sémantiques atteignent 4,5:1, les contours des contrôles et le focus 3:1. Voir les ratios et le périmètre effectivement inspecté dans [la validation](design-redesign-validation.md).

Les seuils suivent [WCAG 2.2, Contrast Minimum](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html). Les logos ne sont pas des contrôles UI. Les variantes blanches sur rose servent à la marque, jamais à contourner les seuils de lecture d'un bouton ou d'un formulaire.

- Placeholders et contrôles désactivés gardent une couleur opaque et lisible.
- Focus visible : contour de 3 px, décalé de 3 px.
- Cibles communes : minimum 44 px ; les filtres compacts existants restent espacés et nommés.
- Lien d'évitement vers le contenu principal.
- Dialogues natifs : focus contenu, Échap, retour au déclencheur. Les confirmations concentrent le focus initial sur Annuler ; une opération occupée ne peut pas être annulée.
- Onglets : Tab atteint la sélection, flèches/Home/End déplacent le focus, Entrée/Espace activent. Une navigation de focus ne déclenche pas de requête de collection.
- Combobox existante conservée : flèches, Home/End, recherche par frappe, Entrée, Échap, Tab.
- Les textes sur artwork utilisent un fond noir ou un voile sombre, avec blanc et gris clair indépendants du thème.

Un scan automatisé ne certifie pas à lui seul tous les états possibles. Les images, gradients et contenus dynamiques demandent aussi une inspection ; les limites observées sont consignées dans la validation.

## Typographie

Deux fichiers WOFF2 variables auto-hébergés couvrent le latin étendu FR/EN/ES. Montserrat 600–800 sert aux titres, navigation, CTA et chiffres ; Inter 400–700 au contenu et aux contrôles. `font-display: swap`. Licences OFL jointes dans `public/fonts/`.

| Style | Token | Taille |
| --- | --- | --- |
| Display | --type-display | 40–64 px, fluide |
| H1 | --type-h1 | 30–44 px, fluide |
| H2 | --type-h2 | 24 px |
| H3 | --type-h3 | 20 px |
| H4 / Subtitle | --type-h4 / --type-subtitle | 18 px |
| Body Large | --type-body-large | 18 px |
| Body | --type-body | 16 px |
| Body Small / Label | --type-body-small / --type-label | 14 px |
| Caption / Overline | --type-caption / --type-overline | 12 px |

Les titres utilisent 700, le branding et Display 800 ; navigation et labels 600. Une donnée essentielle ne doit pas être réduite à une décoration minuscule. Les dimensions propres aux cartes et animations restent adaptées à leur canvas.

## Géométrie, profondeur et motion

Espacement : 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80 px (`--space-*`). Rayons : sm 4, md 8, lg 12, xl 16 px, full pour portraits/pastilles. Card standard : 24 px de padding, bordure 1 px, rayon lg, ombre sm. Une sélection associe contour et libellé ; hover ne déplace pas toute la composition.

La profondeur vient des surfaces et bordures. Les ombres sont noires et discrètes, sans halo rose généralisé. `z` : base 0, sticky 20, dropdown 40, overlay 80, modal 100, toast 120 ; les dialogues natifs utilisent le top layer du navigateur.

Transitions UI : fast 120, normal 180, slow 250 ms. `prefers-reduced-motion` coupe les mouvements continus et raccourcit transitions/animations. Les timings de combat et de révélation suivent leurs machines d'état existantes ; leurs préférences de mouvement réduit restent actives.

Breakpoints : mobile 540, tablette 800, desktop 1200, large 1600 px. Les media queries ne peuvent pas employer directement des variables CSS ; leurs valeurs correspondent aux tokens. La navigation se compacte en rail puis barre mobile ; tables et longs contenus défilent dans leur propre région, pas dans tout le document.

## Composants et utilisation

| Besoin | Fondation utilisée |
| --- | --- |
| Button / IconButton | `Button`, variantes primary/secondary/outline/ghost/danger, loading, disabled ; `IconButton` exige un libellé |
| Formulaires | `Field`, `Input`, `Textarea`, `Select`, `Combobox`, `Checkbox`, `Radio`, `Switch`, `Slider` |
| Onglets / filtres | `Tabs`, `Chip`, boutons `aria-pressed` existants |
| Surfaces / données | `Card`, `StatCard`, `Table`, `Pagination`, `Badge`, `Avatar` (PlayerAvatar) |
| Overlays | `Modal`, `Drawer`, `ConfirmDialog`, `Menu`/`Dropdown`, `Popover`, `Tooltip` |
| États | `Alert`, `Toast`, `Progress`, `Skeleton`, `Loader`, `EmptyState` ; SaleNotice conserve son cycle de vie gameplay |
| Navigation | App Sidebar/Navigation et `Breadcrumb`, utilisant la même famille Icon |

`Menu` et `Popover` sont des disclosures natifs, avec des boutons/liens normaux. Ils ne prétendent pas être des menus ARIA de bureau. `Tooltip` ne doit jamais contenir une action essentielle. Les tableaux nécessitent caption, scope sur les headers, libellés de tri, `aria-sort` quand ils sont triables, état vide et pagination adaptés à la fonctionnalité.

Un formulaire passe explicitement `type="submit"` à son bouton d'envoi. Les autres boutons ont `type="button"` par défaut. `Field` transmet id, aria-describedby, aria-invalid et required au contrôle. Ne pas ajouter une seconde bibliothèque pour un composant déjà couvert.

## Identité et assets

Voir [le catalogue des assets](../public/assets/brand/README.md) pour les variantes, résolutions, espaces de protection et régénération. Les maîtres sont de vrais SVG à chemins, sans image incorporée. Les signatures sont `MORE THAN CARDS` et `COLLECTIONNE · DÉCOUVRE · PARTAGE`. Les cartes abstraites, étoiles, pétales et lignes suffisent à la marque permanente ; aucun personnage de licence externe n'entre dans les logos ou bannières permanentes.

Le japonais `ガチャ` reste optionnel et secondaire. Les trois glyphes Noto Sans JP du logo complet sont vectorisés ; aucune police japonaise n'est chargée dans l'UI. Toute future utilisation doit conserver un logo compréhensible sans ce texte.

Les marques partenaires Yazene et Discord restent identifiables comme marques externes. Elles ne deviennent pas la famille de pictogrammes fonctionnels Gachanime.

## Maintenance

`npm run lint` vérifie la fraîcheur des tokens, l'intégrité vectorielle et l'absence de l'ancienne palette dans l'UI. `npm run check` couvre lint, typage, tests et build ; `npm run smoke` vérifie le build réellement servi et ses assets. La revue navigateur optionnelle est documentée dans la validation. Les tests de contraste portent sur des contrats mesurables, sans snapshots fragiles de pixels exacts.

## Storybook

Storybook 10.6.1 est l'explorateur de composants demandé pour la maintenance de la charte. `npm run storybook` démarre sur http://127.0.0.1:6006 ; `npm run build-storybook` produit `storybook-static/`, ignoré par Git et séparé du build du jeu.

Les stories de `src/design-system/stories/` importent les véritables composants, tokens, logos et fontes. `.storybook/preview.tsx` applique le thème de la barre d'outils ; les boutons Primary/Secondary/Outline/Ghost/Danger, loading/disabled, validations, contrôles, menus, tables, overlays et états sont consultables. Les modales, combobox, onglets, pagination et chips sont interactifs. Les données de démonstration restent locales aux stories : aucun accès gameplay, SSO ou paiement.

Fondations : identité, variantes de logos, palette, typographie, icônes. Le panneau Docs explique les contrats, Controls expose les props, Viewport propose mobile/tablette/desktop, Accessibility utilise axe sur les règles WCAG AA. Les contrôles automatisés complètent l'inspection des gradients et images.

Dépendances directes de développement : `storybook`, `@storybook/react-vite`, `@storybook/addon-docs`, `@storybook/addon-a11y`, toutes fixées à 10.6.1. React 19 et Vite 8 sont pris en charge par leurs peerDependencies. Aucun package UI runtime supplémentaire. Configuration Vite indépendante des plugins de release/SEO du jeu ; télémétrie désactivée. Le patch compatible `source-map-js` 1.2.2 corrige l'avis npm détecté pendant l'installation, sans ajouter de dépendance directe.
