/* Fabloteca — jetons de la charte graphique.
 *
 * Reprend `contexte/charte-graphique-fabloteca.md` §7, avec la correction de
 * l'incohérence B8 : dans la charte, les jetons d'usage n'étaient définis que
 * sous [data-theme], si bien qu'une page sans attribut n'avait aucune couleur.
 * Ils sont ici sur :root, et les trois états du thème sont couverts —
 * préférence système, choix explicite clair, choix explicite sombre.
 */

:root {
  /* Marque */
  --nuit: #0B1628;
  --nuit-2: #111F33;
  --or: #D8AD62;
  /* Or assombri, utilisable sur papier. La charte interdit à juste titre
     `--or` en mode clair : sur `--papier` il tombe à 1,73 de contraste. Mais
     l'interdire sans donner de remplaçant fait disparaître la couleur d'accent
     de la marque sur la moitié des écrans (incohérence B9).
     `#8A6A20` donne 4,18 sur `--papier` et 4,76 sur `--papier-clair` : au-delà
     du seuil des éléments non textuels et des grands textes. */
  --or-fonce: #8A6A20;
  --papier: #F3E9D2;

  /* Neutres */
  --encre: #171A1A;
  --gris: #6B6E73;
  --papier-clair: #FBF8F1;
  --bordure-claire: #E8DDC7;
  --bordure-sombre: #26354A;

  /* États */
  --erreur-clair: #98342A;   --erreur-sombre: #EE9A88;
  --succes-clair: #3A6247;   --succes-sombre: #93CCA6;
  --alerte-clair: #7E5A10;   --alerte-sombre: #EFC97A;

  /* Typographie */
  --recit: "Lora", Georgia, serif;
  --interface: "Nunito Sans", -apple-system, BlinkMacSystemFont, Arial, sans-serif;

  --texte-xs: 0.75rem;  --texte-sm: 0.875rem;  --texte-bouton: 0.9375rem;
  --texte-base: 1rem;   --texte-recit-mobile: 1.125rem; --texte-recit: 1.1875rem;
  --texte-lg: 1.25rem;  --texte-xl: 1.5rem;    --texte-2xl: 1.625rem;
  --texte-3xl: 2rem;    --texte-4xl: 2.5rem;

  --espace-1: .25rem; --espace-2: .5rem;  --espace-3: .75rem; --espace-4: 1rem;
  --espace-5: 1.25rem; --espace-6: 1.5rem; --espace-8: 2rem;  --espace-10: 2.5rem;
  --espace-12: 3rem;  --espace-16: 4rem;

  --rayon-sm: 6px; --rayon-md: 10px; --rayon-lg: 16px;

  --mouvement-vif: 200ms; --mouvement-base: 300ms; --mouvement-lent: 350ms;
  --courbe: cubic-bezier(0.22, 0.61, 0.36, 1);

  --largeur-lecture: 42.5rem;

  /* Rôles — mode clair par défaut, jamais laissés indéfinis. */
  --fond: var(--papier);
  --fond-2: var(--papier-clair);
  --texte: var(--encre);
  --texte-2: #45484B;
  --accent: var(--nuit);
  --bordure: var(--bordure-claire);
  --anneau: var(--nuit);
  --erreur: var(--erreur-clair);
  --succes: var(--succes-clair);
  --alerte: var(--alerte-clair);
  --lueur: var(--or-fonce);
}

/* Préférence système, sauf si le lecteur a explicitement choisi le mode clair. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --fond: var(--nuit); --fond-2: var(--nuit-2);
    --texte: var(--papier-clair); --texte-2: var(--papier);
    --accent: var(--or); --bordure: var(--bordure-sombre); --anneau: var(--or);
    --erreur: var(--erreur-sombre); --succes: var(--succes-sombre); --alerte: var(--alerte-sombre);
    --lueur: var(--or);
  }
}

/* Choix explicite — il l'emporte dans les deux sens. */
:root[data-theme="dark"] {
  --fond: var(--nuit); --fond-2: var(--nuit-2);
  --texte: var(--papier-clair); --texte-2: var(--papier);
  --accent: var(--or); --bordure: var(--bordure-sombre); --anneau: var(--or);
  --erreur: var(--erreur-sombre); --succes: var(--succes-sombre); --alerte: var(--alerte-sombre);
  --lueur: var(--or);
}

*, *::before, *::after { box-sizing: border-box; }
body, h1, h2, h3, p, figure, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }

/* La couleur de fond est posée sur la racine **et** sur le corps. La zone de
   rebond d'iOS — celle qu'on découvre en tirant sur une page déjà en haut —
   prend celle de la racine : sans elle, tirer sur un récit en mode veillée
   ouvre une bande blanche en haut de la chambre. */
html {
  background: var(--fond);
  /* Sans cela, iOS grossit de lui-même le texte au passage en paysage, et le
     récit change de corps entre deux orientations. */
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--fond);
  color: var(--texte);
  font-family: var(--interface);
  font-size: var(--texte-base);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Le rectangle gris que pose iOS sur tout ce qu'on touche appartient au
   système, pas à la marque. On le remplace par un voile de la couleur de
   lueur — le même geste que le bord qui s'éclaire à l'approche, en version
   tactile. */
a, button, summary, label, select, .idee, .vignette, .volume {
  -webkit-tap-highlight-color: rgba(216, 173, 98, .18);
}

h1, h2, h3, .recit { font-family: var(--recit); }
h1 { font-size: var(--texte-3xl); line-height: 1.15; font-weight: 700; }
h2 { font-size: var(--texte-xl); line-height: 1.2; font-weight: 600; }
h3 { font-size: var(--texte-lg); line-height: 1.25; font-weight: 600; }

a { color: var(--accent); }

:focus-visible { outline: 2px solid var(--anneau); outline-offset: 2px; }

/* --- Le symbole de la marque -------------------------------------------- */

/* Le logo livré est un PNG doré, en un seul exemplaire. La charte §3.2 en
   veut deux : nuit sur papier, or sur nuit. On ne garde donc du fichier que
   son canal alpha et on le teinte ici — `background-color` traverse le
   masque, exactement comme `currentColor` remplissait l'ancien SVG. Un seul
   fichier, les trois états du thème couverts, et l'animation de l'écran
   d'attente continue de porter. */
/* Le symbole de la marque est posé par masque : le fichier ne donne que sa
   forme, la couleur vient du CSS. Une seule déclaration pour tout le produit —
   l'en-tête, l'écran d'attente et l'échelle de notation — parce qu'un fichier
   remplacé ne doit pas obliger à corriger le rapport d'aspect à trois endroits.
   Il l'a déjà fallu une fois. */
.symbole, .symbole-note {
  aspect-ratio: 514 / 670;
  -webkit-mask: url("marque/symbole.png") center / contain no-repeat;
          mask: url("marque/symbole.png") center / contain no-repeat;
}
.symbole {
  display: inline-block; vertical-align: middle;
  background-color: currentColor;
}

/* --- Charpente ---------------------------------------------------------- */

/* Les marges latérales et basse tiennent compte des zones que le matériel
   confisque : l'encoche en paysage, la barre de geste en bas. `max()` garde
   la marge de la charte partout où il n'y a rien à contourner — sur un
   ordinateur, `env()` vaut zéro et l'expression retombe sur `--espace-4`. */
.enveloppe {
  max-width: 60rem; margin: 0 auto;
  padding: var(--espace-4);
  padding-left: max(var(--espace-4), env(safe-area-inset-left));
  padding-right: max(var(--espace-4), env(safe-area-inset-right));
  padding-bottom: max(var(--espace-8), env(safe-area-inset-bottom));
}

.entete {
  display: flex; align-items: center; gap: var(--espace-4);
  padding: var(--espace-4); border-bottom: 1px solid var(--bordure);
  padding-left: max(var(--espace-4), env(safe-area-inset-left));
  padding-right: max(var(--espace-4), env(safe-area-inset-right));
  padding-top: calc(var(--espace-4) + env(safe-area-inset-top));
  flex-wrap: wrap;
}
.entete .marque {
  display: flex; align-items: center; gap: var(--espace-3);
  font-family: var(--recit); font-size: var(--texte-lg); font-weight: 600;
  color: var(--texte); text-decoration: none;
  /* Ce qui pousse tout le reste à droite. Portée par le nom plutôt que par la
     navigation, la poussée tient même quand le compteur de lanternes n'est
     pas là — il s'affiche sous condition, la marge automatique non. */
  margin-right: auto;
}
.entete .marque .symbole { height: 2rem; color: var(--accent); }
.entete .reglages > nav {
  display: flex; gap: var(--espace-4); align-items: center; flex-wrap: wrap;
}
/* Sur grand écran, le dépliant n'est pas un menu : c'est une barre de liens,
   et son bouton n'a rien à faire là. Il ne réapparaît qu'au téléphone, tout
   en bas de cette feuille. */
.entete .reglages > summary { display: none; }

/* --- Lanternes : le compteur d'unités (D-016) --------------------------- */

.lanternes { display: flex; align-items: center; gap: var(--espace-2); }
.lanternes svg { width: 1.15rem; height: 1.4rem; }
.lanternes .allumee { color: var(--lueur); }
.lanternes .eteinte { color: var(--bordure); }
.lanternes .legende { font-size: var(--texte-sm); color: var(--texte-2); }

/* --- Cartes et boutons -------------------------------------------------- */

.carte {
  background: var(--fond-2); border: 1px solid var(--bordure);
  border-radius: var(--rayon-lg); padding: var(--espace-6);
  margin-bottom: var(--espace-4);
}
.grille { display: grid; gap: var(--espace-4); grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); }

.bouton {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--espace-2);
  font-family: var(--interface); font-size: var(--texte-bouton); font-weight: 700;
  padding: var(--espace-3) var(--espace-5); border-radius: var(--rayon-md);
  border: 1px solid transparent; cursor: pointer; text-decoration: none;
  /* Grandes zones tactiles : le produit s'utilise d'une seule main, dans le noir. */
  min-height: 2.75rem;
  transition: opacity var(--mouvement-vif) var(--courbe);
}
.bouton:hover { opacity: .88; }
.bouton-principal { background: var(--accent); color: var(--fond); }
.bouton-discret { background: transparent; color: var(--texte); border-color: var(--bordure); }

label { display: block; font-weight: 500; margin-bottom: var(--espace-2); }
/* `email` et `password` sont arrivés avec les écrans de compte (D-042). Sans
   eux dans cette liste, le navigateur rend ses propres boîtes étroites au
   milieu d'une page à la charte : le premier écran du produit était le seul à
   ne pas lui ressembler. */
