/* ============================================================
   PALAMBUR · Feuille de mise en page des aperçus produits
   S'appuie exclusivement sur les jetons de palambur.css.
   Aucune couleur brute, aucune ombre, rayon 0 sauf pastille.
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

body { margin: 0; }

/* === Trame ============================================== */

.pav {
  padding: var(--space-10) var(--space-7);
}
.pav--serre { padding: var(--space-9) var(--space-7); }

.wrap {
  max-width: 1180px;
  margin: 0 auto;
}
.wrap--etroit { max-width: 820px; }

/* === Surfaces alternées ================================= */

.surface-1 { background: var(--bg1); }
.surface-2 { background: var(--bg2); }
.surface-d { background: var(--bg-dark); color: var(--pal-canvas); }
.surface-d2 { background: var(--bg-dark2); color: var(--pal-canvas); }

/* === Niveau de titre et taille de titre ==================
   -------------------------------------------------------------------
   Un titre a DEUX choses qui n'ont rien à voir · sa place dans le plan
   du document, que le lecteur d'écran annonce, et sa taille à l'écran.
   La feuille les confondait · `h3` vaut 36 px, `h4` vaut 28 px, donc
   un titre de carte était écrit `h4` POUR SA TAILLE, et le plan des
   trois autres aperçus sautait de h2 à h4, quinze fois par page.

   Trouvé le 2026-08-06 en portant le plancher d'accessibilité de
   Jomini sur ses voisins · Corvisart, Jacquard et Méneval sautaient
   tous les trois exactement le même niveau, au même endroit, dans les
   cartes. Une faute qui se répète à l'identique sur trois pages n'est
   pas une inattention, c'est une règle manquante.

   UN NIVEAU DE TITRE CHOISI POUR SA TAILLE N'EST PLUS UN NIVEAU, ET
   LE PLAN QU'IL DESSINE N'EST PLUS CELUI DU DOCUMENT.

   Les titres de carte sont donc passés en `h3` · le plan redevient
   juste · et cette classe leur rend l'apparence qu'ils avaient.

   CORRIGÉ LE MÊME JOUR, APRÈS MESURE DANS LE NAVIGATEUR · la première
   version ne rendait que la TAILLE. Elle oubliait deux choses, et la
   promotion, annoncée neutre, ne l'était pas :

     · `h4` portait aussi `line-height: 1.2`, `h3` porte `1.1` · les
       47 titres promus ont perdu 2,8 px d'interligne ;
     · trois règles de composant visaient la BALISE — `.etape h4`,
       `.duel__col h4`, `.tarif h4` — et ne visaient plus rien. Leurs
       marges basses (12 px, 24 px, 8 px) sont tombées sur la marge
       générique de 24 px · 21 titres ont bougé sur trois pages
       commerciales, et aucun des deux bancs n'a rougi.

   UNE RÈGLE DE COMPOSANT QUI VISE UNE BALISE MEURT SANS BRUIT QUAND LA
   BALISE CHANGE · LA CLASSE MORTE LAISSE UNE TRACE DANS LE HTML, LE
   SÉLECTEUR MORT N'EN LAISSE AUCUNE.

   D'où deux suites · cette règle porte maintenant le COUPLE que `h4`
   portait, et les trois règles de composant visent le titre de carte
   au lieu de viser sa balise. Et surtout, `feuilles.py` a gagné un
   cinquième contrôle qui relit chaque sélecteur de cette feuille contre
   les quatre pages et refuse ceux qui ne désignent plus personne. */
.t-carte { font-size: var(--type-h3); line-height: 1.2; }

/* Portée sombre — la charte définit .on-dark ; les surfaces des
   maquettes doivent hériter exactement des mêmes règles, sinon
   l'encre reste navy sur navy. */
.surface-d h1, .surface-d h2, .surface-d h3, .surface-d h4,
.surface-d2 h1, .surface-d2 h2, .surface-d2 h3, .surface-d2 h4 { color: var(--pal-canvas); }
.surface-d p, .surface-d li, .surface-d dd, .surface-d dt,
.surface-d2 p, .surface-d2 li, .surface-d2 dd, .surface-d2 dt { color: var(--pal-text-on-dark); }
.surface-d strong, .surface-d b,
.surface-d2 strong, .surface-d2 b { color: var(--pal-canvas); }
.surface-d a:not([class]), .surface-d2 a:not([class]) { color: var(--pal-yellow); }
.surface-d a:not([class]):hover, .surface-d2 a:not([class]):hover { color: #fff; }

/* Îlots clairs DANS une section sombre — l'encre redevient locale.
   -------------------------------------------------------------------
   Les règles ci-dessus sont des sélecteurs de descendance : elles
   descendent dans TOUTE la section sombre, y compris dans les blocs
   qui rétablissent un fond clair. Un `strong` dans une `.sortie`
   héritait donc de l'encre canvas sur un fond canvas — présent dans
   le HTML, absent de l'écran.

   Trouvé le 2026-08-04 sur la page de Méneval, en regardant : les
   libellés des quatre parties de l'envoi (« Les consignes données au
   modèle », « Votre dossier, tel que vous l'avez déposé ») étaient
   blancs sur blanc. La page dont le sujet ENTIER est « tout ce qui
   est montré est tout ce qui part » cachait le nom de ce qui part.

   Aucun contrôle ne pouvait le voir : le banc lit le innerHTML, et le
   texte y était. C'est la couleur calculée qui ment, et une couleur
   calculée ne se lit pas dans un fichier — elle se regarde. */
/* LES QUATRE DERNIERS SÉLECTEURS ONT REÇU LEUR JUMEAU LE 2026-08-12, lot M31.
   Les deux premières lignes couvraient déjà les deux surfaces · les deux
   suivantes s'arrêtaient à `.surface-d`. La même règle, dans le même bloc, à
   une ligne d'intervalle, écrite deux fois correctement puis deux fois à
   moitié. C'est la signature de la correction faite à l'endroit où le défaut
   s'est montré, et pas à l'endroit où il vit. */
.surface-d .sortie strong, .surface-d .sortie b,
.surface-d2 .sortie strong, .surface-d2 .sortie b,
.surface-d .surface-1 strong, .surface-d .surface-1 b,
.surface-d2 .surface-1 strong, .surface-d2 .surface-1 b,
.surface-d .surface-2 strong, .surface-d .surface-2 b,
.surface-d2 .surface-2 strong, .surface-d2 .surface-2 b { color: var(--fg1); }
.surface-d .sortie, .surface-d2 .sortie { color: var(--fg1); }

/* Boutons sur fond sombre — le navy plein devient invisible :
   on inverse la hiérarchie sans changer la forme. */
.surface-d .btn-primary, .surface-d2 .btn-primary {
  background: var(--pal-canvas);
  color: var(--pal-ink);
}
.surface-d .btn-primary:hover, .surface-d2 .btn-primary:hover { background: #fff; }
.surface-d .btn-secondary, .surface-d2 .btn-secondary {
  color: var(--pal-canvas);
  border-color: var(--pal-muted-dark);
  background: transparent;
}
.surface-d .btn-secondary:hover, .surface-d2 .btn-secondary:hover {
  background: var(--pal-canvas);
  color: var(--pal-ink);
  border-color: var(--pal-canvas);
}

/* Cartes sur fond sombre — jamais un îlot blanc au milieu du navy :
   la carte descend d'un cran, elle ne remonte pas. */
.surface-d .card {
  background: var(--bg-dark2);
  border: 1px solid var(--rule-dark);
}
.surface-d2 .card {
  background: var(--bg-dark);
  border: 1px solid #46536b;
}

/* === Barre de navigation ================================ */

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-5) var(--space-7);
  border-bottom: 1px solid var(--rule);
  background: var(--bg2);
  position: sticky;
  top: 0;
  z-index: 20;
}
.nav__marque {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-head);
  font-weight: var(--w-semi);
  letter-spacing: var(--tracking-tight);
  color: var(--fg1);
  font-size: 20px;
}
.nav__marque img { height: 26px; width: auto; display: block; }
.nav__produit {
  font-family: var(--font-body);
  font-weight: var(--w-reg);
  color: var(--fg3);
  border-left: 1px solid var(--rule);
  padding-left: var(--space-3);
  margin-left: var(--space-1);
  font-size: var(--type-meta-web);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}
