/* ===========================================================================
   jomini.css · le pupitre à deux temps · lot du 2026-08-24
   ===========================================================================

   POURQUOI CE FICHIER EXISTE.

   Jusqu'ici, `apercu_jomini.html` ne liait que la charte commune
   (`palambur.css`, `apercu.css`, `bandeau.css`) · une page de vitrine qui
   défile n'a pas besoin d'un gabarit propre. Le pupitre en a un · un menu de
   gauche fixe, deux volets de droite, un tiroir qui s'ouvre exprès. Ce
   gabarit n'appartient qu'à Jomini · il n'a aucune raison d'entrer dans la
   charte commune, que quatre autres produits lisent aussi.

   AUCUNE COULEUR EN DUR ICI · tout se lit dans les jetons `--pal-*` de
   `_charte/palambur.css`, chargée avant celle-ci. Aucune ombre. Le rayon
   plein reste réservé au bouton principal (`--radius-pill`, définie dans la
   charte) · tout le reste de ce fichier est à angle droit.

   Recopiée par `outils/construire.mjs` dans le fichier hors ligne, au même
   titre que les deux feuilles de la charte · voir la note du lot J26 dans
   `apercu_jomini.html` sur ce que « recopiée » veut dire et ce qu'elle coûte
   si on l'oublie.
   =========================================================================== */

/* === Le conteneur serré du pupitre =========================================

   `.pav` (charte commune) pose 128 px de remplissage vertical · pensé pour
   une section de vitrine qui défile, pas pour un outil qu'on doit voir
   d'un coup d'œil. Le pupitre garde donc son propre remplissage, nettement
   plus court, sans toucher `.pav` lui-même · les sections de l'annexe,
   plus bas sur la page, continuent de s'en servir telles quelles.

   `.pupitre-entete` (le `<header>` séparé qui portait le titre AU-DESSUS
   du pupitre) A VÉCU jusqu'au 01.09.2026 · retiré le jour où Victor a
   demandé que le titre déménage DANS le bandeau d'avancement, à la place
   du nom du produit chez Méneval (§ « EN-TÊTE DE L'OUTIL + AVANCEMENT »
   plus bas, `.entete-outil .marque h1`) · ses quatre règles éparpillées
   dans ce fichier (marge, taille du titre en 22-30px puis 20-27px puis
   28-40px puis 20-26px, une redescente à chaque fois que Victor a vu le
   rendu) sont retirées avec lui plutôt que laissées mortes. */

.pupitre-section { padding: var(--space-5) var(--space-7) var(--space-6); }

/* === Le pupitre · structure générale ====================================== */

.pupitre {
  display: grid;
  grid-template-columns: 220px 1fr;
  align-items: start;
  gap: 0;
  border: 1px solid var(--rule);
}
.surface-1 .pupitre,
.surface-2 .pupitre { background: var(--bg2); }

/* === Le menu de gauche · rôle tablist ===================================== */

.pupitre__menu {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-5) var(--space-4);
  border-right: 1px solid var(--rule);
  background: var(--bg1);
  align-self: stretch;
}
.surface-d .pupitre__menu,
.surface-d2 .pupitre__menu { background: var(--bg-dark2); border-right-color: var(--rule-dark); }

/* LA COLONNE UNIFORMISÉE · petite écriture, alignement gauche · lot J81,
   01.09.2026. Victor · « uniformise la colonne de gauche (petite écriture,
   alignement gauche) ».

   CE QUI A ÉTÉ MESURÉ AVANT DE CHOISIR UNE VALEUR, PAS INVENTÉ · les trois
   familles de texte que `.pupitre__menu` portait déjà, relevées dans ce
   fichier avant ce lot ·
     .pup-onglet          14px  font-body   (ligne alors 81, aucun jeton)
     .pup-lien-limites     12px  font-mono   (ligne 117)
     .pupitre__preuve      12px  font-mono   (`.jeton`, `_charte/apercu.css`)
   Deux jetons sur trois portaient déjà 12px · « petite écriture » ne
   demande donc pas une quatrième valeur, elle demande que `.pup-onglet`
   rejoigne les deux autres. 12px devient LA taille commune de la colonne,
   `.pup-onglet` compris, ci-dessous. Le corps de l'outil, pour mémoire, est
   à 14px (`.pupitre .zone`/`.sortie`, § plus bas, lot du 01.09.2026 déjà en
   place) · 12px reste donc bien PLUS PETIT que le corps de la page
   principale de l'outil, comme demandé, sans réinventer une échelle que le
   fichier ne connaît pas déjà.
   L'ALIGNEMENT À GAUCHE, LUI, N'A RIEN TROUVÉ À CORRIGER · `.pup-onglet`
   le posait déjà en toutes lettres (`text-align: left`, hérité de la
   ligne 75 ci-dessous, jamais retiré), `.pup-lien-limites` et
   `.pupitre__preuve` sont des éléments de bloc sans centrage nulle part
   dans la charte qui les touche (vérifié par lecture de `_charte/apercu.css`
   et `_charte/palambur.css`, aucun `text-align: center` sur un ascendant du
   pupitre). Le seul désaccord venait des deux boutons qui rejoignent cette
   colonne dans ce même lot · `.btn-secondary` (`_charte/boutons.css`) centre
   son texte dans une pilule, exactement ce que cette colonne n'est pas. Ils
   reçoivent donc une classe à eux, `.pup-action` plus bas, taillée sur le
   PATRON de `.pup-onglet` (même boîte, même fer à gauche, même 12px) mais
   sans son état « sélectionné », qu'un bouton d'action n'a jamais.

   LE RELEVÉ CI-DESSUS EST CELUI D’AVANT J81, gardé parce qu’il dit
   pourquoi 12px · le lot J86 (02.09.2026) a ensuite aligné le lien et le
   jeton sur `.pup-action` en ENTIER, police comprise · § leur note plus
   bas. L’uniformité de J81 s’était arrêtée à la taille et au fer à
   gauche, et Victor voyait encore deux formats. */
.pup-onglet {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  text-align: left;
  padding: var(--space-3) var(--space-3);
  border: 1px solid transparent;
  background: transparent;
  color: var(--fg2);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: var(--w-semi, 600);
  cursor: pointer;
}
.pup-onglet:hover { color: var(--fg1); border-color: var(--rule); }
.pup-onglet:focus-visible { outline: 2px solid var(--pal-navy); outline-offset: 2px; }
.pup-onglet[aria-selected="true"] {
  color: var(--pal-canvas-pure);
  background: var(--pal-navy);
  border-color: var(--pal-navy);
}
.surface-d .pup-onglet,
.surface-d2 .pup-onglet { color: var(--pal-text-on-dark); }
.surface-d .pup-onglet:hover,
.surface-d2 .pup-onglet:hover { color: #fff; border-color: var(--rule-dark); }

.pup-onglet__mot { flex: 1 1 auto; }
/* `.pup-onglet__ico` ET `.pup-onglet__compte` RETIRÉES · trouvées mortes le
   2026-09-02 (diagnostic mobile de Victor) · aucune des deux ne correspond
   à un élément du balisage actuel (`apercu_jomini.html`, les deux boutons
   `.pup-onglet` ne portent plus qu'un seul `<span class="pup-onglet__mot">`
   chacun) · confirmé par recherche, aucune occurrence hors leur propre
   définition. Rien n'indique qu'elles datent des lots de ce soir, un
   reliquat plus ancien probablement. */

/* LES BOUTONS D'ACTION DU MENU · « Charger un exemple », « Vider » · lot
   J81, 01.09.2026. Même boîte que `.pup-onglet` juste au-dessus (fer à
   gauche identique, même remplissage, même 12px, même bordure transparente
   qui se colore au survol) · un visiteur qui descend la colonne au clavier
   ou à l'œil ne doit pas voir deux familles de bouton se succéder sans
   raison. Ce qui les distingue reste volontaire ·
     · poids NORMAL, pas `--w-semi` · les onglets choisissent LE panneau
       affiché, un choix qui dure ; ces deux boutons déclenchent un geste
       ponctuel, la hiérarchie visuelle le dit sans un mot de plus ;
     · aucun état `[aria-selected="true"]` · ce ne sont pas des onglets
       (pas de `role="tab"` sur eux, voir apercu_jomini.html), rien ne les
       fait rester « actifs » après un clic.
   `border-radius` repris de `.pup-onglet` (§ plus bas dans ce fichier,
   « LE MENU DE GAUCHE, DES ONGLETS QU'ON TOUCHE ») directement ici, dans
   la même règle · une classe neuve n'a pas à répéter le split historique
   qu'un correctif tardif a imposé à `.pup-onglet`. */
.pup-action {
  display: flex;
  align-items: center;
  width: 100%;
  text-align: left;
  padding: var(--space-3) var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-card-sm);
  background: transparent;
  color: var(--fg2);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: var(--w-reg, 400);
  cursor: pointer;
}
.pup-action:hover { color: var(--fg1); border-color: var(--rule); }
.pup-action:focus-visible { outline: 2px solid var(--pal-navy); outline-offset: 2px; }
.surface-d .pup-action,
.surface-d2 .pup-action { color: var(--pal-text-on-dark); }
.surface-d .pup-action:hover,
.surface-d2 .pup-action:hover { color: #fff; border-color: var(--rule-dark); }

.pupitre__filet {
  border-top: 1px solid var(--rule);
  margin: var(--space-4) 0;
}
.surface-d .pupitre__filet,
.surface-d2 .pupitre__filet { border-top-color: var(--rule-dark); }

/* LE LIEN ET LE JETON PRENNENT LE FORMAT DE `.pup-action` · lot J86,
   02.09.2026. Victor · « le format des boutons "Les six limites publiées"
   et "aucune fuite constatée" doivent avoir le même format que "Charger un
   exemple" et "Vider" ».
   MESURÉ AVANT D’ÉCRIRE, vrai Chrome 1440×900 (`_charte/navigateur.mjs`),
   page livrée · `.pup-action` 187×40 flex, 12px/400, padding 12px, bordure
   1px, rayon 12px · le lien 187×**52** et le jeton 187×**54**, en BLOC,
   padding 8px 12px, rayon 0, en mono (majuscules et interlettrage pour le
   jeton). Les douze pixels de trop ne venaient pas de la boîte mais d’un
   texte passé **sur deux lignes** (2,00 mesurées) · le mono en majuscules
   demande ~178 px pour « AUCUNE FUITE CONSTATÉE » là où la colonne en
   offre 161.
     FORCER UNE HAUTEUR AURAIT COUPÉ LE TEXTE · aligner la police le fait
     tenir sur une ligne, et la boîte retombe à 40 px d’elle-même.
   Gardé par `bancs/colonne.mjs`, qui DÉCOUVRE les enfants du menu et les
   compare entre eux · le prochain élément posé ici sera mesuré le jour
   même. */
.pup-lien-limites {
  display: flex;
  align-items: center;
  width: 100%;
  text-align: left;
  padding: var(--space-3) var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-card-sm);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: var(--w-reg, 400);
  /* UNE MESURE, PAS UN GOÛT · un `<button>` reste à `normal` (14 px en
     Barlow 12 px), un `<a>` et un `<div>` héritent du 1,5 de la page
     (18 px) · c’est ce SEUL écart qui rendait encore 44 px au lieu de 40
     une fois la police alignée. Relevé au banc, jamais deviné. */
  line-height: normal;
  color: var(--fg2);
  /* LE SOULIGNEMENT RESTE · seule marque qui dise, au milieu de quatre
     boutons, que celui-ci NAVIGUE · `.pup-action` n’en porte aucun, rien
     ne se heurte, et Victor a nommé le format, pas la décoration. */
  text-decoration: underline;
}
/* Le survol rejoint celui de `.pup-action` · ce lien SE CLIQUE. Le jeton,
   lui, n’en reçoit aucun · § plus bas. */
.pup-lien-limites:hover { color: var(--fg1); border-color: var(--rule); }
.pup-lien-limites:focus-visible { outline: 2px solid var(--pal-navy); outline-offset: 2px; }
.surface-d .pup-lien-limites,
.surface-d2 .pup-lien-limites { color: var(--pal-text-on-dark); }
.surface-d .pup-lien-limites:hover,
.surface-d2 .pup-lien-limites:hover { color: #fff; border-color: var(--rule-dark); }

/* LE JETON PREND LA BOÎTE DE `.pup-action`, ET RESTE UN ÉTAT · lot J86.
   Il dit le résultat de l’auto-test de sortie réseau (`preuveSortante()`,
   interface.js) · il ne se clique pas. CE QUI L’EN DISTINGUE EST GARDÉ ·
     · sa COULEUR D’ÉTAT · `.jeton--vert/--rouge/--gris`
       (`_charte/apercu.css`) peignent le texte ET la bordure
       (`1px solid currentColor`, § `.jeton`) quand les quatre boutons de la
       colonne ont une bordure TRANSPARENTE · ce liseré plein se lit comme
       un voyant, pas comme un bouton de plus ;
     · aucun `cursor: pointer` · la main promet un clic ;
     · aucun état de survol · une boîte qui répond à la souris attend un
       geste ;
     · sa marge haute (`--space-4`) reste · elle le détache des commandes,
       et Victor a nommé la boîte, pas l’espacement qui la précède.
   ABANDONNÉ · le mono, les majuscules et l’interlettrage de `.jeton` · ce
   sont EUX qui faisaient les deux lignes et les 54 px, les garder rendait
   la demande intenable sans couper le texte. `.jeton` reste posée dans le
   balisage et porte toujours la couleur et la bordure · rien n’est recopié
   d’elle ici (CLAUDE.md § 8), on n’écarte que ses trois propriétés de
   POLICE, dans la feuille du produit, jamais chez elle. */
.pupitre__preuve {
  display: flex;
  align-items: center;
  width: 100%;
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-3);
  border-radius: var(--radius-card-sm);
  text-align: left;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: var(--w-reg, 400);
  /* Même mesure que pour le lien · sans cette ligne le jeton rendait 44 px
     là où les quatre boutons rendent 40. */
  line-height: normal;
  text-transform: none;
  letter-spacing: normal;
  white-space: normal;
  max-width: 100%;
}