input[type=text], input[type=email], input[type=password],
input[type=number], textarea, select {
  width: 100%; padding: var(--espace-3); font: inherit;
  color: var(--texte); background: var(--fond);
  border: 1px solid var(--bordure); border-radius: var(--rayon-md);
}
textarea { min-height: 6rem; resize: vertical; }
.champ { margin-bottom: var(--espace-5); }
.aide { font-size: var(--texte-sm); color: var(--texte-2); margin-top: var(--espace-2); }
.erreur { color: var(--erreur); font-size: var(--texte-sm); margin-top: var(--espace-2); }

.choix { display: flex; gap: var(--espace-3); flex-wrap: wrap; }
.choix label {
  border: 1px solid var(--bordure); border-radius: var(--rayon-md);
  padding: var(--espace-3) var(--espace-4); cursor: pointer; margin: 0;
  display: flex; gap: var(--espace-2); align-items: center;
}
.choix input { margin: 0; }
/* Les cases et boutons radio du navigateur prennent sa couleur système —
   un bleu qui n'appartient pas à la marque. */
input[type=checkbox], input[type=radio] { accent-color: var(--accent); width: 1.05rem; height: 1.05rem; }

/* --- Lecture ------------------------------------------------------------ */

.lecture { max-width: var(--largeur-lecture); margin: 0 auto; }
.lecture .texte {
  font-family: var(--recit); font-size: var(--texte-recit); line-height: 1.6;
}
.lecture .texte p { margin-bottom: 1.25em; }

/* Suivi du texte pendant l'écoute.
 *
 * Le texte au repos est volontairement un peu retiré, et la phrase en cours
 * revient à la pleine valeur. C'est l'inverse du surligneur : rien ne
 * s'allume, c'est le reste qui s'efface. Dans une chambre sombre, une bande
 * de couleur derrière un mot est agressive ; une différence de densité ne
 * l'est pas.
 */
.texte.suivi .phrase { color: var(--texte-2); transition: color var(--mouvement-base) var(--courbe); }
.texte.suivi .phrase.dite { color: var(--texte); }

/* Un filet dans la marge, à la hauteur de la phrase dite : de quoi la
   retrouver d'un coup d'œil sans quitter la ligne des yeux. */
.texte.suivi .phrase.dite { box-shadow: -0.75rem 0 0 -0.6rem var(--lueur); }

@media (prefers-reduced-motion: reduce) {
  .texte.suivi .phrase { transition: none; }
}
@media (max-width: 40rem) { .lecture .texte { font-size: var(--texte-recit-mobile); } }

/* Le lecteur natif est blanc, et un rectangle blanc dans une chambre sombre
   éblouit celui qui vient de s'asseoir au bord du lit. On le pose sur une
   surface de la marque et on le tempère. */
.lecteur {
  background: var(--fond-2); border: 1px solid var(--bordure);
  border-radius: var(--rayon-lg); padding: var(--espace-3);
  margin: var(--espace-6) 0;
}
audio { width: 100%; display: block; }
:root[data-theme="dark"] audio,
:root:not([data-theme="light"]) audio { filter: invert(.92) hue-rotate(180deg); }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) audio { filter: none; } }

/* --- Écran d'attente ---------------------------------------------------- */

.attente { text-align: center; padding: var(--espace-16) var(--espace-4); }
.attente .symbole { height: 6.25rem; color: var(--accent); animation: respirer 3.5s ease-in-out infinite; }
.attente .phrase { font-family: var(--recit); font-size: var(--texte-lg); margin-top: var(--espace-8); }
.attente .sous { color: var(--texte-2); font-size: var(--texte-sm); margin-top: var(--espace-3); }

/* Une respiration, pas une barre de progression trompeuse (charte §6). */
@keyframes respirer {
  0%, 100% { opacity: .45; transform: scale(.98); }
  50%      { opacity: 1;   transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

.discret { color: var(--texte-2); font-size: var(--texte-sm); }
.vide { text-align: center; padding: var(--espace-12) var(--espace-4); color: var(--texte-2); }
/* Sous le nom du lieu, la promesse de la marque : subordonnée au titre, mais
   en Lora, parce qu'elle appartient déjà au récit. */
.promesse { font-size: var(--texte-2xl); line-height: 1.2; color: var(--texte); margin-top: var(--espace-4); }
.bandeau {
  border: 1px solid var(--bordure); border-left: 3px solid var(--alerte);
  border-radius: var(--rayon-md); padding: var(--espace-4); margin-bottom: var(--espace-6);
  font-size: var(--texte-sm);
}

/* --- La fiche ------------------------------------------------------------
   Un formulaire de neuf questions alignées ne dit pas au parent ce qui
   compte, ni combien de temps ça prend. Trois groupes le disent, et ils
   correspondent à trois natures de question réelles : ce qu'on sait, ce qui
   rend l'enfant reconnaissable, une décision sur les histoires.

   Le titre de groupe reprend exactement le traitement de `figcaption` dans le
   portrait — petites capitales, interlettrage, gris de lecture. Un seul
   dispositif d'étiquetage dans l'écran plutôt que deux qui se ressemblent. */
.groupe {
  border: 0;
  padding: 0;
  margin: 0 0 var(--espace-10);
}
.groupe:last-of-type { margin-bottom: var(--espace-8); }

/* Pas de filet de séparation : `legend` se pose **sur** la bordure d'un
   fieldset, et le trait traversait son propre titre. L'espace et l'étiquette
   en petites capitales séparent aussi bien, et ne peuvent pas casser. */
.groupe > legend {
  font-size: var(--texte-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--texte-2);
  padding: 0;
  margin-bottom: var(--espace-4);
}

/* Un mois et une année sont une seule réponse. Empilés sur deux lignes
   pleines, ils se lisaient comme deux champs sans rapport, tous deux vides. */
.duo { display: flex; gap: var(--espace-3); }
.duo select { flex: 1 1 0; min-width: 0; }

/* --- Choisir : une bande à cases égales ----------------------------------
   Les mêmes réponses en `.choix` formaient un escalier — chaque pastille à la
   largeur de son texte, sept liens en 2-2-2-1 — et l'œil lisait du désordre
   avant de lire des options. Une grille à cases égales range tout seule, quel
   que soit le nombre de réponses et la longueur des libellés.

   La case native disparaît : la sélection se lit au trait d'or et à la
   graisse. Deux signes pour une seule idée en font un de trop, et le rond du
   navigateur était le seul élément de l'écran à ne rien devoir à la charte. */
.segments {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: var(--espace-2);
}
.segments label {
  position: relative;
  margin: 0;
  padding: var(--espace-3) var(--espace-4);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-md);
  background: var(--fond);
  color: var(--texte-2);
  font-weight: 400;
  cursor: pointer;
  display: flex;
  align-items: center;
}
.segments label:hover { border-color: var(--texte-2); }
/* Retirée de l'affichage, gardée au clavier : c'est elle qui reçoit le focus,
   et le contour se reporte sur la case qui l'entoure. */
.segments input {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}
.segments label:has(input:checked) {
  background: var(--fond-2);
  color: var(--texte);
  font-weight: 600;
  border-color: var(--lueur);
  box-shadow: inset 0 -2px 0 var(--lueur);
}
.segments label:has(input:focus-visible) {
  outline: 2px solid var(--anneau);
  outline-offset: 2px;
}
/* Une échelle se parcourt : quatre crans plus larges, du plus présent au plus
   absent, et non quatre options rangées n'importe comment. */
.segments-echelle { grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }

/* --- Écrire : la phrase, à trous -----------------------------------------
   Les quatre traits sont le cœur de l'exercice, et le seul endroit du produit
   où un parent écrit librement sur quelqu'un de réel. Ils ne sont donc pas des
   champs : ils sont la phrase que le conteur lira, avec un blanc à remplir.

   L'amorce est en Lora, celle-là même qui partira au récit. Le parent écrit
   dans sa suite, sur une ligne réglée — il voit ce qu'il écrit pendant qu'il
   l'écrit, au lieu de répondre à une question et de découvrir la phrase à
   droite. C'est là que se dépense la singularité de l'écran ; tout le reste
   est tenu au calme.

   Réglé **exactement comme `.portrait p`** — même face, même corps, même
   interligne : la ligne de gauche et la ligne de droite sont la même phrase à
   deux moments de sa vie, et rien ne le dit mieux que de les composer pareil.
   Un corps plus grand paraissait plus « récit », mais coupait les exemples au
   milieu d'un mot, et un exemple tronqué ressemble à une panne. */
.trait {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .1em .45em;
  margin: 0 0 var(--espace-6);
  font-family: var(--recit);
  font-size: var(--texte-base);
  font-weight: 400;
  line-height: 1.6;
  cursor: text;
}
/* L'amorce est donnée, la suite est écrite. Elle recule d'un cran pour que
   l'œil tombe sur ce que le parent a apporté — sans s'effacer, car elle fait
   partie de la phrase et non du décor. */
.trait .amorce { color: var(--texte-2); opacity: .72; }
.trait input[type=text] {
  flex: 1 1 16rem;
  width: auto;
  min-width: 0;
  font: inherit;
  color: var(--texte);
  background: transparent;
  border: 0;
  border-bottom: 1px dashed var(--lueur);
  border-radius: 0;
  padding: 0 .15em .2em;
}
.trait input[type=text]::placeholder { color: var(--texte-2); opacity: .55; }
.trait input[type=text]:focus-visible {
  outline: none;
  border-bottom: 2px solid var(--lueur);
  padding-bottom: calc(.2em - 1px);
}
/* Le texte libre reprend la boîte ordinaire : ce n'est pas une phrase à
   compléter mais un espace ouvert, et lui donner la même ligne réglée
   promettrait une seule ligne. */
.champ-libre { margin-top: var(--espace-8); }

/* --- Le portrait ---------------------------------------------------------
   Le seul composant neuf de l'écran de description, et le seul endroit où
   l'on dépense de la singularité : ailleurs, .carte et .champ suffisent.

   Il est en Lora parce que c'est la police du récit (charte §4.2 : « Lora
   raconte, Nunito Sans accompagne »). Le parent ne lit pas un aperçu de
   formulaire, il lit les premières lignes de l'histoire de son enfant — et
   c'est la typographie qui le lui dit, avant tout texte d'explication. */
.portrait {
  margin: 0 0 var(--espace-6);
  padding: var(--espace-6);
  background: var(--fond-2);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-lg);
  /* Le filet d'or à gauche : la marge d'un livre, pas un bandeau d'alerte. */
  border-left: 3px solid var(--lueur);
}
.portrait figcaption {
  font-family: var(--interface);
  font-size: var(--texte-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--texte-2);
  margin-bottom: var(--espace-4);
}
.portrait p {
  font-family: var(--recit);
  font-size: var(--texte-base);
  line-height: 1.6;
  color: var(--texte);
}
.portrait p + p { margin-top: var(--espace-2); }
.portrait .tete {
  font-size: var(--texte-lg);
  font-weight: 600;
}
.portrait .attente-portrait {
  font-family: var(--interface);
  font-size: var(--texte-sm);
  color: var(--texte-2);
}
/* Chaque ligne arrive doucement quand elle se complète. Une seule animation,
   courte, et neutralisée par la règle générale de mouvement réduit plus bas. */