.nav__liens {
  display: flex;
  gap: var(--space-6);
  align-items: center;
  font-size: var(--type-meta-web);
  letter-spacing: 0.04em;
}
.nav__liens a { color: var(--fg2); }
.nav__liens a:hover { color: var(--pal-red-strong); }

/* === Étiquettes ========================================= */

.etiquette {
  font-family: var(--font-body);
  font-weight: var(--w-semi);
  font-size: var(--type-meta-web);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-accent);
  display: block;
  margin-bottom: var(--space-5);
}
.surface-d .etiquette,
.surface-d2 .etiquette { color: var(--pal-muted-dark); }

/* === Hero =============================================== */

.hero { padding: var(--space-10) var(--space-7) var(--space-9); }
.hero h1 {
  font-size: clamp(42px, 6vw, var(--type-display));
  margin-bottom: var(--space-6);
  max-width: 16ch;
}
.hero .lead { max-width: 62ch; margin-bottom: var(--space-7); }

.actions { display: flex; gap: var(--space-4); flex-wrap: wrap; align-items: center; }

/* === Bandeau de réassurance ============================= */

.reassurance {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  font-family: var(--font-mono);
  font-size: var(--type-meta-web);
  color: var(--fg3);
  padding: var(--space-5) var(--space-7);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  background: var(--bg2);
}
.reassurance span { white-space: nowrap; }
.reassurance span::before { content: "· "; color: var(--pal-red-strong); }

/* === Titres de pavé ===================================== */

.pav h2 { max-width: 20ch; }
.pav .lead { max-width: 64ch; }

/* === Ligne rouge signature ============================== */

.signature {
  display: flex;
  gap: var(--space-5);
  margin: var(--space-7) 0 0;
  max-width: 62ch;
}
.signature p {
  font-style: italic;
  color: var(--fg-signal);
  font-size: var(--type-lead-web);
  line-height: 1.4;
  margin: 0;
}
/* La ligne rouge de signature portait --pal-red #E53935 sur fond sombre, soit
   3.46 de contraste sur #1E293B pour un seuil de 4.5 · la taille est de 22px,
   sous les 24px qui autoriseraient le seuil abaisse de 3.0. Elle est employee
   sur fond sombre dans les apercus Corvisart et Jacquard.
   Le rouge retenu ici n est PAS un nouveau choix de charte · c est celui deja
   arrete pour les jetons de risque sur fond sombre le 2026-08-03, #F87171,
   qui donne 5.29 sur #1E293B et 6.36 sur #0A192F. Une decision prise vaut
   partout ou elle porte. */
.surface-d .signature p,
.surface-d2 .signature p { color: #F87171; }

/* === L'ENCRE ROUGE SUR FOND CLAIR · corrigé le 2026-08-04 ===============

   LA DÉCISION DU 2026-08-03 CI-DESSUS N'AVAIT ÉTÉ APPLIQUÉE QU'À MOITIÉ.
   Elle a réparé le rouge sur fond sombre et laissé le rouge sur fond clair
   exactement où il était. Ce n'est pas un oubli d'attention · c'est un
   oubli d'instrument. Ma sonde de contraste mesurait alors contre un seuil
   de 3.0, qui est celui des GRANDS textes. Le seuil d'un texte courant est
   de 4.5. Une sonde réglée trop bas ne rate pas les défauts par hasard ·
   elle les déclare conformes, et elle imprime « 0 défaut sur 402 ».

   MESURES DU 2026-08-04, seuil 4.5, sur la page de Corvisart ·
     #E53935 sur #FFFFFF ...... 4.23   ligne d'étape « J + 0 », 14 px
     #E53935 sur #F8FAFC ...... 4.04   ligne de signature, 22 px
     #FFFFFF sur #E53935 ...... 4.23   bandeau de maquette, 12 px
   Neuf mentions sous le seuil, sur 292 mesurées. Aucune n'est illisible ·
   toutes sont un peu trop pâles, et c'est justement pour ça qu'aucune
   relecture à l'œil ne les avait signalées.

   LE ROUGE PALAMBUR NE CHANGE PAS. `--pal-red` #E53935 reste la couleur des
   LIGNES · filets, bordures, barres, aplats. Une ligne n'a pas de seuil de
   4.5 à tenir, elle n'est pas du texte. Seule L'ENCRE passe à
   `--pal-red-strong` #DC2626, qui existait déjà dans la charte pour le
   danger · 4.83 sur #FFFFFF et 4.62 sur #F8FAFC. Là encore le rouge retenu
   n'est pas un choix neuf · c'est celui déjà arrêté ailleurs dans la même
   feuille. On ne règle pas un défaut de contraste en inventant une couleur.

   La règle de lecture, pour les ajouts à venir · `--pal-red` dessine,
   `--pal-red-strong` écrit. */
.signature p { color: var(--pal-red-strong); }

/* === Grilles ============================================ */

.grille { display: grid; gap: var(--space-6); }
.g2 { grid-template-columns: repeat(2, 1fr); }
.g3 { grid-template-columns: repeat(3, 1fr); }
.g4 { grid-template-columns: repeat(4, 1fr); }
/* Grille à filets · un trait vertical entre les colonnes.
   ATTENTION, DÉFAUT CORRIGÉ LE 2026-08-01 · la règle ne connaissait que
   `:first-child`, ce qui n'est juste que sur UN SEUL RANG. Dès qu'une
   grille dépassait sa première ligne, le premier élément du rang suivant
   portait un filet à gauche, sans rien à sa gauche. Le défaut était
   invisible parce qu'aucune maquette n'avait encore débordé · les quatre
   grilles existantes tiennent toutes sur un rang. Il serait apparu au
   premier ajout d'un cinquième élément.
   La règle compte désormais les colonnes, et un espacement de rang est
   rétabli · sans lui, deux rangs se touchent. */
.grille--filets { gap: 0; row-gap: var(--space-8); }
.grille--filets > * {
  border-left: 1px solid var(--rule);
  padding: 0 var(--space-6);
}
.grille--filets > *:first-child,
.g2.grille--filets > *:nth-child(2n + 1),
.g3.grille--filets > *:nth-child(3n + 1),
.g4.grille--filets > *:nth-child(4n + 1) { border-left: none; padding-left: 0; }
.surface-d .grille--filets > * { border-left-color: var(--rule-dark); }

/* === Chiffre isolé ====================================== */

.chiffre {
  font-family: var(--font-head);
  font-weight: var(--w-semi);
  font-size: clamp(56px, 7vw, 104px);
  line-height: 0.9;
  letter-spacing: var(--tracking-display);
  color: var(--fg1);
  display: block;
  margin-bottom: var(--space-4);
}
.surface-d .chiffre, .surface-d2 .chiffre { color: var(--pal-canvas); }
/* Encre · `--pal-red-strong`. Voir le bloc « l'encre rouge sur fond clair ». */
.chiffre--signal { color: var(--pal-red-strong); }
.surface-d .chiffre--signal, .surface-d2 .chiffre--signal { color: var(--pal-yellow); }
.chiffre__legende {
  font-size: var(--type-meta-web);
  color: var(--fg3);
  line-height: 1.45;
  display: block;
  max-width: 30ch;
}
.surface-d .chiffre__legende,
.surface-d2 .chiffre__legende { color: var(--pal-muted-dark); }
.chiffre__source {
  display: block;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--fg3);
  margin-top: var(--space-3);
}
.surface-d .chiffre__source, .surface-d2 .chiffre__source { color: var(--pal-muted-dark); }

/* === Étapes numérotées ================================== */

/* Le filet dessine · il garde `--pal-red`. Le numéro écrit · il passe à
   `--pal-red-strong`. Voir le bloc « l'encre rouge sur fond clair ». */