/* LA LED VERTE RESPIRANTE, À CÔTÉ DE « AUCUNE FUITE CONSTATÉE » · lot J83,
   01.09.2026. Victor · « à côté de "aucune fuite constatée" tu mets une
   petite LED verte qui brille légèrement, comme si ça vivait ».

   RÉUTILISE LA COULEUR DU JETON, NE L'INVENTE PAS (CLAUDE.md § 8) ·
   `background: currentColor` hérite directement la couleur posée par
   `.jeton--vert` (`_charte/apercu.css` · `--pal-green-strong` en clair,
   `#34D399` sur `.surface-d`/`.surface-d2`) puisque la LED vit DANS
   `#jeton-sortante`, qui porte cette classe. Si ce vert change un jour de
   valeur, la LED suit sans qu'une seule ligne d'ici n'ait à bouger.

   POSÉE ET RETIRÉE PAR `direCourt()` (interface.js), PAS PAR CETTE FEUILLE ·
   `hidden` masque l'élément par défaut · seul l'état « aucune fuite
   constatée » la révèle, et tout autre état du jeton (rouge, gris) la
   recouvre au passage, voir interface.js.

   LA RESPIRATION, PAS LE CLIGNOTEMENT · une seule propriété qui varie en
   douceur (l'opacité, complétée d'une ombre portée qui grandit avec elle)
   sur un cycle de 2,6 s, `ease-in-out`, largement au-dessus du seuil auquel
   un battement commence à lire comme une alerte. `prefers-reduced-motion`
   coupe l'animation sans rien retirer d'autre · déjà la pratique en usage
   ailleurs dans la maison pour ce même geste (`_charte/boutons.css`,
   `_charte/bandeau.css`) · la LED reste visible, simplement fixe. */
.jeton__led {
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-left: 6px;
  border-radius: 50%;
  background: currentColor;
  vertical-align: middle;
  /* SEULE LIGNE AJOUTÉE AU LOT J86 ICI · le jeton porteur est passé en
     `display: flex` · cette pastille devient élément de flexion et hérite
     d’un `flex-shrink: 1` qui l’écraserait dès que le texte serre.
     `flex: 0 0 auto` lui rend sa taille, et n’a aucun effet hors flexion.
     Couleur héritée, animation et `prefers-reduced-motion` intacts. */
  flex: 0 0 auto;
  animation: jomini-led-respire 2.6s ease-in-out infinite;
}
@keyframes jomini-led-respire {
  0%, 100% { opacity: .5;  box-shadow: 0 0 0 0 currentColor; }
  50%      { opacity: 1;   box-shadow: 0 0 5px 1px currentColor; }
}
@media (prefers-reduced-motion: reduce) {
  .jeton__led { animation: none; }
}

/* === Le contenu de droite ================================================== */

.pupitre__contenu {
  padding: var(--space-5);
  min-width: 0; /* empêche la grille de refuser de rétrécir sous le contenu */
}

.volet[hidden] { display: none; }

/* Les deux volets d'un même temps · même gabarit que la grille `.grille.g2`
   existante, redéclaré ici pour ne dépendre de rien d'autre que ce fichier
   quand il est question de largeur minimale à l'intérieur du pupitre. */
.volet__paire {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-5);
  align-items: start;
}
/* TROIS BLOCS HORIZONTAUX · lot du 01.09.2026, Victor · « 1 le texte
   initial du client, deuxième montre les éléments identifiés et dernier
   le résultat ». Seul `#panneau-masquer` porte cette classe (voir
   apercu_jomini.html) · `#panneau-restituer` garde `.volet__paire` nue, à
   deux colonnes, n'ayant rien d'équivalent à montrer au milieu.
   Rupture intermédiaire à 900px, PROPRE À CETTE VARIANTE · trois colonnes
   de texte serrent plus vite que deux, la règle générale à 700px (plus
   bas, `.volet__paire{grid-template-columns:1fr}`) suffirait sinon à
   laisser un palier étroit et inconfortable entre 900 et 700px.
   `minmax(0, 1fr)`, PAS `1fr` NU · mesuré au banc (`node bancs/mobile.mjs`,
   01.09.2026) · une piste `1fr` seule refuse de rétrécir sous la largeur
   INTRINSÈQUE de son contenu (règle CSS Grid) — et la colonne du milieu
   contient désormais le tableau de relecture (`#tbl-matrice`, cinq
   colonnes), bien plus large que 1/3 de pupitre. Résultat mesuré avant ce
   correctif · la page débordait de 351px à 375px de large, malgré la
   grille déjà repliée en une seule colonne. Même piège, même remède que
   `.pupitre__contenu{min-width:0}` plus haut dans ce fichier — pas un
   correctif nouveau, la continuation du même. */
.volet__paire--3 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); }
@media (max-width: 900px) {
  .volet__paire--3 { grid-template-columns: minmax(0, 1fr); }
}

/* LE MÊME REPLI, POUR `.volet__paire` NUE · trouvé le 2026-09-02, diagnostic
   mobile de Victor (« il y a problème pour Jomini version mobile »). La note
   ci-dessus disait « `#panneau-restituer` garde `.volet__paire` nue… n'ayant
   rien d'équivalent à montrer au milieu » pour justifier l'absence de ce
   second repli · vrai pour le NOMBRE de colonnes, faux pour la LARGEUR
   qu'elles laissent au bouton glissière « Remettre en clair » (§ LOT J82)
   posé dans la colonne de gauche.

   LE SEUIL N'EST PAS CELUI DE `.volet__paire--3` (900px, juste au-dessus) ·
   copié sans mesurer, il aurait laissé un trou. `.volet__paire--3` replie à
   900px pour une raison propre à SON contenu (un tableau de cinq colonnes) ·
   `.volet__paire` porte un bouton de largeur FIXE (363px mesurés, poignée +
   piste, `interface.js`/`brancherGlisse`) dans sa colonne de gauche, et ce
   bouton a son propre seuil, calculé puis VÉRIFIÉ au banc plutôt que deviné ·
   la colonne de gauche vaut (largeur de la fenêtre − 220px de menu − 96px de
   remplissage de section − 48px de remplissage du pupitre − 32px du corps de
   console − 24px de creux entre colonnes) ÷ 2 tant que `.pupitre` n'a pas
   replié son menu (repli à 700px seulement, § plus bas) · elle n'atteint
   363px qu'à ~1148px de fenêtre. 1200px reprend ce calcul avec une marge
   pour la barre de défilement d'un vrai navigateur (masquée dans le banc
   sans tête qui a mesuré ce calcul, jamais sur un poste de travail réel).
   Mesuré avant ce correctif · 800px ne laissait que 187px au bouton (402px
   une fois replié), 1024px seulement 299px (32px de texte coupés, « Remettre
   en clair » lisible mais amputé). Après correctif, zéro coupure mesurée de
   320px à 1280px, colonne de gauche comprise (voir le lot du plan technique
   pour le détail des largeurs vérifiées). */
@media (max-width: 1200px) {
  .volet__paire { grid-template-columns: minmax(0, 1fr); }
}

/* TROIS ÉTAPES, PAS TROIS BLOCS D'UN COUP · lot du 01.09.2026, précisé
   après coup · Victor, ayant vu les trois blocs simultanés · « je veux
   cette dynamique en trois étapes ». `interface.js` (`reglerEtape`) pose
   `.etape-1`/`.etape-2` sur `.volet__paire--3` et cache les colonnes pas
   encore atteintes avec `hidden` · ces deux règles ajustent la grille au
   nombre de colonnes RÉELLEMENT visibles, pour qu'une seule colonne ne
   se retrouve pas prisonnière d'un tiers de largeur avec du vide à côté.
   SCOPÉES AU-DESSUS DE 900px · sous cette largeur, la règle générale
   juste au-dessus empile déjà tout en une seule colonne, et `hidden` y
   suffit seul (rien à ajuster dans une grille qui n'a qu'une piste). Pas
   de classe pour l'étape 3 (pleine largeur) · c'est l'état par défaut du
   balisage, celui qu'un chargement SANS JavaScript laisserait voir ·
   `interface.js` (`etatInitial`, lot J78, 01.09.2026) applique
   `reglerEtape(1)` dès l'ouverture de la page, donc ce n'est jamais ce
   que le visiteur voit en pratique. */