.portrait p.neuve { animation: apparaitre var(--mouvement-base) var(--courbe); }
@keyframes apparaitre {
  from { opacity: 0; transform: translateY(.25rem); }
  to   { opacity: 1; transform: none; }
}

/* L'atelier : le formulaire d'un côté, le portrait de l'autre.
   Plus large que .lecture, qui est calibrée pour lire un récit et non pour
   écrire à côté de ce qu'on écrit.

   Une première version posait le portrait au-dessus du formulaire et le
   rendait collant. Il recouvrait les champs en défilant — « Quel âge ? »
   disparaissait derrière. Deux colonnes suppriment le recouvrement au lieu de
   l'arbitrer, et le portrait reste sous les yeux pendant toute la saisie.

   Sur petit écran, une seule colonne : le portrait passe en tête, lu avant de
   commencer, et sans rien recouvrir puisqu'il ne colle plus. */
.atelier { max-width: 62rem; margin: 0 auto; }
.atelier-grille { display: grid; gap: var(--espace-6); }

@media (min-width: 60rem) {
  .atelier-grille {
    grid-template-columns: 1fr 22rem;
    align-items: start;
  }
  .atelier-grille .portrait {
    order: 2;
    position: sticky;
    top: var(--espace-4);
    margin: 0;
    /* Une page réservée plutôt qu'un petit encadré flottant dans du noir.
       Tant que rien n'est écrit, le bloc garde la hauteur de ce qui viendra —
       c'est une promesse tenue à l'œil, et le filet d'or lui donne sa marge. */
    min-height: 13rem;
  }
  .atelier-grille .carte { order: 1; }
}

/* Le portrait rédigé remplace l'aperçu mécanique. Même bloc, même filet d'or :
   c'est le même objet qui mûrit, pas un second encadré. */
.portrait .redige { font-size: var(--texte-lg); line-height: 1.65; }
.portrait .ecrit {
  font-family: var(--interface);
  font-size: var(--texte-xs);
  letter-spacing: 0;
  text-transform: none;
  color: var(--lueur);
}
.portrait .reecrire { margin-top: var(--espace-5); }

/* --- L'arbre -------------------------------------------------------------
   L'arbre porte toute la famille : il n'y a plus de liste en dessous pour le
   doubler. Chaque carte est donc un **vrai lien HTML**, posé par-dessus un SVG
   qui ne trace plus que les branches.

   Pourquoi ne pas tout garder en SVG : un `<text>` ne se coupe pas en points de
   suspension, ne porte pas de survol lisible, et un arbre-image doublé d'une
   liste disait deux fois les mêmes personnes. Les liens s'ouvrent au clic, se
   parcourent au clavier, et laissent paraître la description au survol — rien
   de tout cela ne s'obtient dans un dessin sans le réécrire à la main.

   Les deux couches s'alignent par une seule variable, `--u` : le serveur rend
   des coordonnées en unités de dessin, et la CSS les multiplie. Le cadre prend
   sa taille de la même multiplication, si bien que traits et cartes ne peuvent
   pas se désaligner.

   Pas de mise à l'échelle : un arbre qui rétrécit pour tenir dans la colonne
   finit par écrire les prénoms en six pixels. Il garde sa taille et défile
   quand il déborde, comme un arbre imprimé qu'on déplie.

   Aucune couleur en dur : les traits et les cadres prennent les jetons de la
   charte, donc le dessin suit le mode veillée sans rien savoir de lui. */
.arbre {
  margin: 0 0 var(--espace-8);
  padding: var(--espace-4) 0;
  overflow-x: auto;
  /* Sert de repère de mesure au dessin : `100cqi` ci-dessous, c'est la largeur
     réellement disponible, et non celle de la fenêtre. */
  container-type: inline-size;
}
.arbre-plan {
  /* L'unité de dessin s'ajuste à la place disponible. Une petite famille
     s'installe au lieu de se recroqueviller au milieu d'un écran vide ; une
     grande garde la taille d'avant et défile, plutôt que d'écrire les prénoms
     en six pixels.

     Le plancher est donc la vraie règle — on ne rétrécit jamais — et le plafond
     empêche une carte de devenir une pancarte quand la famille tient en trois
     personnes. */
  --u: clamp(.085rem, calc(100cqi / var(--largeur)), .105rem);
  position: relative;
  width: calc(var(--largeur) * var(--u));
  height: calc(var(--hauteur) * var(--u));
  margin: 0 auto;
}
.arbre .branches { position: absolute; inset: 0; width: 100%; height: 100%; }
/* Les branches tirent sur l'or de la pastille, pas sur le gris d'une bordure :
   une bordure sépare deux surfaces et peut donc s'effacer, une branche porte
   une information et doit se suivre à l'œil. Atténuées, pour que les prénoms
   restent au premier plan. */
.arbre .branche {
  fill: none;
  stroke: var(--lueur);
  stroke-width: 1.8;
  opacity: 0.55;
  /* Les segments sont des chemins séparés : arrondir leurs extrémités adoucit
     les angles là où ils se rejoignent. Un arbre tracé plutôt qu'un schéma. */
  stroke-linecap: round;
}

.arbre-cartes { list-style: none; margin: 0; padding: 0; }
.arbre-cartes > li {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--carte-l) * var(--u));
  height: calc(var(--carte-h) * var(--u));
}
/* Survolée, la carte passe au-dessus de ses voisines : sinon sa bulle glisse
   sous la génération du dessous. */
.arbre-cartes > li:has(a:hover), .arbre-cartes > li:has(a:focus-visible) { z-index: 3; }
.arbre-cartes a {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--espace-3);
  width: 100%;
  height: 100%;
  padding: 0 var(--espace-4);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-md);
  background: var(--fond-2);
  color: inherit;
  text-decoration: none;
  font-family: var(--recit);
}
/* Un prénom trop long se coupe plutôt que de déborder ou de rétrécir : réduire
   la police d'un seul nom rendrait les cartes inégales, et c'est l'égalité qui
   fait lire une génération comme une ligne. */
.arbre-cartes .prenom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Les quatre crans de présence, lus sur la carte entière.
   Une pastille pleine ou creuse ne disait que deux états sur quatre : on voyait
   qui paraissait, jamais à quelle fréquence. La carte le dit maintenant, et la
   pastille a disparu — deux dispositifs pour une seule idée en faisaient un de
   trop.

   Une seule couleur, l'or de la charte, à quatre intensités. Quatre teintes
   auraient introduit une palette que la marque n'a pas, et un code couleur à
   apprendre ; une intensité se lit sans légende, parce qu'elle dit la même
   chose que le mot — plus présent, moins présent.

   **Un liseré épais, pas une bordure teintée.** Un cadre d'un pixel qui change
   de nuance est un signal trop faible à cette taille : les quatre crans se
   ressemblaient tous. Le liseré reprend le filet d'or de la fiche de portrait,
   qui est déjà une signature de la marque.

        au cœur      liseré plein, et la carte se réchauffe
        souvent      liseré aux deux tiers
        de temps     liseré au quart
        jamais       pas de liseré, cadre en pointillé, sur le fond de la page

   Le mot reste à un survol, et il est dans le nom du lien : ce dégradé aide
   l'œil, il ne porte rien tout seul. */
.arbre-cartes a { border-left-width: 4px; border-left-color: var(--bordure); }
.arbre-cartes a[data-role="heros"] {
  border-left-color: var(--lueur);
  background: color-mix(in srgb, var(--lueur) 16%, var(--fond-2));
}
.arbre-cartes a[data-role="recurrent"] {
  border-left-color: color-mix(in srgb, var(--lueur) 65%, var(--bordure));
}
.arbre-cartes a[data-role="episodique"] {
  border-left-color: color-mix(in srgb, var(--lueur) 28%, var(--bordure));
}
/* `data-parait` et non `data-role="jamais"` : c'est `apparait()` qui décide de
   ce qui paraît, et le redire ici en nommant un cran ferait de la feuille de
   style un second juge. */
.arbre-cartes a[data-parait="non"] {
  border: 1px dashed var(--bordure);
  background: transparent;
  color: var(--texte-2);
}
/* L'étoile du héros, poussée au bord opposé au liseré : le cran d'un côté, le
   rôle de l'autre, et le prénom entre les deux. Elle ne dit rien qu'un lecteur
   d'écran doive entendre — la fréquence est déjà dans le nom du lien. */
.arbre-cartes .etoile {
  flex: none;
  margin-left: auto;
  width: 1.35rem;
  height: 1.35rem;
  color: var(--lueur);
}

/* Le survol ne mange pas le liseré : il éclaire le tour, pas le cran. */
.arbre-cartes a:hover { border-top-color: var(--lueur); border-right-color: var(--lueur); border-bottom-color: var(--lueur); }

/* La description au survol. Elle vivait sur une ligne de liste ; elle vient
   maintenant à la personne qu'on regarde, et ne se lit que pour elle. Au
   clavier aussi : `:focus-visible` ouvre la même bulle, sans quoi la moitié des
   informations serait réservée à la souris. */
.arbre-cartes .souffle {
  position: absolute;
  top: calc(100% + .4rem);
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  width: max-content;
  max-width: 17rem;
  display: grid;
  gap: var(--espace-2);
  padding: var(--espace-3) var(--espace-4);
  background: var(--fond);
  border: 1px solid var(--lueur);
  border-radius: var(--rayon-md);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--mouvement-vif) var(--courbe);
}
.arbre-cartes a:hover .souffle,
.arbre-cartes a:focus-visible .souffle { opacity: 1; visibility: visible; }
/* Le dernier rang ouvre vers le haut : sous lui il n'y a plus de cadre, et une
   bulle cachée compte quand même dans le débordement — le bloc gagnait une
   barre de défilement verticale sans que rien ne dépasse à l'œil. */