.etape { padding-top: var(--space-5); border-top: 3px solid var(--pal-red); }
.etape__num {
  font-family: var(--font-mono);
  font-size: var(--type-meta-web);
  color: var(--pal-red-strong);
  display: block;
  margin-bottom: var(--space-4);
  letter-spacing: 0.1em;
}
/* ET LE MÊME NUMÉRO SUR UNE SURFACE SOMBRE · lot M31.
   `--pal-red-strong` est l'encre du fond CLAIR · elle rend 4,61 sur le canvas,
   et 3,03 sur `--pal-slate`. Les six numéros d'étapes de l'aperçu de Méneval,
   qui vivent dans deux pavés `surface-d2`, étaient donc sous le seuil.
     Le défaut n'était pas visible dans la famille de contrôles écrite plus
   tôt ce jour-là · celle-ci cherche les règles qui posent `.surface-d X` sans
   poser `.surface-d2 X`, et `.etape__num` n'avait AUCUNE version sombre. Une
   règle sans jumelle se remarque · une règle sans famille ne se remarque pas.
     UN CONTRÔLE QUI CHERCHE LES PAIRES DÉPAREILLÉES NE VOIT PAS LES
     CÉLIBATAIRES · IL FAUT MESURER LA PAGE POUR LES TROUVER, ET C'EST LA
     PAGE QUI LES A DÉNONCÉS.
   Le filet, lui, ne change pas · il dessine, et `--pal-red` sur du bleu nuit
   se voit très bien. Seule l'encre bouge. */
.surface-d .etape__num, .surface-d2 .etape__num { color: var(--pal-red-on-dark); }
.etape .t-carte { margin-bottom: var(--space-3); }
.etape p { font-size: var(--type-body-web); margin: 0; }

/* === Tableaux =========================================== */

