/* screens/apprendre.css — le lecteur d'exercice (exPlayer).  Split out of app.css by S0.
   TOKENS ONLY.
   NOTE: these rules also dress the séquence modal (modals.js openSequence) — it plays the same
   exPlayer, deliberately, so there is one grader and one « Explique autrement ».
   Owner after Wave 0: S1 for D3 (inputs ≥ 16px so iOS stops zooming — .ex-in input, .ex-choices
   button are two of the three offenders). */

/* ══ §2.4 (2026-08-15) · UN ÉCRAN, UN POUCE, UN SEUL ENDROIT OÙ LA RÉPONSE APPARAÎT ═════════
   La feuille défilait EN ENTIER (`.sheet` est `max-height: 88vh; overflow-y: auto`), donc le
   verdict et le bouton principal vivaient au bas d'une colonne de longueur variable : répondre,
   défiler pour savoir, défiler encore pour continuer. `.sheet-ex` est une VARIANTE — jamais un
   changement de la base : les quatre autres feuilles (voice · invite · thread · agenda) sont
   intactes par construction, elles ne portent pas cette classe.

   La feuille garde `max-height: 88vh` et n'a pas de hauteur imposée : un exercice court fait donc
   une feuille courte, barre juste sous le contenu ; un exercice long fait une feuille pleine,
   barre épinglée. Le même code sert les deux. TOKENS ONLY. */
.sheet.sheet-ex { display: flex; flex-direction: column; padding-bottom: 0; overflow: hidden; }
.sheet-ex .ex-top { flex: 0 0 auto; display: flex; align-items: flex-start; gap: 10px; }
.sheet-ex .ex-top h2 { flex: 1 1 auto; min-width: 0; }
/* La croix FERME la feuille. Elle ne corrige rien : rien dans cette app ne marque d'une croix le
   travail d'un enfant (tokens.css réserve le seul rouge, et la rubrique « À revoir » est un mot
   gris). 44px de cible (D3). */