.arbre-cartes a[data-bas="oui"] .souffle { top: auto; bottom: calc(100% + .4rem); }
/* Aux extrémités, la bulle s'aligne sur le bord de sa carte plutôt que d'être
   centrée dessus. Centrée, elle dépassait du cadre — et ce qui dépasse à gauche
   d'une zone défilante est coupé sans recours, on ne peut même pas y faire
   défiler. */
.arbre-cartes a[data-bord="gauche"] .souffle { left: 0; transform: none; }
.arbre-cartes a[data-bord="droite"] .souffle { left: auto; right: 0; transform: none; }
/* `.situation` et non `.place` : la charte a déjà une pastille bordée qui
   porte ce nom, et elle s'invitait dans la bulle avec son cadre. */
.arbre-cartes .situation {
  font-family: var(--interface);
  font-size: var(--texte-xs);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--texte-2);
}
.arbre-cartes .dit { font-family: var(--recit); font-size: var(--texte-sm); line-height: 1.5; }

/* --- L'écran de la famille -----------------------------------------------
   Un plan, pas une page de lecture : il sort de la colonne de texte et va d'un
   bord à l'autre de la fenêtre. Une famille de six personnes tenait à peine
   dans les 42 rem de `.lecture`, et défilait dès la septième — au milieu d'un
   écran vide aux deux tiers.

   `calc(50% - 50vw)` de chaque côté : la moitié de la boîte qui contient, moins
   la moitié de la fenêtre. Tous les cadres au-dessus étant centrés, cela ramène
   exactement aux deux bords, quelle que soit leur largeur. L'écriture reste
   juste si `.enveloppe` change de mesure demain.

   Le texte, lui, ne s'étire pas : une ligne de cent caractères ne se lit plus. */
/* `.plan-famille` et non `.famille` : la charte a déjà une `.famille` — une
   étiquette en petites capitales — et tout l'écran est passé en majuscules.
   Troisième collision de nom sur cette feuille : elle n'a pas de portée, il
   faut regarder avant de nommer. */
.plan-famille {
  margin-inline: calc(50% - 50vw);
  /* Le même retrait que l'en-tête, pour que le titre de l'écran tombe sous le
     nom de la marque plutôt qu'un peu à côté. */
  padding-left: max(var(--espace-4), env(safe-area-inset-left));
  padding-right: max(var(--espace-4), env(safe-area-inset-right));
}
.plan-famille > h1 { max-width: var(--largeur-lecture); }

/* Le chapeau de l'écran, et la porte pour agrandir la famille. Le bouton vit au
   niveau de l'arbre parce que c'est là que se lit qui manque. */
.famille-tete {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--espace-4);
  flex-wrap: wrap;
  margin: .75rem 0 1.5rem;
}
.famille-tete .discret { flex: 0 1 34rem; margin: 0; }
.famille-tete .ajouter { flex: none; display: inline-flex; align-items: baseline; gap: var(--espace-2); }
.famille-tete .signe { font-size: var(--texte-lg); line-height: 1; }

/* La liste de secours : elle ne paraît que si l'arbre a refusé de se dessiner,
   pour que les fiches restent joignables et le cycle corrigeable. */
.secours { list-style: none; margin: var(--espace-5) 0 var(--espace-8); padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--espace-3); }
.secours a { color: inherit; }

/* La légende de l'arbre : ce qu'il ne peut pas encore montrer. Discrète, parce
   qu'une famille sans filiation saisie n'a rien fait de mal. */
.arbre .detaches {
  margin-top: var(--espace-4);
  font-size: var(--texte-sm);
  color: var(--texte-2);
  line-height: 1.6;
}
.arbre .detaches a { color: inherit; text-underline-offset: 3px; }

.portrait-vignette { display: block; text-decoration: none; color: inherit; }
.portrait-vignette p { font-family: var(--recit); line-height: 1.5; }
.portrait-vignette .tete { font-size: var(--texte-lg); font-weight: 600; }
/* La place tenue dans les aventures. Même champ `role` pour un enfant et
   pour un habitant, donc même pastille — elle a quitté le scope de la
   vignette le jour où l'écran d'univers a listé ses habitants. */
.place {
  display: inline-block;
  font-family: var(--interface);
  font-size: var(--texte-xs);
  color: var(--texte-2);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-sm);
  padding: 0 var(--espace-2);
}
.portrait-vignette .place { margin-bottom: var(--espace-3); }
.portrait-vignette:hover { border-color: var(--lueur); }

/* --- Le rayon ------------------------------------------------------------
   L'écran d'accueil, et le seul endroit du produit où l'on dépense de la
   singularité après le portrait.

   Un univers n'est pas une carte de tableau de bord — la charte §1 les
   proscrit — mais une **niche** : le symbole de la marque (§2.1), la voûte
   sous laquelle on rangeait les manuscrits. Les cotes sont celles de §2.2,
   pas une approximation : largeur 4 M, hauteur 5 M, voûte de rayon 2 M.
   D'où `aspect-ratio: 4/5`, et une voûte qui est un demi-cercle exact —
   son rayon vertical vaut 2 M, soit 40 % d'une hauteur de 5 M.

   Une voûte timide donnerait un bouton aux coins arrondis ; une niche trop
   étroite, une pierre tombale. Ces deux nombres sont donc liés : changer
   l'un sans l'autre casse le demi-cercle. */
/* Le rayonnage — et non `.rayon`, qui nomme déjà la planche du contrôle de
   notation. Deux classes du même nom dans une seule feuille, et la dernière
   écrite gagne : ici `display: grid` devenait `inline-flex`, et la
   bibliothèque partait en morceaux sans qu'aucune erreur ne le dise. */
.rayonnage {
  display: grid;
  gap: var(--espace-4);
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  margin-top: var(--espace-6);
}

.volume {
  display: flex;
  flex-direction: column;
  aspect-ratio: 4 / 5;
  /* Sans ces deux-là, la taille minimale du contenu remonte jusqu'à la piste
     de grille : la hauteur du texte devient une largeur par `aspect-ratio`,
     qui redevient une hauteur par le padding en pourcentage. La boucle diverge
     et une niche finit par mesurer 1 144 px dans une fenêtre de 500. */
  min-width: 0;
  min-height: 0;
  /* La scène commence à 18 % de la largeur. Les deux nombres sont liés : à
     cette hauteur la voûte laisse passer une scène de 72 %, pas davantage.
     L'agrandir sans la descendre la ferait mordre par l'arc. */
  padding: 18% var(--espace-4) var(--espace-4);
  text-align: center;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  /* Un voile d'encre sur le papier de la niche : assez pour que deux mondes ne
     se ressemblent pas, trop peu pour teindre la bibliothèque. */
  background: color-mix(in oklab, var(--encre, transparent) 7%, var(--fond-2));
  border: 1px solid var(--bordure);
  border-radius: 50% 50% var(--rayon-lg) var(--rayon-lg)
               / 40% 40% var(--rayon-lg) var(--rayon-lg);
  transition: border-color var(--mouvement-vif) var(--courbe);
}
/* Approcher un volume l'éclaire — le même geste que sur les portraits. */
.volume:hover { border-color: var(--lueur); }

.volume .nom {
  font-family: var(--recit);
  font-size: var(--texte-lg);
  font-weight: 600;
  line-height: 1.2;
  /* Un nom long ne doit pas repousser l'ambiance hors de la niche. */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
  overflow: hidden;
}
/* Deux lignes depuis que la scène est là : elle dit déjà ce que la troisième
   aurait dit, et la niche n'est pas extensible. */
.volume .ambiance {
  font-size: var(--texte-sm);
  color: var(--texte-2);
  margin-top: var(--espace-2);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}
/* Collée au socle : l'épaisseur du volume se lit en bas de la tranche. */
.volume .epaisseur {
  margin-top: auto;
  padding-top: var(--espace-2);
  font-size: var(--texte-xs);
  font-weight: 500;
  color: var(--texte-2);
}
/* En or, comme une lanterne allumée : quelque chose est en train de s'écrire. */
.volume .se-prepare { display: block; color: var(--lueur); }

/* La niche vide au bout du rayon. Le trait discontinu dit la place à prendre. */
/* Elle n'a pas de scène : son libellé descend à la hauteur des noms voisins,
   sans quoi il flotterait seul en haut de la voûte. */
.volume-neuf { border-style: dashed; background: transparent; padding-top: 38%; }
.volume-neuf .nom {
  font-family: var(--interface);
  font-size: var(--texte-base);
  font-weight: 700;
  color: var(--texte-2);
}

/* --- Les habitants d'un univers ----------------------------------------- */

/* --- La scène ------------------------------------------------------------
   Le décor d'un univers, dessiné au trait comme le demande la charte §5 :
   géométrie simple, angles doux, aucun volume, aucun dégradé.

   `non-scaling-stroke` est ce qui rend le système possible : les figures sont
   mises à l'échelle pour composer une profondeur, et leur trait garderait
   sinon la même réduction — une figure d'arrière-plan à 0,58 tomberait à
   1,2 px, sous le minimum de la charte. */
/* L'encre du décor. Deux valeurs posées par le gabarit, une pour le papier et
   une pour la veillée : une seule couleur ne peut pas tenir sur les deux fonds.
   Le repli sur --texte-2 couvre les scènes qui n'en portent pas encore.

   Elle ne teint que la scène et le fond de sa niche. Ni un bouton, ni du texte,
   ni une bordure d'interface : dix couleurs lâchées dans le produit feraient
   l'arc-en-ciel que la charte §1 proscrit. */
/* Le ratio est déclaré plutôt que déduit : `height: auto` sur un SVG laisse
   sa hauteur à la discrétion du conteneur, qui l'écrasait à zéro en flex. */
/* Les trois propriétés sont nécessaires ensemble : sans `height: auto`, le SVG
   garde sa hauteur intrinsèque et `aspect-ratio` reste inerte ; sans
   `aspect-ratio`, un conteneur flex en colonne l'écrase à cinquante pixels. */
.scene { display: block; width: 100%; height: auto; aspect-ratio: 2 / 1; color: var(--encre); }

/* `--encre` se résout **là où `--encre-claire` est posée**, donc sur la niche
   et sur la scène elles-mêmes. Déclarée sur :root, elle y était calculée une
   fois pour toutes avec une encre encore inconnue, et retombait sur le repli :
   une propriété personnalisée hérite de sa valeur calculée, pas de sa formule. */
.scene, .volume { --encre: var(--encre-claire, var(--texte-2)); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .scene,
  :root:not([data-theme="light"]) .volume { --encre: var(--encre-sombre, var(--texte-2)); }
}
:root[data-theme="dark"] .scene,
:root[data-theme="dark"] .volume { --encre: var(--encre-sombre, var(--texte-2)); }

