# PROTOCOLE — design system trans-former.fr La « matrice » : les règles que tout site de la constellation applique. Un build n'est pas fini tant que la Definition-of-Done en bas n'est pas cochée. ## 1. Mobile-first — règle de base - Les styles de base ciblent **360px**. On monte ensuite avec des media queries **`min-width` uniquement** (jamais `max-width` pour la structure ; une exception encadrée : l'état hamburger de la Nav). - Typographie **fluide** en `clamp()` — l'échelle `--fs-*` est calibrée entre 360px et 1280px, ne pas la redéfinir par breakpoint. - Cibles tactiles **≥ 44px** (boutons, liens de nav, toggles). Sur `pointer: coarse`, aucune taille ne descend en dessous. ### Breakpoints — constantes Les variables CSS ne fonctionnent pas dans `@media` : ces valeurs sont des **constantes de la constellation**, à utiliser telles quelles partout. | Nom | px | rem | Usage type | |-----|----|-----|------------| | base | 360 | — | styles par défaut (pas de media query) | | sm | 480 | 30rem | ajustements petits écrans larges | | md | 768 | 48rem | passage nav inline, grilles 2-3 col | | lg | 1024 | 64rem | layouts larges | | xl | 1280 | 80rem | plafond de l'échelle fluide | Écrire les media queries en **rem** (`@media (min-width: 48rem)`). ## 2. Motion charter - **Motion piloté-utilisateur** : toute animation répond à une action (scroll, hover, focus, clic). **Jamais d'auto-play** — pas de carrousel automatique, pas d'animation en boucle — sans pause au survol/focus **et** contrôles visibles. - `@media (prefers-reduced-motion: reduce)` **coupe tout mouvement non essentiel**. Le kill-switch global est dans `reset.css` ; tout JS d'animation doit aussi tester `matchMedia("(prefers-reduced-motion: reduce)")` (cf. `js/reveal.js`). - **Budget reveal** : fade + translate court (≤ 12px), durées `--dur-base`/`--dur-slow` max, easing `--ease-out`. Pas de zoom, pas de rotation, pas de parallaxe décorative. - Le JS est **progressif** : sans JS, rien n'est masqué, rien n'est cassé (garde `html[data-js]`). ## 3. Lois design (anti-patterns) — appliquées sans exception - ❌ `border-left`/`border-right` > 1px colorée comme accent (card, callout) - ❌ gradient text (`background-clip: text`) - ❌ glassmorphisme décoratif par défaut - ❌ template hero-metric (grand chiffre + petit label + gradient accent) - ❌ grilles de cards identiques icon+heading+text - ❌ modal comme premier réflexe UX - ❌ em-dashes (`—` / `--`) dans les textes UI - ❌ Inter par défaut sans raison - ❌ gradients violets sans justification - ❌ dark glow décoratif ## 4. Tokens — conventions de nommage - Nommage par **rôle**, jamais par couleur brute : `--primary`, pas `--green`. Un thème peut changer toute la palette sans toucher un composant. - Préfixes d'échelle : `--fs-*` (font-size), `--lh-*` (line-height), `--fw-*` (weight), `--space-*`, `--radius-*`, `--shadow-*`, `--dur-*`, `--ease-*`, `--z-*`. - Paires de contraste : `--primary`/`--on-primary`, `--accent`/`--on-accent`. Toujours utiliser le `on-*` correspondant comme couleur de texte sur ces fonds. - **Layers** : `tokens.css` vit dans `@layer tf-tokens`, `reset.css` dans `@layer tf-reset`. Les thèmes et le CSS des sites restent **non-layerés** → ils gagnent toujours sur la fondation, quel que soit l'ordre de chargement. Ne jamais mettre un thème dans un layer. (Exception voulue : le kill-switch reduced-motion du reset est en `!important` layeré, il bat donc tout le monde.) - Le schéma (noms + échelles) est **universel** et gelé : en ajouter demande une mise à jour ici + dans `tokens.css` + dans les thèmes. En retirer/renommer = breaking change pour tous les sites. - **Tailwind 4** (site racine) : les tokens sont mappés via `tailwind.css` (`@theme inline`). Les namespaces en collision de nom (`--font-*`, `--radius-*`, `--shadow-*`, `--ease-*`) s'utilisent en syntaxe var arbitraire : `rounded-(--radius-md)`, `shadow-(--shadow-md)`, `ease-(--ease-out)`, `font-(family-name:--font-heading)`. ## 5. Ajouter un thème (nouveau site) 1. `cp theme/base.css theme/mon-site.css` 2. Remplacer palette claire, palette sombre (bloc `[data-theme="dark"]` **et** duplication `@media (prefers-color-scheme: dark)` avec le garde `:not([data-theme="light"])`), et les deux stacks de polices. 3. Ne toucher à **rien d'autre** : pas d'échelles, pas de spacing, pas de motion dans un thème. 4. Vérifier les contrastes **AA** (4.5:1 texte courant, 3:1 grands titres/UI) dans les deux modes — y compris `--on-primary` sur `--primary` et `--on-accent` sur `--accent`. 5. Charger les `@font-face` côté site (self-host / fontsource) ; le thème ne définit que les stacks. 6. L'ajouter à la page démo (`src/pages/demo/mon-site.astro`, 4 lignes) et valider le kitchen sink. Clair/sombre : mode clair par défaut + sombre via préférence système, le toggle explicite (`data-theme`) **gagne toujours dans les deux sens**. Un site peut être sombre par défaut (cf. `theme/aep.css` : `:root` sombre, variante claire sur `[data-theme="light"]` seulement). ## 6. Accessibilité — socle - Contraste **AA** partout, dans les deux modes. - **Focus visible** partout : `:focus-visible` global dans `reset.css`, ne jamais le supprimer sans remplacement équivalent. - Navigation **clavier** complète : hamburger avec `aria-expanded`/`aria-controls`, fermeture Échap, focus trap panneau ouvert, skip-link (`BaseLayout`). - `lang` défini sur `` (prop de `BaseLayout`), `aria-current="page"` sur le lien actif, `alt` sur toute image porteuse de sens. ## 7. Definition-of-Done — checklist de fin de build Avant de déclarer un site « fini » : - [ ] Testé à **360, 768, 1280** px — aucun débordement horizontal, hiérarchie lisible aux trois tailles. - [ ] Testé en **clair ET sombre** (préférence système + toggle) — contrastes AA dans les deux. - [ ] Testé avec **prefers-reduced-motion: reduce** — plus aucun mouvement non essentiel. - [ ] Testé **sans JS** — contenu et navigation accessibles (liens visibles, rien de masqué). - [ ] Navigation **clavier seul** : tout est atteignable, focus visible, hamburger Échap + trap OK. - [ ] Cibles tactiles ≥ 44px sur mobile. - [ ] Zéro valeur en dur qui duplique un token (couleur hex, taille de police, spacing) dans le CSS du site. - [ ] Aucune violation des lois design (§3). - [ ] Le site n'importe qu'**un seul** `theme/*.css` ; en changer suffit à changer le look. - [ ] Lighthouse a11y ≥ 95, aucune erreur console.