diff --git a/docs/adr/0010-identite-visuelle.md b/docs/adr/0010-identite-visuelle.md
index 62119a9..4dc67b6 100644
--- a/docs/adr/0010-identite-visuelle.md
+++ b/docs/adr/0010-identite-visuelle.md
@@ -29,7 +29,7 @@ couleur, en monochrome et en taille réelle d'icône (48 et 24 px).
noyer et brique, comme les flèches d'un plateau. En monochrome, les quatre
flèches prennent la couleur du texte.
- **Icône d'application** : symbole sur fond ivoire `#F3EAD8`.
-- **Police** : Alegreya Sans (SIL Open Font License 1.1), pour le logotype et,
+- **Police** : Alegreya Sans (SIL Open Font License 1.1), pour le logotype et
pour l'interface. Pierre a validé cette dépendance, ainsi que fontTools
(MIT), outil de développement qui sert à régénérer le logotype, le
2026-11-03.
diff --git a/docs/identite/README.md b/docs/identite/README.md
index af8d616..06f6fe3 100644
--- a/docs/identite/README.md
+++ b/docs/identite/README.md
@@ -46,3 +46,8 @@ python3 -I docs/identite/generer-logo.py build/police/AlegreyaSans-Bold.ttf docs
Les PNG sont des rendus des SVG par Chrome sans interface
(`google-chrome --headless --screenshot`), à la taille indiquée dans leur nom.
+
+## Charte graphique
+
+La charte complète (couleurs des deux thèmes, typographie, composants) est dans
+`charte/`, avec les liens vers le design system et les maquettes d'écrans.
diff --git a/docs/identite/charte/README.md b/docs/identite/charte/README.md
new file mode 100644
index 0000000..e3801f1
--- /dev/null
+++ b/docs/identite/charte/README.md
@@ -0,0 +1,41 @@
+# Charte graphique d'Ustagammon
+
+Copie de travail du design system, pour l'appliquer à la PWA sans dépendre
+d'un accès à claude.ai. La référence vivante, avec aperçus dans les deux thèmes :
+
+- Design system : https://claude.ai/artifact/K2Z7MPE58XXJzv19n5r11M
+- Maquettes des écrans (accueil, plateau, leçon, fin de partie, thème sombre) :
+ https://claude.ai/artifact/CQw6vbDpi6XQqVWQa4sANe
+
+Décisions : ADR 0010. Fichiers du logo et des icônes : `../logo/`.
+
+## Fichiers
+
+| Fichier | Contenu |
+| --- | --- |
+| `guide-de-marque.md` | Règles d'usage : ton, couleurs, typographie, formes, mouvement, icônes, composants |
+| `tokens.json` | Toutes les valeurs, thèmes clair et sombre, avec une note d'usage par couleur |
+| `bundle.css` | Styles des composants ; mêmes noms de classes que `web/app.css` |
+| `board.js` | Dessin de référence du plateau (repère 640 × 520), pour comparaison |
+
+## Appliquer la charte à `web/`
+
+1. **Couleurs** : les variables du plateau de `web/app.css` (`--frame`, `--bed`,
+ `--point-a`, `--checker-player`…) ont les mêmes noms dans `tokens.json` ;
+ reprendre leurs valeurs, thème clair dans `:root`, thème sombre dans le bloc
+ `prefers-color-scheme: dark`. Remplacer l'accent vert provisoire par la
+ brique (`--accent`, `--highlight`, `--target`) et ajouter les couleurs
+ nouvelles (`surface`, `accent-soft`, `verdict-*`, `focus`, `last-move` en laiton).
+2. **Police** : embarquer Alegreya Sans (Regular, Italic, Medium, Bold,
+ ExtraBold) dans `web/`, avec sa licence OFL, en `@font-face`, et l'ajouter
+ au cache du service worker (hors ligne).
+3. **Composants** : reprendre de `bundle.css` les boutons ronds
+ (`radius-pill`), le filet intérieur des pions, l'anneau de focus et la zone
+ de consigne.
+4. **Icônes et logo** : remplacer `web/icons/` par les fichiers de
+ `../logo/` (icônes any et maskable, favicon), mettre le logo horizontal
+ dans la barre haute, et la couleur `theme-color` du manifeste à `#4A2E1F`.
+
+Les contrastes de tous les textes ont été vérifiés par calcul (4,5:1 au moins
+dans les deux thèmes) ; les marques du plateau, à 3:1 contre au moins un de
+leurs voisins.
diff --git a/docs/identite/charte/board.js b/docs/identite/charte/board.js
new file mode 100644
index 0000000..cce1f44
--- /dev/null
+++ b/docs/identite/charte/board.js
@@ -0,0 +1,74 @@
+/* Dessin de référence du plateau Ustagammon, en SVG, avec les classes de bundle.css.
+ * Repère : 640 × 520, comme web/app.css (.board, aspect-ratio 640 / 520).
+ * Numérotation du point de vue du joueur : 1 à 12 en bas (de droite à gauche),
+ * 13 à 24 en haut (de gauche à droite). Le joueur a les pions ivoire. */
+window.UstaBoard = (function () {
+ var W = 640, H = 520, SIDE = 16, TB = 28, PW = 43, BAR = 40, PH = 190, R = 20;
+ var TRAY_X = 580, TRAY_W = 44;
+
+ function colX(col) { return SIDE + col * PW + (col >= 6 ? BAR : 0); }
+ function place(point) { // point 1..24 → {col, top}
+ return point <= 12 ? { col: 12 - point, top: false } : { col: point - 13, top: true };
+ }
+ function checker(cx, cy, side, extra) {
+ var c = side === "player" ? "player" : "computer";
+ return '' +
+ '';
+ }
+ function die(x, y, n, side) {
+ var s = 36, p = { 1: [[.5, .5]], 2: [[.27, .27], [.73, .73]], 3: [[.27, .27], [.5, .5], [.73, .73]],
+ 4: [[.27, .27], [.73, .27], [.27, .73], [.73, .73]], 5: [[.27, .27], [.73, .27], [.5, .5], [.27, .73], [.73, .73]],
+ 6: [[.27, .25], [.73, .25], [.27, .5], [.73, .5], [.27, .75], [.73, .75]] }[n];
+ var out = '';
+ p.forEach(function (q) { out += ''; });
+ return out;
+ }
+
+ /* state = { checkers: {point: [side, n]}, selected: point, movable: [points],
+ * targets: [points], lastMove: [points], dice: [a, b], diceSide, cube } */
+ function svg(state) {
+ var o = '';
+ }
+
+ var OPENING = { 24: ["player", 2], 13: ["player", 5], 8: ["player", 3], 6: ["player", 5],
+ 1: ["computer", 2], 12: ["computer", 5], 17: ["computer", 3], 19: ["computer", 5] };
+ return { svg: svg, OPENING: OPENING };
+})();
diff --git a/docs/identite/charte/bundle.css b/docs/identite/charte/bundle.css
new file mode 100644
index 0000000..f30bfdf
--- /dev/null
+++ b/docs/identite/charte/bundle.css
@@ -0,0 +1,165 @@
+/* Ustagammon — styles des composants.
+ * Toutes les valeurs viennent de tokens.json (variables CSS du même nom).
+ * Les noms de classes reprennent ceux de web/app.css : ce fichier peut être
+ * recopié dans l'application presque tel quel. */
+
+body {
+ margin: 0;
+ font-family: var(--font-sans);
+ font-size: 17px;
+ line-height: 25px;
+ color: var(--text);
+ background: var(--background);
+}
+
+a { color: var(--accent); text-underline-offset: 3px; }
+
+:focus-visible {
+ outline: 3px solid var(--focus);
+ outline-offset: 2px;
+}
+
+/* ------------------------------------------------------------ Barre haute */
+
+.topbar {
+ display: flex;
+ gap: var(--space-2);
+ align-items: center;
+ padding-block: var(--space-2);
+}
+.topbar .brand { flex: 1; display: flex; align-items: center; min-width: 0; }
+.topbar .brand img { height: 32px; width: auto; display: block; }
+.topbar h1 { flex: 1; margin: 0; font-size: 20px; line-height: 26px; font-weight: 700; }
+
+/* ---------------------------------------------------------------- Boutons */
+
+button, .button {
+ min-height: var(--button-height);
+ padding: 0 20px;
+ font: inherit;
+ font-weight: 700;
+ color: var(--on-accent);
+ background: var(--accent);
+ border: 2px solid var(--accent);
+ border-radius: var(--radius-pill);
+ cursor: pointer;
+}
+button.secondary, .button.secondary {
+ color: var(--text);
+ background: transparent;
+ border-color: var(--border-strong);
+}
+button.quiet, .button.quiet {
+ min-height: 44px;
+ padding: 0 12px;
+ color: var(--text);
+ background: transparent;
+ border-color: transparent;
+ font-weight: 500;
+}
+.topbar button { min-height: 44px; padding: 0 14px; font-size: 15px; }
+button:disabled { opacity: 0.45; cursor: default; }
+
+.actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
+.actions button { flex: 1; }
+
+/* ------------------------------------------------------- Zone de consigne */
+
+.pips { margin: var(--space-1) 0 0; font-size: 15px; line-height: 20px; color: var(--muted); text-align: center; font-variant-numeric: tabular-nums; }
+.info, .prompt { min-height: 25px; margin: 6px 0; }
+.info { color: var(--muted); }
+.prompt { font-weight: 700; }
+.prompt.thinking::after { content: ""; animation: thinking 1.2s steps(4, end) infinite; }
+@keyframes thinking { 0% { content: ""; } 25% { content: "."; } 50% { content: ".."; } 75% { content: "..."; } }
+@media (prefers-reduced-motion: reduce) { .prompt.thinking::after { animation: none; content: "…"; } }
+
+/* ---------------------------------------------------------------- Plateau */
+
+.board { display: block; width: 100%; height: auto; user-select: none; -webkit-tap-highlight-color: transparent; }
+.board-frame { fill: var(--frame); }
+.board-bed { fill: var(--bed); }
+.board-bar { fill: var(--bar); }
+.board-tray { fill: var(--tray); }
+.point-a { fill: var(--point-a); }
+.point-b { fill: var(--point-b); }
+.point-number { fill: var(--point-number); font-size: 13px; font-weight: 500; text-anchor: middle; font-family: var(--font-sans); }
+.checker { stroke-width: 2; }
+.checker-player { fill: var(--checker-player); stroke: var(--checker-player-edge); }
+.checker-computer { fill: var(--checker-computer); stroke: var(--checker-computer-edge); }
+.checker-ring { fill: none; stroke-width: 1.5; }
+.checker-player + .checker-ring, .ring-player { stroke: var(--checker-player-edge); }
+.ring-computer { stroke: var(--checker-computer-edge); }
+.checker.movable { stroke: var(--highlight); stroke-width: 3; }
+.checker.selected { stroke: var(--highlight); stroke-width: 6; }
+.checker-count { font-size: 18px; font-weight: 700; text-anchor: middle; font-family: var(--font-sans); }
+.count-player { fill: var(--count-player); }
+.count-computer { fill: var(--count-computer); }
+.target-zone { fill: var(--target); }
+.last-move { fill: var(--last-move); }
+.die-player { fill: var(--die-player); stroke: var(--checker-player-edge); stroke-width: 1.5; }
+.die-computer { fill: var(--die-computer); stroke: var(--checker-computer-edge); stroke-width: 1.5; }
+.pip-player { fill: var(--pip-player); }
+.pip-computer { fill: var(--pip-computer); }
+.cube-face { fill: var(--cube); stroke: var(--checker-player-edge); stroke-width: 2; }
+.cube-value { fill: var(--cube-text); font-size: 17px; font-weight: 800; text-anchor: middle; font-family: var(--font-sans); }
+
+/* ------------------------------------------------------------------ Cartes */
+
+.card {
+ background: var(--surface);
+ border: 1px solid var(--border);
+ border-radius: var(--radius-md);
+ box-shadow: var(--shadow-raised);
+ padding: var(--space-4);
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-2);
+}
+.overline { font-size: 13px; line-height: 16px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
+
+/* --------------------------------------------------- Appréciation d'un coup */
+
+.verdict {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--space-1);
+ font-weight: 700;
+ font-size: 15px;
+ line-height: 20px;
+}
+.verdict svg { width: 18px; height: 18px; flex: none; }
+.verdict-good { color: var(--verdict-good); }
+.verdict-doubtful { color: var(--verdict-doubtful); }
+.verdict-bad { color: var(--verdict-bad); }
+
+/* -------------------------------------------------------- Fiche de glossaire */
+
+.glossary-card h3 { margin: 0; font-size: 20px; line-height: 26px; font-weight: 700; }
+.glossary-card .en { color: var(--muted); font-size: 15px; line-height: 20px; font-style: italic; }
+.glossary-card p { margin: 0; }
+.glossary-card .see { font-size: 15px; line-height: 20px; color: var(--muted); }
+
+/* ------------------------------------------------ Demander à une IA (prompt) */
+
+.ask-ai { display: flex; flex-direction: column; gap: var(--space-2); }
+.ask-ai pre {
+ margin: 0;
+ max-height: 7.5em;
+ overflow: auto;
+ padding: var(--space-3);
+ background: var(--surface-sunken);
+ border-radius: var(--radius-md);
+ font: 15px/20px var(--font-sans);
+ white-space: pre-wrap;
+ color: var(--text);
+}
+.ask-ai .done { color: var(--verdict-good); font-weight: 700; font-size: 15px; }
+
+/* ---------------------------------------------------------- Carte de leçon */
+
+.lesson-card { flex-direction: row; align-items: center; gap: var(--space-3); }
+.lesson-card .body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
+.lesson-card h3 { margin: 0; font-size: 17px; line-height: 25px; font-weight: 700; }
+.lesson-card .state { font-size: 15px; line-height: 20px; color: var(--muted); }
+.progress { height: 6px; border-radius: var(--radius-pill); background: var(--surface-sunken); overflow: hidden; }
+.progress > span { display: block; height: 100%; background: var(--accent); border-radius: inherit; }
diff --git a/docs/identite/charte/guide-de-marque.md b/docs/identite/charte/guide-de-marque.md
new file mode 100644
index 0000000..5b98500
--- /dev/null
+++ b/docs/identite/charte/guide-de-marque.md
@@ -0,0 +1,61 @@
+Ustagammon apprend le backgammon comme on l'apprend à une table de café : quelqu'un qui sait montre à quelqu'un qui découvre. L'interface est **chaleureuse, artisanale, claire et intemporelle**, discrètement turque par la matière (le bois, l'ivoire, la brique), jamais par le folklore. Elle doit donner envie à un débutant sans paraître naïve à un joueur confirmé : un maître bienveillant, pas un logiciel d'analyse, pas un casino.
+
+Ce système s'applique à la PWA (`web/`). Les noms des couleurs du plateau sont exactement ceux des variables de `web/app.css` ; `components/bundle.css` reprend ses noms de classes et peut y être recopié.
+
+## Contenus et ton
+
+- **Vouvoiement**, phrases courtes, verbes d'action. Le joueur est « vous », l'adversaire est « l'ordinateur » (ou le nom d'un joueur réel).
+- **Les mots du jeu**, toujours les mêmes, ceux du glossaire (`docs/glossaire/`) : flèche, pion, barre, videau, compte de points, sortir. Un terme technique s'explique la première fois qu'il apparaît, avec un lien vers sa fiche.
+- **Les boutons disent ce qu'ils font** : « Lancer les dés », « Annuler », « Doubler », « Prendre », « Passer », « Nouvelle partie ». Pas de « OK », pas de « Valider ». Les textes de l'app vivent dans `app/src/ui/texts.ts`.
+- **Le maître encourage, il ne juge pas.** « Bien joué : ce coup protège votre point 8. » plutôt que « Coup correct (−0,012) ». Les chiffres d'équité ne viennent que sur demande.
+- **Les erreurs disent quoi faire** : « Ce pion ne peut pas aller là : la flèche est tenue par deux pions adverses. »
+- **Ni émoji, ni point d'exclamation en série, ni majuscules de réclame.** Les capitales sont réservées au style `overline`.
+- Le nom s'écrit **Ustagammon**, en un mot, majuscule initiale.
+
+## Couleurs
+
+La palette, c'est le bois, les pions et le café, avec **un seul accent : le rouge brique** (`accent`).
+
+- Fond de page `background`, cartes et panneaux `surface`, zones en retrait `surface-sunken`.
+- Texte `text` ; texte secondaire `muted`, jamais pour une consigne.
+- `accent` est rare et a toujours un sens : le bouton principal de l'écran (un seul), un lien, le pion sélectionné (`highlight`), la case où il peut aller (`target`), le focus clavier (`focus`). Ce n'est jamais une couleur de décoration ni une couleur d'erreur.
+- `accent-soft` : fond léger pour signaler « c'est à vous », avec du texte `text` dessus.
+- Les appréciations de coups ont leurs propres couleurs, distinctes de la brique : `verdict-good` (vert), `verdict-doubtful` (ocre), `verdict-bad` (lie-de-vin). **Toujours avec le mot et l'icône**, jamais la couleur seule.
+- `brand-laiton` (via `last-move`) marque le dernier coup joué, comme les charnières en laiton d'un plateau de tavla. Rien d'autre.
+- Le plateau : cadre `frame` en noyer, fond `bed`, flèches alternées `point-a` (noyer clair) et `point-b` (chêne), barre `bar`, sorties `tray`. Le joueur a les pions ivoire (`checker-player`, l'apprenti), l'ordinateur les pions noyer (`checker-computer`, le maître), comme dans le logo.
+- **À éviter** : le vert feutre de casino, le noir et or, les dégradés, les néons.
+
+Les deux thèmes, clair et sombre, sont complets. Tous les textes atteignent 4,5:1 sur leurs fonds dans les deux thèmes ; les contours et marques porteuses de sens, 3:1.
+
+## Typographie
+
+Une seule famille, **Alegreya Sans** (licence SIL OFL, fichiers dans `fonts/`), sans empattement humaniste, chaleureuse et lisible en petit. À embarquer dans l'app : elle doit fonctionner hors ligne.
+
+- `display` (32px, 800) : un seul par écran, accueil et fin de partie.
+- `title` (24px) : titre d'écran ; `heading` (20px) : titre de section ou de carte.
+- `body` (17px) : tout le texte à lire, jamais plus petit. `body-strong` pour la consigne du moment et les boutons. `body-italic` pour la parole du maître ou un exemple.
+- `caption` (15px) : compte de points, légendes. `overline` (13px, capitales espacées) : étiquette au-dessus d'un titre, avec parcimonie.
+- Chiffres alignés (`font-variant-numeric: tabular-nums`) dès que des nombres se comparent (compte de points, scores).
+
+## Formes, espace et profondeur
+
+- **Boutons ronds comme des pions** : `radius-pill`, hauteur `button-height` (48px). Aucune cible tactile sous 44px.
+- Cartes et fiches : `radius-md`, contour `border`, ombre `shadow-raised` et rien de plus profond. Dés et videau : `radius-sm`.
+- Espacements : `space-1` à `space-8`. Gouttière de page `space-4` sur téléphone ; écart entre blocs `space-6`. Contenu limité à `page-width` sur grand écran.
+- Le plateau occupe toute la largeur sur téléphone ; c'est lui le héros de l'écran de jeu, pas les panneaux autour.
+- Focus clavier : anneau `focus` plein de 3px, décalé de 2px, sur tous les éléments interactifs.
+
+## Mouvement
+
+Sobre et utile : un pion glisse vers sa flèche (150 à 250 ms, sans rebond), les dés roulent brièvement. Les trois points de « l'ordinateur réfléchit » sont la seule animation en boucle. Tout s'arrête avec `prefers-reduced-motion`.
+
+## Iconographie
+
+- Le **symbole** (deux pions sur une flèche, le 8 caché) et le **logotype** (les « mm » en flèches) sont dans le groupe Logos ; versions couleur, sombre, noire et blanche. Ne jamais les redessiner, déformer ou recolorer.
+- Barre haute : `logo-horizontal-couleur.svg` en thème clair, `logo-horizontal-sombre.svg` en thème sombre, 32px de haut.
+- Icônes d'interface : traits simples de 2px à bouts ronds, dessinés en SVG dans le code (pas de police d'icônes, pas d'émoji). Les seules icônes du système pour l'instant : les trois appréciations de coups (coche, point d'interrogation, croix) et la copie (deux feuillets).
+- Dés, pions et videau sont dessinés en SVG avec les couleurs du plateau, jamais en images.
+
+## Composants
+
+Plateau (`Board`) et ses pièces (`Checker`, `Die`, `DoublingCube`), boutons (`Button`), barre haute (`TopBar`), zone de consigne (`GamePrompt`), appréciation d'un coup (`MoveVerdict`), fiche de glossaire (`GlossaryCard`), carte de leçon (`LessonCard`) et « Demander à une IA » (`AskAI`). Chacun a sa fiche avec ses règles d'usage et un aperçu dans les deux thèmes.
diff --git a/docs/identite/charte/tokens.json b/docs/identite/charte/tokens.json
new file mode 100644
index 0000000..611b4d5
--- /dev/null
+++ b/docs/identite/charte/tokens.json
@@ -0,0 +1,530 @@
+{
+ "name": "Ustagammon",
+ "version": 1,
+ "color": {
+ "themes": [
+ {
+ "id": "light",
+ "name": "Clair"
+ },
+ {
+ "id": "dark",
+ "name": "Sombre"
+ }
+ ],
+ "tokens": [
+ {
+ "name": "background",
+ "value": {
+ "light": "#F5EFE5",
+ "dark": "#17110D"
+ },
+ "usage": "Fond de page (papier ivoire / café torréfié)."
+ },
+ {
+ "name": "surface",
+ "value": {
+ "light": "#FFFCF6",
+ "dark": "#221913"
+ },
+ "usage": "Fond des cartes, fiches de glossaire, panneaux posés sur `background`."
+ },
+ {
+ "name": "surface-sunken",
+ "value": {
+ "light": "#ECE3D4",
+ "dark": "#2C211A"
+ },
+ "usage": "Zones en retrait : bloc de prompt à copier, piste de progression."
+ },
+ {
+ "name": "text",
+ "value": {
+ "light": "#2B1D15",
+ "dark": "#EFE5D5"
+ },
+ "usage": "Texte courant et titres, sur `background`, `surface` et `surface-sunken`."
+ },
+ {
+ "name": "muted",
+ "value": {
+ "light": "#6B5C50",
+ "dark": "#A99886"
+ },
+ "usage": "Texte secondaire (compte de points, légendes, aide), sur `background` et `surface`."
+ },
+ {
+ "name": "border",
+ "value": {
+ "light": "#DED2C0",
+ "dark": "#3A2D24"
+ },
+ "usage": "Séparateurs et contours décoratifs de cartes (ne porte aucun sens)."
+ },
+ {
+ "name": "border-strong",
+ "value": {
+ "light": "#8E7D6A",
+ "dark": "#7D6B5B"
+ },
+ "usage": "Contour des boutons secondaires et des champs : 3:1 sur `background` et `surface`."
+ },
+ {
+ "name": "accent",
+ "value": {
+ "light": "#A8432B",
+ "dark": "#D0694B"
+ },
+ "usage": "Rouge brique, l'accent unique : bouton principal, liens, case où le pion peut aller, focus. Texte en brique sur `background` et `surface`."
+ },
+ {
+ "name": "on-accent",
+ "value": {
+ "light": "#FFFFFF",
+ "dark": "#1A110C"
+ },
+ "usage": "Texte et icônes posés sur un aplat `accent`."
+ },
+ {
+ "name": "accent-soft",
+ "value": {
+ "light": "#F1D9CF",
+ "dark": "#4A2519"
+ },
+ "usage": "Fond léger d'accent : puce « à toi de jouer », sélection dans une liste. Texte `text` dessus."
+ },
+ {
+ "name": "focus",
+ "value": {
+ "light": "#A8432B",
+ "dark": "#E58A6E"
+ },
+ "usage": "Anneau de focus clavier, 3 px plein, décalé de 2 px : 3:1 sur tous les fonds."
+ },
+ {
+ "name": "error",
+ "value": {
+ "light": "#8C1C3A",
+ "dark": "#F08FA6"
+ },
+ "usage": "Message d'erreur technique (texte), toujours accompagné d'un mot. Lie-de-vin, distinct de la brique."
+ },
+ {
+ "name": "verdict-good",
+ "value": {
+ "light": "#2F6B4F",
+ "dark": "#7CCBA4"
+ },
+ "usage": "« Bon coup » : texte et icône, toujours avec le mot. Sur `background` et `surface`."
+ },
+ {
+ "name": "verdict-doubtful",
+ "value": {
+ "light": "#7E5A0F",
+ "dark": "#E0B04F"
+ },
+ "usage": "« Imprécision » (doubtful) : texte et icône, toujours avec le mot."
+ },
+ {
+ "name": "verdict-bad",
+ "value": {
+ "light": "#8C1C3A",
+ "dark": "#F08FA6"
+ },
+ "usage": "« Erreur » et « grosse erreur » (bad, very bad) : texte et icône, toujours avec le mot."
+ },
+ {
+ "name": "brand-noyer",
+ "value": {
+ "light": "#4A2E1F",
+ "dark": "#4A2E1F"
+ },
+ "usage": "Noyer du logo : pion maître. Ne sert pas au texte de l'interface."
+ },
+ {
+ "name": "brand-ivoire",
+ "value": {
+ "light": "#F3EAD8",
+ "dark": "#F3EAD8"
+ },
+ "usage": "Ivoire du logo : pion apprenti, fond de l'icône d'application."
+ },
+ {
+ "name": "brand-laiton",
+ "value": {
+ "light": "#8F6A1C",
+ "dark": "#D6A64A"
+ },
+ "usage": "Laiton, comme les charnières d'un plateau de tavla : marque du dernier coup joué, rien d'autre."
+ },
+ {
+ "name": "frame",
+ "value": {
+ "light": "#4A2E1F",
+ "dark": "#2A1A10"
+ },
+ "usage": "Cadre du plateau (noyer)."
+ },
+ {
+ "name": "bed",
+ "value": {
+ "light": "#E9DCC4",
+ "dark": "#4A3626"
+ },
+ "usage": "Fond du plateau, entre les flèches."
+ },
+ {
+ "name": "bar",
+ "value": {
+ "light": "#3F2619",
+ "dark": "#24170E"
+ },
+ "usage": "Barre centrale."
+ },
+ {
+ "name": "tray",
+ "value": {
+ "light": "#3A2418",
+ "dark": "#22150D"
+ },
+ "usage": "Plateaux de sortie, à droite."
+ },
+ {
+ "name": "point-a",
+ "value": {
+ "light": "#6B4430",
+ "dark": "#3A2519"
+ },
+ "usage": "Flèches sombres (noyer clair), une sur deux."
+ },
+ {
+ "name": "point-b",
+ "value": {
+ "light": "#C9AE88",
+ "dark": "#7E6142"
+ },
+ "usage": "Flèches claires (chêne), une sur deux."
+ },
+ {
+ "name": "point-number",
+ "value": {
+ "light": "#F3EAD8",
+ "dark": "#CDBFA8"
+ },
+ "usage": "Numéros des flèches, posés sur `frame`."
+ },
+ {
+ "name": "checker-player",
+ "value": {
+ "light": "#F7F0E2",
+ "dark": "#EDE3CF"
+ },
+ "usage": "Pions du joueur : ivoire, l'apprenti."
+ },
+ {
+ "name": "checker-player-edge",
+ "value": {
+ "light": "#8C7A62",
+ "dark": "#8E7C64"
+ },
+ "usage": "Contour et filet des pions du joueur."
+ },
+ {
+ "name": "checker-computer",
+ "value": {
+ "light": "#2E1C12",
+ "dark": "#140D09"
+ },
+ "usage": "Pions de l'ordinateur : noyer sombre, le maître."
+ },
+ {
+ "name": "checker-computer-edge",
+ "value": {
+ "light": "#120A05",
+ "dark": "#A8957D"
+ },
+ "usage": "Contour et filet des pions de l'ordinateur ; clair en thème sombre pour rester visible."
+ },
+ {
+ "name": "count-player",
+ "value": {
+ "light": "#2B1D15",
+ "dark": "#2B1D15"
+ },
+ "usage": "Nombre écrit sur une pile de pions du joueur."
+ },
+ {
+ "name": "count-computer",
+ "value": {
+ "light": "#F3EAD8",
+ "dark": "#F3EAD8"
+ },
+ "usage": "Nombre écrit sur une pile de pions de l'ordinateur."
+ },
+ {
+ "name": "die-player",
+ "value": {
+ "light": "#F7F0E2",
+ "dark": "#EDE3CF"
+ },
+ "usage": "Dés du joueur."
+ },
+ {
+ "name": "pip-player",
+ "value": {
+ "light": "#2B1D15",
+ "dark": "#2B1D15"
+ },
+ "usage": "Points des dés du joueur."
+ },
+ {
+ "name": "die-computer",
+ "value": {
+ "light": "#2E1C12",
+ "dark": "#140D09"
+ },
+ "usage": "Dés de l'ordinateur."
+ },
+ {
+ "name": "pip-computer",
+ "value": {
+ "light": "#F3EAD8",
+ "dark": "#EDE3CF"
+ },
+ "usage": "Points des dés de l'ordinateur."
+ },
+ {
+ "name": "cube",
+ "value": {
+ "light": "#F7F0E2",
+ "dark": "#EDE3CF"
+ },
+ "usage": "Face du videau."
+ },
+ {
+ "name": "cube-text",
+ "value": {
+ "light": "#2B1D15",
+ "dark": "#2B1D15"
+ },
+ "usage": "Valeur du videau (2, 4, 8…)."
+ },
+ {
+ "name": "highlight",
+ "value": {
+ "light": "#A8432B",
+ "dark": "#E07A5A"
+ },
+ "usage": "Contour d'un pion jouable ou sélectionné du joueur : la brique. Il contraste à 3:1 au moins avec le pion ivoire (clair) ou avec le fond du plateau (sombre)."
+ },
+ {
+ "name": "target",
+ "value": {
+ "light": "rgba(168,67,43,0.32)",
+ "dark": "rgba(224,122,90,0.38)"
+ },
+ "usage": "Voile sur la flèche où le pion sélectionné peut aller."
+ },
+ {
+ "name": "last-move",
+ "value": {
+ "light": "{brand-laiton}",
+ "dark": "{brand-laiton}"
+ },
+ "usage": "Marque du dernier coup joué (laiton)."
+ }
+ ]
+ },
+ "type": {
+ "fonts": [
+ {
+ "family": "Alegreya Sans",
+ "file": "fonts/AlegreyaSans-Regular.ttf",
+ "weight": "400"
+ },
+ {
+ "family": "Alegreya Sans",
+ "file": "fonts/AlegreyaSans-Italic.ttf",
+ "weight": "400",
+ "style": "italic"
+ },
+ {
+ "family": "Alegreya Sans",
+ "file": "fonts/AlegreyaSans-Medium.ttf",
+ "weight": "500"
+ },
+ {
+ "family": "Alegreya Sans",
+ "file": "fonts/AlegreyaSans-Bold.ttf",
+ "weight": "700"
+ },
+ {
+ "family": "Alegreya Sans",
+ "file": "fonts/AlegreyaSans-ExtraBold.ttf",
+ "weight": "800"
+ }
+ ],
+ "families": {
+ "sans": "\"Alegreya Sans\", \"Gill Sans\", \"Segoe UI\", system-ui, sans-serif"
+ },
+ "groups": [
+ {
+ "name": "Titres",
+ "family": "sans",
+ "styles": [
+ {
+ "name": "display",
+ "fontSize": "32px",
+ "lineHeight": "36px",
+ "fontWeight": 800,
+ "letterSpacing": "-0.01em",
+ "sample": "Une partie contre le maître",
+ "usage": "Titre d'accueil et de fin de partie, une fois par écran."
+ },
+ {
+ "name": "title",
+ "fontSize": "24px",
+ "lineHeight": "30px",
+ "fontWeight": 700,
+ "sample": "Le point 8",
+ "usage": "Titre d'écran (leçon, aide)."
+ },
+ {
+ "name": "heading",
+ "fontSize": "20px",
+ "lineHeight": "26px",
+ "fontWeight": 700,
+ "sample": "Les ouvertures",
+ "usage": "Sous-titre de section, titre de carte."
+ }
+ ]
+ },
+ {
+ "name": "Texte",
+ "family": "sans",
+ "styles": [
+ {
+ "name": "body",
+ "fontSize": "17px",
+ "lineHeight": "25px",
+ "fontWeight": 400,
+ "sample": "Ce pion peut rejoindre votre point 8.",
+ "usage": "Texte courant ; jamais en dessous de 17px pour le contenu à lire."
+ },
+ {
+ "name": "body-strong",
+ "fontSize": "17px",
+ "lineHeight": "25px",
+ "fontWeight": 700,
+ "sample": "À vous de jouer : 6 et 1.",
+ "usage": "Consigne du moment (zone prompt), boutons."
+ },
+ {
+ "name": "body-italic",
+ "fontSize": "17px",
+ "lineHeight": "25px",
+ "fontWeight": 400,
+ "fontStyle": "italic",
+ "sample": "Philippe aurait joué 13/7 8/7.",
+ "usage": "Parole du maître, citation, exemple."
+ },
+ {
+ "name": "caption",
+ "fontSize": "15px",
+ "lineHeight": "20px",
+ "fontWeight": 400,
+ "sample": "Vous : 167 · Ordinateur : 152",
+ "usage": "Compte de points, légendes, mentions."
+ },
+ {
+ "name": "overline",
+ "fontSize": "13px",
+ "lineHeight": "16px",
+ "fontWeight": 700,
+ "letterSpacing": "0.08em",
+ "sample": "LEÇON 3 SUR 12",
+ "usage": "Étiquette en capitales au-dessus d'un titre ; avec parcimonie."
+ }
+ ]
+ }
+ ]
+ },
+ "spacing": {
+ "tokens": [
+ {
+ "name": "space-1",
+ "value": "4px",
+ "usage": "Écart entre une icône et son texte."
+ },
+ {
+ "name": "space-2",
+ "value": "8px",
+ "usage": "Écart entre boutons voisins, marges internes serrées."
+ },
+ {
+ "name": "space-3",
+ "value": "12px",
+ "usage": "Marge interne des puces et du bloc prompt."
+ },
+ {
+ "name": "space-4",
+ "value": "16px",
+ "usage": "Gouttière latérale de page sur téléphone, marge interne des cartes."
+ },
+ {
+ "name": "space-6",
+ "value": "24px",
+ "usage": "Écart entre blocs d'un écran."
+ },
+ {
+ "name": "space-8",
+ "value": "32px",
+ "usage": "Écart entre sections."
+ },
+ {
+ "name": "button-height",
+ "value": "48px",
+ "usage": "Hauteur des boutons ; aucune cible tactile sous 44px."
+ },
+ {
+ "name": "page-width",
+ "value": "40rem",
+ "usage": "Largeur maximale du contenu sur grand écran."
+ }
+ ]
+ },
+ "radius": {
+ "tokens": [
+ {
+ "name": "radius-sm",
+ "value": "6px",
+ "usage": "Dés, videau, puces de verdict."
+ },
+ {
+ "name": "radius-md",
+ "value": "12px",
+ "usage": "Cartes, fiches, bloc prompt."
+ },
+ {
+ "name": "radius-pill",
+ "value": "999px",
+ "usage": "Boutons : ronds comme des pions."
+ }
+ ]
+ },
+ "shadow": {
+ "tokens": [
+ {
+ "name": "shadow-raised",
+ "value": {
+ "light": "0 1px 2px rgba(43,29,21,0.10)",
+ "dark": "0 1px 2px rgba(0,0,0,0.40)"
+ },
+ "usage": "Seule ombre permise : cartes posées sur le fond. Rien de plus profond."
+ }
+ ]
+ },
+ "meta": {
+ "source": "Brief créatif + ADR 0010 + web/app.css (noms des variables du plateau)"
+ }
+}
diff --git a/docs/journal.md b/docs/journal.md
index 0828303..d321746 100644
--- a/docs/journal.md
+++ b/docs/journal.md
@@ -89,3 +89,24 @@ Une entrée datée par session : ce qui a été fait, décidé, et la suite.
- Sous Firefox sur PC, un tour de l'ordinateur a pris jusqu'à 5,1 s
(Chromium : 0,4 s) ; Firefox sur le téléphone reste à mesurer.
- Validation par Pierre de Playwright (Apache-2.0), outil de `make test-browser`.
+
+## 2026-11-03 (nuit) : identité visuelle
+
+**Fait**
+- Identité choisie par Pierre en trois tours sur une planche de travail :
+ accent brique, symbole « P3d » (deux pions sur une flèche, le 8 caché),
+ logotype « L3 » (les « mm » en flèches), icône sur fond ivoire. ADR 0010,
+ fichiers du logo et des icônes dans `docs/identite/logo/` (MR !12).
+- Design system publié (https://claude.ai/artifact/K2Z7MPE58XXJzv19n5r11M) :
+ couleurs des deux thèmes reprenant les noms de variables de `web/app.css`,
+ Alegreya Sans, onze composants, contrastes vérifiés par calcul. Copie dans
+ `docs/identite/charte/`.
+- Maquettes des quatre écrans et du thème sombre
+ (https://claude.ai/artifact/CQw6vbDpi6XQqVWQa4sANe).
+
+**Reste à faire**
+- Appliquer la charte à la PWA (couleurs, police embarquée, icônes, logo) :
+ à planifier pour l'agent développeur, voir `docs/identite/charte/README.md`.
+- Les maquettes proposent des éléments de produit qui ne sont pas encore
+ décidés (leçons, « Conseil du maître », bilan de fin de partie) : à valider
+ par Pierre avant toute mise en œuvre.