/* Les silhouettes en aplat. Un contour approximatif se lit comme du fil de fer
   à 48 px ; un aplat approximatif se lit encore comme un animal. La charte §5
   demande les deux — « trait régulier » et « silhouettes reconnaissables » —
   et sur les formes vivantes c'est la seconde qui gagne (voir incoherences.md). */
.scene .pleine path, .scene .pleine circle, .scene .pleine ellipse {
  fill: currentColor; stroke: none;
}
.scene path, .scene circle, .scene ellipse {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
/* L'horizon est le fond de scène : il recule d'un ton derrière ses figures. */
.scene .horizon { opacity: .55; }

/* Dans le tympan de la niche. La voûte descend jusqu'à la mi-largeur ; la
   scène s'y loge en haut, et le nom reprend juste dessous. */
/* `flex: none` n'est pas cosmétique : la niche est un conteneur flex en
   colonne, et un SVG y est compressible jusqu'à une hauteur nulle. Un nom long
   suffisait à faire disparaître la scène sans rien signaler. */
.volume .scene { width: 72%; margin: 0 auto var(--espace-2); flex: none; }

/* Sur téléphone, `auto-fill` ne tiendrait qu'une colonne : une seule arche
   occuperait l'écran entier, et un rayon d'un seul volume n'est pas un rayon.
   Deux colonnes imposées, avec un volume plus compact — sinon le texte déborde
   d'une niche deux fois plus petite. */
@media (max-width: 30rem) {
  .rayonnage { grid-template-columns: repeat(2, 1fr); gap: var(--espace-3); }
  .volume { padding: 14% var(--espace-3) var(--espace-3); }
  .volume-neuf { padding-top: 34%; }
  .volume .nom { font-size: var(--texte-base); }
  .volume .scene { width: 68%; }
  /* Une ligne d'ambiance sur téléphone : la scène a pris la place, et elle en
     dit autant. */
  .volume .ambiance { -webkit-line-clamp: 1; }
}

.habitants { display: flex; flex-wrap: wrap; gap: var(--espace-4); margin-top: var(--espace-4); }
.habitants li { display: flex; align-items: center; gap: var(--espace-2); }
/* La voix d'un habitant, à côté de sa place. Discrète : c'est un réglage, pas
   une information qu'on relit à chaque passage. Elle prend la couleur d'accent
   une fois donnée, parce qu'alors elle dit quelque chose de l'habitant. */
.habitants .voix {
  font-family: var(--interface);
  font-size: var(--texte-xs);
  color: var(--texte-2);
  text-decoration: none;
  border-bottom: 1px dotted var(--bordure);
}
.habitants .voix:hover { color: var(--texte); border-bottom-color: var(--lueur); }

/* Les quatre gestes d'un univers. Repris trait pour trait de l'attribut
   `style` que portait le gabarit : une règle qui a un nom peut être reprise au
   téléphone, un attribut de gabarit non. */
.actions-univers {
  display: flex; flex-wrap: wrap;
  gap: var(--espace-2);
  margin-top: var(--espace-6);
}

/* --- Le sommaire d'un univers -------------------------------------------
   Les aventures d'un univers forment une suite, pas une collection d'objets
   isolés : un filet les sépare là où une carte les aurait détachées. */
.sommaire { margin-top: var(--espace-4); }
.sommaire li {
  display: flex; align-items: center; gap: var(--espace-4);
  padding: var(--espace-4) 0;
  border-bottom: 1px solid var(--bordure);
}
.sommaire li > div { flex: 1; min-width: 0; }
.sommaire .titre { display: block; font-size: var(--texte-lg); font-weight: 600; }
.sommaire .discret, .sommaire .erreur { display: block; }

@media (max-width: 30rem) {
  .sommaire li { flex-direction: column; align-items: stretch; }
  /* Empilée, la ligne devient une carte : une note centrée à elle seule y
     flotte entre un titre à gauche et un bouton pleine largeur. Elle se remet
     donc à l'horizontale, calée à gauche avec le reste du détail. */
  .sommaire .note-lue {
    flex-direction: row; align-items: center;
    gap: var(--espace-2); align-self: flex-start;
  }
  .sommaire .note-lue .symbole-note.symbole-mini { height: 1.8rem; }
}

/* --- L'écran du décor ----------------------------------------------------
   Cinquante-six figures tiennent sur une page à condition d'être rangées :
   une planche par famille, des vignettes carrées, l'étiquette sous le trait.
   Sans étiquette, une silhouette au trait à 48 px se devine mal — et deviner
   n'est pas choisir. */

/* L'horizon en tête d'un univers : large et bas, il se lit comme une ligne
   de paysage et non comme une illustration qui prendrait la parole. */
.bandeau-scene { margin-bottom: var(--espace-6); }
.bandeau-scene .scene { max-width: 26rem; }

.apercu-volume { margin: 0 0 var(--espace-8); display: flex; justify-content: center; }
/* La niche telle qu'elle sera dans la bibliothèque, pas une vignette de
   réglage : le parent doit reconnaître sa tuile avant de valider. */
.volume-apercu { width: 15rem; cursor: default; }
.volume-apercu .nom { font-family: var(--recit); font-size: var(--texte-lg); font-weight: 600; }
.volume-apercu .ambiance { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }

fieldset { border: 0; padding: 0; margin: 0 0 var(--espace-8); }
legend { font-family: var(--recit); font-size: var(--texte-xl); font-weight: 600; padding: 0; }
.famille {
  font-family: var(--interface); font-size: var(--texte-xs); font-weight: 500;
  letter-spacing: .08em; text-transform: uppercase; color: var(--texte-2);
  margin: var(--espace-6) 0 var(--espace-3);
}

.planche { display: grid; gap: var(--espace-2); margin-top: var(--espace-3); }
.planche-decors { grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); }
.planche-figures { grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr)); }

.vignette {
  display: flex; flex-direction: column; align-items: center; gap: var(--espace-2);
  margin: 0; padding: var(--espace-3) var(--espace-2);
  border: 1px solid var(--bordure); border-radius: var(--rayon-md);
  cursor: pointer; text-align: center; font-weight: 400;
  transition: border-color var(--mouvement-vif) var(--courbe);
}
.vignette:hover { border-color: var(--lueur); }
/* La case reste dans le flux pour le lecteur d'écran et la navigation au
   clavier ; c'est la vignette entière qui montre l'état, pas une pastille. */
.vignette input { position: absolute; opacity: 0; width: 0; height: 0; }
.vignette:has(input:checked) { border-color: var(--accent); background: var(--fond-2); }
.vignette:has(input:focus-visible) { outline: 2px solid var(--anneau); outline-offset: 2px; }
.vignette .scene { width: 100%; color: var(--texte); }
.vignette .etiquette { font-size: var(--texte-xs); color: var(--texte-2); line-height: 1.3; }

/* --- Le seuil : noter la veillée ----------------------------------------
 *
 * L'arche de la marque se remplit de lumière, de bas en haut. Noter revient à
 * dire combien de lumière l'histoire a laissée dans la chambre.
 *
 * Deux versions ont été jetées avant celle-ci — cinq étoiles déguisées en
 * livres, puis les mêmes livres mieux dessinés. Cinq objets alignés restent un
 * histogramme quel que soit le soin qu'on y met. Ce qui manquait, c'était de
 * se servir de ce que la marque a déjà.
 */

.seuil { border: 0; padding: 0; margin: 0; }
.seuil legend {
  padding: 0;
  font-family: var(--recit);
  font-size: var(--texte-lg);
  color: var(--texte);
}

.seuil-commandes {
  display: flex; align-items: center; justify-content: center;
  gap: var(--espace-6);
  margin: var(--espace-6) 0 var(--espace-4);
}

/* Le même symbole, mais rempli à moitié : deux aplats superposés passent au
   travers du masque, celui du bas monte avec la note. `.symbole` ne suffit pas
   ici, il n'a qu'une couleur. */
.symbole-note {
  position: relative; display: inline-block; vertical-align: middle;
  height: 6.75rem; flex: none;
}
.symbole-note span { position: absolute; left: 0; right: 0; display: block; }
/* La part éteinte reste visible : sans elle, une note basse laisserait un
   livre ouvert flottant dans le vide. Teintée d'or plutôt que grise — c'est le
   logo endormi, pas un logo absent. */
.symbole-eteint { top: 0; bottom: 0;
                  background: color-mix(in oklab, var(--lueur) 20%, var(--bordure)); }
.symbole-lumiere { bottom: 0; background: var(--lueur);
                   transition: height var(--mouvement-base) var(--courbe); }

/* La même note, relue dans une ligne de sommaire. Deux classes pour départager
   les hauteurs, jamais l'ordre des règles : `.symbole-note.symbole-mini` gagne
   sur `.symbole-note` quelle que soit la place du bloc dans la feuille. */
.symbole-note.symbole-mini { height: 2.5rem; }
.note-lue {
  display: flex; flex-direction: column; align-items: center; gap: var(--espace-1);
  flex: none; text-align: center;
}
.note-lue .verdict-court { font-size: var(--texte-xs); color: var(--texte-2); }

.cran {
  display: grid; place-items: center;
  width: 3rem; height: 3rem;
  border: 1px solid var(--bordure); border-radius: 50%;
  background: transparent; color: var(--texte);
  cursor: pointer;
  transition: border-color var(--mouvement-vif) var(--courbe),
              color var(--mouvement-vif) var(--courbe);
}
.cran svg { width: 1.25rem; height: 1.25rem; fill: none; stroke: currentColor;
            stroke-width: 2; stroke-linecap: round; }
.cran:hover:not(:disabled) { border-color: var(--lueur); color: var(--lueur); }
/* Un bouton au bout de sa course le dit, plutôt que de laisser appuyer
   dans le vide. */
.cran:disabled { opacity: .3; cursor: default; }

.verdict {
  font-family: var(--recit);
  font-size: var(--texte-lg);
  color: var(--texte);
  text-align: center;
  min-height: 1.6em;
  margin: 0;
}

.visuellement-cache {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .symbole-lumiere { transition: none; }
}

/* --- Le chantier : ouvrir un univers -------------------------------------
   Une question par écran, et le volume qui se compose à côté.

   Rien ici n'est une carte : une question seule dans un encadré de 60 rem
   ressemble à un champ oublié sur un formulaire. La question porte la page,
   et le seul objet dessiné est le frontispice. */

.chantier { max-width: 62rem; margin: 0 auto; }

/* Le fil des cinq questions.
   Les mots eux-mêmes font la barre de progression : le filet passe sous ceux
   qui sont franchis et s'arrête à celui qu'on lit. Des numéros diraient moins
   — « 3 sur 5 » n'apprend rien que « La scène » ne dise déjà mieux. */