@media (min-width: 901px) {
  .volet__paire--3.etape-1 { grid-template-columns: minmax(0, 1fr); }
  .volet__paire--3.etape-2 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

/* LA TAILLE DES BOÎTES · Victor, 01.09.2026 · « regarder que la taille des
   boites sont grand ». Revient sur quatre resserrements successifs du
   24.08.2026 (130 → 110 → 90px, § plus bas dans ce fichier, chacun daté et
   motivé par « tout voir d'un coup d'œil sans défiler ») · cette
   contrainte de tenir sur un seul écran n'est PLUS celle que Victor
   priorise aujourd'hui, et la faire taire silencieusement en laissant les
   anciennes valeurs aurait laissé les commentaires du 24.08 mentir sur ce
   qui gouverne la page. `--space-*` n'a pas de jeton assez grand ici · une
   valeur en dur, comme les trois resserrements qu'elle remplace.
   240px dépasse même le gabarit par défaut de la charte (190px, note
   d'origine ci-dessus) · la page défilera plus qu'au 24.08, en échange de
   boîtes qu'on peut lire sans les agrandir à la main. `resize:vertical`
   reste disponible pour qui veut plus encore. */
.volet .zone { min-height: 240px; }
.volet .sortie { min-height: 240px; max-height: 420px; overflow-y: auto; }
.volet .console__corps { padding: var(--space-4); }

/* HAUTEUR RÉGLABLE ET SYNCHRONISÉE · lot J79, 01.09.2026, Victor · « fais en
   sorte que les trois fenêtres "Votre texte" "Éléments identifiés" "Texte
   pseudonymisé" soient de taille réglable par l'utilisateur et de la même
   hauteur (20 lignes en mode 3 fenêtres) ».

   SCOPÉ AU MODE 3 FENÊTRES SEUL · `.volet__paire--3`, largeur ≥ 901px (même
   seuil que `.etape-1`/`.etape-2` juste au-dessus, où les trois colonnes sont
   RÉELLEMENT côte à côte). Le panneau « Redonner en clair » (`.volet__paire`
   à deux colonnes, plus bas dans la page) garde `.volet .zone`/`.volet
   .sortie` ci-dessus, inchangées · Victor n'a nommé que les trois fenêtres
   citées. Sous 901px, le repli mobile en une colonne garde lui aussi ses
   valeurs actuelles (`.relecture__cadre` à 170px, § plus bas, tours 2 à 4 du
   24.08.2026) · rien de ce bloc n'y descend.

   LES TROIS PANNEAUX RETENUS APRÈS RELECTURE DE `apercu_jomini.html`, PAS LE
   CONTENEUR `.console__corps` COMME UN PREMIER REGARD LE SUGGÉRAIT · chaque
   `.console__corps` du mode 3 fenêtres porte, SOUS l'élément qu'on veut
   redimensionner, une rangée de boutons (`.actions`, et pour la première
   colonne le dépôt de fichier `#bloc-depot`) qui doivent rester VISIBLES en
   permanence, pas glisser dans une zone qu'on redimensionne ou qu'on fait
   défiler. Poser `resize`/hauteur sur `.console__corps` aurait emporté ces
   boutons dans la boîte réglable. La bonne cible est donc l'élément de
   LECTURE lui-même · `.zone` (le `<textarea>`), `.sortie` (le `<div>`), et
   pour le tableau `.relecture__cadre` (le `<div class="tbl-hz
   relecture__cadre">` qui l'enveloppe DÉJÀ, posé le 24.08.2026 pour son
   propre défilement horizontal · un `<table>` brut ne peut pas porter
   `resize` ni un `overflow-y` utile, mais son enveloppe existante le peut
   sans qu'il faille en inventer une seconde).

   20 LIGNES, MESURÉES DANS UN VRAI NAVIGATEUR, PAS DEVINÉES DEPUIS CETTE
   FEUILLE · `_charte/navigateur.mjs`, page ouverte à 1440×900, computed style
   de `#entree`/`#sortie` (mode 3 fenêtres) · `font-size: 14px`,
   `line-height: 21px` (§ plus bas, « TAILLE REVUE À LA BAISSE », 14px/1.5).
   `.zone`/`.sortie` portent chacune 16px de remplissage haut ET bas
   (`--space-4`, charte commune) et 1px de bordure haut ET bas
   (`_charte/apercu.css`) · mesuré, pas supposé. Avec `box-sizing:
   border-box` (charte commune, `*, *::before, *::after`), la hauteur de
   BOÎTE qui montre exactement 20 lignes de texte est ·

       20 × 21px (texte)  +  16px + 16px (remplissage)  +  1px + 1px (bordure)
     = 420px              +  32px                        +  2px
     = 454px

   MÊME HAUTEUR DE BOÎTE SUR `.relecture__cadre`, PAS LE MÊME NOMBRE DE
   LIGNES · mesuré, ce cadre ne porte lui-même ni remplissage ni bordure
   (0px des deux côtés) · ses 454px sont donc entièrement de la zone de
   défilement, et le nombre de RANGÉES de tableau qui y tient diffère (les
   cellules du tableau mesurent 12px/18px, pas 14px/21px · une autre police,
   § plus bas). C'est voulu : Victor a demandé la même HAUTEUR pour les trois
   boîtes, pas le même nombre de lignes dans un tableau qui n'a pas la
   typographie de la prose.

   `resize: vertical` · `.zone` l'a déjà par la charte commune
   (`_charte/apercu.css`, `.zone { resize: vertical }`) · POSÉ ICI, PAS
   RECOPIÉ (CLAUDE.md § 8) · donc seules `.sortie` et `.relecture__cadre` le
   reçoivent dans ce bloc. `overflow-y: auto` est ce que `resize` exige pour
   s'appliquer à un axe · `.sortie` et `.relecture__cadre` l'ont déjà par
   ailleurs (juste au-dessus, et § « La relecture, compactée en hauteur »
   plus bas) · répété ici pour que ce bloc reste lisible seul, sans obliger à
   sauter dans le fichier pour savoir si `resize` va réellement s'activer.

   `min-height: 96px` évite qu'une poignée tirée trop loin ne rende la boîte
   inutilisable (environ 4 lignes de texte) · pas de `max-height`, dans le
   même esprit que « LA TAILLE DES BOÎTES » ci-dessus · rien n'empêche
   d'agrandir encore.

   LES TROIS RESTENT ÉGALES ENTRE ELLES QUAND ON EN TIRE UNE · ce bloc pose
   seulement la hauteur PAR DÉFAUT et la poignée. Le fait que les deux autres
   suivent au premier geste est un comportement, pas un style · il vit dans
   `interface.js` (recherchez « HAUTEURS SYNCHRONISÉES DES TROIS FENÊTRES »,
   lot J79), qui égalise les trois par `ResizeObserver` · CSS seul ne sait
   pas répondre à un redimensionnement manuel d'un élément voisin. */
@media (min-width: 901px) {
  .volet__paire--3 .zone,
  .volet__paire--3 .sortie,
  .volet__paire--3 .relecture__cadre {
    height: 454px;
    min-height: 96px;
    max-height: none;
    overflow-y: auto;
  }
  .volet__paire--3 .sortie,
  .volet__paire--3 .relecture__cadre {
    resize: vertical;
  }
}

/* === La relecture, compactée en hauteur, jamais masquée ==================== */

.relecture__cadre {
  max-height: 200px;
  overflow-y: auto;
}

/* === Les tiroirs · vigilance et détail de restitution ====================== */

details.tiroir { border: 1px solid var(--rule); background: var(--bg2); }
.surface-d details.tiroir,
.surface-d2 details.tiroir { background: var(--bg-dark2); border-color: var(--rule-dark); }

details.tiroir > summary {
  list-style: none;
  cursor: pointer;
}
details.tiroir > summary::-webkit-details-marker { display: none; }
details.tiroir > summary::marker { content: ""; }
details.tiroir > summary::before {
  content: "▸";
  display: inline-block;
  margin-right: var(--space-3);
  font-size: 10px;
  transition: transform 0.15s ease;
}
details.tiroir[open] > summary::before { transform: rotate(90deg); }
details.tiroir > summary:focus-visible { outline: 2px solid var(--pal-navy); outline-offset: -2px; }

/* Une ligne d'alerte ne se replie jamais · elle vit hors du tiroir, et cette
   règle ne fait que l'espacer proprement de ce qui l'entoure. */
#r-ligne-inventes { margin-top: var(--space-5); }

/* === Resserrement du pupitre · tour de correction du 24.08.2026 ============

   Victor, le 24.08.2026 au matin · « l'utilisateur doit tout voir d'un coup
   d'œil ». Le premier passage laissait le pupitre déborder d'environ 636 px
   sous un exemple réel (une donnée détectée, une restée en clair, donc le
   tiroir de vigilance ouvert de lui-même). Ces règles resserrent ce qui peut
   l'être SANS retirer un mot ni masquer le relevé de vigilance par défaut ·
   le tiroir de vigilance reste FERMÉ par défaut (tour 2, corrigé après une
   première version qui le forçait ouvert) · seul le compte passe en rouge
   sur le `<summary>` pour dire qu'il y a quelque chose à lire, et sa LISTE,
   une fois ouverte à la main, défile au-delà d'une hauteur raisonnable,
   comme le fait déjà la table de relecture juste au-dessus
   (`.relecture__cadre`). L'écart restant, et pourquoi il subsiste, est
   documenté dans le compte rendu remis à Victor · ce n'est pas un oubli, un
   texte réel avec un signalement ne tient pas dans 900 px sans rogner un
   composant que la maison a interdit de rogner. */

.pupitre__contenu { padding: var(--space-4); }
.pupitre__contenu .console__corps { padding: var(--space-3); }
/* `.volet .zone`/`.volet .sortie` resserrées ici à 110px ont été portées à
   240px le 01.09.2026 (§ plus haut, « LA TAILLE DES BOÎTES ») · Victor a
   priorisé la lisibilité des boîtes sur le tenir-en-un-écran que ce tour
   visait. La règle ne se répète pas ici, pour ne laisser qu'UNE valeur qui
   fasse foi (§ 7 de CLAUDE.md) — ce paragraphe reste pour dire QUE ce tour
   a existé et pourquoi, pas pour continuer à agir. */

#verdict { margin-top: var(--space-4); }
#note-raccourci { margin-top: var(--space-3); }
#bloc-relecture { margin-top: var(--space-3); }
#bloc-vigilance { margin-top: var(--space-3); }
#rapport-detail { margin-top: var(--space-3); }
#rapport-restitution { margin-top: var(--space-4); }

/* La liste des signalements défile au-delà de 190 px · la phrase de tête
   (`#phrase-vigilance`) et l'avertissement « préfère la fausse piste au
   silence » restent, eux, TOUJOURS visibles sans défilement · seule
   l'énumération, qui grandit avec le nombre de signalements, est cadrée. */
#corps-vigilance { max-height: 190px; overflow-y: auto; }

/* === Second resserrement · tour 3, après la relecture adverse du 24.08.2026
   au soir ================================================================

   La relecture adverse a mesuré, en ouvrant réellement le fichier livré
   (pas un serveur local), un débordement de 253 px à 1440×900 et de 423 px
   à 1024×768 pour la démonstration précâblée. La table de relecture
   (`.relecture__cadre`) ne peut plus se replier par contrat · ce qui suit
   resserre ce qui reste légitimement resserrable autour d'elle. Ce n'est
   PAS présenté comme suffisant pour faire tenir 1024×768 dans un seul écran
   · voir le compte rendu remis à Victor pour les deux chiffres mesurés
   après ce resserrement, aux deux largeurs demandées. */

.pupitre-section { padding: var(--space-4) var(--space-7) var(--space-5); }
/* `.volet .zone`/`.volet .sortie` resserrées ici à 90px · même sort que le
   tour 2 ci-dessus, portées à 240px le 01.09.2026 (§ « LA TAILLE DES
   BOÎTES »). */
.relecture__cadre { max-height: 170px; }
#verdict { margin-top: var(--space-3); }
#note-raccourci { margin-top: var(--space-2); }
#bloc-relecture { margin-top: var(--space-2); }

/* === Quatrième geste · essai puis retour arrière, tour 4
   (24.08.2026 au soir) =======================================================

   Interrogé sur deux options — accepter le reste de défilement du pupitre
   (159 px à 1440×900, 332 px à 1024×768), ou assouplir la fenêtre de
   `.relecture__cadre` pour qu'elle montre plusieurs lignes d'un coup —
   Victor a répondu « je dirai assouplir ». Un premier essai a porté la
   fenêtre à 330 px (l'en-tête et cinq lignes visibles) : mesuré après coup,
   cela AGRANDISSAIT le débordement du pupitre de 160 px aux deux largeurs
   (jusqu'à 492 px à 1024×768), puisque `.relecture__cadre` vit dans le flux
   normal de la page. C'était l'inverse de ce qui avait été présenté à
   Victor avant sa réponse (« assouplir » devait faire tenir davantage sur
   un seul écran, pas moins) · erreur de consigne à la construction,
   corrigée le soir même en revenant à la valeur du tour 3.

   `.relecture__cadre` reste donc à 170 px (~2 lignes visibles, le reste
   accessible par défilement interne, natif, aucune ligne retirée ni
   résumée) · le débordement du pupitre reste celui mesuré au tour 3 (159 px
   à 1440×900, 332 px à 1024×768). Faire mieux demanderait de resserrer un
   AUTRE élément du pupitre (les consoles, l'en-tête, les tiroirs) plutôt
   que la table, qui est déjà la pièce la plus compacte qu'elle puisse être
   sans violer le contrat « jamais masquée ». */

.relecture__cadre { max-height: 170px; }

/* L'en-tête de la table (Garder / Confiance / Valeur d'origine / Marqueur /
   Type / Occurrences · « Confiance » en deuxième depuis le 05.09.2026, voir
   `interface.js`) reste visible pendant qu'on fait défiler les lignes · posé
   sur les `<th>` plutôt que sur `<thead>`, qui n'a pas toujours porté le
   collage de Safari pour ce sélecteur. Le fond reprend le jeton de la
   console qui l'entoure (`--bg2`, la même valeur que `.console` plus haut
   dans ce fichier) · le pupitre ne vit que sur `.surface-2`, jamais sur une
   surface sombre, donc aucune variante `--bg-dark*` n'est nécessaire ici. */
#tbl-matrice thead th {
  position: sticky;
  top: 0;
  background: var(--bg2);
  z-index: 1;
}

/* === LE DOUTE MIS EN AVANT · lot J92, 02.09.2026 ===========================
   Une ligne « à vérifier » porte `tr.doute` (posée par `interface.js`, lue
   dans `entree.confiance`) et un filet ambre à gauche · le même idiome que
   `.preuve-sortante--doute` (`_charte/apercu.css`), aucune teinte inventée
   (CLAUDE.md § 8). Le filet est un `box-shadow` intérieur et non une
   bordure · une bordure changerait la largeur de la cellule et ferait
   sauter l'alignement des cases à cocher entre lignes douteuses et lignes
   sûres. Le jeton de rang reprend `.jeton` de la charte, resserré d'un
   cran pour tenir dans une cellule de tableau sans en gonfler la hauteur. */
#tbl-matrice tr.doute td:first-child { box-shadow: inset 3px 0 0 var(--pal-amber); }
#tbl-matrice .jeton { padding: 2px 6px; }

/* LE JETON D'UN SEUL TENANT, MÊME À 375 PX. `_charte/apercu.css` ligne 1025
   pose `.jeton { white-space: normal }` sous son média étroit, et sa raison
   est écrite à côté · sur téléphone la barre de console passe en colonne,
   « le jeton a toute la largeur, il peut donc se couper ». Ici le jeton vit
   dans une CELLULE d'un cadre `.tbl-hz` qui défile · il n'a pas toute la
   largeur, et se couper donne « À » seul sur une ligne et « VÉRIFIER »
   dessous (capture `bancs/captures/confiance-375x812-relecture.png` du
   05.09.2026). Le coût est une colonne plus large DANS le cadre, jamais
   hors de lui · `bancs/mobile.mjs` et la partie D de `bancs/confiance.mjs`
   mesurent que la page reste à 375 px et le pupitre à +0. Même geste que
   `.pupitre .tbl td.num`, plus bas · une ligne éprouvable plutôt qu'un
   hasard de spécificité. Spécificité (1,1,0) contre (0,1,0). */
#tbl-matrice .jeton { white-space: nowrap; }

/* La légende des trois rangs, un rang par ligne · `interface.js` la remplit
   avec un retour à la ligne entre les phrases, et c'est cette règle qui le
   rend · sans elle, le rendu HTML replie les espaces et le nom du rang
   suivant se colle à la fin de la phrase du précédent. Vu à l'œil sur les
   captures du banc, le 05.09.2026 · pas mesuré par lui. */