.ex-close {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; margin: -6px -6px 0 0;
  border-radius: var(--r-pill); background: transparent; border: 1px solid transparent;
  color: var(--ink);
}
.ex-close:hover { background: var(--btn-bg); border-color: var(--line); }
.sheet-ex .ex-host { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
/* `min-height: 0` sur les deux : sans lui, un enfant flex refuse de rétrécir sous sa hauteur de
   contenu et c'est la FEUILLE qui déborde au lieu de la colonne qui défile. */
.sheet-ex .ex-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.sheet-ex .ex-bar {
  flex: 0 0 auto; border-top: 1px solid var(--line);
  padding: 12px 0 calc(14px + env(safe-area-inset-bottom));
  background: var(--sheet-bg);
}

/* ── la jauge : où on en est, sans montrer une clé de base ──────────────────
   `.ex-step` disait « EXERCICE 1 / 5 · CP-MATH-01-E3 » — une clé primaire sous les yeux d'un
   enfant de huit ans. L'identifiant vit maintenant dans `data-ex-id` sur l'hôte. */
.ex-rail { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; margin: 14px 0 4px; }
.ex-pips { display: flex; gap: 5px; flex: 0 0 auto; }
.ex-pip { width: 7px; height: 7px; border-radius: var(--r-pill); background: var(--line-2); }
/* Fait / en cours / à venir : le remplissage ET la halo changent, pas seulement la teinte (D7).
   ⚠ `ex-pip-done`, PAS `done` : `.sheet .done` (modals.css) est le bouton principal des feuilles,
   et il vaut 0,2,0 contre 0,1,0 pour `.ex-pip.done` — la jauge héritait donc de `width: 100%`,
   `padding: 13px` et du violet `--voice`. Vu à l'écran : trois gros disques lavande au lieu de
   trois pastilles de 7px. La jauge vit DANS une feuille, donc elle ne peut porter aucun nom que
   modals.css revendique déjà. */
.ex-pip-done { background: var(--school); }
.ex-pip-now  { background: var(--school); box-shadow: 0 0 0 3px var(--school-soft); }
.ex-count { font: 600 11px/1 var(--mono); letter-spacing: .1em; color: var(--ink); }

/* ── l'énoncé : sa propre respiration, une vraie taille ─────────────────────
   16,5px au milieu d'options à 16px, d'un verdict à 14px et d'une aide à 13,5px : une colonne
   plate à presque une seule graisse — c'est ÇA qui se lisait « brouillon ». */
/* LE MUR DE TEXTE (2026-09-07, vu à l'écran par Steven) — `white-space: pre-line`.
   Le curriculum ÉCRIT la structure de ses énoncés : « Relie chaque matière… ↵ 1. maths
   2. science… ↵↵ a. littérature b. mathématiques… » — la consigne, puis les deux colonnes.
   Sans cette ligne le navigateur écrase les sauts en espaces et l'enfant reçoit un mur d'un
   seul tenant, où il faut chercher où finit la question et où commencent les réponses.
   MESURÉ : **1 038 exercices sur 8 233 (12,6 %)** portent au moins un saut de ligne, dont
   109 un saut double. Un huitième du corpus dont on jetait la mise en forme.
   `pre-line` et non `pre-wrap` : il préserve les sauts ET replie les espaces multiples, or
   le curriculum aligne ses colonnes avec des espaces doubles qu'on ne veut pas montrer.
   Précédent dans la maison : `.fil-msg p` porte déjà `pre-wrap` (screens/fil.css:36). */
.ex-q { font: 400 18px/1.5 var(--font); margin-top: 10px; white-space: pre-line; }
/* ── §3.1 · LES LISTES DE L'ÉNONCÉ (2026-09-08) — un item par ligne, la marque en gouttière ──
   Ce que Steven a vu : « 6. » en bout de ligne, « English » à la suivante. apprendre.js
   `peindreEnonce` découpe (via enonce.js) et peint ; ici on ne fait que TENIR la ligne :
   · chaque item est une grille de deux colonnes — la marque (« 1. », « a) », « (2) »), puis le
     texte. Le texte qui se replie revient sous LUI-MÊME, jamais sous la marque : c'est le retrait
     suspendu d'un vrai cahier, et c'est ce qui permet de balayer la colonne des marques d'un
     coup d'œil.
   · 2,2em de gouttière : « 10. » et « (8) » y tiennent à 18px ; mesuré sur le corpus, aucune
     marque n'est plus longue (la plus longue suite compte dix items).
   · la marque en 600 et à pleine encre — PAS `--ink-muted` : mesuré le 2026-08-14 dans ce même
     fichier, l'encre atténuée passe sous 4,5:1 en Terrain de jeu, et 18px n'est pas du « grand
     texte ». Ce qui la distingue du texte, c'est la graisse, jamais une encre plus pâle.
   · `min-width: 0` + `overflow-wrap: anywhere` sur le texte : un mot long (« Physical ») ne
     pousse jamais la grille hors des 390 px — verify-ui-listes.js mesure scrollWidth.
   · sans liste, `.ex-q` reste un bloc de texte : aucune de ces règles ne s'applique.
   ⚠ L'ORDRE DES TROIS PREMIÈRES RÈGLES COMPTE. Les remises à zéro (`.ex-q-p`, `.ex-q-l`) ont la
     même spécificité que `.ex-q > * + *` ; écrite AVANT elles, la respiration entre blocs était
     écrasée — vu sur la capture (2026-09-08) : la consigne collée à « 1. », « 6. English » collé
     à « a. littérature ». L'assertion d'écart de verify-ui-listes.js le tient depuis. */
.ex-q-p { margin: 0; }
.ex-q-l { list-style: none; margin: 0; padding: 0; }
.ex-q > * + * { margin-top: 10px; }   /* consigne → liste, liste → liste : deux groupes, pas une colonne */
.ex-q-i { display: grid; grid-template-columns: 2.2em minmax(0, 1fr); column-gap: 4px; align-items: baseline; }
.ex-q-i + .ex-q-i { margin-top: 4px; }
.ex-q-k { font-weight: 600; }
.ex-q-t { min-width: 0; overflow-wrap: anywhere; }
/* La GRILLE d'un énoncé (quatre énoncés de CM2 français l'écrivent en Markdown) : une vraie table,
   la tête en 600, des cases qui gardent leur hauteur même vides — c'est là que l'enfant répond,
   sur le papier ; à l'écran elle se lit. TOKENS ONLY. */
.ex-q-table { border-collapse: collapse; width: 100%; font-size: 15px; line-height: 1.35; white-space: normal; }
.ex-q-table th, .ex-q-table td { border: 1px solid var(--line); padding: 6px 8px; text-align: left; vertical-align: top; min-width: 3em; }
.ex-q-table th { font-weight: 600; }
.ex-scroll { padding-bottom: 12px; }

/* ── les options : des CIBLES, avec une lettre et une coche ─────────────────
   Lettres A · B · C (choix de Steven, 2026-08-15) : un parent peut lire une réponse à voix haute
   — « la B ». 48px de haut, une gouttière à gauche, le libellé au milieu, la coche à droite.
   Le juste s'allume dans la lumière école ET porte la coche ; le faux se relit en NEUTRE, jamais
   en rouge et jamais barré d'une croix — la même règle que `.ex-blank.bad` et que la pastille
   « À revoir ». Ce qui porte l'information, c'est le MOT dans la barre, toujours à l'écran. */
.ex-choices { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.ex-choice {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 48px;
  text-align: left; padding: 10px 14px; border-radius: var(--r-sm);
  background: var(--surface-2); border: 1px solid var(--line);
}
.ex-choice-k {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: var(--r-pill);
  background: var(--btn-bg); border: 1px solid var(--line);
  font: 600 12.5px/1 var(--font); color: var(--ink);
}
.ex-choice-t { flex: 1 1 auto; min-width: 0; font: 400 16px/1.35 var(--font); color: var(--ink); } /* D3 (S1): 16px min */
svg.ex-choice-g { flex: 0 0 auto; width: 18px; height: 18px; color: var(--school); visibility: hidden; }
.ex-choice.good { background: var(--school-soft); border-color: var(--school-line); }
.ex-choice.good .ex-choice-k { background: var(--school); border-color: var(--school); color: var(--ink-on-school); }
.ex-choice.good .ex-choice-g { visibility: visible; }
.ex-choice.bad { background: var(--surface-2); border-color: var(--line-2); }
/* ── U1.2 · « ton choix » — le mot qui remplace la croix qu'on n'écrira jamais ──────────────
   Depuis U1.2, la BONNE option s'allume à côté de celle qui a été touchée. `.ex-choice.bad` ne
   changeait qu'un fond et un trait — presque rien à l'œil, et c'était tenable tant que rien
   d'autre n'était marqué. Avec une option en lumière école juste à côté, l'enfant voit laquelle
   était juste mais ne retrouve plus la sienne : l'état ne tiendrait plus qu'à une teinte, ce que
   D7 interdit. On ne peut pas non plus barrer d'une croix — tokens.css réserve le seul rouge de
   l'app, et la maison a tranché deux fois (`.ex-blank.bad`, la pastille « À revoir ») qu'on ne
   marque pas d'une croix le travail d'un enfant de huit ans. C'est donc un MOT, la grammaire de
   `.ex-part-fix` : du texte posé à côté, qui dit ce qui s'est passé sans le juger.
   `--ink` et PAS `--ink-muted` : mesuré le 2026-08-14 dans ce même fichier, l'encre atténuée sur
   --surface-2 vaut 3,93:1 en Terrain de jeu, sous les 4,5:1 de WCAG AA — et 11,5px en 600 n'est
   pas du « grand texte ». Ce qui le tient à sa place de repère et non de libellé, c'est la
   taille, la graisse et l'approche, jamais une encre plus pâle.
   Caché tant que le choix n'est pas marqué, exactement comme la coche au-dessus — `display: none`
   plutôt que `visibility` parce qu'un mot invisible réserverait sa largeur au milieu du libellé.
   TOKENS ONLY. */
.ex-choice-mine {
  display: none; flex: 0 0 auto;
  font: 600 11.5px/1 var(--font); letter-spacing: .04em; color: var(--ink);
}
.ex-choice.bad .ex-choice-mine { display: inline-block; }
.ex-choice[disabled] { opacity: 1; }   /* verrouillé ≠ effacé : la copie reste lisible après coup */
/* ── §3.3 bis · relier deux boutons (2026-09-10, Steven : « ok go on for the linking buttons ») ──
   Deux colonnes de cibles (48px, un chiffre à gauche, une lettre à droite) ; on touche une ligne de
   gauche puis sa paire. Le LIEN se lit trois fois, dont deux qui ne sont pas une teinte (D7) : la
   lettre de la paire s'écrit sur la ligne de gauche, le chiffre sur la ligne de droite, et — quand
   les libellés sont courts (≤ 28 caractères, le critère du papier) et que les colonnes tiennent côte
   à côte — un trait les joint. Les libellés longs empilent les deux colonnes ; le trait n'a alors
   plus de gouttière et ne se dessine pas, les marques suffisent. Le juste s'allume en lumière école,
   le raté se relit en NEUTRE avec sa correction « → b. … » posée dessous — jamais de rouge sur le
   travail d'un enfant (`.ex-part-fix`, la même grammaire). TOKENS ONLY. */
.ex-relie { position: relative; margin-top: 14px; display: flex; flex-direction: column; gap: 14px; }
.ex-relie.cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 28px; align-items: start; }
.ex-relie-col { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.ex-relie-b {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; width: 100%; min-height: 48px;
  text-align: left; padding: 8px 10px; border-radius: var(--r-sm);
  background: var(--surface-2); border: 1px solid var(--line); color: var(--ink);
}
.ex-relie-k {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: var(--r-pill);
  background: var(--btn-bg); border: 1px solid var(--line);
  font: 600 12px/1 var(--font); color: var(--ink);
}
.ex-relie-t { flex: 1 1 0; min-width: 0; font: 400 16px/1.3 var(--font); color: var(--ink); overflow-wrap: break-word; } /* D3 (S1): 16px min */
.ex-relie-m { flex: 0 0 auto; min-width: 1.2em; text-align: right; font: 700 13px/1 var(--font); color: var(--school); }
/* côte à côte, la colonne est étroite : chrome plus fin, pour que chaque mot (≤ 10 lettres, critère du
   joueur) tienne sur sa ligne — les libellés restent à 16px (D3) */
.ex-relie.cols .ex-relie-b { padding: 8px 8px; gap: 6px; }
.ex-relie.cols .ex-relie-k { width: 22px; height: 22px; font-size: 11.5px; }
.ex-relie.cols .ex-relie-m { min-width: 1em; }
.ex-relie-b.on { background: var(--sport-soft); border-color: var(--sport); box-shadow: 0 0 0 2px var(--sport-line); }
.ex-relie-b.on .ex-relie-k { background: var(--sport); border-color: var(--sport); color: var(--ink-on-sport); }
.ex-relie-b.lie { border-color: var(--school-line); }
.ex-relie-b.good { background: var(--school-soft); border-color: var(--school-line); }
.ex-relie-b.good .ex-relie-k { background: var(--school); border-color: var(--school); color: var(--ink-on-school); }
.ex-relie-b.bad { background: var(--surface-2); border-color: var(--line-2); }
.ex-relie-b[disabled] { opacity: 1; }   /* verrouillé ≠ effacé : la copie reste lisible après coup */
.ex-relie-b .ex-part-fix { flex: 0 0 100%; margin-top: 2px; }
.ex-relie.lecture .ex-relie-b { background: var(--surface); }
.ex-relie-svg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.ex-relie-l { stroke: var(--school); stroke-width: 2.5; stroke-linecap: round; }
.ex-in { display: flex; gap: 8px; margin-top: 14px; }
.ex-in input { flex: 1; background: var(--field-bg); border: 1px solid var(--line); border-radius: var(--r-sm); color: var(--ink); padding: 11px 14px; font-size: 16px; } /* D3 (S1): 16px min */

/* ── l'action principale : une seule, à hauteur de pouce, qui ne bouge jamais ─
   Son LIBELLÉ bouge (Valider → Suivant → Terminer → Fermer), pas sa place. `.ex-do` a disparu
   avec elle : le bouton « Voir ce qu'on attendait » EST cette action-là, et ce qui rend « aucun
   champ sur un exercice sans réponse » vérifiable est désormais `data-act="voir"`. */
.ex-primary { width: 100%; justify-content: center; padding: 13px; }
.ex-primary[disabled] { opacity: .55; }

/* ── §2.3 · une réponse par sous-question (ATELIER-UX-PLAN.md §2.3) ─────────
   Trois formes, une seule grammaire. Ce qui est juste s'allume dans la lumière école ; ce qui est
   raté se relit en NEUTRE, avec la bonne réponse posée juste à côté — jamais du rouge sur le
   travail d'un enfant de huit ans (tokens.css dit de --danger « le seul rouge de l'app »). Le
   signal n'est donc jamais la seule teinte : la correction « → … » APPARAÎT, et c'est ce texte
   qui porte l'information (D7). TOKENS ONLY. */
.ex-parts { margin-top: 12px; }
.ex-part { padding: 10px 0; border-top: 1px dashed var(--line-dashed); }
.ex-part-q { font: 400 14.5px/1.45 var(--font); color: var(--ink); }
.ex-part.good .ex-part-q { color: var(--school); }
.ex-part.bad .ex-part-q { color: var(--ink-muted); }
.ex-part input { display: block; width: 100%; margin-top: 8px; background: var(--field-bg); border: 1px solid var(--line); border-radius: var(--r-sm); color: var(--ink); padding: 11px 14px; font-size: 16px; } /* D3 (S1) : 16px min */
/* Le trou vit DANS la phrase : il se dimensionne sur le texte qui l'entoure, jamais sur la
   colonne, et il reste sur la ligne de base pour que la phrase se lise encore comme une phrase. */
/* 5,5em et pas davantage. Mesuré à l'écran le 2026-08-14 : à 8,5em, « Calcule les doubles :
   2 + 2 = ___ ; 4 + 4 = ___ ; 5 + 5 = ___ » passait à la ligne à CHAQUE trou et la phrase se
   lisait en colonne — ce qui annule la seule raison de mettre la saisie DANS la phrase. Largeur
   UNIFORME, jamais ajustée à la réponse attendue : un champ taillé sur « 8 » ou sur « Victor
   Schœlcher » soufflerait sa longueur. Une réponse plus longue défile, comme sur un cahier on
   écrit plus serré. */
.ex-blank { display: inline-block; width: 5.5em; max-width: 100%; margin: 0 3px; padding: 3px 8px; background: var(--field-bg); border: 1px solid var(--line); border-radius: var(--r-sm); color: var(--ink); font-size: 16px; }
.ex-blank.good { border-color: var(--school-line); background: var(--school-soft); color: var(--school); }
/* `--ink`, PAS `--ink-muted` — la même mesure que .ex-rub-b ci-dessous : l'encre atténuée sur
   --surface-2 vaut 3,93:1 en Terrain de jeu. C'est la réponse que l'enfant vient d'écrire ; elle
   ne s'efface pas parce qu'elle est fausse. Ce qui signale l'erreur, c'est « → … » à côté. */
.ex-blank.bad { border-color: var(--line-2); background: var(--surface-2); color: var(--ink); }
.ex-part-fix { display: inline-block; margin-top: 6px; font: 600 12.5px/1.4 var(--font); color: var(--school); }
/* Vrai / Faux : un jugement, pas une saisie. 44px de haut, 16px de texte — une cible de doigt (D3). */
.ex-part-vf { display: flex; gap: 8px; margin-top: 8px; }
.ex-part-vf button { flex: 1 1 auto; min-height: 44px; padding: 11px 14px; border-radius: var(--r-pill); border: 1px solid var(--line); background: var(--surface-2); color: var(--ink); font: 600 13px/1 var(--font); }
.ex-part-vf button.on { background: var(--school); border-color: var(--school); color: var(--ink-on-school); }
.ex-parts .btn { margin-top: 12px; }
@media (prefers-reduced-motion: no-preference) {
  .ex-part-vf button { transition: background-color .12s ease, color .12s ease, border-color .12s ease; }
}
:root[data-calme="1"] .ex-part-vf button { transition: none; } /* U2 — data-calme coupe aussi ce confort */
/* Le verdict vit dans la BARRE : c'est le seul endroit du lecteur qui soit toujours à l'écran,
   avant comme après la réponse. Il porte l'aria-live (exPlayer), donc un lecteur d'écran l'entend
   là où l'œil le lit. `--ink`, pas `--ink-muted` : sur --sheet-bg en Terrain, l'encre atténuée
   vaut 4,23:1, sous AA — et c'est le résultat, pas une légende. */
.ex-fb { font: italic 400 15px/1.4 var(--serif); color: var(--ink); min-height: 1.4em; }
.ex-fb.ok { color: var(--school); }
.ex-bar .ex-fb { margin: 0 0 10px; }
.ex-help { margin-top: 10px; padding: 12px 14px; border-radius: var(--r-sm); background: var(--school-soft); border: 1px solid var(--school-line); font-size: 13.5px; color: var(--school); }

/* ── 2.2 · la clôture jugée à la main (ATELIER-UX-PLAN.md §2.2) ─────────────
   Quatre mots, un geste, aucun chiffre. La même rampe que les pastilles de l'arc
   (screens/atelier.css `.ag .rub-*`) : UNE seule lumière — l'école, c'est du travail d'école — et
   quatre POIDS, plein → fond léger → contour seul → neutre. Elle descend dans le même ordre en
   Crépuscule et en Terrain, parce qu'elle ne tient à aucune différence de teinte (D7).

   Le choix se signale par le FOND et par `aria-pressed`, jamais par la seule couleur.
   TOKENS ONLY. */
.ex-rub { margin-top: 16px; padding-top: 14px; border-top: 1px dashed var(--line-dashed); }
.ex-rub-q { font: 600 15px/1.35 var(--font); color: var(--ink); }
.ex-rub-pick { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
/* 44px de haut, 16px de texte : une cible de doigt, pas une puce (D3). */
/* `--ink`, PAS `--ink-muted` : mesuré le 2026-08-14, l'encre atténuée sur --surface-2 vaut
   3,93:1 en Terrain de jeu, sous les 4,5:1 de WCAG AA — et 13px en 600 n'est pas du « grand
   texte » qui aurait droit à 3:1. Ces quatre mots sont l'action principale de l'écran, pas une
   légende. La paire est désormais tenue par scripts/test-contrast.js, qui ne la connaissait pas. */
.ex-rub-b {
  flex: 1 1 auto; min-height: 44px; padding: 11px 14px;
  border-radius: var(--r-pill); border: 1px solid var(--line);
  background: var(--surface-2); color: var(--ink);
  font: 600 13px/1 var(--font); white-space: nowrap;
}
.ex-rub-b.on { background: var(--school); border-color: var(--school); color: var(--ink-on-school); }
.ex-rub-skip { margin-top: 8px; font: italic 400 12.5px/1.45 var(--serif); color: var(--ink-muted); }
.ex-rub-say { margin-top: 8px; font: italic 400 14px/1.5 var(--serif); color: var(--school); }
.ex-rub-more { margin-top: 10px; }
.ex-rub-crit { margin-top: 8px; padding: 12px 14px; border-radius: var(--r-sm); background: var(--school-soft); border: 1px solid var(--school-line); }
.ex-rub-crit p { font: 400 13px/1.5 var(--font); color: var(--school); }
.ex-rub-crit p + p { margin-top: 6px; }
@media (prefers-reduced-motion: no-preference) {
  .ex-rub-b { transition: background-color .12s ease, color .12s ease, border-color .12s ease; }
}
:root[data-calme="1"] .ex-rub-b { transition: none; } /* U2 — data-calme coupe aussi ce confort */

/* ── U1 · l'oralisation (UX-UPLIFT-PLAN.md §3) ──────────────────────────────
   L'énoncé et l'aide portent chacun un bouton qui les dit à voix haute. Le bouton n'est DESSINÉ
   que si le navigateur sait parler (apprendre.js le décide, pas la CSS) : ces règles ne créent
   jamais un espace vide. Sans bouton, `.ex-say-row` est une ligne flex d'un seul enfant — soit
   exactement l'écran d'avant. TOKENS ONLY. */
.ex-say-row { display: flex; align-items: flex-start; gap: 8px; }
.ex-say-row .ex-q { flex: 1 1 auto; min-width: 0; }
.ex-help { display: flex; align-items: flex-start; gap: 8px; }
.ex-help-t { flex: 1 1 auto; min-width: 0; }
/* 40px de cible : c'est un bouton pour une main d'enfant ou un parent debout, pas une icône
   décorative. `flex-shrink: 0` — il ne se laisse jamais écraser par un énoncé long. */
.ex-say {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; margin-top: -1px;
  border-radius: var(--r-pill);
  background: var(--btn-bg); border: 1px solid var(--line); color: var(--ink-muted);
}
/* En cours de lecture : la forme change (le fond se remplit), pas seulement la couleur — même
   règle que l'onglet actif de la barre (D7). */
.ex-say.on { background: var(--school); border-color: var(--school); color: var(--ink-on-school); }
.ex-help .ex-say { background: transparent; border-color: var(--school-line); color: var(--school); }
.ex-help .ex-say.on { background: var(--school); border-color: var(--school); color: var(--ink-on-school); }
@media (prefers-reduced-motion: no-preference) {
  .ex-say { transition: background-color .12s ease, color .12s ease, border-color .12s ease; }
}
:root[data-calme="1"] .ex-say { transition: none; } /* U2 — data-calme coupe aussi ce confort */

/* ── U1.1 · mode parent — les deux verdicts ────────────────────────────────
   « Trouvé » / « Pas cette fois » est LE geste du mode parent : c'est la seule chose qu'on
   demande au téléphone dans toute la séquence. Deux `.btn` de 12,5px posés côte à côte en
   feraient deux liens sous un paragraphe. Ils prennent donc la ligne entière, à parts égales, et
   48px de haut — la même cible que `.ex-choice`, pour la même raison (un pouce, debout, à 20h40).
   La boîte de réponse au-dessus, elle, est le `.ex-help` déjà dessiné plus haut : une seule
   révélation dans le lecteur, une seule mise en page à tenir.
   Une fois le verdict pris, les deux boutons se désactivent — mais celui qui a été GARDÉ conserve
   sa pleine encre, sinon la trace de ce qu'on vient de dire disparaîtrait dans le gris commun
   de `.btn[disabled]`. Ce n'est pas une teinte qui porte l'information (D7) : c'est la coche sur
   « Trouvé », et le mot dans la barre. TOKENS ONLY. */
.ex-duo { margin-top: 14px; }
.ex-duo .btn {
  flex: 1 1 0; justify-content: center; min-height: 48px;
  font-size: 14.5px; padding: 12px 14px; text-align: center;
}
.ex-duo .btn svg { width: 14px; height: 14px; }
.ex-duo .btn.on { opacity: 1; }

/* ── « Explorer tout le programme » — l'enveloppe des menus (aussi utilisée par l'Atelier) ─────
   `.explore-sel` A ÉTÉ SUPPRIMÉE le 2026-08-15 AVEC son dernier appelant, dans le même commit :
   c'était le style du `<select>` natif, et c'est lui qui peignait la liste d'options en blanc sur
   blanc (1,05:1 mesuré à l'écran). Les huit menus de l'app sont des F.picker (modals.css).
   La laisser ici aurait fait rougir la porte CSS-MORTE de famille-gate, qui échoue sur une classe
   stylée que plus aucun JS ne pose — d'où « supprimer dans le même commit que la dernière
   conversion », et non « plus tard ».
   L'enveloppe, elle, reste : elle range les déclencheurs en colonne, avec leur gouttière. */
.explore-picks { display: flex; flex-direction: column; gap: 8px; margin: 12px 0; }

/* ── U5 · les intitulés officiels du programme (UX-UPLIFT-PLAN.md §3) ───────
   La bande qui coiffe un groupe de séquences : « Nombres et calculs », « Espace et géométrie »,
   « Lecture et compréhension de l'écrit » — le libellé vient du référentiel seedé, servi par
   /programme dans `theme`. Registre de bande de la maison (.quote span, .ex-step), teinté par la
   lumière école parce que c'est du contenu de classe.

   Le groupe SANS thème n'a pas de bande du tout : aucune règle ici ne dessine un vide, donc un
   curriculum sans `theme` rend exactement la liste plate d'avant U5.

   La marge du haut fait la respiration entre deux groupes ; le trait pointillé de la dernière
   `.ag` du groupe précédent (base.css) devient de fait la ligne de fin de ce groupe.

   PAS de `text-transform: uppercase`, contrairement aux autres bandes de la maison : ces
   libellés sont la formulation officielle et doivent se lire telle qu'elle est écrite. Les
   capitales abîmeraient « Le XIXe siècle » en « LE XIXE SIÈCLE » — une bande jolie qui ment sur
   le mot. Le registre tient donc à la graisse, à l'approche et à la lumière école. (Le patron
   maison qui met des capitales, .ex-step, les porte dans sa CHAÎNE, pas dans sa CSS.)
   TOKENS ONLY. */
.ex-band {
  font: 600 11.5px/1.35 var(--font); letter-spacing: .06em;
  color: var(--school);
  margin: 16px 0 3px;
}
.ex-band:first-child { margin-top: 8px; }

/* ── la bibliothèque ouverte : une ligne de séquence est une CIBLE ──────────────────────────
   Mesuré le 2026-08-15 (scripts/a11y-famille.js) : 378×20. C'est le seul geste qui ouvre une
   séquence dans l'explorateur, et il tenait dans un cinquième de pouce. Le plancher WCAG 2.2 AA
   (2.5.8) est 24×24 ; on prend 44, celui d'Apple HIG, parce que c'est un pouce de parent sur un
   téléphone et que la ligne a la place. Le texte ne bouge pas — c'est la zone qui s'ouvre. */
.expl-seq { min-height: 44px; padding: 11px 2px; display: flex; align-items: center; }

/* ── U1.1 (famille-faisabilité, 2026-09-06) · CE QUI SE FAIT SUR LA FEUILLE ──────────────────
   814 exercices du corpus se font sur du papier — relier, tracer, entourer. L'écran ne peut pas
   les tendre, et depuis cette unité il ne fait plus semblant : il dit ce que l'exercice demande
   et il mène à la feuille. Trente-sept d'entre eux réclamaient jusqu'ici une réponse TAPÉE.

   La boîte est celle de `.ex-help` — même rayon, même lumière école, même encre — et ce n'est pas
   une coquetterie : c'est déjà la boîte « voici ce qu'il faut savoir » du lecteur, donc l'œil sait
   où regarder sans qu'on lui apprenne un second endroit. Elle ne réemploie pas la classe pour
   autant : `.ex-help` est en `display: flex` (le texte et son bouton de lecture sur une ligne) et
   porte un `display: none` piloté par le JS. Deux comportements dans une même classe finiraient
   par se marcher dessus.

   L'encre est `--school` sur `--school-soft`, la SEULE paire déjà mesurée sur ce fond dans ce
   fichier (`.ex-help`, `.ex-rub-crit p`). La seconde ligne se distingue par la taille, l'italique
   et le serif — le registre secondaire de la maison (`.ex-fb`, `.ex-rub-skip`) — et jamais par une
   encre plus pâle : `--ink-muted` sur ce fond n'a jamais été mesuré, et une porte des couleurs ne
   dit rien du contraste. TOKENS ONLY. */
.ex-papier {
  margin-top: 14px; padding: 14px;
  border-radius: var(--r-sm);
  background: var(--school-soft); border: 1px solid var(--school-line);
}
.ex-papier-l { font: 400 15px/1.45 var(--font); color: var(--school); }
.ex-papier-n { margin-top: 6px; font: italic 400 13px/1.45 var(--serif); color: var(--school); }
/* Le geste de cet exercice, donc une vraie cible : la ligne entière et 48px, exactement comme
   `.ex-duo .btn` — même raison, un pouce de parent debout. La barre, elle, garde « Suivant » :
   avancer ne demande pas d'avoir imprimé. */
.ex-papier-b {
  width: 100%; justify-content: center; min-height: 48px;
  margin-top: 12px; padding: 12px 14px; font-size: 14.5px;
}
.ex-papier-b svg { width: 14px; height: 14px; }

/* ── Les 61 · 1 · LA DICTÉE — le texte, pour celui qui lit ──────────────────────────────────
   La grammaire de `.ex-papier` (même boîte, même lumière école) : c'est la même chose qui se
   dit — « celui-ci ne se joue pas tout seul sur l'écran ». Le texte révélé est en 18px et en
   600 : il est fait pour être LU À VOIX HAUTE par quelqu'un qui tient le téléphone à bout de
   bras, pas pour être déchiffré par l'enfant. TOKENS ONLY. */
.ex-dictee {
  margin-top: 14px; padding: 14px;
  border-radius: var(--r-sm);
  background: var(--school-soft); border: 1px solid var(--school-line);
}
.ex-dictee-l { font: 400 15px/1.45 var(--font); color: var(--school); }
.ex-dictee-b {
  width: 100%; justify-content: center; min-height: 48px;
  margin-top: 12px; padding: 12px 14px; font-size: 14.5px;
}
.ex-dictee-b svg { width: 14px; height: 14px; }
.ex-dictee-t { margin-top: 12px; font: 600 18px/1.4 var(--font); color: var(--ink); white-space: pre-line; }