.fil {
  display: flex; flex-wrap: wrap; gap: var(--espace-5);
  margin-bottom: var(--espace-8);
  font-size: var(--texte-xs); letter-spacing: .08em; text-transform: uppercase;
}
.fil li {
  padding-bottom: var(--espace-2);
  border-bottom: 2px solid var(--bordure);
  color: var(--texte-2);
}
.fil li a { color: var(--texte-2); text-decoration: none; }
.fil li a:hover { color: var(--texte); }
.fil .faite { border-bottom-color: var(--lueur); }
.fil .ici { border-bottom-color: var(--lueur); color: var(--texte); font-weight: 700; }

.chantier-grille { display: grid; gap: var(--espace-8); }

/* --- Le frontispice ------------------------------------------------------
   La niche de la bibliothèque (D-027), aux mêmes cotes, remplie sous les yeux
   du parent. Ce n'est pas un aperçu de formulaire : c'est la tuile qu'il
   retrouvera sur son rayon, et c'est ce qui donne un sens à chaque réponse au
   moment où il la donne.

   L'arche marque le seuil, une seule fois — l'écran d'univers ne la reprend
   pas. Ici, on est encore sur le seuil : la niche se creuse. */
.frontispice { margin: 0; }
.frontispice .volume-apercu { width: 100%; max-width: 15rem; }
/* Tant qu'il n'a pas de nom, le trait reste discontinu : c'est la place à
   prendre, pas encore un volume. Le nommer referme la niche. */
.frontispice .sans-nom { border-style: dashed; }
.frontispice .en-creux { color: var(--texte-2); font-style: italic; }

/* La tranche du volume : ce qui se lit de côté, une fois rangé. */
.frontispice .tranche {
  margin-top: var(--espace-4);
  text-align: center;
  font-size: var(--texte-xs); letter-spacing: .08em; text-transform: uppercase;
  color: var(--texte-2);
}
.frontispice .tranche .separation { margin: 0 var(--espace-2); }

/* --- La question --------------------------------------------------------- */

/* Le libellé du champ **est** le titre de la page. L'étiquette et le titre ne
   sont donc pas deux éléments : la seconde lecture n'apprendrait rien. */
.demande { font-size: var(--texte-2xl); line-height: 1.25; margin-bottom: var(--espace-5); }
.demande label { display: inline; margin: 0; font-weight: inherit; font-size: inherit; }

/* Deux langues, cinq conteurs : assez peu pour être posés à plat, assez pour
   que des étiquettes serrées se lisent mal. */
.choix-large label { flex: 1 1 9rem; justify-content: flex-start; padding: var(--espace-4); }
.choix-large label:has(input:checked) { border-color: var(--accent); background: var(--fond-2); }

.question .planche { margin-bottom: var(--espace-5); }
.question fieldset { border: 0; padding: 0; margin: 0 0 var(--espace-6); }
.question legend { padding: 0; font-weight: 500; }

.suite { display: flex; align-items: center; gap: var(--espace-5); margin-top: var(--espace-8); }
.revenir { color: var(--texte-2); font-size: var(--texte-sm); }

/* --- Les trois idées -----------------------------------------------------
   Le seul endroit du produit où un appel externe part d'un clic du parent et
   se voit arriver. Un filet plutôt qu'un encadré : les propositions
   appartiennent à la question, elles ne sont pas un second sujet. */
/* Le cadre vide ne prend pas de place et ne trace rien.
   La fiche d'un habitant en aligne cinq, dont quatre restent souvent vides :
   cinq filets sous cinq champs feraient une grille là où il n'y a qu'un
   formulaire. `:has(> *)` est vrai seulement quand la baguette a rapporté —
   le gabarit rendu vide ne contient que des espaces. */
.idees-cadre:has(> *) { margin-top: var(--espace-4); }
.idees-cadre .aide { margin-top: var(--espace-3); }

/* Sur le parcours d'ouverture, un filet sépare la question de ses idées : il
   n'y a qu'un champ sur l'écran, et rien d'autre pour marquer la limite. */
.question .idees-cadre:has(> *) {
  margin-top: var(--espace-6);
  padding-top: var(--espace-5);
  border-top: 1px solid var(--bordure);
}

/* La respiration de l'écran d'attente, pas une barre de progression trompeuse
   (charte §6). Deux secondes d'attente n'ont pas besoin d'être mesurées. */
.cherche {
  font-family: var(--recit); color: var(--texte-2);
  animation: respirer 3.5s ease-in-out infinite;
}

/* --- La baguette ---------------------------------------------------------
   « Donne-moi trois idées », posée contre le champ plutôt que sous la page.

   Une commande vit à un seul endroit. Celui-ci est à portée de la main qui
   écrit, et il ne bouge pas : le parent l'apprend une fois, sur le nom, et la
   retrouve sur l'ambiance.

   `align-items: flex-start` la garde en haut d'une zone de texte qui grandit —
   une baguette qui descendrait avec le texte serait une commande qui se
   déplace toute seule. */
.champ-baguette { display: flex; align-items: flex-start; gap: var(--espace-3); }
.champ-baguette > input, .champ-baguette > textarea { flex: 1; min-width: 0; }

.baguette {
  flex: none;
  display: grid; place-items: center;
  width: 2.75rem; height: 2.75rem;
  padding: 0;
  border: 1px solid var(--bordure); border-radius: var(--rayon-md);
  background: transparent; color: var(--texte-2);
  cursor: pointer;
  transition: border-color var(--mouvement-vif) var(--courbe),
              color var(--mouvement-vif) var(--courbe);
}
/* Le même geste que partout : approcher éclaire. */
.baguette:hover:not(:disabled) { border-color: var(--lueur); color: var(--lueur); }
/* Pendant qu'elle cherche, elle le dit plutôt que de laisser appuyer dans le
   vide — comme les crans de la note. */
.baguette:disabled { opacity: .4; cursor: default; }
.baguette svg { width: 1.35rem; height: 1.35rem; }
.baguette .tige {
  fill: none; stroke: currentColor;
  stroke-width: 2.1; stroke-linecap: round;
}
.baguette .etincelle { fill: currentColor; stroke: none; }

/* Les propositions arrivent sans qu'on les demande : il faut donc dire ce
   qu'elles sont, en un mot, sinon trois phrases apparaissent sous la question
   sans qu'on sache qui les a écrites. */
.legende-idees {
  font-size: var(--texte-xs); letter-spacing: .08em; text-transform: uppercase;
  color: var(--texte-2);
  margin-bottom: var(--espace-3);
}

.idees { display: grid; gap: var(--espace-2); margin-bottom: var(--espace-4); }

/* Une proposition est du contenu, pas une commande : elle est en Lora, comme
   le portrait et comme le récit. Le parent lit un morceau de son univers, pas
   l'étiquette d'un bouton — et il doit pouvoir en juger à la voix qu'elle
   aura, pas à celle de l'interface.

   Le bord qui s'éclaire à l'approche est le geste que le produit tient
   partout : sur un volume du rayon, sur un portrait, sur une vignette de
   décor. Tout ce qui se prend s'éclaire. */
.idee {
  display: block; width: 100%; text-align: left;
  font-family: var(--recit); font-size: var(--texte-base); line-height: 1.5;
  color: var(--texte); background: var(--fond-2);
  border: 1px solid var(--bordure); border-radius: var(--rayon-md);
  padding: var(--espace-3) var(--espace-4);
  cursor: pointer;
  transition: border-color var(--mouvement-vif) var(--courbe);
}
.idee:hover { border-color: var(--lueur); }

@media (min-width: 60rem) {
  .chantier-grille { grid-template-columns: 17rem 1fr; align-items: start; }
  .frontispice { position: sticky; top: var(--espace-4); }
}

/* Sur téléphone, le frontispice passe en tête et rétrécit : il motive la
   réponse, il ne doit pas occuper l'écran à sa place. */
@media (max-width: 60rem) {
  .frontispice .volume-apercu { max-width: 11rem; margin: 0 auto; }
}

/* --- La porte : connexion et inscription ---------------------------------
   Une colonne étroite et centrée, comme l'écran de lecture. Un formulaire de
   compte n'est pas un tableau de bord : il n'a que deux ou quatre champs, et
   les étaler sur toute la largeur les rendrait plus intimidants qu'ils ne
   sont. */
.porte { max-width: 26rem; margin: 0 auto; padding: var(--espace-8) 0; }
.porte h1 { text-align: center; }
.porte > .discret { text-align: center; margin-top: var(--espace-3); }
.porte .promesse { text-align: center; }
.porte .carte { margin-top: var(--espace-6); }
.porte .bouton-principal { width: 100%; }
.porte-promesse { margin-bottom: var(--espace-2); }
.porte-suite { margin-top: var(--espace-4); }

/* --- La page d'avant le compte -------------------------------------------
 *
 * Reprise de l'écran `landing` du prototype Claude Design. Tout est porté par
 * `.presentation` : les écrans de connexion et d'inscription ont déjà leurs
 * `.porte-promesse` et `.porte-suite`, et deux pages qui partageraient ces
 * noms se déformeraient l'une l'autre au premier ajustement.
 *
 * Le mobile d'abord, ce que le prototype ne faisait pas — il n'avait aucune
 * requête de média alors que le brief demandait le contraire
 * (`incoherences.md` D4). Les paliers sont donc ici, pas là-bas.
 */
.presentation { max-width: 60rem; margin: 0 auto; }

.presentation .hero { padding: var(--espace-8) 0 var(--espace-12); }
.presentation .cible {
  font-size: var(--texte-sm);
  color: var(--texte-2);
  letter-spacing: .02em;
  margin-bottom: var(--espace-4);
}
.presentation .hero h1 {
  font-family: var(--recit);
  font-size: var(--texte-3xl);
  line-height: 1.25;
  max-width: 20ch;
}
.presentation .promesse-texte {
  max-width: var(--largeur-lecture);
  margin-top: var(--espace-5);
  color: var(--texte-2);
}
.presentation .actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-3);
  margin-top: var(--espace-8);
}

.presentation section + section {
  border-top: 1px solid var(--bordure);
  padding-top: var(--espace-12);
  margin-top: var(--espace-12);
}
.presentation h2 { font-family: var(--recit); font-size: var(--texte-2xl); }
.presentation .chapeau { color: var(--texte-2); margin-top: var(--espace-2); }

/* Les trois étapes. Numérotées par le compteur de la liste : l'ordre est du
 * sens ici, et le redire à la main le ferait mentir le jour où l'une bouge. */