#legende-confiance { white-space: pre-line; }

/* === L'annexe repliée · tour de correction du 24.08.2026 ====================

   Chaque section qui occupait hier le premier écran (la preuve, les vingt
   et un types de données, le mode tableau, les six limites, le nom, la FAQ,
   « aller plus loin ») vit désormais dans un `<details>` fermé par défaut ·
   un tiroir qu'on ouvre EXPRÈS. Rien n'est retiré du contenu, `.pav` garde
   son remplissage habituel une fois ouvert · seul le `<summary>` ci-dessous
   est nouveau. */

.annexe-entete { padding-top: var(--space-6); padding-bottom: var(--space-5); }

/* === LE RÉSUMÉ COMPACT · Victor, 01.09.2026 ================================
   Remplace `.hero`/`.signature`/`.reassurance` (partagés, `_charte/apercu.css`)
   pour CETTE reprise mi-page seulement · voir le commentaire HTML au-dessus
   du `<div class="annexe-resume">`. Un encadré, pas un pavé plein écran ·
   même filet `1px solid var(--rule)` que `.pupitre` (jomini.css:51), même
   famille visuelle que le reste de l'outil plutôt qu'un composant de plus. */
.annexe-resume {
  margin-top: var(--space-6);
  padding: var(--space-5) var(--space-6);
  border: 1px solid var(--rule);
  background: var(--bg2);
}
.annexe-resume > p {
  margin: 0 0 var(--space-4);
  max-width: 62ch;
  font-size: var(--type-body-web);
  line-height: 1.5;
}
.annexe-puces {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2) var(--space-6);
  margin: 0;
  padding: 0;
  list-style: none;
}
.annexe-puces li {
  position: relative;
  padding-left: var(--space-4);
  font-size: 14px;
  line-height: 1.5;
  color: var(--fg2);
}
.annexe-puces li strong { color: var(--fg1); }
.annexe-puces li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 6px;
  height: 6px;
  background: var(--pal-red);
}
@media (max-width: 640px) {
  .annexe-puces { grid-template-columns: 1fr; }
}

.tiroir-annexe {
  border-top: 1px solid var(--rule);
}
.tiroir-annexe:last-of-type { border-bottom: 1px solid var(--rule); }

.tiroir-annexe__resume {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-7);
  cursor: pointer;
  list-style: none;
}
.tiroir-annexe__resume::-webkit-details-marker { display: none; }
.tiroir-annexe__resume::marker { content: ""; }
.tiroir-annexe__resume::before {
  content: "▸";
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--fg3);
  transition: transform 0.15s ease;
}
.tiroir-annexe[open] > .tiroir-annexe__resume::before { transform: rotate(90deg); }
.tiroir-annexe__resume:focus-visible { outline: 2px solid var(--pal-navy); outline-offset: -2px; }
.tiroir-annexe__resume:hover { background: var(--bg2); }

.tiroir-annexe__titre {
  font-family: var(--font-heading, var(--font-body));
  font-weight: var(--w-semi, 600);
  font-size: 16px;
}
.tiroir-annexe__sous {
  font-size: 13px;
  color: var(--fg3);
}

@media (max-width: 700px) {
  .tiroir-annexe__resume { flex-direction: column; gap: var(--space-1); padding: var(--space-4) var(--space-5); }
}

/* === Sous 700 px · le menu redevient une barre d'onglets horizontale ======= */

/* SOUS 700px, LE PUPITRE REPREND TOUTE LA LARGEUR DE L'ÉCRAN · Victor,
   01.09.2026 · « utilise bien toute la largeur de l'écran sur mobile ·
   enfin avec une marge de quelques pixels ou je ne sais pas les standard ».
   `.pupitre-section` (§ « Second resserrement » plus haut) garde
   `--space-7` (48px) de remplissage horizontal à TOUTES les largeurs ·
   correct sur un écran large où le pupitre reste lisible entouré de
   respiration, mais 2 × 48px mange plus d'un quart des 375px d'un
   téléphone. « Le standard » du dossier, déjà posé ailleurs pour la même
   raison · `.pav` (`_charte/apercu.css`, sous 900px) retombe à `--space-5`
   (24px), pas à zéro · un bord du texte collé au bord de l'écran ne se lit
   pas mieux qu'un bord trop large, seulement autrement mal. Même valeur
   reprise ici pour la même raison, pas inventée. */
@media (max-width: 700px) {
  .pupitre-section { padding-left: var(--space-5); padding-right: var(--space-5); }
}

@media (max-width: 700px) {
  .pupitre { grid-template-columns: 1fr; }
  .pupitre__menu {
    flex-direction: row;
    flex-wrap: wrap;
    border-right: none;
    border-bottom: 1px solid var(--rule);
  }
  .surface-d .pupitre__menu,
  .surface-d2 .pupitre__menu { border-bottom-color: var(--rule-dark); }
  .pup-onglet { width: auto; }
  /* `.pup-action` REJOINT `.pup-onglet` ICI, lot J81 · sous 700px le menu
     redevient une barre horizontale qui s'enroule (`flex-wrap: wrap`
     ci-dessus) · sans ce `width: auto`, les deux boutons déménagés
     resteraient à `width: 100%` (leur valeur par défaut, § plus haut) et
     forceraient chacun sa propre ligne dans une barre pourtant pensée pour
     tenir plusieurs éléments côte à côte, comme le fait déjà `.pup-onglet`. */
  .pup-action { width: auto; }
  .pupitre__filet { display: none; }
  /* MÊME `width: auto` POUR LE LIEN ET LE JETON, lot J86 · ils viennent de
     recevoir `width: 100%` avec le format de `.pup-action`, qui leur ferait
     prendre une ligne entière chacun dans cette barre qui s’enroule. Avant
     le lot, blocs sans largeur posée, ils se dimensionnaient sur leur texte
     (mesuré à 375 px · 196,81 et 218,53 px, jamais 325) · cette ligne leur
     rend ce comportement, elle n’en invente pas un nouveau. */
  .pup-lien-limites,
  .pupitre__preuve,
  .bandeau-gratuit { width: auto; margin-top: 0; }
  /* `minmax(0, 1fr)`, pas `1fr` nu · même remède qu'au-dessus (§ trois
     blocs horizontaux, 01.09.2026), posé ici aussi pour que cette règle ne
     redevienne pas le trou par lequel le même débordement reviendrait. */
  .volet__paire { grid-template-columns: minmax(0, 1fr); }
}

/* === Sous 700 px · les deux barres de console qui ne se replient jamais
   (relecture, vigilance) empilent leur libellé et leur mot d'état ===========

   Trouvé à l'œil par le lot J74 (31.08.2026), sur `jomini_hors_ligne.html`
   ouvert réellement à 375×812, puis posé au tour suivant, le même jour.
   `.console__barre` (`_charte/apercu.css:508`) est une pièce commune,
   pensée pour un couple court « libellé / mot d'état », sans règle `@media`
   d'aucune sorte, ni ici ni chez elle. Sous 375 px, `justify-content:
   space-between` écrase le libellé le plus long des deux barres qui NE SE
   REPLIENT JAMAIS par contrat (`#bloc-relecture`, lot J18 ; `#bloc-vigilance`,
   lot J72 tour 2) à une largeur mesurée en direct de 71 px, et le fait
   passer sur cinq à six lignes. C'est exactement le défaut que
   `.tiroir-annexe__resume` portait avant d'être corrigé, ligne 338-340
   ci-dessus · le même geste, scopé aux deux seuls blocs concernés, dans le
   fichier où l'équivalent vit déjà · jamais dans `_charte/apercu.css`, pièce
   commune à cinq produits et hors du périmètre de ce dossier. */