.tbl-hz { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tbl { width: 100%; border-collapse: collapse; font-size: 16px; }
.tbl th {
  text-align: left;
  font-family: var(--font-body);
  font-weight: var(--w-semi);
  font-size: var(--type-meta-web);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}
.tbl td {
  padding: var(--space-4);
  border-bottom: 1px solid var(--rule);
  color: var(--fg2);
  vertical-align: top;
}
.tbl tr:last-child td { border-bottom: none; }
.tbl .num { font-family: var(--font-mono); text-align: right; white-space: nowrap; color: var(--fg1); }
.surface-d .tbl td, .surface-d2 .tbl td { color: var(--pal-text-on-dark); border-bottom-color: var(--rule-dark); }
.surface-d .tbl th, .surface-d2 .tbl th { color: var(--pal-muted-dark); border-bottom-color: var(--rule-dark); }
.surface-d2 .tbl td, .surface-d2 .tbl th { border-bottom-color: #46536b; }

/* === Comparatif deux colonnes =========================== */

.duel { display: grid; grid-template-columns: 1fr 1fr; gap: 0; border: 1px solid var(--rule); }
.duel__col { padding: var(--space-7); }
.duel__col + .duel__col { border-left: 1px solid var(--rule); }
.duel__col .t-carte { margin-bottom: var(--space-5); }
.duel ul { list-style: none; margin: 0; padding: 0; }
.duel li {
  padding: var(--space-3) 0 var(--space-3) var(--space-6);
  border-bottom: 1px solid var(--rule);
  position: relative;
  color: var(--fg2);
  font-size: 17px;
}
.duel li:last-child { border-bottom: none; }
.duel li::before {
  position: absolute;
  left: 0;
  font-family: var(--font-mono);
  font-size: 15px;
}
.oui li::before { content: "+"; color: var(--pal-green-strong); font-weight: 700; }
/* Le « × » n'est pas une décoration · c'est LUI qui dit que la ligne est un
   danger, le texte à côté ne le répète pas. C'est de l'encre. */
.non li::before { content: "×"; color: var(--pal-red-strong); font-weight: 700; }
.surface-d .duel, .surface-d2 .duel { border-color: var(--rule-dark); }
.surface-d .duel__col + .duel__col { border-left-color: var(--rule-dark); }
.surface-d .duel li, .surface-d2 .duel li { border-bottom-color: var(--rule-dark); color: var(--pal-text-on-dark); }

/* === Pastilles de risque ================================ */

.jeton {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 3px 8px;
  border: 1px solid currentColor;
  white-space: nowrap;
}
/* LA MÊME MOITIÉ MANQUANTE QUE POUR LE ROUGE, ET SUR LES MÊMES JETONS.
   Le 2026-08-03, les trois variantes SOMBRES ont été corrigées · voir plus
   bas. Les trois variantes CLAIRES sont restées où elles étaient, et le
   2026-08-04 la sonde réglée au bon seuil les a trouvées sur la page de
   Jacquard ·
     #059669 sur #F8FAFC ...... 3.60   « déjà fait », « à faire »
     #D97706 sur #F8FAFC ...... 3.04   « à arbitrer », « seulement si mesuré »
   Six jetons sur 226 mentions. Le rouge, lui, était déjà juste · il pointait
   sur `--pal-red-strong`, arrêté pour le danger. Autrement dit LE SEUL DES
   TROIS QUI ÉTAIT CORRECT L'ÉTAIT PAR EFFET DE BORD.

   Les deux jetons d'encre manquants sont donc écrits ici, au même rang que
   `--pal-red-strong`, et choisis dans la même famille · un cran plus foncé
   que la couleur de marque, pas une teinte inventée.
     #047857 ... 5.48 sur #FFFFFF · 5.24 sur #F8FAFC
     #B45309 ... 5.02 sur #FFFFFF · 4.80 sur #F8FAFC
   `--pal-green` et `--pal-amber` ne bougent pas · ils dessinent les barres
   de proportion, où ils sont des aplats et non de l'encre.

   DÉPLACÉS LE 2026-08-12, lot M31 · « écrits ici » était l'erreur, et elle a
   mis huit jours à se voir. Les deux jetons vivaient dans un `:root` de
   CETTE feuille · ils n'existaient donc que pour les pages qui la lient. Le
   tableau de bord porte son style en ligne et ne la lit pas · il a réécrit
   du vert de trait dans son texte, à 3,77, sans avoir jamais pu savoir qu'un
   vert d'encre avait été arrêté pour lui.
     UN JETON RANGÉ DANS UNE FEUILLE QUE TOUTES LES PAGES NE LISENT PAS N'EST
     PAS UNE RÈGLE DE LA MAISON · C'EST UNE RÈGLE DE CETTE FEUILLE, ET LES
     AUTRES PAGES SONT EN FAUTE SANS AVOIR ÉTÉ PRÉVENUES.
   Ils sont maintenant dans `palambur.css`, à côté de `--pal-red-strong`.
   Rien n'a changé de leur valeur ni de leur raison · seulement de leur
   portée. Les trois lignes ci-dessous n'ont pas bougé d'un caractère. */
.jeton--vert  { color: var(--pal-green-strong); }
.jeton--ambre { color: var(--pal-amber-strong); }
.jeton--rouge { color: var(--pal-red-strong); }
/* Quatrieme etat, mesure et non peint · un rapprochement qui n a rien pu
   demontrer sort en « inconnu ». Il doit s afficher, pas se taire. */
.jeton--gris  { color: var(--pal-muted); }
/* Les variantes claircies etaient posees sur .surface-d SEULE, alors que la
   console de demonstration est en .surface-d2. Le jeton ROUGE s y affichait
   donc a 3.03 de contraste sur #1E293B, le VERT a 3.88 · sous le seuil de
   4.5. Mesure du 2026-08-03 · le jeton qui signale le danger etait le moins
   lisible des trois. Les deux surfaces sont desormais traitees ensemble. */
.surface-d .jeton--vert,  .surface-d2 .jeton--vert  { color: #34D399; }
.surface-d .jeton--ambre, .surface-d2 .jeton--ambre { color: #FBBF24; }
.surface-d .jeton--rouge, .surface-d2 .jeton--rouge { color: #F87171; }
.surface-d .jeton--gris,  .surface-d2 .jeton--gris  { color: var(--pal-muted-dark); }

/* === Console / démonstration ============================ */

.console {
  border: 1px solid var(--rule);
  background: var(--bg2);
}
.console__barre {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--fg3);
  text-transform: uppercase;
}
.console__corps { padding: var(--space-6); }
.surface-d .console { background: var(--bg-dark2); border-color: var(--rule-dark); }
.surface-d2 .console { background: var(--bg-dark); border-color: #46536b; }
.surface-d .console__barre,
.surface-d2 .console__barre { border-bottom-color: #46536b; color: var(--pal-muted-dark); }

.zone {
  width: 100%;
  min-height: 190px;
  font-family: var(--font-mono);
  font-size: 14px;
  line-height: 1.7;
  color: var(--fg1);
  background: var(--bg2);
  border: 1px solid var(--rule);
  padding: var(--space-4);
  border-radius: var(--radius-none);
  resize: vertical;
}
.zone:focus { outline: 2px solid var(--pal-navy); outline-offset: -2px; }

/* Une zone qui reçoit une réponse et non un document · trois lignes visibles au
   lieu de dix. Elle sert là où une console en pose plusieurs à la suite, et où
   la hauteur pleine ferait défiler la page entière pour lire la question
   suivante.

   ELLE RESTE ÉTIRABLE, et c’est le point · une réponse plus longue que la boîte
   n’est jamais coupée, elle défile, et le coin d’étirement permet d’ouvrir la
   boîte sans quitter la page. Une hauteur réduite qui interdirait d’en sortir
   serait une limite de longueur déguisée en choix de dessin, et personne ne
   l’aurait décidée. */
.zone--courte { min-height: 76px; }

/* Un choix rendu à l’écran · même grain que la zone de texte, sur une ligne.
   Sert partout où l’aperçu laisse le visiteur corriger ce que la machine a
   compris, plutôt que de le lui montrer en lecture seule. */
.choix {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--fg1);
  background: var(--bg2);
  border: 1px solid var(--rule);
  padding: 6px 8px;
  border-radius: var(--radius-none);
  max-width: 100%;
}
.choix:focus { outline: 2px solid var(--pal-navy); outline-offset: -2px; }
.choix-ligne {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: baseline;
  margin-top: var(--space-3);
}
.choix-ligne__cle {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--fg2);
  min-width: 150px;
}

.sortie {
  min-height: 190px;
  font-family: var(--font-mono);
  font-size: 14px;
  line-height: 1.7;
  white-space: pre-wrap;
  word-break: break-word;
  border: 1px solid var(--rule);
  padding: var(--space-4);
  background: var(--bg1);
  color: var(--fg1);
}
/* `cursor: help` n'est pas une decoration · c'est le seul indice qui dit
   qu'il y a quelque chose a survoler. Une infobulle sans signal est une
   infobulle que personne ne trouve, et une fonction que personne ne trouve
   n'existe pas.
   Elle ne remplace jamais le tableau de relecture · le titre ne s'atteint
   qu'a la souris, et ce qui ne s'atteint qu'a la souris ne doit jamais etre
   le seul chemin vers une information. */
.marq {
  background: var(--pal-navy);
  color: var(--pal-canvas-pure);
  padding: 1px 5px;
  font-weight: 500;
  cursor: help;
}
.surl {
  border-bottom: 2px solid var(--pal-red);
  background: rgba(229, 57, 53, 0.07);
  cursor: help;
}

/* === Rapport chiffré sous une console ===================
   Un relevé de quelques lignes · un libellé à gauche, une valeur
   monospacée à droite, un filet entre les deux. Sert à afficher ce
   qu'un moteur a réellement compté, plutôt qu'une phrase de synthèse
   qui arrondit.
   La variante --alerte n'est PAS un état d'erreur de la page · elle
   signale une anomalie constatée dans la donnée observée. Elle se
   distingue par une couleur ET par un filet gauche, pour rester
   lisible sans la couleur. ------------------------------------- */

.rapport {
  margin-top: var(--space-4);
  border-top: 1px solid var(--rule);
}
.rapport__ligne {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--rule);
}
.rapport__cle {
  font-size: 13px;
  color: var(--fg2);
}
/* LE `nowrap` EST PARTI, ET C'EST LA TROISIÈME FOIS QU'IL COÛTE · 23.08.2026.

   Il était là pour que les valeurs courtes · un nombre, un état · fassent une
   colonne qui se lit d'un coup d'œil. Une valeur courte ne se coupe pas, avec
   ou sans `nowrap` · elle tient. Le `nowrap` ne décidait donc QUE du sort des
   valeurs longues, c'est-à-dire exactement de celles qui débordent.

   MESURE · `04_MENEVAL/apercu_meneval.html`, section du rapport, valeur
   « aucun dans cette séance · essayez les deux boutons de refus » · 530 px
   demandés dans une colonne de 436 (`.grille.g2` à deux colonnes). La page
   glissait de côté à 950, 1000, 1050, 1099 et 1100 px, et PAS à 375 ni à
   1280 · la bande intermédiaire n'était mesurée par aucun banc. Elle l'est
   depuis (`banc_visuel.mjs`, troisième largeur).

   Le média étroit posait déjà `white-space: normal` pour la même raison, et
   son commentaire disait déjà la leçon · « une exception qu'il faut penser à
   demander n'est pas une protection ». Elle valait pour toutes les largeurs.

   `.rapport__val--long` RESTE · `01_JOMINI/interface.js` le pose encore, et il
   ajoute `word-break: break-word`, qui coupe DANS un mot · c'est plus que
   `anywhere` ne fait sur une chaîne sans espace courte. Une classe qu'on
   retire pendant qu'un script la pose est une classe qui devient muette. */
.rapport__val {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--fg1);
  text-align: right;
  white-space: normal;
  overflow-wrap: anywhere;
  min-width: 0;
}
.rapport__val--long { white-space: normal; word-break: break-word; }

.rapport__ligne--alerte {
  border-left: 3px solid var(--pal-red-strong);
  padding-left: var(--space-3);
}
.rapport__ligne--alerte .rapport__cle,
.rapport__ligne--alerte .rapport__val { color: var(--pal-red-strong); }

.surface-d .rapport,
.surface-d .rapport__ligne,
.surface-d2 .rapport,
.surface-d2 .rapport__ligne { border-color: #46536b; }
.surface-d .rapport__cle,
.surface-d2 .rapport__cle { color: var(--pal-muted-dark); }
.surface-d .rapport__val,
.surface-d2 .rapport__val { color: var(--pal-canvas-pure); }
.surface-d .rapport__ligne--alerte,
.surface-d2 .rapport__ligne--alerte { border-left-color: #F87171; }
.surface-d .rapport__ligne--alerte .rapport__cle,
.surface-d .rapport__ligne--alerte .rapport__val,
.surface-d2 .rapport__ligne--alerte .rapport__cle,
.surface-d2 .rapport__ligne--alerte .rapport__val { color: #F87171; }

/* === Ce qu'on doit dire ================================
   Des phrases, pas des mesures · le `.rapport` ci-dessus
   aligne des valeurs en chasse fixe à droite, ce qui est
   illisible pour de la prose. Ici chaque phrase porte son
   filet gauche et son code de provenance, pour qu'on voie
   qu'elle est calculée et non tapée à la main.

   Celles qui bloquent se distinguent par le filet ET par
   le mot « ne cliquez pas » qu'elles contiennent · jamais
   par la couleur seule. -------------------------------- */

.dire { margin-top: var(--space-4); }
.dire__ligne {
  border-left: 3px solid var(--rule);
  padding: var(--space-2) 0 var(--space-2) var(--space-4);
  margin-top: var(--space-4);
}
.dire__ligne:first-child { margin-top: 0; }
.dire__code {
  display: block;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--fg2);
  margin-bottom: var(--space-2);
}
.dire__texte {
  font-size: 16px;
  line-height: 1.6;
  color: var(--fg1);
  margin: 0;
}
.dire__ligne--bloque { border-left-color: var(--pal-red-strong); }
.dire__ligne--bloque .dire__code { color: var(--pal-red-strong); }

.surface-d .dire__ligne,
.surface-d2 .dire__ligne { border-left-color: #46536b; }
.surface-d .dire__code,
.surface-d2 .dire__code { color: var(--pal-muted-dark); }
.surface-d .dire__texte,
.surface-d2 .dire__texte { color: var(--pal-canvas-pure); }
.surface-d .dire__ligne--bloque,
.surface-d2 .dire__ligne--bloque { border-left-color: #F87171; }
.surface-d .dire__ligne--bloque .dire__code,
.surface-d2 .dire__ligne--bloque .dire__code { color: #F87171; }

/* === Indicateurs de tableau de bord ===================== */

.kpi { padding: var(--space-6) 0; }
.kpi__valeur {
  font-family: var(--font-head);
  font-weight: var(--w-semi);
  font-size: 52px;
  line-height: 1;
  letter-spacing: var(--tracking-display);
  color: var(--pal-canvas);
  display: block;
}
.kpi__libelle {
  font-size: 13px;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--pal-muted-dark);
  display: block;
  margin-bottom: var(--space-4);
}
.kpi__note { font-size: 13px; color: var(--pal-muted-dark); display: block; margin-top: var(--space-3); font-family: var(--font-mono); }

/* === Barres de proportion =============================== */

.barre { display: flex; height: 10px; margin: var(--space-2) 0 var(--space-3); }
.barre span { display: block; height: 100%; }
.barre .b-rouge { background: var(--pal-red); }
.barre .b-ambre { background: var(--pal-amber); }
.barre .b-vert  { background: var(--pal-green); }
.barre .b-vide  { background: var(--rule-dark); }

/* === Tarifs ============================================= */

.tarif { border: 1px solid var(--rule); padding: var(--space-7); background: var(--bg2); display: flex; flex-direction: column; }
.tarif--phare { border: 1px solid var(--pal-navy); border-top: 3px solid var(--pal-red); }
.tarif .t-carte { margin-bottom: var(--space-2); }
.tarif__prix {
  font-family: var(--font-head);
  font-weight: var(--w-semi);
  font-size: 44px;
  letter-spacing: var(--tracking-display);
  color: var(--fg1);
  display: block;
  margin: var(--space-4) 0 var(--space-2);
}
.tarif__unite { font-size: var(--type-meta-web); color: var(--fg3); display: block; margin-bottom: var(--space-5); }
.tarif ul { list-style: none; margin: 0 0 var(--space-6); padding: 0; flex: 1; }
.tarif li { padding: var(--space-3) 0; border-bottom: 1px solid var(--rule); font-size: 16px; color: var(--fg2); }
.tarif li:last-child { border-bottom: none; }

/* === Citation ========================================== */

.citation {
  border-left: 2px solid var(--pal-red);
  padding-left: var(--space-6);
  max-width: 60ch;
}
.citation p {
  font-size: var(--type-h3);
  line-height: 1.35;
  font-family: var(--font-head);
  font-weight: var(--w-reg);
  letter-spacing: var(--tracking-tight);
  color: var(--fg1);
  margin-bottom: var(--space-4);
}
.surface-d .citation p, .surface-d2 .citation p { color: var(--pal-canvas); }
.citation cite {
  font-style: normal;
  font-size: var(--type-meta-web);
  color: var(--fg3);
  font-family: var(--font-mono);
}
.surface-d .citation cite, .surface-d2 .citation cite { color: var(--pal-muted-dark); }

/* === Foire aux questions =============================== */

.faq details {
  border-bottom: 1px solid var(--rule);
  padding: var(--space-5) 0;
}
.faq summary {
  font-family: var(--font-head);
  font-weight: var(--w-med);
  font-size: var(--type-h3);
  letter-spacing: var(--tracking-tight);
  color: var(--fg1);
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: var(--space-5);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--pal-red-strong); font-family: var(--font-mono); }
.faq details[open] summary::after { content: "−"; }
.faq details p { margin: var(--space-5) 0 0; max-width: 70ch; }

/* === Pied de page ====================================== */

.pied {
  padding: var(--space-8) var(--space-7);
  border-top: 1px solid var(--rule-dark);
  font-size: var(--type-meta-web);
  color: var(--pal-muted-dark);
}
.pied a { color: var(--pal-muted-dark); }
.pied a:hover { color: var(--pal-yellow); }

/* === L'AVERTISSEMENT ==================================== */

/* RAMENÉ À UNE NOTE LE 02.09.2026 · Victor, sur Jomini · « c'est trop gros et
   rouge, réduis la taille ». C'était un APLAT pleine largeur, blanc sur rouge
   vif, en capitales espacées · dessiné quand il annonçait « ceci est une
   maquette » et devait être la première ligne qu'on lit. Il ne sert plus à
   cela · sur Jomini il porte une panne technique qui, servie en HTTP, ne
   devrait jamais paraître, et qu'on n'aperçoit qu'un instant au chargement.
       UN SIGNAL DIMENSIONNÉ POUR CE QU'IL ANNONÇAIT AUTREFOIS CRIE POUR CE
       QU'IL ANNONCE AUJOURD'HUI · ET C'EST L'INSTANT OÙ IL CRIE POUR RIEN
       QUE LE VISITEUR RETIENT.
   Il devient un filet rouge à gauche sur un fond teinté · le rouge SIGNALE
   toujours, il ne remplit plus l'écran. Le texte passe en encre rouge foncée
   (`--pal-red-ink`, faite pour être lue) sur une teinte à 8 % du même rouge ·
   c'est le couple que la charte destine au texte, là où l'ancien mettait du
   blanc sur un aplat et devait se justifier au centième de contraste.
   Capitales et interlettrage retirés · ils tiennent sur trois mots, pas sur
   quatre lignes de prose technique. */
.avertissement {
  background: color-mix(in srgb, var(--pal-red-strong) 8%, transparent);
  color: var(--pal-red-ink);
  border-left: 3px solid var(--pal-red-strong);
  padding: var(--space-2) var(--space-3);
  font-size: var(--type-meta-web);
  line-height: 1.5;
  text-align: left;
}

/* === Utilitaires ======================================= */

/* L'ATTRIBUT `hidden` DOIT GAGNER · corrigé le 2026-08-01.
   Le navigateur cache un élément `hidden` avec une règle `display: none`
   de sa feuille par défaut, que N'IMPORTE QUELLE règle d'auteur posant un
   `display` écrase. Une ligne de rapport en `display: flex` marquée
   `hidden` restait donc VISIBLE, sans que rien ne le signale · le DOM
   répondait `hidden === true` pendant que l'écran l'affichait.
   Défaut trouvé sur la ligne d'alerte du rapport de restitution de Jomini,
   qui s'affichait en permanence avec un tiret à la place du chiffre.
   `!important` est ici la convention établie, pas un raccourci · c'est ce
   que fait toute feuille de normalisation sérieuse, et pour cette raison. */
[hidden] { display: none !important; }

.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
/* Les échelons 3, 4 et 5 manquaient · une page qui écrivait `mt-4` n'obtenait
   RIEN, en silence, sans erreur nulle part. Ajoutés le 2026-08-01. */
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }
.mt-7 { margin-top: var(--space-7); }
.mt-8 { margin-top: var(--space-8); }
.note-mono { font-family: var(--font-mono); font-size: 13px; color: var(--fg3); }
/* Meme defaut que celui des jetons, trouve le 2026-08-03 en cherchant s il
   s en cachait d autres de la meme forme · la variante claircie etait posee
   sur .surface-d SEULE. Dans une section .surface-d2, .note-mono retombait
   donc sur --fg3, soit #64748B, et ressortait a 3.07 de contraste sur
   #1E293B pour un seuil de 4.5. C est la ligne qui declare COMMENT chaque
   rapprochement a ete obtenu, « gabarit », « inconnu · piste » · autrement
   dit LA MENTION QUI PORTE L HONNETETE DU TABLEAU ETAIT LA MOINS LISIBLE DU
   TABLEAU. Mesure sur .surface-d aussi · 3.70, sous le seuil egalement. */
.surface-d .note-mono, .surface-d2 .note-mono { color: var(--pal-muted-dark); }

/* === Le téléphone · corrigé le 2026-08-04 ===============================

   LES QUATRE PAGES PRODUIT GLISSAIENT HORIZONTALEMENT SUR UN TÉLÉPHONE.
   Mesuré à 375 px de large · Jomini 398, Corvisart 422, Jacquard 439,
   Méneval 476. Aucun banc ne l'a jamais vu · un banc en Node n'a pas de
   moteur de mise en page, il ne connaît ni la largeur d'une fenêtre ni la
   largeur minimale d'un contenu. C'est la même famille de fautes que
   l'encre blanche sur fond blanc du même jour · elle ne se lit pas dans un
   fichier, elle se regarde.

   Ce n'est pas un détail d'esthétique. Le cahier des charges de Méneval dit
   que le téléphone est un cas de premier rang, et le public visé · les
   chercheurs d'emploi · postule en grande partie depuis un téléphone. Une
   page qui glisse de côté à chaque défilement est une page qu'on quitte.

   TROIS CAUSES DISTINCTES, et les tableaux n'en font pas partie · ils sont
   déjà tous enveloppés dans `.tbl-hz`, qui les fait défiler chez eux. La
   règle anticipait le problème et elle fonctionne.

   1 · Un élément de grille ne descend jamais sous la largeur minimale de son
       contenu tant que `min-width` vaut `auto`. Une seule ligne de JSON non
       sécable dans `.sortie` élargissait donc toute la colonne à 430 px, et
       la colonne poussait la page. C'est le défaut de Méneval.

   2 · `.nav__liens` reste une rangée unique. Le menu passe bien en colonne
       sur mobile, mais la rangée de liens qu'il contient, elle, ne passe
       jamais à la ligne · cinq ou six entrées suffisent à dépasser. C'est
       le défaut des trois autres pages.

   3 · UNE CAUSE QUE LES DEUX PREMIÈRES CORRECTIONS ONT DÉMASQUÉE, pas créée.
       Une fois 1 et 2 réparées, Jomini et Corvisart tombaient à 375 et
       Jacquard restait à 395. Le coupable · un chemin de fichier en fonte
       monospacée, `0600_RESSOURCES/06.05_Lean_Qualite_Production · référentiel
       des postes`, dans un `.note-mono` large de 235 px qui en réclamait
       312. Un chemin, une URL ou une ligne de commande n'a pas d'espace ·
       le navigateur n'a donc aucun endroit où couper et laisse déborder.
       C'est exactement ce que Jomini affiche dans son bandeau « le moteur
       n'a pas pu être chargé » · trois commandes et une adresse, toutes
       insécables, sur la page la plus étroite qu'un visiteur puisse avoir.
       `anywhere` plutôt que `break-word` · les deux coupent le mot trop
       long, mais `anywhere` réduit aussi la largeur minimale du contenu,
       et c'est cette largeur-là qui pousse une colonne de grille. */
.grille > *, .duel > * { min-width: 0; }
.mono, .note-mono, code, .chiffre__source { overflow-wrap: anywhere; }

/* La sortie montre la charge utile EXACTE. On ne la recoupe pas pour la
   faire tenir · on la fait défiler dans sa propre boîte. Recouper les
   lignes d'un envoi qu'on affiche pour prouver ce qui part reviendrait à
   montrer autre chose que ce qui part. */
.sortie { overflow-x: auto; }

@media (max-width: 900px) {
  .g2, .g3, .g4, .duel { grid-template-columns: 1fr; }
  .grille--filets > * { border-left: none; padding: 0; }
  .duel__col + .duel__col { border-left: none; border-top: 1px solid var(--rule); }
  .surface-d .duel__col + .duel__col,
  .surface-d2 .duel__col + .duel__col { border-top-color: #46536b; }
  .pav { padding: var(--space-8) var(--space-5); }
  .nav { flex-direction: column; gap: var(--space-3); align-items: flex-start; position: static; }
  .nav__liens { flex-wrap: wrap; gap: var(--space-2) var(--space-4); }
  .tbl { font-size: 15px; }
  .tbl th { padding: var(--space-3); }
  .tbl td { padding: var(--space-3); }

  /* CAUSE 4 · LA MÊME FAUTE QUE 2, À UN AUTRE ENDROIT. Un `nowrap` posé
     pour une bonne raison sur un large écran devient un débordement sur un
     étroit · il n'y a plus de colonne de droite où aligner quoi que ce soit.

     `.rapport__val` est en `nowrap` parce que sur un écran large les valeurs
     sont courtes · un nombre, un état · et l'alignement à droite en fait une
     colonne qui se lit d'un coup d'œil. Sur un téléphone la ligne n'a plus
     de largeur à donner, et « aucun défaut · 1450 caractères sur 1450
     montrés » réclamait 430 px dans une boîte de 327. Mesuré le 2026-08-04
     sur la page de Méneval, section `#consentement` · c'est-à-dire sur LA
     LIGNE QUI ANNONCE QUE RIEN N'EST CACHÉ. Elle sortait de l'écran.

     La clé passe donc au-dessus de la valeur, alignées à gauche toutes les
     deux, et la valeur a le droit de revenir à la ligne. Le modificateur
     `.rapport__val--long` existait déjà pour ce cas · il fallait le poser à
     la main sur chaque ligne longue, et personne ne l'avait fait sur
     celle-là. Une exception qu'il faut penser à demander n'est pas une
     protection. */
  .rapport__ligne { flex-direction: column; align-items: flex-start; gap: var(--space-1); }
  .rapport__val { white-space: normal; overflow-wrap: anywhere; text-align: left; }

  /* Même famille · les mentions du bandeau de réassurance sont en `nowrap`
     pour ne pas se couper en deux au milieu d'une garantie. « Aucun envoi
     automatique aux employeurs » fait 336 px et n'entre pas dans 375 moins
     les marges. Elles se coupent donc, plutôt que de sortir de l'écran ·
     une garantie tronquée hors du cadre ne rassure personne. */
  .reassurance { padding: var(--space-5); gap: var(--space-3) var(--space-5); }
  .reassurance span { white-space: normal; }

  /* CAUSE 5 · LE MÊME `nowrap`, UNE TROISIÈME FOIS, ET LE SEUL ENDROIT OÙ
     LIRE LA FEUILLE NE POUVAIT PAS SUFFIRE À LE TROUVER.

     Un `.jeton` est court quand on l'écrit dans la page · « scellé »,
     « dossier entier ». Il devient long quand LE SCRIPT le réécrit à
     l'exécution · « SCELLÉ · RIEN NE PART SANS LUI » réclame 263 px,
     « DOSSIER ENTIER · 2 INDICES RECONNUS » en réclame 304, et la barre de
     console qui les porte n'en a plus. Les deux sortaient de l'écran de
     Méneval, section `#consentement`, le 2026-08-10.

       UN LIBELLÉ ÉCRIT DANS LE HTML SE MESURE EN LISANT LE HTML · UN
       LIBELLÉ ÉCRIT PAR LE SCRIPT NE SE MESURE QU'EN FAISANT TOURNER LA
       PAGE. LA MOITIÉ DES TEXTES DE CES QUATRE PAGES SONT DE LA SECONDE
       SORTE.

     Le `nowrap` reste sur grand écran · il tient la pastille d'un seul
     tenant à côté de son titre. Sur téléphone la barre passe déjà en
     colonne · le jeton a toute la largeur, il peut donc se couper sans
     jamais se retrouver seul contre un titre. */
  .jeton { white-space: normal; }
}

/* =============================================================================
   L'AUTO-TEST DE SORTIE · Jomini, lot J7
   =============================================================================

   Le bloc qui dit, à chaque ouverture, ce que le navigateur a fait d'une
   requête sortante tentée exprès. Trois états, trois couleurs, et la couleur
   n'est jamais le seul porteur du sens · le texte suffit à comprendre, ce qui
   est la règle pour qui ne distingue pas le rouge du vert.

   `--essai` est l'état de départ. Il se voit une fraction de seconde, mais il
   doit exister · un bloc qui n'aurait que ses trois conclusions laisserait un
   vide au chargement, et un vide se lit comme une panne.

   RÉÉCRIT LE 2026-08-12, lot M31 · ce bloc parlait une langue que la maison
   ne parle pas. Il appelait `--vert`, `--rouge`, `--ambre`, `--gris-60`,
   `--surface-2`, `--texte-attenue` · SIX NOMS QUI NE SONT DÉFINIS NULLE PART.
   Chacun portait une valeur de repli, et c'est toujours le repli qui rendait.
   Or ces replis venaient d'une maquette sur fond sombre · un vert tendre
   `#3fb27f`, un gris clair `#b6bcc6`, un fond blanc à 4 % d'opacité. Posés
   sur le canvas clair de la maison, ils donnaient 2,55 et 1,83 · la phrase
   qui dit « la requête a été BLOQUÉE », c'est-à-dire la seule preuve visible
   que Jomini tient sa promesse, était le texte le moins lisible des deux
   pages. Le repli n'a jamais rougi, parce qu'un repli ne rougit pas · il
   remplace, silencieusement, et pour toujours.
     UNE VALEUR DE REPLI N'EST PAS UN FILET DE SÉCURITÉ QUAND LE JETON N'A
     JAMAIS EXISTÉ · C'EST LA VALEUR RÉELLE, DÉGUISÉE EN SECOURS, ET PLUS
     PERSONNE NE LA RELIT.
   Les six noms sont remplacés par les jetons de la charte. Aucun repli n'est
   conservé · s'il en manquait un, on veut que cela se voie tout de suite,
   pas que cela s'arrange. La couleur reste ce qu'elle était en intention ·
   vert tenu, rouge rompu, ambre douteux · mais en encre, pas en trait.
   ============================================================================= */

.preuve-sortante {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-6);
  margin-top: var(--space-8);
  /* `var(--radius-md, 8px)` · le septième nom fantôme, et le plus instructif.
     `--radius-md` n'existe pas, et `palambur.css` écrit noir sur blanc, à
     côté de `--radius-pill` · « the ONLY non-zero radius ». Ce bloc avait donc
     les coins arrondis contre une règle explicite de la charte, non pas
     malgré elle mais À TRAVERS elle · la règle était respectée par le jeton,
     et contournée par le repli du jeton. */
  border-radius: var(--radius-none);
  background: var(--pal-canvas-pure);
  border: 1px solid var(--rule);
  border-left: 4px solid var(--pal-muted);
}

.preuve-sortante__etat {
  font-family: var(--font-mono), monospace;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.preuve-sortante__detail {
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--fg2);
}

/* LE TRAIT ET L'ENCRE SONT SÉPARÉS ICI · le filet de gauche garde la couleur
   de marque, qui est faite pour être vue en aplat ; le mot d'état prend
   l'encre, qui est faite pour être lue. C'est le même signal, dit deux fois,
   dans les deux langues qu'il faut. */

/* Tenue · le navigateur a nommé la règle qui a bloqué. C'est le seul cas où
   la page a le droit d'être affirmative. */
.preuve-sortante--tenue { border-left-color: var(--pal-green); }
.preuve-sortante--tenue .preuve-sortante__etat { color: var(--pal-green-strong); }

/* Rompue · la page promet sans mécanisme. C'est un défaut de publication, pas
   un avertissement d'usage · le ton doit le dire. */
.preuve-sortante--rompue { border-left-color: var(--pal-red); }
.preuve-sortante--rompue .preuve-sortante__etat { color: var(--pal-red-strong); }

/* Doute · on ne conclut pas, et on le dit plutôt que de choisir la conclusion
   qui arrange. UN RÉSULTAT NON CONCLUANT ANNONCÉ VAUT MIEUX QU'UN VERT FAUX. */
.preuve-sortante--doute { border-left-color: var(--pal-amber); }
.preuve-sortante--doute .preuve-sortante__etat { color: var(--pal-amber-strong); }

.preuve-sortante--essai .preuve-sortante__etat { color: var(--fg2); }


/* ===========================================================================
   ACCESSIBILITÉ · lot J25

   Deux classes, et une seule idée · ce qui aide l'oreille ne doit pas gêner
   l'œil, et ce qui aide l'œil ne doit pas se taire à l'oreille.
   =========================================================================== */

/* Le lien d'évitement. Il est HORS DE L'ÉCRAN, pas caché · `display:none`
   l'aurait retiré de l'ordre de tabulation, c'est-à-dire retiré à la seule
   personne à qui il sert. Il revient au premier coup de tabulation. */
.saut {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 20px;
  background: var(--bleu, #1c3f6e);
  color: #fff;
  text-decoration: none;
  font-weight: 600;
}
.saut:focus { left: 0; }

/* La ligne de verdict · elle dit en une phrase ce que l'écran dit à quatre
   endroits. Discrète, jamais invisible · un état qu'on ne voit pas ne se
   dément pas. */
.verdict {
  /* PAS DE `margin: 0` ICI. La première version l'écrivait, pour effacer les
     marges par défaut d'un <p> · elle effaçait du même geste la classe
     utilitaire `mt-7` que la page pose sur cet élément, et le bloc se
     retrouvait collé au panneau du dessus. UNE RÈGLE DE COMPOSANT QUI POSE
     UNE MARGE ÉCRASE L'UTILITAIRE QUI DEVAIT LA DÉCIDER, et elle l'écrase
     sans bruit · rien dans le HTML ne dit que `mt-7` ne sert plus à rien.
     On ne touche donc qu'au bas, que personne ne pilote. */
  margin-block-end: 0;
  padding: 12px 16px;
  border-left: 3px solid var(--bleu, #1c3f6e);
  background: rgba(28, 63, 110, .06);
  font-size: .95rem;
  color: var(--fg1, inherit);
}

/* ---------------------------------------------------------------------------
   LA ZONE DE DÉPÔT · Méneval, lot M6.

   Un cadre en pointillés, et rien d'autre. Pas d'icône de nuage · un nuage
   dessiné sur une zone qui ne monte RIEN sur un serveur est un contresens
   qu'on met dix ans à corriger dans la tête des gens.

   L'INPUT DE FICHIER RESTE CLIQUABLE ET RESTE ATTEIGNABLE AU CLAVIER.
   La tentation, ici, est de le cacher derrière un `<label>` maquillé en
   bouton · c'est joli, et cela retire du parcours clavier le seul contrôle
   de l'écran qui ouvre un fichier. On le laisse visible sous la phrase.
   --------------------------------------------------------------------------- */
.depot {
  border: 2px dashed var(--rule);
  padding: var(--space-6);
  background: var(--bg2);
  color: var(--fg1);
  text-align: center;
}
.depot p { margin-inline: auto; max-width: 46ch; color: var(--fg2); }
.depot strong { color: var(--fg1); }
.depot .etiquette { color: var(--fg3); }
.depot input[type="file"] {
  margin-top: var(--space-4);
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--fg2);
}
/* L'état « on survole avec un fichier dans la main ». Il est posé par le
   script et retiré par lui · une classe d'état qui n'existe que dans la
   feuille ne se voit pas quand le script cesse de la poser. */
.depot--vise { border-color: var(--pal-navy); background: var(--bg1); }

/* AUCUNE VARIANTE SOMBRE, ET CE N'EST PAS UN OUBLI · c'est le contrôle des
   feuilles qui l'a exigé, le 2026-08-06.

   La première version posait `.surface-d .depot` et `.surface-d2 .depot`
   « au cas où ». Aucune page ne pose de zone de dépôt sur fond sombre · ces
   quatre règles décrivaient un écran qui n'existe pas, et elles le
   décrivaient FAUX · encre claire sur le fond clair que `.depot` pose
   lui-même, mesuré à 1.05 de contraste. Une règle écrite pour un cas qu'on
   n'a jamais regardé se trompe sans que personne ne la lise.

   Ce qui reste est plus solide qu'une variante · l'îlot porte SON fond ET
   SON encre. Posé dans une section sombre, il reste lisible sans que la
   feuille ait eu à prévoir le montage. C'est la leçon des libellés blancs
   sur blanc du 2026-08-04, appliquée du bon côté cette fois. */

/* ---------------------------------------------------------------------------
   LES GABARITS EN BLOCS · Méneval, lot M24.

   Trois vignettes de mise en page, faites de rectangles gris et de rien
   d'autre. Elles s'affichent AVANT tout dépôt, et il n'y a rien dedans qui
   puisse fuir · c'est le seul écran du produit dont on peut dire cela sans
   avoir à le mesurer.

   POURQUOI DES BLOCS ET PAS UN VRAI CV EN MINIATURE. Une vignette remplie
   fait comparer au candidat des CONTENUS qu'il connaît par cœur au lieu de
   comparer des FORMES · il relit sa propre expérience trois fois et ne voit
   pas la mise en page. Elle exigerait en plus trois rendus complets avant
   qu'il ait choisi, soit trois passages de moteur pour deux qu'on jette.

   TOUT EST EN CSS, RIEN N'EST UNE IMAGE. Une capture d'écran de gabarit
   dérive du gabarit au premier correctif, exactement comme un moteur recopié
   à la main dérive de ses sources · et rien ne le signalerait. Ici la
   vignette EST du CSS, comme le gabarit qu'elle annonce.

   LES BLOCS SONT DÉCORATIFS ET LE DISENT · `aria-hidden` sur la vue, et le
   texte de la carte porte l'information. Un lecteur d'écran qui énumérerait
   onze rectangles vides ne rendrait service à personne.

   AUCUNE VARIANTE SOMBRE · même raison qu'à `.depot` ci-dessus. La vignette
   porte SON fond et SON encre, elle reste lisible où qu'on la pose, et on
   n'écrit pas de règle pour un montage qu'aucune page ne fait.
   --------------------------------------------------------------------------- */
.gabarit {
  border: 1px solid var(--rule);
  background: var(--bg2);
  color: var(--fg1);
  padding: var(--space-5);
}
.gabarit .t-carte { margin-block: var(--space-4) var(--space-3); }
.gabarit p { font-size: var(--type-body-web); margin: 0; color: var(--fg2); }
.gabarit p + p { margin-top: var(--space-3); }
.gabarit__note {
  font-family: var(--font-mono);
  font-size: var(--type-meta-web);
  color: var(--pal-muted);
}

/* La vue · une page A4 en réduction. Le rapport est celui du papier, non
   pour faire joli · une vignette carrée ferait croire qu'une colonne
   latérale tient plus large qu'elle ne tient. */
.gabarit__vue {
  aspect-ratio: 1 / 1.414;
  background: var(--pal-canvas-pure);
  border: 1px solid var(--rule);
  padding: 9%;
  display: flex;
  flex-direction: column;
  gap: 4%;
}
.gab-bloc { background: #cbd5e1; border-radius: 1px; }
.gab-bloc--titre  { height: 7%; background: #94a3b8; }
.gab-bloc--sous   { height: 4%; width: 55%; }
.gab-bloc--ligne  { height: 3%; }
.gab-bloc--court  { height: 3%; width: 62%; }
.gab-bloc--pave   { flex: 1; }
.gab-bloc--filet  { height: 1.5%; background: var(--pal-red); }
.gab-bloc--photo  { width: 100%; aspect-ratio: 1; background: #94a3b8; flex: none; }

/* La rangée d'en-tête · photo à gauche, deux blocs de texte à droite.
   LA RANGÉE PORTE UNE HAUTEUR DÉFINIE, ET CE N'EST PAS DU CONFORT. Une
   hauteur en pourcentage se résout contre le parent · un parent dont la
   hauteur est `auto` ne donne rien à résoudre, et l'enfant tombe à zéro.
   La première version laissait la rangée en hauteur automatique · le titre
   et le sous-titre du gabarit Classique mesuraient 0 pixel, la vignette
   s'affichait AMPUTÉE DE SON EN-TÊTE, et rien ne le disait · un bloc de
   zéro pixel ne laisse pas de trou, il laisse une vignette plausible.
   Mesuré dans Chrome, pas deviné · le harnais d'aperçu rend une fenêtre de
   largeur nulle et n'aurait rien pu en dire. */
.gab-rang { display: flex; gap: 4%; align-items: stretch; height: 14%; flex: none; }
.gab-rang > .gab-pile {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.gab-rang > .gab-bloc--photo { width: auto; height: 100%; }
.gab-rang .gab-bloc--titre { flex: 0 0 45%; height: auto; }
.gab-rang .gab-bloc--sous  { flex: 0 0 28%; height: auto; }

/* Les deux flux de la colonne latérale · c'est LE point risqué du lot, et
   la vignette le montre plutôt que de le lisser. */
.gabarit__vue--bande { flex-direction: row; gap: 6%; }
.gabarit__vue--bande > .gab-bande {
  width: 32%;
  background: #e2e8f0;
  padding: 6%;
  display: flex;
  flex-direction: column;
  gap: 8%;
  flex: none;
}
.gabarit__vue--bande > .gab-corps {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 5%;
}
.gab-bande .gab-bloc { background: #94a3b8; }

/* IL N'Y A PAS DE MODIFICATEUR POUR LE GABARIT SOBRE, ET C'EST VOULU.
   La première version en posait un, qui fonçait son bandeau de titre · à
   l'écran, le gabarit « sobre » était le plus appuyé des trois, ce qui est
   exactement le contraire de ce que son nom promet. Et surtout · le sobre
   ne se distingue pas par une règle, il se distingue par CE QU'IL N'A PAS ·
   pas de photo, pas de filet rouge. La vignette le dit en portant moins de
   blocs, comme le vrai gabarit le dira en portant moins d'éléments.
   UNE CLASSE QUI EXISTE POUR NOMMER UNE DIFFÉRENCE QU'ELLE NE PORTE PAS
   FINIRA PAR SE VOIR CONFIER UNE DIFFÉRENCE. */

/* LE BOUTON CHOISI · ajouté le 2026-08-11 avec l'étape 6 de Méneval.

   Trois boutons choisissent une mise en page, et le script marquait le choix
   avec une classe QUI N'EXISTAIT NULLE PART. Les trois restaient donc
   identiques à l'écran · le visiteur cliquait « Sobre », le fichier sortait
   bien en sobre, et rien ne le lui disait.

   LE BANC NE POUVAIT PAS LE VOIR, et ce n'est pas un manque du banc · il lit
   `className`, et `className` était juste. Node n'a pas de moteur de style.
   C'est le troisième défaut de cette famille dans ce dépôt, après le libellé
   blanc sur blanc du 2026-08-08 · un état que le code tient correctement et
   que la feuille ne peint pas est le seul défaut qu'un banc CERTIFIE.

   L'inversion reprend celle de `:hover` · même encre, même fond, aucun style
   nouveau. Le choix se lit donc comme un survol qui reste, ce qui est
   exactement ce qu'il est. */
.btn-secondary.est-choisi {
  background: var(--pal-navy);
  color: var(--pal-canvas-pure);
}
.surface-d .btn-secondary.est-choisi,
.surface-d2 .btn-secondary.est-choisi {
  background: var(--pal-canvas-pure);
  color: var(--pal-navy);
}

/* Le contour de focus n'est JAMAIS retiré. Une maquette qui l'efface pour
   faire propre rend le clavier inutilisable, et cela ne se voit pas à la
   souris · c'est-à-dire jamais, pour qui la conçoit. */
:focus-visible {
  outline: 2px solid var(--bleu-clair, #4a8fd4);
  outline-offset: 2px;
}