.presentation .etapes ol {
  list-style: none;
  display: grid;
  gap: var(--espace-8);
  margin-top: var(--espace-8);
  counter-reset: etape;
}
.presentation .etapes li { counter-increment: etape; }
.presentation .etapes h3 {
  font-size: var(--texte-lg);
  display: flex;
  align-items: baseline;
  gap: var(--espace-3);
}
.presentation .etapes h3::before {
  content: counter(etape);
  font-family: var(--recit);
  font-size: var(--texte-2xl);
  color: var(--or-fonce);
  line-height: 1;
}
.presentation .etapes p { color: var(--texte-2); margin-top: var(--espace-2); }

/* Les deux refus, dits sur le fond de nuit : ce sont les phrases du soir. */
.presentation .refus {
  background: var(--nuit);
  color: var(--papier);
  border-radius: var(--rayon-lg);
  padding: var(--espace-10) var(--espace-8);
  display: grid;
  gap: var(--espace-6);
}
.presentation .refus p {
  font-family: var(--recit);
  font-size: var(--texte-lg);
  line-height: 1.55;
  max-width: 40ch;
}
.presentation .refus + section { border-top: 0; }

.presentation details {
  border-bottom: 1px solid var(--bordure);
  padding: var(--espace-5) 0;
}
.presentation details summary {
  cursor: pointer;
  font-weight: 600;
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: var(--espace-4);
}
.presentation details summary::-webkit-details-marker { display: none; }
.presentation details summary::after {
  content: "+";
  color: var(--or-fonce);
  font-size: var(--texte-lg);
  line-height: 1;
}
.presentation details[open] summary::after { content: "–"; }
.presentation details p { color: var(--texte-2); margin-top: var(--espace-3); }

.presentation .fin { text-align: center; }
.presentation .fin p {
  font-family: var(--recit);
  font-size: var(--texte-lg);
  margin-bottom: var(--espace-6);
}

@media (min-width: 48rem) {
  .presentation .hero { padding: var(--espace-16) 0; }
  .presentation .hero h1 { font-size: var(--texte-4xl); }
  .presentation .etapes ol { grid-template-columns: repeat(3, 1fr); }
  .presentation .refus { grid-template-columns: 1fr 1fr; gap: var(--espace-10); }
}

/* Le bloc des refus est peint en `--nuit`, ce qui le détache du papier — mais
 * `--nuit` **est** le fond du mode veillée, où le bloc disparaissait alors
 * purement et simplement. On le remonte d'un ton, et on lui donne le liseré
 * qui le tient : un aplat qui ne se distingue plus n'est plus un aplat. */
:root[data-theme="dark"] .presentation .refus,
:root:not([data-theme="light"]) .presentation .refus {
  background: var(--nuit-2);
  border: 1px solid var(--bordure-sombre);
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .presentation .refus { background: var(--nuit); border: 0; }
}

/* --- Poser l'icône sur l'écran d'accueil (D-046) -------------------------
 *
 * Ni maquette de téléphone ni captures d'écran : le parent qui lit cette
 * section tient l'appareil dans l'autre main. Ce qu'il lui manque n'est pas
 * une image de son écran, c'est de savoir **où regarder** — et à quoi
 * ressemble le résultat.
 *
 * D'où les deux seuls objets de la section : trois lignes séparées d'un filet,
 * chacune ouverte par ce qu'on cherche du regard, et la tuile.
 *
 * Aucune couleur neuve, aucune fonte neuve, aucun mouvement. La charte §6
 * demande un mouvement qui accompagne et n'annonce jamais : une tuile qui se
 * poserait au défilement annoncerait, et parlerait plus fort que le titre de
 * la page. Le seul aplat saturé de la section est l'icône elle-même, qui n'est
 * pas une décoration mais le fichier livré.
 */

.presentation .poser-grille {
  display: grid;
  gap: var(--espace-8);
  margin-top: var(--espace-8);
  align-items: center;
}

.poser .gestes { margin: 0; padding: 0; list-style: none; }
.poser .gestes li {
  display: grid;
  grid-template-columns: 1.5rem 1fr;
  gap: var(--espace-4);
  align-items: start;
  padding: var(--espace-4) 0;
}
.poser .gestes li:first-child { padding-top: 0; }
.poser .gestes li + li { border-top: 1px solid var(--bordure); }

/* Les deux premiers pictogrammes sont ceux du système, empruntés : ils sont
   au gris de lecture, comme une citation. Le troisième est celui de la marque,
   et il est en or — c'est le geste où ce qui paraît à l'écran cesse
   d'appartenir à iOS. Le trait est celui de la baguette et des crans : une
   seule écriture de pictogramme dans tout le produit. */
.poser .glyphe {
  display: grid; place-items: center;
  height: 1.5rem;
  color: var(--texte-2);
}
.poser .glyphe svg {
  width: 1.4rem; height: 1.4rem;
  fill: none; stroke: currentColor;
  stroke-width: 2.1; stroke-linecap: round; stroke-linejoin: round;
}
/* Plus petit que les deux autres, à dessein : une forme pleine pèse plus
   qu'un trait de même hauteur, et à 1,5rem l'ogive écrasait ses voisines. */
.poser .glyphe .symbole { height: 1.3rem; color: var(--lueur); }

/* Le mot exact d'iOS, en Nunito Sans : c'est une étiquette qu'on cherche, pas
   une phrase qu'on lit — et la charte §4.2 range les étiquettes de ce côté. */
.poser .gestes strong { display: block; font-weight: 600; }
.poser .gestes .ou {
  display: block;
  margin-top: var(--espace-1);
  font-size: var(--texte-sm);
  color: var(--texte-2);
}

/* La tuile, à la taille où iOS la dessine — 60 px, et pas un de plus. Une
   icône grossie pour faire figure dirait le contraire de ce que la section
   affirme. Le rayon de 23 % est celui du masque d'iOS : à cette taille, la
   différence avec la vraie superellipse est d'un pixel et demi. */
/* `stretch` et non `center` : centrée, la figure se réduisait à la largeur de
   sa légende et son bord droit tombait dix-huit pixels avant celui de la
   section. Étirée sur sa colonne, elle finit là où finissent les filets pleine
   largeur de la page, et tout le reste se centre à l'intérieur. */
.poser .tuile { margin: 0; justify-self: stretch; text-align: center; }
.poser .tuile .icone {
  display: block;
  width: 3.75rem; height: 3.75rem;
  margin: 0 auto var(--espace-3);
  border-radius: 23%;
  background: url("marque/icone-180.png") center / cover no-repeat;
}
/* En veillée, le fond de la tuile **est** le fond de la page — l'icône est
   peinte en `--nuit`, et `--nuit` est le mode veillée. Sans contour, il ne
   reste qu'un peu d'or qui flotte, et une icône qui n'a plus de bord n'est
   plus une icône. Même remède que pour le bloc des refus, plus haut : un
   liseré, et rien d'autre. `box-shadow` plutôt qu'une bordure, pour ne pas
   déplacer le fond dans son propre cadre arrondi. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .poser .tuile .icone {
    box-shadow: 0 0 0 1px var(--bordure);
  }
}
:root[data-theme="dark"] .poser .tuile .icone {
  box-shadow: 0 0 0 1px var(--bordure);
}

.poser .tuile .nom {
  display: block;
  font-size: var(--texte-xs);
  font-weight: 500;
}
/* Les marges automatiques ne sont pas cosmétiques : sur téléphone la figure
   prend toute la largeur, et une boîte de 11rem sans elles se colle à gauche
   pendant que la tuile reste au centre. Le texte y était centré, la boîte
   non — le genre d'écart qu'on ne voit qu'à l'écran. */
.poser .tuile .dit {
  display: block;
  margin: var(--espace-4) auto 0;
  max-width: 11rem;
  font-size: var(--texte-xs);
  color: var(--texte-2);
  line-height: 1.5;
}

/* Une remarque, pas un avertissement : ni encadré, ni bandeau, et pas de filet
   non plus. Il y en avait un, et il donnait à la section une troisième
   longueur de trait — après celle des lignes et celle du bord de section.
   Trois traits de trois longueurs se lisent comme du désordre. L'espace dit la
   même chose et ne se contredit pas. */
.poser .aparte {
  margin-top: var(--espace-8);
  font-size: var(--texte-sm);
  color: var(--texte-2);
  max-width: 44rem;
}

@media (min-width: 48rem) {
  /* La tuile passe à droite, au centre optique des trois lignes : elle est le
     résultat de la suite, pas sa quatrième étape.
     Colonne de largeur fixe plutôt qu'`auto` : sur `auto`, la colonne prenait
     la largeur de la légende et la tuile flottait à 150 px du texte comme à
     90 px du bord, calée sur rien. Fixée, elle tombe sur le bord droit de la
     section, où tombent déjà tous les filets pleine largeur de la page. */
  .presentation .poser-grille { grid-template-columns: 1fr 10rem; gap: var(--espace-10); }
}

/* La dernière question porte déjà la ligne de la section suivante. */
.presentation .questions-frequentes details:last-of-type { border-bottom: 0; }

/* --- Le téléphone ---------------------------------------------------------
 *
 * Tout ce qui précède tient sur un écran large. Ce qui suit est la même chose
 * sur un écran de main, posé sur l'écran d'accueil d'un iPhone (D-046) — donc
 * sans la barre de Safari pour revenir en arrière, et sans souris pour viser.
 *
 * Deux seuils, et ils ne disent pas la même chose :
 *   - 48rem : la barre de navigation se replie en bouton. C'est une question
 *     de largeur disponible, pas de tactile — une fenêtre étroite sur un
 *     ordinateur mérite le même traitement.
 *   - 30rem, déjà employé plus haut : le vrai petit téléphone, où le rayon
 *     passe à deux colonnes.
 *
 * Le seuil est écrit `47.999rem` et non `48rem` : à l'égalité exacte, les deux
 * requêtes seraient vraies en même temps et la barre porterait son bouton.
 */