@media (max-width: 700px) {
  #bloc-relecture > .console__barre,
  #bloc-vigilance > .console__barre {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-1);
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   UN ÉCRAN D'APPLICATION, PAS UNE FICHE TECHNIQUE · lot du 01.09.2026
   ═══════════════════════════════════════════════════════════════════════
   Victor, après le lot des trois blocs horizontaux · « il faut redesigner
   et redimensionner toutes les boxes et textes... mettre les titres et
   texte en bonne proportion et bonne police. On doit pouvoir voir ce
   qu'on fait sur PC et sur téléphone. » Puis, précisé · « inspire-toi des
   écrans des applications Apple et Claude, au moins ce sont des designs
   éprouvés. »

   CE QUE ÇA CHANGE, ET POURQUOI CE N'EST PAS UNE INFRACTION SILENCIEUSE À
   « PALAMBUR EST PLAT » · `_charte/palambur.css` pose ce principe pour les
   CARTES DE VITRINE (`.pav`, `.tiroir-annexe`, les tableaux comparatifs
   plus haut sur cette même page) — des surfaces qu'on LIT. Le pupitre,
   lui, est un écran qu'on UTILISE · on y tape, on y coche, on y glisse.
   Le site avait déjà posé cette distinction pour lui-même (`--radius-card`/
   `--radius-card-sm`, réservés aux flip-cards des outils et aux paliers de
   réserve — pas au reste du site) · rattrapé dans `_charte/palambur.css`
   le même jour plutôt que d'inventer un troisième rayon ici.

   CE QUI HÉRITE, ET CE QUI RESTE PLAT · `.pupitre` (le rayon et l'ombre du
   conteneur) et le TITRE (`.entete-outil .marque h1`, depuis le 01.09.2026 ·
   voir plus bas) sont scopés au pupitre seul. `.console`/`.marq`/`.tbl`, eux, sont des pièces COMMUNES à toute
   la page Jomini (le mode relevé bancaire de l'annexe en pose aussi) · les
   retoucher SANS les scoper au pupitre leur donne le même rayon doux
   partout où ils apparaissent, plutôt qu'une même classe à deux visages
   selon l'endroit — un choix, pas un oubli. Le reste de l'annexe (`.pav`,
   `.tiroir-annexe`, les tableaux comparatifs plus haut) garde le gabarit
   plat de la charte sans y toucher · elle, elle se lit, pas ne s'utilise.

   LA POLICE DU TEXTE PRINCIPAL CHANGE, PAS CELLE DES MARQUEURS · `.zone`/
   `.sortie` portaient `--font-mono` (hérité de `_charte/apercu.css`, pièce
   commune à cinq produits, jamais touchée ici) pour TOUT le texte, y
   compris la prose d'une lettre ou d'un e-mail — lisible pour un extrait de
   code, laborieux pour un paragraphe. `--font-body` (Barlow, la police de
   lecture du site) reprend la prose · `.marq` (le jeton `[PERSONNE_1]`
   inséré dans le texte) GARDE le mono, pour rester visuellement un jeton
   de code au milieu d'une phrase ordinaire — la distinction qui compte,
   pas la police en elle-même. */

.pupitre {
  border-radius: var(--radius-card);
  overflow: hidden; /* le menu et le contenu, deux fonds différents en grille, doivent se faire couper au rayon du conteneur, pas déborder en coins carrés */
  box-shadow: 0 1px 2px rgba(10, 25, 47, .04), 0 8px 24px -12px rgba(10, 25, 47, .10);
}

.console {
  border-radius: var(--radius-card-sm);
  overflow: hidden; /* même raison qu'au-dessus · `.console__barre` doit se couper au rayon, pas déborder en angle droit dans un coin rond */
  box-shadow: 0 1px 2px rgba(10, 25, 47, .05);
}
/* LE LIBELLÉ DE BARRE, MOINS CRIÉ · `.console__barre` (charte commune) pose
   du mono 12px, tout en capitales, espacé — juste pour une fiche technique,
   fatigant répété neuf fois sur un même écran d'usage quotidien. Sentence
   case, police de lecture, un poil plus de chair : un sous-titre d'app,
   pas une étiquette d'entrepôt. */
.pupitre .console__barre {
  font-family: var(--font-body);
  font-weight: var(--w-med);
  font-size: 14px;
  letter-spacing: normal;
  text-transform: none;
}

/* TAILLE REVUE À LA BAISSE LE 01.09.2026, PLUS TARD LE MÊME JOUR · Victor,
   sur la version en ligne · « les polices sont trop grosses et qu'on ne
   visualise qu'une infime partie du texte et qu'il faut scroll ». 16px/1.6
   (un premier essai, jamais déployé isolément) laissait tenir ~9 lignes
   dans les 240px de la boîte · 14px/1.5 en tient ~11, sans revenir au
   monospace d'avant (§ plus haut, toujours la bonne police de lecture, pas
   la bonne taille du premier jet). La boîte, elle, reste à 240px · Victor
   voulait des boîtes plus GRANDES, jamais un texte plus GROS à
   l'intérieur, et le premier jet avait confondu les deux. */
.pupitre .zone,
.pupitre .sortie {
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.5;
  border-radius: var(--radius-card-sm);
}
.pupitre .zone:focus { border-radius: var(--radius-card-sm); }

/* Les marqueurs restent des jetons de code dans une phrase de lecture ·
   `.marq` (charte commune) porte déjà le mono, `--pal-navy` plein et un
   padding serré — juste retouché pour un rayon doux au lieu de l'angle
   droit hérité du fond plat, cohérent avec le reste du pupitre. */
.pupitre .marq { border-radius: 4px; }

/* LE MENU DE GAUCHE, DES ONGLETS QU'ON TOUCHE · même logique que les
   consoles — un rayon doux sur l'onglet actif, pour qu'il se lise comme un
   bouton qu'on presse et non comme une ligne de tableau qu'on surligne. */
.pup-onglet {
  border-radius: var(--radius-card-sm);
}

/* LA TABLE DES ÉLÉMENTS IDENTIFIÉS, RESSERRÉE POUR TENIR DANS UN TIERS DE
   PUPITRE · elle vit maintenant dans la colonne du milieu (§ trois blocs
   horizontaux), nettement plus étroite que la pleine largeur qu'elle
   occupait avant. Padding et taille réduits, MARQUEUR et TYPE autorisés à
   passer à la ligne plutôt que forcés sur une seule (le `nowrap` d'origine
   supposait une pleine largeur) · `.tbl-hz` (déjà en place) garde le
   défilement horizontal en dernier recours, jamais retiré. */
.pupitre .tbl { font-size: 14px; }
.pupitre .tbl th,
.pupitre .tbl td {
  padding: var(--space-2) var(--space-3);
  white-space: normal;
}
.pupitre .tbl th { font-size: 12px; }

/* LA CASE « GARDER », SANS AUCUNE TAILLE POSÉE · trouvée le 2026-09-02,
   diagnostic mobile de Victor. `interface.js` (ligne où `cb.type =
   "checkbox"` s'écrit) pose le nom accessible de la case (§ note du fichier
   à cet endroit) mais AUCUNE classe · rien dans cette feuille ni dans
   `_charte/*.css` ne l'a jamais ciblée, et elle rendait donc à sa taille
   native (13×13px mesurés au banc) · sous les 24×24px que la mission de
   diagnostic citait elle-même (recommandation WCAG 2.5.8, cible minimale).
   C'est la SEULE action possible sur cette ligne du tableau (décider
   qu'une valeur détectée reste masquée ou non) · une cible qui se manque
   du doigt sur un téléphone. `accent-color` reprend le bleu marine du
   pupitre sans inventer une teinte (CLAUDE.md § 8) plutôt que de laisser
   la case à la couleur système par défaut. */
#tbl-matrice input[type="checkbox"] {
  width: 24px;
  height: 24px;
  accent-color: var(--pal-navy);
  cursor: pointer;
}

@media (max-width: 700px) {
  .pupitre { border-radius: var(--radius-card-sm); }
}

/* LE GESTE GLISSER SUR « ANALYSER » · Victor, 01.09.2026 · « le bouton
   analyser doit être le nouveau bouton slider ». Un premier passage du
   même geste, posé le même jour sur Chaptal (`05_CHAPTAL/outil_chaptal.html`
   `.lt-verrou-cta--glisse`) pour DÉBITER DES ÉCUS, avait d'abord échoué
   posé sur de simples liens d'ouverture · Victor l'a corrigé lui-même ·
   « le but c'était de le mettre quand on paie, lance un calcul, on
   débloque, pas quand on ouvre l'url ». « Analyser » LANCE UN CALCUL — le
   second des trois cas qu'il a nommés — donc c'est un bon endroit, pas une
   redite de la même erreur.

   MÊME MÉCANIQUE, NOM PROPRE À JOMINI · `interface.js` (`brancherGlisse`)
   est la même fonction, portée ici plutôt que recopiée sous le nom de
   Chaptal (CLAUDE.md § 8 · « importe, ne réécris pas » vaut pour le
   mécanisme, pas pour l'espace de noms d'un produit voisin). Poignée qui
   porte le texte, piste vide à 2/3 de sa largeur, seuil de 16px déjà
   corrigé chez Chaptal (l'ancien, 8px, confondait un clic de souris
   ordinaire avec un geste). Le clic simple reste toujours disponible
   (WCAG 2.5.1) · `interface.js` pose l'`onclick` ET `brancherGlisse` sur
   le même bouton. */
.btn-primary.glisse {
  display: inline-flex;
  align-items: stretch;
  gap: 0;
  padding: 0;
  overflow: hidden;
  background: color-mix(in srgb, var(--pal-navy) 26%, #0B1220);
  filter: brightness(calc(1 + var(--glisse-progres, 0) * .12));
  /* `touch-action: none` posé ICI, SUR LE BOUTON ENTIER · trouvé le
     2026-09-02, geste tactile réel qui échouait silencieusement. Avant ce
     lot, seule `.glisse__poignee` (plus bas) le portait · `interface.js`
     (`brancherGlisse`) écoute `pointerdown` sur `bouton` lui-même, pas sur
     la poignée seule, et un doigt qui se pose sur `.glisse__piste-vide`
     (l'autre moitié du même bouton, invisible, ~40 % de sa largeur) n'avait
     donc AUCUNE règle `touch-action` à cet endroit précis · le navigateur
     lisait « auto », convertissait le geste en défilement de page dès son
     propre seuil interne (plus bas que `SEUIL_GESTE = 16` dans
     `interface.js`), et envoyait un `pointercancel` qu'un geste posé
     ailleurs sur le bouton ne recevait jamais. Confirmé par contact tactile
     RÉEL (`Input.dispatchTouchEvent`, pas un `PointerEvent` de synthèse) ·
     un geste parti de la piste vide ne validait JAMAIS (`--glisse-progres`
     restait à « 0 »), le même geste parti de la poignée validait toujours.
     Une valeur posée sur le bouton s'applique à TOUT ce qu'il contient,
     `.glisse__piste-vide` compris, sans devoir répéter la règle enfant par
     enfant (la propriété se calcule par intersection avec les ancêtres,
     §CSS Touch Action). Gardée aussi sur `.glisse__poignee` ci-dessous ·
     redondant à l'exécution, mais deux lectures indépendantes de la même
     intention valent mieux qu'une règle qui ne tiendrait qu'à un seul fil. */
  touch-action: none;
}
.btn-primary.glisse .glisse__poignee {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 14px 20px 14px 28px;
  border-radius: var(--radius-pill);
  background: var(--pal-navy);
  color: #fff;
  font-family: var(--font-head);
  font-weight: var(--w-med);
  font-size: var(--type-body-web);
  white-space: nowrap;
  cursor: grab;
  touch-action: none;
  transition: transform .22s ease-out;
}
.btn-primary.glisse.en-glissement .glisse__poignee { transition: none; cursor: grabbing; }
/* `touch-action: none` répétée ici · même raison que sur `.btn-primary.glisse`
   ci-dessus (§ note du 2026-09-02) · la piste vide est la moitié du bouton
   qui manquait la règle. */
.btn-primary.glisse .glisse__piste-vide { flex-shrink: 0; width: 0; touch-action: none; }
.btn-primary.glisse .glisse__chevrons { flex-shrink: 0; animation: jomini-glisse-chevrons 1.6s ease-in-out infinite; }
@keyframes jomini-glisse-chevrons {
  0%, 100% { transform: translateX(0); opacity: .85; }
  50% { transform: translateX(3px); opacity: .5; }
}
.btn-primary.glisse.en-glissement .glisse__chevrons { animation: none; }
.btn-primary.glisse.valide .glisse__chevrons { animation: none; opacity: .55; }

/* LE BOUTON GLISSIÈRE, RESSERRÉ EN DEUX PALIERS (780px PUIS 400px) · trouvé
   le 2026-09-02, diagnostic mobile de Victor (« il y a problème pour Jomini
   version mobile »). Les deux seuils sont expliqués et mesurés séparément,
   après ce premier palier et après le second, plus bas.

   Le bouton se dimensionne sur SA POIGNÉE (`interface.js`, `brancherGlisse`,
   `vide.style.width = poignee.offsetWidth * 2/3`) · rien dans ce fichier ne
   fixait de largeur au bouton lui-même, qui reste donc aussi large que
   « Remettre en clair » (poignée) + sa piste (les deux tiers de plus) exige,
   soit 363px MESURÉS (`_charte/navigateur.mjs`) · plus large que la colonne
   disponible sur un téléphone (267px à 375px de large, 212px à 320px). La
   grille `.actions` (`_charte/apercu.css`) ne force normalement pas un
   élément à rétrécir sous sa taille de contenu · mais `overflow: hidden`
   sur `.btn-primary.glisse` (plus haut) annule cette protection par défaut
   (la taille minimale automatique d'un item flexible tombe à zéro dès qu'il
   ne porte pas `overflow: visible`, §CSS Flexible Box) · le bouton se
   laissait donc écraser par sa colonne, `justify-content: center` centrait
   ce qui restait, et le texte se faisait TRONQUER symétriquement par le
   même `overflow: hidden` · mesuré avant ce correctif, de 28px coupés à
   414px jusqu'à 88px coupés à 800px (« ttre en clair » au lieu de « Remettre
   en clair »), à TOUTES les largeurs testées sauf 700px pile et au-delà de
   1279px. `#btn-analyser` (« Analyser », même construction) n'affichait
   jamais ce défaut · son texte plus court (145px de poignée contre 218px)
   perdait, lui, uniquement dans le remplissage interne de la poignée.

   LE CORRECTIF RESSERRE LA POIGNÉE PLUTÔT QUE D'AUTORISER LE BOUTON À
   DÉBORDER · une largeur minimale forcée (`min-width` ou `flex-shrink: 0`)
   aurait empêché le rétrécissement, mais aurait fait déborder le bouton de
   sa colonne à la place du texte · aucun ascendant du pupitre ne porte
   `overflow-x: hidden` (vérifié), un tel débordement aurait donc fait
   défiler la PAGE ENTIÈRE horizontalement, exactement le défaut que
   `minmax(0, 1fr)` (§ plus haut, `.volet__paire--3`) a été écrit pour
   empêcher ailleurs dans ce même fichier. Resserrer le contenu, pas
   permettre le débordement, reste la réponse cohérente avec le reste de la
   feuille. `--type-meta-web` (14px) remplace `--type-body-web` (18px) · la
   même petite taille que `.btn--petit` porte déjà ailleurs dans la charte
   (`_charte/boutons.css`), pas une valeur inventée. La piste vide (JS, ligne
   citée plus haut) SUIT automatiquement cette poignée plus étroite à sa
   PROCHAINE mesure (chargement de la page, ou bascule d'onglet pour
   « Remettre en clair », § LOT J82) · aucune ligne d'`interface.js` n'a
   besoin de changer, la piste n'étant jamais qu'un pourcentage de sa
   poignée. Valeurs choisies puis VÉRIFIÉES au banc, pas devinées · CE SEUL
   PREMIER PALIER ne suffit pas encore sous 400px (§ le second palier, plus
   bas) · c'est la mesure complète des deux ensemble, pas celle-ci seule,
   qui rend zéro pixel coupé du bord bas (320px) au bord haut (1440px) testés
   (voir le lot du plan technique pour le détail des largeurs vérifiées). */
@media (max-width: 780px) {
  .btn-primary.glisse .glisse__poignee {
    padding: 10px 14px 10px 18px;
    gap: 4px;
    font-size: var(--type-meta-web);
  }
  .btn-primary.glisse .glisse__chevrons { width: 11px; height: 9px; }
}
/* 780px, PAS 700px COMME LE RESTE DE CE FICHIER · seuil mesuré, pas copié.
   `.pupitre` ne replie son menu de 220px qu'À 700px (§ plus bas, règle
   générale) · à 701px, ce menu REVIENT d'un coup pendant que la colonne du
   bouton reste à une seule piste (§ `.volet__paire` ci-dessus, repli à
   1200px) · un creux mesuré au banc entre 701px et ~760px, où la poignée
   resserrée ci-dessus (170px de contenu) ne rentrait pas encore dans une
   colonne qui n'avait pas fini de s'élargir. 780px laisse une marge de
   20px au-delà du seuil mesuré (760px), par la même prudence que les
   marges de poids du fichier hors ligne plus bas dans ce dépôt. */

/* UN SECOND PALIER, SOUS 400px · le premier resserrement (ci-dessus) ne
   suffit pas à lui seul en dessous de 390px de large (mesuré au banc) · un
   iPhone SE (320px) montrait encore 31px de texte coupés une fois le premier
   palier seul posé. `font-size` descend ici sous `--type-meta-web` (14px) ·
   aucun jeton de la charte ne va plus bas, et cette taille ne sert QUE la
   poignée d'un bouton glissière sur l'écran le plus étroit testé, jamais un
   texte de lecture. Choisie puis VÉRIFIÉE au banc (zéro pixel coupé mesuré
   ensuite à 320px), pas devinée. */
@media (max-width: 400px) {
  .btn-primary.glisse .glisse__poignee {
    padding: 8px 10px 8px 13px;
    gap: 3px;
    font-size: 11px;
  }
  .btn-primary.glisse .glisse__chevrons { width: 9px; height: 7px; }
}

/* LE DÉPÔT D'UN DOCUMENT (PDF, DOCX) · lot J77, 2026-09-01
   Trois lignes empilées (le libellé, le champ natif, le message d'état) ·
   `.note-mono`/`.mb-0` (charte commune) portent déjà la police et l'espace,
   ce bloc ne pose que l'empilement et les deux états qui ne se déduisent
   de rien d'existant · l'erreur, et le survol pendant un glisser-déposer. */
.depot {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  border-top: 1px solid var(--rule);
  padding-top: var(--space-4);
}
.surface-d .depot,
.surface-d2 .depot { border-top-color: #46536b; }

/* `--fg-signal` (charte commune) est déjà le rouge d'ATTENTION du reste de
   la page · le même que la ligne « marqueurs inventés » de la restitution ·
   jamais une teinte inventée pour ce message-ci. */
.depot__etat--erreur { color: var(--fg-signal); }

/* Le glisser-déposer est un raccourci pour la souris, pas un second champ ·
   le filet qui apparaît au survol se pose sur la CONSOLE ENTIÈRE (le cadre
   qui contient déjà la zone de texte), pour que la cible visée pendant le
   geste soit aussi large que la cible réellement acceptée par `interface.js`. */
.console.depot--survole {
  outline: 2px dashed var(--pal-navy);
  outline-offset: -2px;
}

/* ═══════════════════════════════════════════════════════════════════════
   EN-TÊTE DE L'OUTIL + AVANCEMENT, INSPIRÉS DE MÉNEVAL · 01.09.2026
   ═══════════════════════════════════════════════════════════════════════
   Victor, deux tours. Premier · « inspire-toi du bandeau de Méneval pour
   le header de Jomini · mais avec les 3 étapes » — posé d'abord avec le
   titre encore SÉPARÉ, au-dessus du pupitre (`.pupitre-entete`, retirée
   depuis · voir sa note de départ plus haut dans ce fichier). Second
   tour, capture à l'appui · « fait le bandeau comme ça mais tu changes
   les étapes et tu mets le titre à la place de "Méneval" » — chez
   Méneval, `.marque` PORTE le `<h1>` (leur propre nom, court) à côté du
   filet · le `<h1>` de Jomini (plus long, une phrase entière) déménage
   donc dans SA `.marque`, à la même place exacte.
   Repris de `04_MENEVAL/maquette_meneval.html` (`.entete-app`, `.marque`,
   `.avance`), mêmes jetons de la charte commune, adapté de 7 étapes à 3.
   Scopé à `#panneau-masquer` (voir apercu_jomini.html) · « Redonner en
   clair » n'a aucune progression à montrer, et c'est aussi pourquoi le
   SEUL `<h1>` de la page vit dans l'onglet ouvert par défaut à l'arrivée,
   jamais masqué au premier chargement.

   LE FILET ROUGE N'EST PAS UNE RÉPÉTITION DE `--fg-signal` · c'est le
   même filet de 3px que Méneval pose à côté de son propre nom, un repère
   de MARQUE, pas une alerte. */
.pupitre .entete-outil {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
.pupitre .entete-outil .marque {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}
.pupitre .entete-outil .filet {
  width: 3px;
  align-self: stretch;
  min-height: 20px;
  background: var(--pal-red);
  flex: none;
}
/* PAS DE `white-space: nowrap` ICI, À LA DIFFÉRENCE DE MÉNEVAL · leur
   `.marque h1` ne porte qu'un nom de produit, jamais assez long pour
   casser. Celui de Jomini est une phrase entière (§ plus bas dans
   apercu_jomini.html) · elle DOIT pouvoir passer à la ligne, sous peine
   de déborder ou de se faire tronquer par une ellipse qui la rendrait
   illisible. */
.pupitre .entete-outil .marque h1 {
  font-family: var(--font-head), sans-serif;
  font-size: clamp(15px, 1.5vw, 18px);
  font-weight: var(--w-semi);
  letter-spacing: -0.01em;
  line-height: 1.3;
  color: var(--pal-navy);
  margin: 0;
}
.pupitre .entete-outil .creux { flex: 1; }
.pupitre .entete-outil .compteur { font-size: 13px; color: var(--fg3); flex: none; }
.pupitre .entete-outil .compteur b { color: var(--fg1); font-weight: var(--w-semi); }

/* LE RAIL DIT L'AVANCEMENT, L'ÉTIQUETTE DIT LE NOM · même principe que
   chez Méneval, à trois segments au lieu de sept. `data-fait` (étape
   dépassée) passe en marine, `aria-current` (étape en cours) passe en
   rouge · un clic ne peut jamais ouvrir une étape que l'analyse n'a pas
   encore atteinte (`interface.js`, `etapeMax`) — reculer reste toujours
   permis, avancer sans donnée ne l'est jamais. */
.pupitre .avance {
  display: flex;
  gap: 0;
  margin-bottom: var(--space-5);
  border-bottom: 1px solid var(--rule);
}
.pupitre .avance button {
  flex: 1 1 0;
  min-width: 0;
  text-align: left;
  cursor: pointer;
  background: none;
  border: 0;
  padding: 0 var(--space-3) var(--space-2) 0;
  font-family: inherit;
}
.pupitre .avance .rail {
  display: block;
  height: 3px;
  background: var(--rule);
  margin-bottom: var(--space-2);
  transition: background .18s;
}
.pupitre .avance .txt {
  display: block;
  font-size: 12.5px;
  color: var(--fg3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color .18s;
}
.pupitre .avance .txt i {
  font-style: normal;
  font-size: 11px;
  margin-right: 7px;
  color: var(--fg3);
  font-family: var(--font-mono);
}
.pupitre .avance [data-fait] .rail { background: var(--pal-navy); }
.pupitre .avance [data-fait] .txt { color: var(--fg2); }
.pupitre .avance [data-fait] .txt i { color: var(--pal-navy); }
.pupitre .avance [aria-current] .rail { background: var(--pal-red); }
.pupitre .avance [aria-current] .txt { color: var(--fg1); font-weight: var(--w-semi); }
.pupitre .avance [aria-current] .txt i { color: var(--pal-red-strong); }
.pupitre .avance button:hover .txt { color: var(--fg1); }
.pupitre .avance button:focus-visible { outline: 2px solid var(--pal-navy); outline-offset: 2px; }

/* SOUS 700px · aucune des deux règles mobiles de Méneval n'avait suivi
   « repris de 04_MENEVAL/maquette_meneval.html » (§ note plus haut, lot du
   01.09.2026) · trouvé le 2026-09-02, diagnostic mobile de Victor. Chez
   Méneval, ce même bloc porte un `@media (max-width: 620px)` qui (a) cache
   visuellement le libellé par la technique sr-only pour éviter que trois
   (chez eux sept) libellés se chevauchent dans une barre trop étroite, et
   (b) fixe une cible tactile de 44px de haut. Sans lui, mesuré au banc
   (`_charte/navigateur.mjs`) avant ce correctif · les trois boutons de
   `.avance` restaient à 35px de haut (sous les 44px WCAG que Méneval
   applique déjà pour ce même contrôle), et « Éléments identifiés » (le
   libellé le plus long) débordait sa colonne de 120px de large pour 67 à
   99px de large réellement disponibles selon la largeur · rattrapé par
   l'ellipse déjà posée (`.txt`, plus haut) mais jamais testé pour ce cas
   précis. 700px reprend le seuil DE CE FICHIER (§ partout ailleurs dans
   cette feuille), pas les 620px de Méneval · aucune des deux valeurs n'est
   plus juste que l'autre, et rester cohérent avec le reste de `jomini.css`
   compte plus ici que recopier un chiffre d'un fichier voisin. `.compteur`
   (« Étape N sur 3 », § plus haut, `aria-live="polite"`) porte déjà la même
   information en toutes lettres · rien n'est perdu quand `.txt` disparaît
   ici, c'est dit deux fois et il en reste une · exactement le raisonnement
   que Méneval documente pour son propre repli. */
@media (max-width: 700px) {
  .pupitre .avance button { padding: 0 0 11px 0; min-height: 44px; }
  .pupitre .avance .txt {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .pupitre .avance .rail { margin-top: 30px; margin-bottom: 0; height: 4px; }
}

/* ==========================================================================
   LE MODE RELEVÉ BANCAIRE · TROISIÈME ONGLET · lot J85, 2026-09-02

   RIEN DE NEUF N'EST INVENTÉ ICI POUR LE TABLEAU LUI-MÊME. `.tbl`, `.tbl-hz`,
   `.marq`, `.num` et `.mono` vivent dans la charte commune
   (`_charte/apercu.css`, lignes 389 à 413, 601 et 946) et servent DÉJÀ deux
   tableaux de cette page · celui de la relecture (`#tbl-matrice`) et la
   démonstration du tiroir « Le mode relevé bancaire ». Le troisième les
   reprend tels quels (CLAUDE.md § 8). Ce bloc n'ajoute que ce qui n'existait
   nulle part · le cadre du tableau, la ligne de réglages, et UNE garde de
   spécificité qui, elle, décide d'une promesse.
   ========================================================================== */

/* LA GARDE QUI DÉCIDE DE LA PROMESSE 4 À L'ÉCRAN.

   `_charte/apercu.css` ligne 410 pose `.tbl .num { white-space: nowrap }` ·
   spécificité (0,2,0). `jomini.css` ligne 840, plus haut dans ce fichier,
   pose `.pupitre .tbl td { white-space: normal }` · spécificité (0,2,1). LA
   SECONDE GAGNE. Dans le pupitre, un `<td class="num">` peut donc se replier,
   et la règle de la charte qui existe précisément pour l'en empêcher est
   silencieusement désarmée.

   Sur `1'234.50` cela ne se voit pas · il n'y a pas d'espace où casser. Sur
   `CHF 1'234.50`, `1 234.50` ou `-1'234.50 CHF`, si · le montant se coupe en
   deux lignes, ET LA PAGE DÉMENT À L'ŒIL CE QUE LE MOTEUR A TENU. La promesse
   4 ne dit pas « le moteur ne coupe pas », elle dit « le format suisse n'est
   jamais coupé » · un lecteur qui voit un montant en deux morceaux n'a pas à
   savoir lequel des deux, du moteur ou de la feuille de style, l'a fait.

   Une ligne, éprouvable, plutôt qu'un hasard de spécificité. Elle ne touche
   QUE `td.num` · les autres cellules gardent leur repli, qui leur est utile.
   Le repli reste possible pour `th` · un en-tête long doit pouvoir casser. */
.pupitre .tbl td.num { white-space: nowrap; }

/* LE TITRE DU TROISIÈME PANNEAU · un `<p>`, PAS UN `<h1>`. La page n'a qu'un
   seul `<h1>` et il vit dans `#panneau-masquer` (§ plus haut dans
   apercu_jomini.html, lot du 01.09.2026 · « le seul `<h1>` de la page vit
   dans l'onglet ouvert par défaut »). Un second `<h1>` casserait ce contrat
   et ferait annoncer deux titres de page à un lecteur d'écran. Le style est
   repris à l'identique de `.marque h1` juste au-dessus · même police, même
   clamp, même marine, même absence de `nowrap` (c'est une phrase entière,
   elle doit pouvoir passer à la ligne). */
.pupitre .entete-outil .marque .releve-titre {
  font-family: var(--font-head), sans-serif;
  font-size: clamp(15px, 1.5vw, 18px);
  font-weight: var(--w-semi);
  letter-spacing: -0.01em;
  line-height: 1.3;
  color: var(--pal-navy);
  margin: 0;
}

/* LE CADRE DU RELEVÉ · SON PROPRE DÉFILEMENT, DANS LES DEUX SENS.

   `.tbl-hz` (charte) donne déjà le défilement HORIZONTAL · c'est lui qui
   garantit qu'un relevé à douze colonnes ne pousse jamais la page entière
   vers la droite sur un téléphone. Ce qu'il ne donne pas, c'est le plafond de
   HAUTEUR · un relevé de quatre cents lignes déroulerait quatre cents lignes
   dans le flux, et le bouton « Copier le tableau » posé dessous partirait
   trois écrans plus bas.

   440px, et non les 170px de `.relecture__cadre` (§ plus haut) · ces deux
   boîtes ne montrent pas la même chose. La relecture montre une LISTE qu'on
   coche, où deux lignes visibles suffisent à comprendre la forme. Le relevé
   masqué est LE RÉSULTAT · le fiduciaire doit y reconnaître son document, ce
   qui demande une dizaine de lignes d'un coup. La valeur est posée ici, pas
   dérivée d'une autre · elle se remesure si le contenu change. */
.releve__cadre {
  max-height: 440px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* LA LIGNE DE RÉGLAGES · les trois corrections que l'utilisateur peut
   imposer. Même famille visuelle que le reste du pupitre · fer à gauche,
   12px, filet de la charte, aucune couleur inventée. */
.releve-reglages {
  border: 1px solid var(--rule);
  border-radius: var(--radius-card-sm);
  padding: var(--space-3);
}
.releve-reglages__ligne {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}
.releve-reglages__ligne label { flex: 1 1 auto; margin: 0; }
.releve-select {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--fg1);
  background: var(--pal-canvas-pure);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card-sm);
  padding: var(--space-2);
  max-width: 100%;
  min-height: 32px;
  cursor: pointer;
}
.releve-select:focus-visible { outline: 2px solid var(--pal-navy); outline-offset: 2px; }
/* MÊME CIBLE TACTILE QUE LA CASE « GARDER » (§ plus haut, lot J84) · 24×24px,
   recommandation WCAG 2.5.8. Une case laissée à sa taille native rend 13×13px
   et se manque du doigt · le défaut a déjà été trouvé une fois sur cette
   page, il n'a pas à revenir sur une case neuve. */
.releve-case {
  width: 24px;
  height: 24px;
  accent-color: var(--pal-navy);
  cursor: pointer;
  flex: none;
}

/* LE TABLEAU DES RÔLES DE COLONNE · plus serré que le relevé lui-même, il ne
   porte que trois colonnes et sert à décider, pas à lire. */
#tbl-roles { font-size: 13px; }
#tbl-roles td { vertical-align: middle; }

/* SOUS 700px · le seuil DE CE FICHIER (§ partout ailleurs dans cette feuille),
   celui où `.pupitre` replie son menu en barre horizontale.
   `.releve-reglages__ligne` passe en colonne · un sélecteur de rôle et son
   étiquette côte à côte sur 375px laissent au sélecteur une largeur où
   « Montant · laissé intact » se fait tronquer par le navigateur.
   Le cadre du relevé baisse à 320px · sur un téléphone la page défile déjà,
   et une boîte de 440px qui défile DANS une page qui défile est un piège
   tactile connu (`overscroll-behavior: contain`, posé plus haut, empêche au
   moins que le geste ne passe à travers). */
@media (max-width: 700px) {
  .releve-reglages__ligne { flex-direction: column; align-items: stretch; }
  .releve-reglages__ligne .releve-case { align-self: flex-start; }
  .releve-select { width: 100%; }
  .releve__cadre { max-height: 320px; }
}

/* LA DATE NE SE COUPE PAS NON PLUS · trouvée À L'ŒIL le 2026-09-02 sur la
   capture du panneau relevé, jamais par un banc · `01.01.2026` sortait sur
   TROIS lignes dans la colonne du pupitre · « 01.0 / 1.20 / 26 ».

   LA CAUSE EST LA MÊME QUE POUR LES MONTANTS, PAR UN AUTRE CHEMIN. `.mono`
   porte `overflow-wrap: anywhere` (`_charte/apercu.css` ligne 946), posé là
   pour qu'un IBAN ou une adresse très longue ne fasse pas déborder sa boîte ·
   règle juste, et ruineuse sur une date, qui n'a aucune raison de casser et
   dont chaque morceau se lit comme un autre nombre.

   La donnée, elle, est INTACTE · le moteur n'a pas touché à la colonne des
   dates, et le CSV qui repart porte `01.01.2026` d'une seule pièce. C'est donc
   l'écran, et lui seul, qui dément ce que la promesse 2 tient · exactement la
   faute que la garde `td.num` juste au-dessus répare pour les montants. Deux
   symptômes, une seule maladie · une feuille de style qui contredit un moteur
   qui a bien travaillé.

   `releve-date` EST POSÉE PAR `interface.js` EN PLUS DE `mono`, jamais à sa
   place · la chasse fixe reste voulue (une colonne de dates s'aligne à l'œil),
   c'est seulement la césure qu'on retire. */
.pupitre .tbl td.releve-date {
  white-space: nowrap;
  overflow-wrap: normal;
}

/* LE TABLEAU DES RÔLES DÉFILE PLUTÔT QUE DE S'ÉCRASER · trouvé à l'œil sur la
   même capture · ses trois colonnes tenaient dans la moitié gauche du pupitre,
   et la colonne « Pourquoi » y rendait UN MOT PAR LIGNE (« 20 / cellule(s) /
   sur / 20 / se / lisent / comme / une / date »). Illisible, alors que la
   phrase est courte.
   `min-width` sur le tableau, pas une réduction de police ni une troncature ·
   `.tbl-hz` (charte) qui l'enveloppe DÉJÀ lui donne alors son défilement
   horizontal propre, le même mécanisme qui sert `#tbl-matrice` (cinq colonnes
   dans un tiers de pupitre) depuis le 01.09.2026 et le relevé masqué juste à
   côté. On ne réduit pas, on laisse défiler · c'est le geste de la maison pour
   un tableau plus large que sa boîte, pas une invention de ce lot. */
#tbl-roles { min-width: 420px; }

/* ===========================================================================
   L'AVERTISSEMENT DE SECOURS · révélé par la feuille, pas par un script
   ---------------------------------------------------------------------------
   02.09.2026 · Victor · « un bandeau rouge qu'on voit un instant à
   l'ouverture ». Le message partait VISIBLE et `interface.js` le masquait une
   fois le moteur importé · un module s'importe APRÈS le premier rendu, donc
   chaque visiteur le voyait clignoter.
       UN MESSAGE DE SECOURS QUI PARAÎT À CHAQUE OUVERTURE N'AVERTIT PLUS DE
       RIEN · IL DEVIENT CE QU'ON APPREND À IGNORER.
   EN CSS, ET PAS EN JAVASCRIPT · la page ne tolère qu'UNE balise de script
   (elle scelle la sienne par empreinte) · `construire.mjs` a refusé d'écrire
   quand j'en ai ajouté une seconde. La garde a dicté cette solution.
   L'élément part `hidden` · une animation de deux secondes lui rend son
   `display`, et `interface.js` le RETIRE dès que le moteur arrive, bien avant
   l'échéance. `display` en image-clé est discrète · un navigateur qui l'ignore
   ne révèle rien, ce qui est le bon échec pour une page servie par un serveur,
   où les modules se chargent toujours.
   DEUX FOIS, MES PROPRES COMMENTAIRES ONT CASSÉ LA FABRIQUE · ils écrivaient
   le nom de la balise en toutes lettres, ici et dans `apercu_jomini.html` ·
   `construire.mjs` découpe le corps du script en cherchant ce nom, la découpe
   partait donc du commentaire et avalait la prose de la page.
       UN OUTIL QUI LIT DU TEXTE NE SAIT PAS QU'IL LIT UN COMMENTAIRE.
   =========================================================================== */
#alerte-module[hidden] {
  display: none;
  animation: alerte-secours 0s 2s forwards;
}
@keyframes alerte-secours { to { display: block; } }

/* ===========================================================================
   LES BOUTONS ŒIL ET LA MISE EN PAGE QUI SE REPARTIT · lots du 23.09.2026
   ---------------------------------------------------------------------------
   Victor, 23.09.2026, en réaction au repli en onglets sous 700 px (lot J74) ·
   « on peut mettre des petites boutons œil pour masquer ou non chaque bloc ».
   Premier jet le même jour · un bouton nu de 22 px, gris, qui ne repliait que
   le corps du bloc et laissait la barre et un trou dans la rangée. Retour de
   Victor · « les boutons œil dans Jomini sont catastrophiques. Le bouton en
   lui-même est à refaire dans le style Palambur, couleurs. Et il faut que ça
   masque la zone mais que, du coup, les blocs non masqués se partagent
   l'espace, comme des fenêtres Windows qui s'adaptent pour remplir l'écran. »

   DEUX CHANGEMENTS, UN PAR PHRASE DE VICTOR ·

   1. LE BOUTON reprend la direction des boutons du site (proposition 2,
      v3.26, `_charte/boutons.css`) · la PILULE, seule forme ronde de la
      charte, un filet de 1.5 px en `--pal-navy`, et au survol le dégradé
      signature marine (`--pal-navy-deep` vers `--pal-navy-light`) avec
      l'icône qui passe au blanc. Le focus au clavier est le halo de la charte
      (`0 0 0 .18em` de `--pal-navy` à 28 %). Rien n'est écrit en dur · les
      seules couleurs sont les jetons `--pal-*`. Le bloc masqué se rouvre par
      une PASTILLE pleine (même dégradé, œil barré), dans une barre de blocs
      masqués au-dessus de la rangée.
   2. LA MISE EN PAGE · un bloc masqué n'est plus replié, il DISPARAÎT
      (`display: none`, posé par `interface.js` sur `data-oeil="masque"`) et
      les blocs restants se partagent la rangée (`flex: 1 1 0`) · deux
      visibles font 50/50, un seul prend toute la largeur. Le contenu n'est
      JAMAIS effacé · le bloc reste dans le DOM, seul son affichage change.

   LES CONSOLES SONT EN FLEX AU-DESSUS DE 900 PX (rangée à trois) ET DE 1200 PX
   (rangée à deux), et restent en pile en dessous · ce sont les seuils que
   `.volet__paire` portait déjà en grille, mesurés au lot J84 (§ plus haut).
   Une grille aux colonnes fixes ne se recompte pas quand un enfant part ·
   `flex: 1 1 0` si. C'est aussi pourquoi les deux règles `.etape-1` et
   `.etape-2` plus haut ne servent plus à rien ici · elles restent pour la
   pile (aucun effet) et pour un chargement sans script.

   L'ANIMATION EST DE LA CSS PURE, PAS UN TEMPORISATEUR · `flex-grow` va de 1 à
   0 en 260 ms pendant que l'opacité s'éteint, et `display` bascule à la fin
   grâce à `allow-discrete` (Chrome 117, Firefox 129, Safari 17.4) · un
   navigateur plus ancien coupe simplement sans transition, ce qui est le bon
   échec. Le retour part de `@starting-style` (flex-grow 0). L'animation
   n'est posée QUE sur les blocs déjà touchés par un œil (`[data-oeil]`) · les
   révélations d'étape de `reglerEtape`, elles, gardent leur immédiateté
   (les bancs mesurent juste après un clic). `prefers-reduced-motion` la coupe.
   =========================================================================== */

/* --- La barre du bloc · le titre, le mot d'état, puis le bouton ------------ */
.pupitre .console__barre--avec-oeil { justify-content: flex-start; }
.pupitre .console__barre--avec-oeil > span:nth-child(2) { margin-left: auto; }
/* Sous 700 px, la barre de la relecture empile titre et état en colonne (§ plus
   haut) · le bouton ne doit pas tomber SOUS eux, il reste à droite, centré sur
   les deux lignes. */
@media (max-width: 700px) {
  #bloc-relecture > .console__barre.console__barre--avec-oeil {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: var(--space-2);
    row-gap: var(--space-1);
  }
  #bloc-relecture > .console__barre--avec-oeil > span:nth-child(1) { grid-column: 1; grid-row: 1; }
  #bloc-relecture > .console__barre--avec-oeil > span:nth-child(2) { grid-column: 1; grid-row: 2; margin-left: 0; }
  #bloc-relecture > .console__barre--avec-oeil > .oeil-bouton { grid-column: 2; grid-row: 1 / span 2; }
}

/* --- Le bouton œil · la pilule utilitaire de la charte ---------------------
   La boîte cliquable est `.oeil-bouton` ; la pilule visible est son `::before`.
   Sur écran tactile ou étroit la boîte fait 44 px (cible de doigt), la pilule
   reste à 40×32 au centre, et des marges négatives rendent à la barre la
   hauteur qu'elle avait (sa marge intérieure de 12 px absorbe le reste) · la
   barre de `#bloc-entree` est mesurée au pixel par `bancs/mobile.mjs`. */
.oeil-bouton {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 36px;
  height: 28px;
  margin: 0 0 0 var(--space-2);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--pal-navy);
  font-family: var(--font-head);
  font-weight: var(--w-semi);
  font-size: 13px;
  letter-spacing: 0.01em;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--dur-base) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.oeil-bouton::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 1.5px solid var(--pal-navy);
  border-radius: var(--radius-pill);
  /* DEUX COUCHES dans la même pilule · dessus, un voile de la couleur du fond
     de la barre (`--bg2`) qui fait le « filet vide » du repos ; dessous, le
     dégradé signature. Au survol le voile se retire de gauche à droite
     (`background-size` de 100 % à 0) et le dégradé glisse de 40 px, comme
     `.btn-primary`. Pas de pseudo-élément de plus · un voile séparé laissait
     une couture de demi-pixel au bord de la pilule (vu à la capture). */
  background-color: var(--pal-navy);
  background-image:
    linear-gradient(var(--bg2), var(--bg2)),
    linear-gradient(100deg, var(--pal-navy-deep) 0%, var(--pal-navy) 55%, var(--pal-navy-light) 100%);
  background-size: 100% 100%, calc(100% + 40px) 100%;
  background-position: 100% 0, 0 0;
  background-repeat: no-repeat;
  background-clip: padding-box;
  background-origin: padding-box;
  transition: background-size var(--dur-base) var(--ease-out), background-position var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.oeil-bouton[hidden] { display: none; }
/* Le trait diagonal de l'œil barré · posé par `interface.js` (attribut `hidden`
   ôté sur le bloc masqué et sur la pastille). Nommé ici pour que la recette voie
   une classe qui a une règle, et pour dire qu'il porte le même trait que l'œil. */
.oeil-bouton__barre { stroke-width: 1.75; }
.oeil-bouton__icone { position: relative; z-index: 1; flex: 0 0 auto; width: 16px; height: 16px; }
.oeil-bouton__texte { position: relative; z-index: 1; }
.oeil-bouton:hover:not([aria-disabled="true"])::before { background-size: 0 100%, calc(100% + 40px) 100%; background-position: 100% 0, -40px 0; }
.oeil-bouton:hover:not([aria-disabled="true"]) { color: var(--pal-canvas-pure); }
.oeil-bouton:active:not([aria-disabled="true"]) { transform: scale(0.97); }
.oeil-bouton:focus-visible {
  outline: 2px solid transparent; /* le halo ci-dessous ne se voit pas en contraste forcé · ce filet, si */
  outline-offset: 3px;
}
.oeil-bouton:focus-visible::before {
  box-shadow: 0 0 0 0.18em color-mix(in srgb, var(--pal-navy) 28%, transparent);
}
/* Désactivé · le dernier bloc visible ne se masque pas · la pilule s'éteint,
   le curseur le dit, l'infobulle et le libellé d'accessibilité disent pourquoi. */
.oeil-bouton[aria-disabled="true"] { cursor: not-allowed; color: var(--pal-muted); }
.oeil-bouton[aria-disabled="true"]::before { border-color: var(--pal-hairline); background-color: transparent; background-image: linear-gradient(var(--bg2), var(--bg2)); background-size: 100% 100%; }
@media (forced-colors: active) {
  .oeil-bouton::before { border-color: ButtonText; }
  .oeil-bouton:focus-visible { outline-color: Highlight; }
}

/* Sur écran tactile ou étroit · une boîte de 44 px, la pilule de 40×32 au
   centre, les marges négatives (12 px en haut et en bas) rendent à la barre sa
   hauteur d'avant. */
@media (pointer: coarse), (max-width: 900px) {
  .oeil-bouton { width: 44px; height: 44px; margin-block: -12px; margin-right: -2px; }
  .oeil-bouton::before { inset: 6px 2px; }
}

/* --- La pastille de retour · la même pilule, pleine, œil barré -------------- */
.blocs-masques {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
}
.blocs-masques[hidden] { display: none; }
.blocs-masques__titre {
  font-size: 12px;
  font-weight: var(--w-med);
  color: var(--fg3);
  margin-right: var(--space-1);
}
.oeil-bouton--pastille {
  width: auto;
  min-height: 36px;
  height: auto;
  margin: 0;
  padding: 0 var(--space-4) 0 var(--space-3);
  max-width: 100%;
  color: var(--pal-canvas-pure);
  white-space: nowrap;
}
.oeil-bouton--pastille::before { inset: 0; background-size: 0 100%, calc(100% + 40px) 100%; background-position: 100% 0, 0 0; }
.oeil-bouton--pastille .oeil-bouton__texte { overflow: hidden; text-overflow: ellipsis; max-width: 16em; }
.oeil-bouton--pastille:hover::before { background-position: 100% 0, -40px 0; }
@media (pointer: coarse), (max-width: 900px) {
  .oeil-bouton--pastille { min-height: 44px; margin-block: 0; margin-right: 0; }
  .oeil-bouton--pastille::before { inset: 4px 0; }
}

/* --- Le partage de l'espace · flex à la place des colonnes fixes ------------ */
@media (min-width: 901px) {
  .volet__paire--3 { display: flex; gap: var(--space-5); align-items: flex-start; }
  .volet__paire--3 > .console { flex: 1 1 0; min-width: 0; }
  /* `#bloc-relecture` portait 8 px de marge haute pour la pile (§ plus haut) ·
     en rangée elle décalait la colonne du milieu sous ses voisines. */
  .volet__paire--3 > #bloc-relecture { margin-top: 0; }
}
@media (min-width: 1201px) {
  .volet__paire:not(.volet__paire--3) { display: flex; gap: var(--space-5); align-items: flex-start; }
  .volet__paire:not(.volet__paire--3) > .console { flex: 1 1 0; min-width: 0; }
}
/* Un bloc masqué disparaît · rien d'autre ne le retient dans la mise en page. */
.pupitre .console[data-oeil="masque"] { display: none; }

@media (prefers-reduced-motion: no-preference) {
  .pupitre .console[data-oeil] {
    transition: flex-grow 260ms var(--ease-out), opacity 200ms var(--ease-out), display 260ms allow-discrete;
  }
  .pupitre .console[data-oeil="masque"] { flex-grow: 0; opacity: 0; }
  @starting-style {
    .pupitre .console[data-oeil="affiche"] { flex-grow: 0; opacity: 0; }
  }
}

/* === LE BANDEAU « GRATUIT » · Victor, 23.09.2026 ==========================
   Sous « aucune fuite constatée », même gabarit que `.pupitre__preuve` (même
   padding, même rayon, même corps de 12 px), fond vert OPAQUE et texte blanc ·
   vert du site (`--pal-green-ink`, contraste blanc/vert vérifié > 4.5). */
.bandeau-gratuit {
  display: flex;
  align-items: center;
  box-sizing: border-box;
  width: 100%;
  margin-top: var(--space-2);
  padding: var(--space-3);
  /* Liseré de 1 px comme celui du jeton voisin (même couleur que le fond) ·
     la colonne n'a ainsi qu'UN format, jugé par `bancs/colonne.mjs`. */
  border: 1px solid var(--pal-green-ink, #047955);
  border-radius: var(--radius-card-sm);
  background: var(--pal-green-ink, #047955);
  color: #fff;
  font-family: var(--font-body);
  font-size: 12px;
  line-height: normal;
  text-align: left;
}
.bandeau-gratuit__titre { font-size: inherit; /* 12 px · à 14 px la boîte rendait 43 px contre 40 */ font-weight: 700; color: #fff; }

/* === LES TROIS FENÊTRES SUR MOBILE · Victor, 23.09.2026 ====================
   « les boîtes qui accueillent les textes (3) doivent être de même taille et
   assez grandes (hauteur 3/4 écran) » · sous 901 px les trois (`.zone`,
   `.sortie`, `.relecture__cadre`) valaient 240, 240 à 420 et 170 px, donc
   trois hauteurs. Au-dessus de 901 px, `interface.js` les égalise (J79) · ici
   le CSS suffit, une hauteur fixe de trois quarts d'écran pour les trois.
   `svh` (hauteur stable, sans la barre d'adresse qui bouge) avec `vh` en repli. */
@media (max-width: 900px) {
  .volet__paire--3 .zone,
  .volet__paire--3 .sortie,
  .volet__paire--3 .relecture__cadre {
    box-sizing: border-box;
    height: 75vh;
    height: 75svh;
    min-height: 75vh;
    min-height: 75svh;
    max-height: none;
    overflow-y: auto;
  }
}

/* === LE CHAMP « FICHIER » TRADUIT · Victor, 23.09.2026 ====================
   Le champ natif écrit « Choisir un fichier / Aucun fichier choisi » dans la
   langue DU NAVIGATEUR, pas de la page · sur la page anglaise d'un
   navigateur français, il restait en français. Le champ natif reste dans le
   document (clavier, lecteur d'écran, glisser-déposer) mais se cache
   visuellement ; un bouton et un nom de fichier, traduits par `data-tr`, le
   remplacent. Le bouton s'allume quand le champ natif prend le focus. */
.depot__natif {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.depot__ligne { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin-top: var(--space-3); }
.depot__bouton {
  display: inline-block;
  padding: 8px 14px;
  border: 1px solid var(--pal-navy);
  border-radius: var(--radius-card-sm);
  background: var(--bg1);
  color: var(--pal-navy);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.depot__natif:focus-visible + .depot__ligne .depot__bouton { outline: 2px solid var(--pal-navy); outline-offset: 2px; }
.depot__nom { font-size: 13px; color: var(--fg2); overflow-wrap: anywhere; }

/* === LE TABLEAU DE RELECTURE SUR MOBILE · même jour ========================
   Six colonnes dont une figée à 90 px (`style` en ligne sur « Garder ») ne
   tenaient pas en 340 px · « Type » et « Occurrences » sortaient à droite.
   Corps et remplissage resserrés, colonne « Garder » libérée, mots coupables. */
@media (max-width: 700px) {
  .pupitre-section { padding-left: var(--space-3); padding-right: var(--space-3); }
  .volet__paire--3 .console__corps { padding: var(--space-2); }
  .volet__paire--3 .tbl { font-size: 11px; }
  .volet__paire--3 .tbl td { padding: 6px 3px; overflow-wrap: anywhere; }
  .volet__paire--3 .tbl th {
    padding: 6px 3px;
    font-size: 9px;
    letter-spacing: 0;
    overflow-wrap: normal;
    word-break: normal;
    hyphens: none;
  }
  .volet__paire--3 .tbl th:first-child { width: auto !important; }
}

/* FENÊTRE D'ACCUEIL/AIDE · à CHAQUE visite, sans rien mémoriser (arbitrage de Victor, 28.09.2026 : la
   promesse « rien ne reste dans le navigateur » de Jomini reste intacte).
   Fermeture par croix, COMPRIS, Échap ou clic sur le voile. */

.aide-voile{position:fixed;inset:0;background:rgba(10,25,60,.45);z-index:20;display:none}
.aide-voile.on{display:block}
.pop-aide{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);
  width:min(600px,calc(100vw - 32px));max-height:calc(100vh - 32px);overflow:auto;
  display:none;z-index:21;border-radius:18px;box-shadow:0 24px 60px -12px rgba(10,25,60,.35);
  background:#fff}
.pop-aide.on{display:flex}
@media (max-width:640px){.pop-aide{flex-direction:column}}
.pop-aide__marge{position:relative;flex:0 0 178px;width:178px;padding:22px 18px 18px;
  background:linear-gradient(165deg,#14265E,#1E3A8A,#2D52B8);color:#fff;overflow:hidden;
  display:flex;flex-direction:column;border-radius:18px 0 0 18px;box-sizing:border-box}
@media (max-width:640px){.pop-aide__marge{width:100%;flex:0 0 auto;border-radius:18px 18px 0 0;padding:18px 20px}}
.pop-aide__forme{position:absolute;left:-80px;bottom:-118px;width:220px;height:220px;pointer-events:none}
.pop-aide__marque{position:relative;z-index:1;display:block;width:26px;height:22px;
  background:url('https://www.palambur.ch/assets/logo-feuille-128-blanc.png') no-repeat center/contain}
.pop-aide__nom{position:relative;z-index:1;font-family:'Space Grotesk';font-weight:700;color:#fff;
  font-size:25px;line-height:1.15;margin-top:12px}
.pop-aide__phrase{position:relative;z-index:1;font-family:'Barlow';font-size:12.5px;
  color:#C3D0F0;line-height:1.4;margin-top:8px}
.pop-aide__aide{position:relative;z-index:1;margin-top:auto;font-family:'JetBrains Mono';
  font-size:9px;letter-spacing:.12em;text-transform:uppercase;color:#7C8FC9}
.pop-aide__droite{position:relative;flex:1 1 auto;background:#fff;padding:24px 26px 20px;
  border-radius:0 18px 18px 0;box-sizing:border-box}
@media (max-width:640px){.pop-aide__droite{border-radius:0 0 18px 18px}}
.pop-aide__x{position:absolute;top:14px;right:14px;border:0;background:none;cursor:pointer;
  font-size:15px;color:var(--pal-muted);line-height:1;padding:6px;border-radius:9999px}
.pop-aide__x:hover{background:#F1F5F9;color:var(--pal-ink)}
.pop-aide__x:focus-visible{outline:2px solid var(--pal-navy);outline-offset:1px}
.pop-aide__titre{font-family:'Space Grotesk';font-size:18px;font-weight:600;color:#0A192F;
  margin:0 26px 14px 0}
.pop-aide__etapes{list-style:none;margin:0;padding:0}
.pop-aide__etapes li{display:flex;gap:14px;align-items:flex-start;padding:12px 0;
  border-top:1px solid #EDF1F9}
.pop-aide__etapes li:first-child{border-top:0;padding-top:0}
.pop-aide__num{font-family:'Space Grotesk';font-weight:700;font-size:22px;color:#C7D2E8;
  flex:0 0 auto;min-width:26px}
.pop-aide__texte{font-family:'Barlow';font-size:14px;color:#1E293B;line-height:1.4;
  padding-top:2px}
.pop-aide__pied{display:flex;justify-content:flex-end;margin-top:18px}
.pop-aide__ok{border:0;border-radius:9999px;padding:11px 22px;cursor:pointer;
  font-family:'JetBrains Mono';font-size:10.5px;letter-spacing:.05em;text-transform:uppercase;
  background:linear-gradient(90deg,#1E3A8A,#2D52B8);color:#fff}
.pop-aide__ok:focus-visible{outline:2px solid var(--pal-navy);outline-offset:2px}