@media (max-width: 47.999rem) {

  /* --- La barre ---------------------------------------------------------
     Elle reste en haut. Posé sur l'écran d'accueil, le produit n'a plus ni
     barre d'adresse ni flèche de retour : cette ligne est le seul chemin vers
     la bibliothèque, et une seule ligne est un prix acceptable pour cela. */
  .entete {
    position: sticky; top: 0; z-index: 20;
    background: var(--fond);
    gap: var(--espace-3);
    padding-top: calc(var(--espace-3) + env(safe-area-inset-top));
    padding-bottom: var(--espace-3);
    flex-wrap: nowrap;
  }
  /* Le nom est aussi le chemin du retour : dans l'application posée sur
     l'écran d'accueil, c'est le seul. Il se touche donc comme un bouton, et
     non comme un titre — 28 px de haut ne se visent pas d'un pouce. */
  .entete .marque {
    font-size: var(--texte-base); gap: var(--espace-2); min-width: 0;
    min-height: 2.75rem;
  }
  .entete .marque .symbole { height: 1.75rem; flex: none; }
  .entete .marque span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .lanternes { flex: none; }
  .lanternes .legende { font-size: var(--texte-xs); white-space: nowrap; }

  /* --- Le bouton du menu -------------------------------------------------
     Même boîte que la baguette et que les crans de la note : bordure, coin
     doux, et le bord qui s'éclaire quand on la prend. Un composant de plus
     n'aurait pas mérité un dessin de plus. */
  .reglages { flex: none; }
  .entete .reglages > summary {
    display: grid; place-items: center;
    width: 2.75rem; height: 2.75rem;
    border: 1px solid var(--bordure); border-radius: var(--rayon-md);
    color: var(--texte-2); cursor: pointer;
    list-style: none;
    transition: border-color var(--mouvement-vif) var(--courbe),
                color var(--mouvement-vif) var(--courbe);
  }
  /* Le triangle du navigateur dirait « dérouler » là où le trait dit déjà
     « menu ». Deux signes pour une idée en font un de trop. */
  .entete .reglages > summary::-webkit-details-marker { display: none; }
  .entete .reglages > summary::marker { content: ""; }
  .reglages > summary svg {
    width: 1.35rem; height: 1.35rem;
    fill: none; stroke: currentColor; stroke-width: 2.1; stroke-linecap: round;
  }
  .reglages[open] > summary { color: var(--texte); border-color: var(--lueur); }
  .reglages .croix { display: none; }
  .reglages[open] .trois-traits { display: none; }
  .reglages[open] .croix { display: block; }

  /* --- Le panneau --------------------------------------------------------
     Il tombe de toute la largeur sous la barre, et non en petite boîte calée
     sous son bouton : ses lignes sont des destinations, pas un menu
     contextuel. Le bloc positionnant est `.entete`, qui est collante — donc
     positionnée. */
  .entete .reglages > nav {
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; flex-wrap: nowrap;
    gap: 0;
    background: var(--fond-2);
    border-bottom: 1px solid var(--bordure);
    box-shadow: 0 14px 28px -18px rgba(0, 0, 0, .65);
  }
  .reglages > nav > * { margin: 0; }
  .reglages > nav > * + * { border-top: 1px solid var(--bordure); }

  /* Une ligne se touche dans le noir, d'un pouce : 3,25rem de haut, toute la
     largeur, et le libellé calé à gauche comme dans une liste. */
  .reglages > nav a,
  .reglages > nav .bouton,
  .reglages > nav select {
    display: flex; align-items: center; justify-content: flex-start;
    width: 100%; min-height: 3.25rem;
    padding: 0 max(var(--espace-5), env(safe-area-inset-left));
    border-radius: 0; background: transparent;
    color: var(--texte); text-decoration: none;
    font-family: var(--interface); font-size: var(--texte-base); font-weight: 500;
  }
  /* Le bouton perd sa boîte, pas sa bordure : mise à zéro, elle emporterait
     aussi le filet de séparation que la ligne reçoit juste au-dessus — une
     règle plus précise que celle qui le pose. Transparente, elle disparaît
     sans rien emporter. */
  .reglages > nav .bouton { border-color: transparent; }

  /* La liste des langues garde le corps de base : en dessous de 16 px, iOS
     zoome la page à la mise au point et le parent se retrouve dans une page
     grossie qu'il n'a pas demandée.
     `appearance: none` n'empêche pas le sélecteur natif de s'ouvrir — il
     retire seulement la boîte du système, et avec elle les quatre pixels
     qu'elle ajoute à l'intérieur : sans cela, « Français » ne s'alignait pas
     sur « Ma famille ». */
  .reglages > nav select {
    appearance: none; -webkit-appearance: none;
    height: 3.25rem; border: 0;
  }
  /* Le chevron perdu avec la boîte du système, redessiné : deux filets et un
     quart de tour. Il est posé sur la ligne et non sur la liste, pour rester
     à la marge de l'écran quelle que soit la longueur du nom de la langue. */
  .reglages > nav > form:has(select) { position: relative; }
  .reglages > nav > form:has(select)::after {
    content: "";
    position: absolute; pointer-events: none;
    right: max(var(--espace-5), env(safe-area-inset-right));
    top: 50%; margin-top: -.4rem;
    width: .5rem; height: .5rem;
    border-right: 2px solid var(--texte-2);
    border-bottom: 2px solid var(--texte-2);
    transform: rotate(45deg);
  }

  /* --- Les cartes --------------------------------------------------------
     24 px de marge de chaque côté prenaient un septième de l'écran. */
  .carte { padding: var(--espace-4); border-radius: var(--rayon-md); }

  /* --- Les réponses ------------------------------------------------------
     En bande souple, les pastilles prenaient chacune la largeur de son texte
     et se rangeaient en 1-1-2-1 : l'œil lisait du désordre avant de lire des
     options. Une par ligne, pleine largeur — c'est ce que fait déjà
     `.segments` sur les écrans qui l'emploient, et c'est la seule forme qui
     tienne quelle que soit la longueur d'un libellé traduit. */
  .choix { gap: var(--espace-2); }
  .choix > label,
  .choix > .bouton,
  .choix > form { flex: 1 1 100%; }
  .choix > label { min-height: 3rem; padding: var(--espace-3) var(--espace-4); }
  .choix > form > .bouton { width: 100%; }
  /* `.choix-large` donne aux cases une base de 9rem, qui devient une hauteur
     dès qu'on les empile : sans cela, chaque conteur mesurerait 144 px. */
  .choix-large label { flex: 1 1 100%; }

  /* --- Ce qui valide ----------------------------------------------------
     Le geste qui termine un écran prend toute la largeur : c'est la cible la
     plus facile à viser d'une main, et la plus difficile à manquer. */
  form > .bouton-principal { width: 100%; }
  .suite { flex-direction: column; align-items: stretch; gap: var(--espace-4); }
  .suite .bouton { width: 100%; }
  .suite .revenir { text-align: center; }

  /* --- L'écran d'un univers ---------------------------------------------- */
  .actions-univers {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: var(--espace-2);
  }
  .actions-univers .bouton-principal { grid-column: 1 / -1; }
  .actions-univers .bouton {
    padding-left: var(--espace-3); padding-right: var(--espace-3);
    font-size: var(--texte-sm);
  }

  /* Les habitants formaient un paragraphe de noms, de places et de liens tous
     mêlés. Un par ligne : le nom à gauche, ce qui se règle à droite. */
  .habitants {
    flex-direction: column; align-items: stretch;
    gap: 0; margin-top: var(--espace-2);
  }
  .habitants li {
    justify-content: space-between;
    min-height: 3rem; padding: var(--espace-3) 0;
    border-bottom: 1px solid var(--bordure);
  }
  .habitants li .recit { flex: 1 1 auto; min-width: 0; }
  .habitants li .place, .habitants .voix { flex: none; }

  /* --- L'arbre -----------------------------------------------------------
     Il garde sa taille et défile plutôt que de rétrécir : c'est une décision
     de son écran, et elle vaut aussi ici — six pixels de prénom ne sont pas
     un arbre. Deux choses seulement sont ajoutées pour le pouce.

     Il déborde jusqu'aux bords de l'écran : un dessin coupé net par le bord
     se lit comme « ça continue », le même dessin arrêté avant une marge se
     lit comme « c'est fini ».

     Et surtout `overscroll-behavior-x`. Sans elle, arriver au bout du
     défilement passe la main au geste de retour de Safari : le parent qui
     tire vers la droite pour voir un cousin quitte la page. */
  .arbre {
    margin-left: calc(var(--espace-4) * -1);
    margin-right: calc(var(--espace-4) * -1);
    padding-left: var(--espace-4);
    padding-right: var(--espace-4);
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }

  /* --- Le parcours d'ouverture -------------------------------------------
     Le fil et le frontispice occupaient l'écran entier avant la question. Ils
     motivent la réponse : ils ne peuvent pas prendre sa place. */
  .fil { gap: var(--espace-3); margin-bottom: var(--espace-6); }
  .chantier-grille { gap: var(--espace-6); }

  /* --- Le seuil ---------------------------------------------------------- */
  .seuil-commandes { gap: var(--espace-5); }
  .symbole-note { height: 5.5rem; }

  /* --- La page d'avant le compte ----------------------------------------
     Une question fréquente est un dépliant, donc une cible : elle se touche
     avec le pouce, pas avec la pointe d'un curseur. */
  .presentation details summary { min-height: 3rem; align-items: center; }
  .presentation .actions .bouton { flex: 1 1 100%; }
}

/* Sur le vrai petit téléphone, la niche du parcours d'ouverture rétrécit
   encore : elle reste reconnaissable à 8,5rem, et la question passe au-dessus
   de la ligne de flottaison. */
@media (max-width: 30rem) {
  .frontispice .volume-apercu { max-width: 8.5rem; }
  .frontispice .tranche { margin-top: var(--espace-3); }
  .presentation .refus { padding: var(--espace-8) var(--espace-5); }
  .presentation .hero { padding: var(--espace-6) 0 var(--espace-10); }
}

/* --- Choisir une voix en l'écoutant --------------------------------------
   Une étiquette ne dit rien d'une voix : « grave » ou « posée » ne se juge
   qu'à l'oreille. Le lecteur est donc à côté du bouton radio, pas ailleurs
   dans la page — sinon on choisit sans écouter, ce qui est le défaut qu'on
   corrige. */
.voix-choix { list-style: none; margin: var(--espace-2) 0 0; padding: 0; display: grid; gap: var(--espace-1); }
.voix-choix li {
  display: grid; grid-template-columns: 1fr; gap: var(--espace-1);
  padding: var(--espace-3); border: 1px solid var(--bordure); border-radius: var(--rayon-sm);
}
.voix-choix li:has(input:checked) { border-color: var(--lueur); background: var(--fond-2); }
.voix-choix label { display: flex; align-items: center; gap: var(--espace-3); cursor: pointer; }
.voix-choix .libelle { font-size: var(--texte-base); }
/* 28 px : assez pour viser du pouce, assez bas pour ne pas dominer la ligne. */
.voix-choix audio { width: 100%; height: 28px; }
@media (min-width: 34rem) {
  .voix-choix li { grid-template-columns: 1fr 15rem; align-items: center; gap: var(--espace-4); }
}
