/* Les jetons de la charte Hodologic (design/CHARTE-HODOLOGIC.md, étape 1, 02/10) :
   brume, marine, filets à 13 % d'encre, vert profond d'état, encre du sable pour
   la réserve. Les RAMPES de données ne sont pas des jetons et ne bougent pas
   (test_rampes_inchangees.py). Police, contrôles 28 px et rayons 3/2/0 inchangés :
   la typographie est l'étape 2.

   Feuille neuve : rien n'est repris de css/01-theme.css, qui sert /map. */

:root {
    --fond:        #F4F6F4;   /* brume du site, pas celle de la planche (§ 1) */
    --papier:      #FFFFFF;
    --encre:       #0F2A3A;   /* marine */
    --encre-douce: #34495A;
    /* 3,64:1 sur --papier et 3,36:1 sur --fond, pour des textes de 10 px : sous
       le seuil de 4,5:1 (86, 24/09). #5B6B7A est le --muted d'Hodologic, la
       valeur que la charte retient. Gardé par test_contraste_jetons.py. */
    --encre-pale:  #5B6B7A;
    --trait:       rgba(15, 42, 58, .13);   /* filet à 13 % d'encre */
    --trait-pale:  rgba(15, 42, 58, .07);
    /* LE VERT PROFOND dit l'état et la sélection, par un FILET seul : le fond
       vert pâle disparaît (§ 4 bis). */
    /* L'ÉTAT ET LA SÉLECTION, EN BORDEAUX (v1.6.2, comme le Kiosque ; e0, 25/10). Lu par cette
       feuille seule (barres de sélection, boutons actifs, focus), jamais par ce qui dessine la
       carte : les couleurs des données et la rampe ne bougent pas. Le vert profond #2E554B
       était l'état de la charte du 02/10. */
    --etat:        #7A1F2B;   /* = --gia-bordeaux ; en clair, test_contraste_jetons le mesure */
    --etat-survol: #681A25;   /* = --gia-bordeaux-survol */
    --sur-etat:    #F8F7F3;   /* blanc chaud, l'encre sur le vert */
    --r-grand: 3px;
    --r-petit: 2px;
    --controle: 28px;
    /* LA TEINTE DE LA RÉSERVE, reprise de la maquette arbitrée. Elle n'est pas
       une alerte : l'ambre dit « lis ceci avant de conclure », le vert de
       `--etat` dit « voici où l'on en est ». *Deux encres pour deux actes de
       parole* — et la circularité du modèle n'est ni un état ni un défaut. */
    --reserve:      #8A6A43;  /* encre du sable : 4,97:1 sur blanc, jamais sur le sable, jamais seule */
    --reserve-fond: #F4F6F4;  /* le bloc « à lire avant de comparer » : brume + filet de sable */
}

* { box-sizing: border-box; }

/* Une surface masquée par l'attribut `hidden` doit disparaître, quelle que
   soit la classe qu'elle porte.
   
   Le navigateur pose bien `[hidden] { display: none }`, mais c'est une règle
   de SA feuille : n'importe quelle règle d'auteur avec `display` la bat. Les
   deux volets de la coque portent `class="rail"`, qui vaut `display: flex` —
   l'attribut était posé, correct pour l'accessibilité, et sans effet visible.
   Les deux volets cohabitaient, et `#volet-dossier` occupait une colonne vide
   avant même qu'on clique.
   
   `!important` est ici le fond du sujet, pas une facilité : sans lui, cette
   règle entre dans une course de spécificité que la prochaine classe à
   `display` gagnera. C'était déjà le cas — une rustine `.voile[hidden]`
   existait pour la palette seule, et elle n'a pas empêché le défaut de
   revenir sur les volets. Une règle par classe est une règle qu'on oublie. */
[hidden] { display: none !important; }

body {
    margin: 0;
    font-family: var(--gia-texte);   /* v1.6.4 : plus d’IBM Plex, plus de Google Fonts (c0) */
    -webkit-font-smoothing: antialiased;
    background: var(--fond);
    color: var(--encre);
    height: 100vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.bandeau {
    height: 48px;
    flex-shrink: 0;
    background: var(--papier);
    border-bottom: 1px solid var(--trait);
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 0 18px;
}

/* La marque du bandeau est .gia-marque, déclarée dans css/marque.css (v1.6.2). */

.jalon { margin-left: auto; }

.corps { flex-grow: 1; display: flex; min-height: 0; }

.volet {
    width: 272px;
    flex-shrink: 0;
    background: var(--papier);
    border-right: 1px solid var(--trait);
    display: flex;
    flex-direction: column;
    overflow-y: auto;
}

.volet h2 {
    margin: 0;
    padding: 16px 16px 9px;
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--encre-pale);
}

.groupe-titre {
    padding: 12px 16px 5px;
    font-size: 11px;
    font-weight: 600;
    color: var(--encre-douce);
    border-top: 1px solid var(--trait-pale);
}

.couche {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 16px;
    min-height: var(--controle);
    cursor: pointer;
}
.couche:hover { background: var(--fond); }
.couche.absente { cursor: default; opacity: 0.55; }
.couche.absente:hover { background: transparent; }
.couche.allumee { box-shadow: inset 3px 0 0 var(--etat); }

.puce { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; border: 1px solid var(--trait); }
.puce.trait { width: 14px; height: 3px; border-radius: 0; }

.couche-texte { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.couche-nom { font-size: 12.5px; line-height: 1.25; }
.couche-sous { font-size: 10px; color: var(--encre-pale); line-height: 1.25; }

.mention {
    margin-left: auto;
    font-size: 10px;
    color: var(--encre-pale);
    white-space: nowrap;
}

.pied {
    margin-top: auto;
    padding: 12px 16px;
    font-size: 10.5px;
    color: var(--encre-pale);
    border-top: 1px solid var(--trait-pale);
    line-height: 1.45;
}
/* La ligne de la marque (v1.6.2), sous le pied de la pile : mêmes marges que lui.
   Au téléphone, c'est elle qui dit « une plateforme Hodologic » (e0, 25/10). */
.pied + .gia-lien-marque { margin: 0; padding: 0 16px 12px; }

#carte { flex-grow: 1; min-width: 0; }
.leaflet-container { background: var(--fond); font-family: inherit; }

/* ─── Le rail ─────────────────────────────────────────────────────────── */

.rail {
    width: 232px;
    flex-shrink: 0;
    background: var(--papier);
    border-right: 1px solid var(--trait);
    display: flex;
    flex-direction: column;
    overflow-y: auto;
}

.rail h2 {
    margin: 0;
    padding: 16px 16px 9px;
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--encre-pale);
}

.rail-item {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    padding: 10px 16px;
    border-left: 3px solid transparent;
    cursor: pointer;
}
.rail-item:hover { background: var(--fond); }
.rail-item.actif { border-left-color: var(--etat); }
.rail-item.inerte { cursor: default; opacity: 0.5; }
.rail-item.inerte:hover { background: transparent; }

.rail-item .titre { font-size: 12.5px; font-weight: 500; line-height: 1.3; }
.rail-item .quoi { font-size: 10.5px; color: var(--encre-pale); line-height: 1.35; }
.rail-item .marque-p {
    font-size: 9px; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--encre-pale); border: 1px solid var(--trait-pale);
    border-radius: var(--r-petit); padding: 1px 4px; margin-left: 6px;
}

/* ─── La pile des couches ─────────────────────────────────────────────── */

.pile { width: 296px; }

.pile-tete {
    display: flex; align-items: baseline; gap: 8px;
    padding: 16px 16px 9px;
}
.pile-tete h2 { padding: 0; }
.pile-tete .compte { font-size: 10.5px; color: var(--encre-pale); margin-left: auto; }

.entree {
    display: flex; align-items: center; gap: 10px;
    padding: 7px 16px; min-height: var(--controle);
    border-left: 3px solid transparent;
}
.entree:hover { background: var(--fond); }
.entree.choisie { border-left-color: var(--etat); }

.oeil {
    width: var(--controle); height: var(--controle);
    flex-shrink: 0; border: 0; background: none; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    color: var(--encre-pale); border-radius: var(--r-petit);
}
.oeil:hover { background: var(--trait-pale); }
.oeil[aria-pressed="true"] { color: var(--etat); }
.oeil svg { width: 16px; height: 16px; }

.entree-texte { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex-grow: 1; cursor: pointer; }
.entree-nom { font-size: 12.5px; line-height: 1.25; }
.entree-sous { font-size: 10px; color: var(--encre-pale); line-height: 1.25; }

/* LE SEUL PORTEUR QUI RESTE du signe « ce nombre est juste et ne se lit pas
   comme les autres ». Il n'y a pas de barre ici : les pointillés passent sous
   le mot qui le nomme. Les deux porteurs de classement sont partis à la tâche
   23 — un fait se déplace, une catégorie n'était pas une réserve. Ce qui reste
   est un DEGRÉ, et c'est ce que le signe veut dire. Voir
   js/v2-panneau-commun.js et la note qui remplace `.prov.sous-reserve`. */
.entree.sous-reserve .entree-nom { color: var(--encre-pale); }
.entree.sous-reserve .entree-sous {
    text-decoration: underline dotted;
    text-underline-offset: 2px;
}

.retirer {
    border: 0; background: none; cursor: pointer; color: var(--encre-pale);
    font-size: 15px; line-height: 1; padding: 4px 6px; border-radius: var(--r-petit);
    opacity: 0; flex-shrink: 0;
    /* 24 × 24 AU MOINS (WCAG 2.5.8, e0) : visible au toucher, il doit aussi
       s'y viser (map-a-390, test_ecran_390.py). */
    min-width: 24px; min-height: 24px;
    display: inline-flex; align-items: center; justify-content: center;
}
.entree:hover .retirer { opacity: 1; }
/* AU TÉLÉPHONE, :hover ne vient jamais : le × restait à opacité nulle, et on
   retirait une couche sans la voir (map-a-390, test_ecran_390.py). */
@media (hover: none) { .retirer { opacity: 1; } }
.entree:focus-within .retirer { opacity: 1; }
.retirer:hover { background: var(--trait-pale); color: var(--encre); }

.opacite { padding: 2px 16px 10px 52px; display: flex; align-items: center; gap: 9px; }
.opacite label { font-size: 10.5px; color: var(--encre-pale); }
.opacite input { flex-grow: 1; min-width: 0; accent-color: var(--etat); height: 24px; margin: 0; }
.opacite output {
    font-family: ui-monospace, monospace;
    font-size: 10.5px; color: var(--encre-douce); min-width: 34px; text-align: right;
}

.ajouter {
    display: flex; align-items: center; gap: 9px;
    margin: 10px 16px; padding: 0 11px; height: 30px;
    border: 1px dashed var(--trait); border-radius: var(--r-grand);
    background: none; cursor: pointer; color: var(--encre-pale);
    font: inherit; font-size: 12px; width: calc(100% - 32px);
}
.ajouter:hover { border-color: var(--etat); color: var(--etat); }
.ajouter kbd {
    margin-left: auto; font-family: ui-monospace, monospace;
    font-size: 10.5px; border: 1px solid var(--trait-pale);
    border-radius: var(--r-petit); padding: 1px 5px;
}

/* ─── La palette ⌘K ───────────────────────────────────────────────────── */

/* Leaflet empile ses propres couches à partir de 400 (.leaflet-pane) et monte
   jusqu'à 1000 pour ses contrôles. Un voile à 40 passait donc DERRIÈRE la carte :
   la palette s'ouvrait, on ne voyait pas ce qu'on tapait. 1200 la met au-dessus
   de tout ce que Leaflet pose, sans entrer en concurrence avec autre chose —
   c'est la seule surface flottante de la coque. */
.voile {
    position: fixed; inset: 0; background: rgba(15, 42, 58, .28);
    display: flex; justify-content: center; padding-top: 12vh; z-index: 1200;
}

.palette {
    width: 620px; max-width: calc(100vw - 32px); max-height: 70vh;
    background: var(--papier); border: 1px solid var(--trait);
    border-radius: var(--r-grand); box-shadow: 0 18px 48px rgba(15, 42, 58, .18);
    display: flex; flex-direction: column; overflow: hidden;
}

.palette-saisie {
    display: flex; align-items: center; gap: 10px;
    padding: 0 14px; height: 46px; border-bottom: 1px solid var(--trait-pale);
    flex-shrink: 0;
}
.palette-saisie input {
    flex-grow: 1; border: 0; outline: 0; font: inherit; font-size: 14px;
    background: none; color: var(--encre);
}
.palette-saisie .compte { font-size: 10.5px; color: var(--encre-pale); }

.palette-resultats { overflow-y: auto; flex-grow: 1; }
.palette-groupe {
    padding: 11px 14px 4px; font-size: 10px; font-weight: 500;
    letter-spacing: 0.1em; text-transform: uppercase; color: var(--encre-pale);
}

.resultat {
    display: flex; align-items: center; gap: 10px;
    padding: 7px 14px; min-height: var(--controle); cursor: pointer;
}
.resultat[aria-selected="true"] { background: var(--fond); box-shadow: inset 2px 0 0 var(--etat); }
.resultat.absente { cursor: default; }
.resultat .nom { font-size: 12.5px; }
.resultat .ou { font-size: 10.5px; color: var(--encre-pale); }
.resultat .etat { margin-left: auto; font-size: 10px; color: var(--encre-pale); white-space: nowrap; }
/* CE QUI NE TIENT PAS SUR LA LIGNE PASSE À LA LIGNE, au lieu de sortir de la
   palette. Mesuré à 390 px : la phrase de coût d'une couche dépassait la
   palette de 19 px, et le bord la coupait. *Un avertissement tronqué est un
   avertissement qui n'a pas été donné*, et celui-ci est le seul qui arrive
   avant que l'utilisateur allume la couche.

   `flex-wrap` sur la ligne plutôt qu'une largeur imposée : la phrase reste à
   droite tant qu'elle tient — c'est le cas sur un écran large — et descend
   seule quand la place manque. Une règle qui la ferait descendre toujours
   changerait un affichage qui va bien pour réparer celui qui ne va pas. */
.resultat { flex-wrap: wrap; }
.resultat .etat.cout { white-space: normal; text-align: right; line-height: 1.35; }
/* LA RAISON D'UNE COUCHE ABSENTE PASSE À LA LIGNE POUR LA MÊME RAISON. Elle dit
   ce qui manque — la source que le site en ligne ne sert pas, la requête que
   seule /map lance — et une raison vraie est plus longue que « pas encore
   dans cette vue » : en `nowrap`, le bord la couperait comme il coupait le
   coût. Posée sur `.absente`, que la palette pose déjà, et non sur `.cout` :
   une raison n'est pas un coût. */
.resultat.absente .etat { white-space: normal; text-align: right; line-height: 1.35; }

.palette-pied {
    display: flex; align-items: center; gap: 16px;
    padding: 8px 14px; border-top: 1px solid var(--trait-pale);
    font-size: 10.5px; color: var(--encre-pale); flex-shrink: 0;
}
.palette-pied kbd {
    font-family: ui-monospace, monospace;
    border: 1px solid var(--trait-pale); border-radius: var(--r-petit);
    padding: 1px 5px; margin-right: 4px;
}
.palette-pied .indexees { margin-left: auto; }

.vide { padding: 22px 14px; font-size: 12px; color: var(--encre-pale); text-align: center; }

/* ─── Sous 900 px ─────────────────────────────────────────────────────────

   CE QU'IL Y AVAIT ICI RETIRAIT LE PRODUIT, ET LA RÈGLE SUIVANTE LE PROUVAIT :

       @media (max-width: 900px) { .rail { display: none; } .pile { width: 240px; } }

   `.rail` habille TROIS éléments — le rail de navigation, la pile des couches
   et le panneau de dossier. La règle en cachait donc trois là où elle en visait
   un. *Et la ligne d'en dessous rétrécissait la pile à 240 px* : on ne rétrécit
   pas ce qu'on vient de cacher. L'intention était de garder la pile ; le
   sélecteur l'a emportée avec le reste.

   Sous 900 px il ne restait donc que l'en-tête et une carte nue. Les sept
   destinations du rail — quatre dossiers, l'Exploration, les Fiches, l'Atelier —
   n'avaient plus aucun chemin. *Celui-là est établi : c'est l'utilisateur qui
   l'a vu sur sa propre machine, et la règle est là pour le lire.* Un utilisateur à 880 px ne voyait pas un produit
   dégradé : il voyait un produit qui n'a qu'une carte, et il en concluait que
   c'est le produit.

   UN ÉLÉMENT QU'ON CACHE EN DESSOUS D'UN SEUIL DOIT ÊTRE REMPLACÉ, PAS
   SUPPRIMÉ. Cacher un rail de 232 px sur un écran étroit est le geste juste ;
   ce qui manquait est le SECOND geste, et personne ne l'avait demandé parce
   qu'aucune suite ne vérifiait ce qui reste ATTEIGNABLE — toutes vérifient ce
   qui est affiché.

   Le rail devient donc un TIROIR, rappelé par un bouton ; et les volets
   prennent toute la largeur en cédant la place à la carte de façon RÉVERSIBLE,
   par un second bouton. Rien ne disparaît sans substitut. */

.etroit-seul { display: none; }

@media (max-width: 900px) {
    .etroit-seul {
        display: inline-flex; align-items: center; height: 24px; padding: 0 9px;
        border: 0; border-radius: var(--r-grand); box-shadow: inset 0 0 0 1px var(--trait);
        background: var(--papier); color: var(--encre);
        font: inherit; font-size: 11px; cursor: pointer;
        /* ILS NE SE RÉTRÉCISSENT PAS ET NE SE COUPENT PAS. Ce sont les seuls
           chemins vers le produit à cette largeur : tout le reste de la barre
           peut céder avant eux. */
        flex-shrink: 0; white-space: nowrap;
    }

    /* ET CE QUI PEUT CÉDER, CÈDE. Le jalon de développement ne mène nulle part ;
       à 390 px, lui et l'ancien sous-titre occupaient 240 px de la barre, la
       place des deux boutons. Le sous-titre de la marque, « une plateforme
       Hodologic » depuis v1.6.2, NE cède plus : c'est lui qui dit la marque, et
       empilé sous « GIA » il tient dans la barre à 320 px (test_marque_hodologic). */
    .jalon { display: none; }
    .etroit-seul[aria-expanded="true"] { background: var(--encre); color: var(--papier); }

    /* LE RAIL EN TIROIR. Il se pose PAR-DESSUS plutôt que de pousser : à 390 px,
       un rail de 232 px qui pousse ne laisse rien à côté de lui. */
    #rail {
        /* 48 px, la hauteur du bandeau — et non 44, qui laissait une bande de
           quatre pixels où la carte affleurait sous le tiroir. */
        position: absolute; top: 0; left: 0; bottom: 0; width: min(280px, 86vw);
        /* 1100 : AU-DESSUS DES CONTRÔLES DE LEAFLET, EN DESSOUS DE LA PALETTE.
           Posé d'abord à 600, il passait sous les boutons de zoom — Leaflet
           empile ses panneaux de 200 à 700 et ses contrôles à 1000 — donc à
           390 px, où le tiroir couvre la carte, le zoom aurait flotté dessus.
           Et il reste sous la palette (1200) : ⌘K est un dialogue, il doit
           passer devant tout, y compris devant le tiroir qui l'a précédé.
           *Deux surfaces flottantes demandent de dire laquelle passe devant.* */
        z-index: 1100; box-shadow: 2px 0 12px rgba(0, 0, 0, 0.12);
    }
    body:not(.rail-ouvert) #rail { display: none; }

    /* LES VOLETS PRENNENT TOUTE LA LARGEUR, et cèdent la place à la carte —
       dans les deux sens. Un panneau qui s'efface sans retour possible est la
       même faute que le rail caché sans bouton. */
    .pile, .dossier { width: 100%; border-right: 0; }
    body.vue-carte .pile, body.vue-carte .dossier { display: none; }
    body:not(.vue-carte) #carte { display: none; }

    .corps { position: relative; }
}

/* ─── Le dossier ──────────────────────────────────────────────────────── */

.dossier { width: 372px; }

.dossier-tete { padding: 16px 16px 12px; border-bottom: 1px solid var(--trait-pale); }
.dossier-tete h1 { margin: 0 0 3px; font-size: 15px; font-weight: 600; letter-spacing: 0.01em; }
.dossier-tete p { margin: 0; font-size: 11.5px; color: var(--encre-pale); line-height: 1.4; }

.chiffre { padding: 16px; border-bottom: 1px solid var(--trait-pale); }
.chiffre .quoi {
    font-size: 10px; font-weight: 500; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--encre-pale); margin-bottom: 8px;
}
.chiffre .gros {
    font-size: 30px; font-weight: 600; line-height: 1.05; letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
}
.chiffre .apres { font-size: 12.5px; color: var(--encre-douce); line-height: 1.45; margin-top: 4px; }
.chiffre .soit { font-size: 11.5px; color: var(--encre-pale); margin-top: 6px; }
.chiffre .soit b { color: var(--encre-douce); font-weight: 600; }

.composition { padding: 12px 16px; border-bottom: 1px solid var(--trait-pale); }
.composition h2 { padding: 0 0 6px; }

.classement { padding: 14px 16px; border-bottom: 1px solid var(--trait-pale); }
.classement h2 { padding: 0 0 3px; }
.classement .colonne {
    font-size: 10px; color: var(--encre-pale); margin-bottom: 9px;
}

/* `auto` et non 34 px : la colonne était taillée pour « 16 % » et sept valeurs
   sur neuf passaient à la ligne, le nombre au-dessus de son signe. Une largeur
   fixe suppose connue la plus large des valeurs à venir ; `auto` la mesure.
   Le `nowrap` est la ceinture : même à l'étroit, « 60,9 % » ne se coupe plus. */
.prov { display: grid; grid-template-columns: 1fr auto; gap: 4px 9px; align-items: baseline; margin-bottom: 7px; }
.prov .nom { font-size: 12px; }
.prov .val {
    font-size: 11.5px; text-align: right; font-variant-numeric: tabular-nums;
    color: var(--encre-douce); white-space: nowrap;
}
.prov .barre {
    grid-column: 1 / -1; height: 3px; background: var(--trait-pale); border-radius: 0;
}
/* Pas de jeton d'accent ici : la teinte vient de la carte, posée en ligne par
   v2-dossier-panneau.js. Ce gris n'est qu'un repli — une barre verte sur une
   colonne qui classe un problème est ce qu'on vient de corriger. */
.prov .barre i { display: block; height: 100%; background: var(--encre-pale); }
/* LE PONT. Une ligne liée se distingue sans changer de couleur de fond ni de
   teinte : un filet à gauche et un fond très léger, comme la pile marque une
   couche allumée. La barre, elle, ne bouge pas — elle porte une valeur. */
.prov.liee { box-shadow: inset 2px 0 0 var(--etat); }
.prov { border-radius: 2px; padding: 1px 3px; margin-left: -3px; margin-right: -3px; }
.prov:focus { outline: 2px solid var(--encre); outline-offset: 1px; }
.prov:focus:not(:focus-visible) { outline: none; }

/* LE SIGNE N'HABILLE PLUS DE LIGNE DE CLASSEMENT — `.prov.sous-reserve` a été
   retiré à la tâche 23. Ses deux porteurs de classement sont partis : Nyanga
   portait un FAIT, qui se déplace maintenant dans le groupe à part ; les 18
   voies non classées portaient une CATÉGORIE, qui n'a jamais été une réserve.
   Il ne reste que `.entree.sous-reserve` (ligne 226), pour un DEGRÉ. Une règle
   qu'aucun écran ne rend est une promesse que rien ne tient : si un classement
   a un jour une ligne dont la valeur est estimée, il redéclarera ce qu'il lui
   faut, et le nom l'attend dans js/v2-panneau-commun.js. */

/* L'ordinal d'affichage d'un classement long. Discret : il sert à retrouver une
   ligne, pas à la hiérarchiser — la barre et le nombre le font déjà. */
.prov .rang {
    display: inline-block; min-width: 18px; margin-right: 3px;
    color: var(--encre-pale); font-size: 10.5px;
    font-variant-numeric: tabular-nums;
}
/* LE GROUPE À PART — ce qui ne peut pas être mesuré, et pourquoi.
   Voir js/v2-panneau-commun.js pour la raison ; ici, la forme.

   ELLE EST CELLE DU CLASSEMENT PRIVÉE DE SON ÉCHELLE : même grille, même
   rangée basse. Là où une ligne classée porte une barre, celle-ci porte une
   phrase. C'est ce qui se voit sans lire — on suit une colonne de barres, puis
   il n'y en a plus — et c'est une différence de STRUCTURE, donc elle survit aux
   niveaux de gris de la phase 6.

   Le filet du haut sépare, il n'encadre pas : un cadre ferait du groupe un
   second tableau, et un second tableau se lit comme une autre liste au lieu
   d'une suite de celle-ci. Mesuré à 900 px, où le risque est le plus grand. */
/* LE MÊME RETRAIT QUE TOUS LES AUTRES COMPOSANTS DU VOLET, ET IL MANQUAIT.
   Mesuré sur les quatre dossiers : `dossier-tete`, `chiffre`, `legende`,
   `classement` et `methode` posent leur texte à 16 px du bord ; `composition`
   le posait à 0 et `groupe-a-part` à −3. *Deux composants communs collés au
   bord, sur tous les écrans qui les emploient* — et c'est le plus ancien qui
   avait raison, pas le plus récent.

   ET LE RETRAIT ABSORBE LA MARGE NÉGATIVE DE `.gap-ligne`. Elle reste : c'est
   elle qui fait déborder le fond de la ligne liée hors du texte, ce qui la
   fait lire comme désignée. Sans retrait à absorber, ce débordement sortait du
   volet — dont `overflow-y: auto` rend l'axe horizontal `auto` par la règle
   CSS — et le volet défilait de 3 px sur un téléphone. *La marge n'était pas
   le défaut ; l'absence de place pour elle l'était.*

   Le filet du haut, lui, garde toute la largeur : il sépare deux listes, et
   une séparation en retrait se lirait comme un encadré. */
.groupe-a-part {
    margin-top: 12px; padding: 9px 16px 0;
    border-top: 1px solid var(--trait-pale);
}
.gap-titre {
    margin: 0 0 7px; font-size: 11px; font-weight: 600;
    color: var(--encre-douce); letter-spacing: .01em;
}
.gap-ligne {
    display: grid; grid-template-columns: 1fr auto; gap: 2px 9px;
    align-items: baseline; margin-bottom: 7px;
    border-radius: 2px; padding: 1px 3px; margin-left: -3px; margin-right: -3px;
}
.gap-quoi { font-size: 12px; color: var(--encre); }
.gap-chiffre {
    font-size: 11.5px; text-align: right; font-variant-numeric: tabular-nums;
    color: var(--encre-douce); white-space: nowrap;
}
/* La rangée que la barre occupe dans un classement. C'est la place que la
   ligne avait déjà : le groupe ne coûte pas de hauteur en plus par ligne. */
.gap-motif {
    grid-column: 1 / -1; font-size: 10.5px; color: var(--encre-douce);
    line-height: 1.45; margin-top: 1px;
}
/* Le pont marque une ligne du groupe comme il marque une ligne classée : une
   province déplacée désigne toujours un lieu sur la carte. */
.gap-ligne.liee { box-shadow: inset 2px 0 0 var(--etat); }
.gap-ligne:focus { outline: 2px solid var(--encre); outline-offset: 1px; }
.gap-ligne:focus:not(:focus-visible) { outline: none; }
/* LA BORNE. Sortir du classement n'est pas sortir du total, et sans cette
   phrase un lecteur conclut que ces lignes ont été retirées du pays. */
.gap-borne {
    margin: 8px 0 0; font-size: 10.5px; line-height: 1.5; color: var(--encre-douce);
}

/* LA LÉGENDE A SES PROPRES NOMS, préfixés `leg-`, et aucun n'est déclaré
   ailleurs dans cette feuille. La première version réemployait `.puce`, qui
   existe depuis la liste des couches (ligne 121) et vaut 10 × 10 px : chaque
   clé de légende se retrouvait enfermée dans une boîte de 10 px dont son
   libellé débordait, et les deux libellés s'imprimaient l'un sur l'autre.
   `.legende .puce` redéclarait cinq propriétés et pas la largeur — le contrat
   était tenu par l'habitude.

   Une surcharge aurait corrigé ce cas ; un nom propre empêche le suivant.
   C'est l'arbitrage pris pour `[hidden]` à la tâche 09, dans le même sens.
   test_v2_dossier.js vérifie qu'aucun de ces noms n'est déclaré deux fois. */
.legende { padding: 12px 16px; border-bottom: 1px solid var(--trait-pale); }
.legende h2 { padding: 0 0 3px; }
.leg-quoi { font-size: 10px; color: var(--encre-pale); margin-bottom: 7px; }
/* Les segments se partagent la largeur à proportion de ce qu'ils couvrent :
   c'est `flex-grow` qui le fait, avec `flex-basis: 0` pour que la proportion
   ne dépende pas du contenu (il n'y en a pas). */
.leg-axe { display: flex; height: 9px; border-radius: 2px; overflow: hidden; }
.leg-bande { flex-basis: 0; min-width: 2px; }
.leg-bornes {
    display: flex; justify-content: space-between; margin-top: 3px;
    font-size: 9.5px; color: var(--encre-pale); font-variant-numeric: tabular-nums;
}
.leg-hors { display: flex; gap: 14px; margin-top: 8px; flex-wrap: wrap; }
.leg-cle {
    display: flex; align-items: center; gap: 5px; min-width: 0;
    font-size: 10.5px; color: var(--encre-douce); line-height: 1.3;
}
.leg-cle i { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.leg-note { margin: 9px 0 0; font-size: 10.5px; color: var(--encre-pale); line-height: 1.45; }

/* La note des deux populations : plus discrète qu'un avertissement, parce que
   ce n'est pas une mise en garde mais une différence de périmètre entre deux
   analyses qui ont chacune raison. */
.note-population {
    margin: 6px 16px 10px; font-size: 10.5px; color: var(--encre-pale);
    line-height: 1.5;
}
.note-population b { color: var(--encre-douce); font-weight: 600; }

.avertissement {
    margin: 10px 16px; padding: 9px 11px;
    border-left: 2px solid var(--encre-pale); background: var(--fond);
    font-size: 11px; color: var(--encre-douce); line-height: 1.5;
}
/* Les réserves en liste (Fragilité, étape 2 de la charte) : une clause par
   ligne, telle que l'analyse l'émet ; celles qui dépassent se déplient. */
.reserves-tete { margin: 0 0 6px; }
.reserves-liste { margin: 0; padding-left: 16px; }
.reserves-liste li { margin-bottom: 6px; }
.reserves-plus {
    font: inherit; color: var(--encre); background: none; border: 0; padding: 0;
    text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}

.methode {
    padding: 12px 16px; font-size: 10.5px; color: var(--encre-pale);
    line-height: 1.6; border-top: 1px solid var(--trait-pale); margin-top: auto;
}
.methode b { color: var(--encre-douce); font-weight: 500; }
.methode .gardes { margin: 7px 0 0; padding-left: 14px; }
.methode .gardes li { margin-bottom: 3px; }
.prov .combien { color: var(--encre-pale); font-size: 10.5px; }

/* ─── Le dossier « Signaux » ───────────────────────────────────────────── */

/* LE BILAN DES RÈGLES, ET POURQUOI IL EST TOUJOURS LÀ.
   Un bandeau qui n'apparaît qu'en cas de panne apprend à ne pas être cherché,
   et son absence redevient une bonne nouvelle par défaut — le défaut même
   qu'il corrige. Il parle donc aussi quand tout va bien, et c'est alors une
   ligne grise ; `.alarme` est la seule forme qui se voit. */
.bilan-regles {
    margin: 10px 16px; padding: 9px 11px;
    border-left: 2px solid var(--trait); background: var(--fond);
    font-size: 11px; color: var(--encre-pale); line-height: 1.5;
}
.bilan-regles.alarme { border-left-color: #d03b3b; color: var(--encre-douce); }
.bilan-titre { margin: 0; font-size: 11.5px; font-weight: 600; color: var(--encre); }
.bilan-regles:not(.alarme) .bilan-titre { font-weight: 400; color: var(--encre-pale); }
/* `.bilan-liste` est partie à la tâche 23 : les règles non évaluées ne sont
   plus une liste à puces dans un bandeau, mais des lignes du groupe à part —
   voir `.groupe-a-part`. Ce qui reste ici habille les deux cas qui ne sont PAS
   un groupe à part : « toutes les règles ont pu être évaluées », et le cas où
   le fichier ne dit pas lesquelles — qui n'est pas une absence de mesure mais
   une panne de lecture, et n'a donc pas de ligne à montrer. */
.bilan-note { margin: 7px 0 0; font-size: 10.5px; line-height: 1.5; }

.alertes { padding: 14px 16px; border-bottom: 1px solid var(--trait-pale); }
.alertes h2 { padding: 0 0 3px; }
.alertes .colonne { font-size: 10px; color: var(--encre-pale); margin-bottom: 11px; }

/* Une alerte est une FICHE, pas une ligne de classement : elle porte une
   phrase entière, et les deux autres dossiers n'ont rien de cette forme.
   Le filet à gauche marque celle dont la preuve est à l'écran — même signe que
   la couche allumée dans la pile et que la ligne liée par le pont. */
.alerte {
    padding: 10px 0 12px; border-top: 1px solid var(--trait-pale);
}
.alerte:first-of-type { border-top: 0; }
.alerte.ouverte {
    box-shadow: inset 2px 0 0 var(--etat);
    padding-left: 9px; padding-right: 9px; margin-left: -9px; margin-right: -9px;
    border-radius: 2px;
}
.alerte-tete { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
/* PASTILLE ET MOT, TOUJOURS. Deux des quatre teintes d'état passent sous le
   seuil de contraste : une pastille seule ne dit rien à qui ne les distingue
   pas, et rien du tout en impression noir et blanc. */
.alerte-tete .gravite {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 10px; font-weight: 600; letter-spacing: 0.04em;
    text-transform: uppercase; color: var(--encre-douce);
}
.alerte-tete .gravite i { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.alerte-tete .regle { font-size: 10.5px; color: var(--encre-pale); }
.alerte-tete .age {
    margin-left: auto; font-size: 10px; color: var(--encre-pale);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.alerte h3 {
    margin: 6px 0 0; font-size: 12.5px; font-weight: 600; line-height: 1.35;
}
.alerte .detail { margin: 4px 0 0; font-size: 11.5px; color: var(--encre-douce); line-height: 1.5; }
/* La durée est le fait que cet écran existe pour porter — depuis quand une
   alerte tient. Discrète mais jamais absente. */
.alerte .duree { margin: 5px 0 0; font-size: 10.5px; color: var(--encre-pale); line-height: 1.45; }
.alerte .duree b { color: var(--encre-douce); font-weight: 500; }

.alerte .actes { display: flex; align-items: baseline; gap: 9px; margin-top: 8px; flex-wrap: wrap; }
/* L'ACTION PRIMAIRE EST LE BOUTON DE LA CHARTE (étape 1, 02/10) : vert profond,
   encre blanc chaud, rayon de 3 px — celui du site Hodologic. Le contour reste
   aux actions secondaires. */
.alerte .preuve {
    height: var(--controle); padding: 0 11px; border: 0; border-radius: var(--r-grand);
    background: var(--etat); color: var(--sur-etat);
    font: inherit; font-size: 11px; font-weight: 500; cursor: pointer;
}
.alerte .preuve:hover { background: var(--encre-douce); }
.alerte .preuve:disabled { background: var(--trait); color: var(--encre-pale); cursor: default; }
.alerte.ouverte .preuve { background: transparent; color: var(--encre-douce); box-shadow: inset 0 0 0 1px var(--trait); }
.alerte .montre { font-size: 10.5px; color: var(--encre-pale); line-height: 1.4; }
/* Une preuve absente ou incomplète se DIT. Une carte qui ne montre pas tout ce
   que l'alerte affirme, présentée comme la preuve, vaut moins que rien. */
.alerte .sans-preuve {
    margin: 7px 0 0; padding: 7px 9px; background: var(--papier);
    border-left: 2px solid var(--trait); border-radius: var(--r-petit);
    font-size: 10.5px; color: var(--encre-douce); line-height: 1.5;
}

/* Zéro alerte n'est pas une bonne nouvelle, et ne se met donc pas en page
   comme une liste vide ordinaire — texte à gauche, pas de gris d'absence. */
.zero {
    margin: 0; padding: 10px 11px; background: var(--fond);
    border-left: 2px solid var(--trait);
    font-size: 11.5px; color: var(--encre-douce); line-height: 1.5;
}

/* LA GRAVITÉ QUI NE DISTINGUE PLUS RIEN SE TAIT. Au-dessus du seuil de
   concentration, la gravité majoritaire passe en gris de mention : elle reste
   écrite — pastille ET mot, la règle ne bouge pas — mais elle cesse de crier.
   Une marque doit être forte là où elle est rare ; identique sur vingt fiches
   de vingt-huit, le rouge donnait son poids maximal à ce qui ne sépare rien. */
.alerte-tete .gravite.muette { color: var(--encre-pale); font-weight: 500; }
.alerte-tete .gravite.muette i { background: var(--encre-pale); }


/* La même mesure, dans la fiche — pour qui regarde le panneau, imprime, ou ne
   distingue pas un trait fin d'un autre. */
.alerte .distance-preuve {
    margin: 7px 0 0; font-size: 10.5px; color: var(--encre-douce); line-height: 1.5;
}
.alerte .distance-preuve b {
    font-family: ui-monospace, monospace; font-weight: 500;
}

/* ─── Le dossier « Chantiers » ─────────────────────────────────────────── */

.chantiers { padding: 14px 16px; border-bottom: 1px solid var(--trait-pale); }
.chantiers h2 { padding: 0 0 3px; }
.chantiers .colonne { font-size: 10px; color: var(--encre-pale); margin-bottom: 11px; }

/* SEPT LIGNES NE DOIVENT PAS AVOIR L'AIR D'UN DOSSIER CASSÉ À CINQUANTE. Chaque
   chantier est une fiche à part entière, avec de l'air : sept fiches remplissent
   une colonne, sept lignes de tableau l'auraient laissée vide aux trois quarts.
   Le vide se voit, il ne se mesure pas. */
.chantier {
    padding: 12px 0 14px; border-top: 1px solid var(--trait-pale);
}
.chantier:first-of-type { border-top: 0; }
.chantier:focus { outline: 2px solid var(--encre); outline-offset: 2px; }
.chantier:focus:not(:focus-visible) { outline: none; }
.chantier.liee { box-shadow: inset 2px 0 0 var(--etat);
                 border-radius: 2px; padding-left: 9px; margin-left: -9px; }

.chantier-tete { display: flex; align-items: baseline; gap: 9px; justify-content: space-between; }
/* Le nom reste tel quel — c'est un nom propre. Il est posé en TITRE et non dans
   une phrase française : un titre n'est pas une phrase, et la question de la
   marque typographique ne se pose donc pas. */
.chantier-tete h3 { margin: 0; font-size: 12.5px; font-weight: 600; line-height: 1.3; }
.chantier-tete .chantier-statut {
    font-size: 10px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--encre-douce); white-space: nowrap;
}

/* LES DEUX BLOCS, À LA MÊME FORCE. La base dit X ; une personne dit Y, le tant.
   Ni l'un n'écrase l'autre : même taille de texte, même retrait, deux titres de
   même rang. Reléguer les observations en plus petit ferait lire l'ajout-seul
   comme un formulaire qui avale. */
.chantier h4 {
    margin: 10px 0 5px; font-size: 10px; font-weight: 500; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--encre-pale);
}
.declare-rang { display: flex; align-items: baseline; gap: 8px; margin-bottom: 3px; }
.declare-nom { font-size: 11.5px; color: var(--encre-douce); }
.declare-val {
    margin-left: auto; font-size: 11.5px; font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* Le repère qui relie les deux blocs sans les mélanger : la valeur officielle
   dit qu'elle est commentée, l'observation reste à sa place. Sans lui, un
   lecteur devrait comparer les deux listes de tête. */
.declare-observe {
    font-size: 9.5px; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--encre-pale); border: 1px solid var(--trait); border-radius: var(--r-petit);
    padding: 0 4px; white-space: nowrap;
}

.observation {
    padding: 6px 0 7px; border-top: 1px dotted var(--trait-pale);
}
.obs-tete { display: flex; align-items: baseline; gap: 7px; }
.obs-champ { font-size: 10.5px; font-weight: 600; color: var(--encre-douce); }
/* Les trois états d'une note sont des ÉTATS, pas des alarmes : filet gris pour
   les trois. Une note en attente n'a rien d'anormal — c'est ce que fait une
   note qui voyage. */
.obs-etat {
    font-size: 9.5px; color: var(--encre-pale); border-left: 2px solid var(--trait);
    padding-left: 5px;
}
.obs-quand {
    margin-left: auto; font-size: 10px; color: var(--encre-pale); white-space: nowrap;
}
.obs-valeur { font-size: 11.5px; margin-top: 2px; }
.obs-note { font-size: 11.5px; color: var(--encre-douce); line-height: 1.5; margin-top: 2px; }
.obs-vide { margin: 0; font-size: 11px; color: var(--encre-pale); line-height: 1.5; }

/* LE DÉSACCORD EST L'INFORMATION. Il se signale, il ne s'arbitre pas : rien ne
   départage deux observations qu'une date, et une date ne dit pas qui a raison.
   Filet gris, pas rouge — deux personnes qui ne voient pas la même chose sur un
   chantier, ce n'est pas une panne. */
.desaccord {
    margin: 6px 0 0; padding: 7px 9px; background: var(--fond);
    border-left: 2px solid var(--trait); border-radius: var(--r-petit);
    font-size: 10.5px; color: var(--encre-douce); line-height: 1.5;
}

/* LE DÉPÔT D'UNE OBSERVATION.

   Il est sous le fil du chantier, pas sous la fiche : une note doit atterrir à
   côté de la valeur qu'elle commente, sans défiler. Reléguée en bas de panneau,
   l'ajout-seul se lirait comme un formulaire qui avale. */
.depot { margin-top: 9px; }
/* L'action primaire est noire — le vert du drapeau est l'identité, pas un
   bouton. Celle-ci est secondaire : elle ouvre, elle n'envoie rien. */
.depot-ouvrir, .depot-annuler {
    height: var(--controle); padding: 0 10px; border-radius: var(--r-grand);
    border: 0; box-shadow: inset 0 0 0 1px var(--trait);
    background: transparent; color: var(--encre-douce);
    font: inherit; font-size: 11px; cursor: pointer;
}
.depot-ouvrir:hover, .depot-annuler:hover { background: var(--fond); }
.depot-champ, .depot-valeur, .depot-note {
    display: block; width: 100%; margin-bottom: 6px; padding: 5px 7px;
    border: 1px solid var(--trait); border-radius: var(--r-grand);
    background: var(--papier); color: var(--encre);
    font: inherit; font-size: 11.5px;
}
.depot-note { min-height: 56px; resize: vertical; }
.depot-actes { display: flex; gap: 7px; }
.depot-envoyer {
    height: var(--controle); padding: 0 12px; border: 0; border-radius: var(--r-grand);
    background: var(--etat); color: var(--sur-etat);
    font: inherit; font-size: 11px; font-weight: 500; cursor: pointer;
}
.depot-envoyer:hover { background: var(--encre-douce); }
/* UN REFUS SE DIT, IL NE S'ALARME PAS. Que le stockage soit bloqué ou qu'un
   champ manque, ce n'est pas une panne : c'est une chose que l'écran ne peut
   pas faire, et il vaut mieux la dire que la promettre. Filet gris. */
.depot-refus {
    margin: 7px 0 0; padding: 7px 9px; background: var(--fond);
    border-left: 2px solid var(--trait); border-radius: var(--r-petit);
    font-size: 10.5px; color: var(--encre-douce); line-height: 1.5;
}

/* Repartir est SÛR : deux envois du même identifiant font une note, pas deux.
   Le bouton est donc offert sans avertissement. Une note refusée, elle, porte
   sa raison et pas de bouton — offrir un bouton qui ne peut pas réussir est une
   promesse de plus. */
.obs-repartir {
    margin-top: 5px; height: 22px; padding: 0 8px; border: 0;
    border-radius: var(--r-grand); box-shadow: inset 0 0 0 1px var(--trait);
    background: transparent; color: var(--encre-douce);
    font: inherit; font-size: 10px; cursor: pointer;
}
.obs-repartir:hover { background: var(--fond); }
.obs-refus { margin: 5px 0 0; font-size: 10.5px; color: var(--encre-douce); line-height: 1.5; }

/* LE GROUPE À PART, une troisième fois. Ces lignes ne sont pas des observations
   de moindre qualité : elles sont d'une AUTRE NATURE, et les mêler au fil ferait
   croire à un chantier qui existe encore. Même taille de texte que le fil — un
   groupe à part n'est pas un groupe diminué. */
.orphelines { padding: 14px 16px; border-bottom: 1px solid var(--trait-pale); }
.orphelines h2 { padding: 0 0 3px; }
.orphelines .colonne { font-size: 10px; color: var(--encre-pale); margin-bottom: 11px; }
.orph-chantier {
    margin-top: 3px; font-size: 10.5px; color: var(--encre-pale);
    font-family: ui-monospace, monospace;
}

/* CE QUI LÈVE UN REFUS, à côté du refus. Ne pas offrir le renvoi n'est pas ne
   rien offrir : une impasse sans issue affichée se lit comme une perte. */
.obs-actes { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 5px; }
.obs-issue { font-size: 10.5px; color: var(--encre-douce); line-height: 1.4; }

/* UNE COUCHE QUI N'A PAS PU SE CHARGER LE DIT, à côté de son œil. Sans cette
   ligne, l'œil la montre éteinte et rien ne distingue « je ne l'ai pas
   allumée » de « elle n'a pas pu l'être ». Filet gris et pas rouge : ce n'est
   pas une alarme, c'est un état — et c'est souvent l'environnement, pas la
   donnée, qui manque. */
.entree-echec {
    font-size: 10px; color: var(--encre-douce); line-height: 1.3;
    border-left: 2px solid var(--trait); padding-left: 5px; margin-top: 2px;
}

/* LA RÉSERVE D'UNE COUCHE ABSENTE — une seule, et elle borne sa portée.

   Il y en avait deux, collées, même gris et même filet : elles se lisaient
   comme un seul pavé et la seconde n'était plus lue. Elles ont la même cause
   unique, donc une seule phrase les porte.

   Et elle dit ce qui TIENT autant que ce qui ne tient pas. Sans cette moitié,
   un lecteur prudent jetait tout l'écran après trois annonces de panne — alors
   que le classement, lui, vient de l'artefact et reste juste. *Une réserve qui
   ne borne pas sa portée contamine tout ce qui la suit.* */
.reserve-couche {
    margin: 8px 16px 0; padding: 7px 9px; background: var(--fond);
    border-left: 2px solid var(--trait); border-radius: var(--r-petit);
    font-size: 10.5px; color: var(--encre-douce); line-height: 1.5;
}
.reserve-couche b { color: var(--encre); font-weight: 500; }

/* L'ADRESSE AU SECOND RANG. Le fait en français d'abord — « la donnée n'a pas
   pu être chargée » — puis l'adresse, pour qui doit rapporter le problème. Ce
   que le lecteur doit comprendre avant ce que nous devons diagnostiquer : un
   ministère qui lit une URL brute voit une fuite technique, pas une panne. */
.entree-echec b { font-weight: 500; color: var(--encre-douce); display: block; }
.entree-adresse {
    display: block; margin-top: 1px; font-size: 9px; color: var(--encre-pale);
    font-family: ui-monospace, monospace;
    overflow-wrap: anywhere;
}



/* ── L'ATELIER ───────────────────────────────────────────────────────────────

   LA CONDITION DE LIVRAISON EST UNE RÈGLE DE MISE EN PAGE AVANT D'ÊTRE UNE
   RÈGLE DE TEXTE : « le gain et le ratio local arrivent ENSEMBLE à l'œil, ou le
   produit ne sort pas ». Pas une note de bas de page, pas un panneau
   dépliable — et à 900 px, pas sous le pli.

   Ce qui le tient ici : le ratio est COLLÉ au gain (aucune marge entre eux,
   c'est le même bloc visuel), il ne porte aucune règle de média, et il n'est
   pas plus petit que le corps du texte. Les trois se vérifient dans
   test_v2_etroit.js — *une intention de mise en page qu'aucune règle ne porte
   est une intention.*

   ET IL SE DISTINGUE SANS LA COULEUR, en prévision des fiches imprimables : un
   filet à gauche et un retrait, pas une teinte. */
.atelier-ouverture h2 { margin: 0 0 6px; font-size: 14px; }
.atelier-quoi { margin: 0 0 10px; font-size: 12px; line-height: 1.5; color: var(--encre-douce); }
/* ── L'OUVERTURE DE L'ATELIER ────────────────────────────────────────────────

   LE REMBOURRAGE DE 16 px N'EST PAS UN GOÛT, C'EST LA CONVENTION DU VOLET,
   MESURÉE. Dans le dossier de l'accès aux soins, `dossier-tete`, `chiffre`,
   `legende`, `classement` et `methode` portent toutes 16 px ; le texte de
   l'Atelier commençait à 0. *Un texte collé au bord se lit comme un défaut
   d'affichage avant d'être lu comme une phrase.*

   CE QUE LA MESURE A AUSSI TROUVÉ, ET QUI N'EST PAS CORRIGÉ ICI : `composition`
   et `groupe-a-part` sont à 0 dans LES CINQ panneaux. Ce sont des composants du
   commun ; les rembourrer change quatre écrans que cette tâche ne demandait pas
   et que cette branche n'a pas vérifiés. C'est signalé, pas fait. */
.atelier-ouverture { padding: 14px 16px 16px; }
.atelier-chapeau {
    margin: 0 0 5px; font-size: 10.5px; font-weight: 600; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--encre-pale);
}
.atelier-exemple-gain {
    margin: 0 0 1px; font-size: 27px; font-weight: 600; line-height: 1.12;
    letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.atelier-exemple-unite { font-size: 14px; font-weight: 400; color: var(--encre-douce); }
.atelier-exemple-quoi { margin: 0; font-size: 12.5px; color: var(--encre-douce); }
/* LE RATIO EST COLLÉ AU GAIN — zéro marge entre les deux, et c'est une
   condition de livraison, pas une préférence : le gain et le ratio arrivent
   ensemble à l'œil, ou le produit ne sort pas. Elle vaut pour l'exemple comme
   pour la réponse. */
.atelier-exemple-ratio {
    margin: 0; padding-left: 9px; border-left: 2px solid var(--trait);
    font-size: 12.5px; line-height: 1.5; color: var(--encre);
}
.atelier-exemple-ou { margin: 9px 0 0; font-size: 12.5px; color: var(--encre); }
.atelier-exemple-zone { margin: 4px 0 0; font-size: 11.5px; color: var(--encre-douce); }
/* UNE réserve montée, et le lien vers les dix. Le fond de réserve est celui du
   reste de l'application — une teinte de plus dirait qu'il y a deux sortes de
   réserves. */
.atelier-exemple-reserve {
    margin: 12px 0 0; padding: 9px 11px; font-size: 11.5px; line-height: 1.5;
    color: var(--encre-douce); background: var(--reserve-fond);
    border-left: 2px solid var(--reserve);
    border-radius: 0 var(--r-petit) var(--r-petit) 0;
}
.atelier-exemple-reserve a { color: var(--encre); white-space: nowrap; }
.atelier-action {
    display: block; width: 100%; margin: 13px 0 0; padding: 8px 10px;
    font: inherit; font-size: 12.5px; font-weight: 600; text-align: center;
    color: var(--sur-etat); background: var(--etat); border: 1px solid var(--etat);
    border-radius: var(--r-petit); cursor: pointer;
}
.atelier-action:focus-visible { outline: 2px solid var(--encre); outline-offset: 2px; }
/* LE GESTE QUI SORT LA FEUILLE. Discret et large, comme celui des fiches :
   c'est le DERNIER geste, pas le premier. Un bouton plein ferait de l'envoi le
   sujet de l'écran, alors que le sujet est la réponse qu'on relit avant. */
.atelier-vers-feuille {
    display: block; width: calc(100% - 32px); margin: 12px 16px 0; padding: 7px 10px;
    font: inherit; font-size: 12px; text-align: center;
    color: var(--encre); background: transparent;
    border: 1px solid var(--trait); border-radius: var(--r-petit); cursor: pointer;
}
.atelier-vers-feuille:focus-visible { outline: 2px solid var(--encre); outline-offset: 2px; }
/* LA FEUILLE À L'ÉCRAN EST UN APERÇU, et elle garde la largeur du volet — même
   règle que les fiches, et pour la même raison : c'est volontairement PROCHE du
   rendu papier sans prétendre l'être. */
.feuille-hote { padding: 10px 16px 0; }

/* LE RENVOI VERS LE RAIL — une ligne, pas un bloc. Les quatre dossiers sont
   sortis du panneau ; il reste de quoi les retrouver. */
.atelier-renvoi-rail {
    margin: 0; padding: 0 16px 14px; font-size: 11px; color: var(--encre-pale);
}

.atelier-reponse h2 { margin: 0 0 8px; font-size: 14px; line-height: 1.3; }
/* L'énoncé porte sa propre imprécision — « dans cette zone d'environ 8 km² » —
   parce que la granularité n'est pas une réserve SUR le chiffre : c'est son
   unité. Une seconde mention au même rang que le ratio n'en ferait lire
   aucune. */
.atelier-gain { margin: 0; font-size: 13px; line-height: 1.55; color: var(--encre); }
.atelier-motif { margin: 0 0 8px; font-size: 12px; line-height: 1.55; color: var(--encre-douce); }
.atelier-motif-compte { margin: 0; font-size: 10.5px; color: var(--encre-pale); }
/* COLLÉ AU GAIN. `margin-top: 8px` et rien de plus : au-delà, l'œil les lit
   comme deux choses, et la condition de livraison demande une seule lecture. */
/* LE LOT DE CENTRES. Les gains ne s'additionnent pas — chaque ligne porte sa
   condition, et aucun total n'est affiché. La mise en forme suit la règle : la
   condition est dans le même souffle que le nombre, en retrait et non sur une
   ligne à elle, parce qu'une condition qu'on peut sauter des yeux est une
   condition qu'on saute. */
.atelier-lot { margin: 12px 0; }
.atelier-etapes { margin: 6px 0 0; padding-left: 20px; }
.atelier-etape { margin-bottom: 4px; line-height: 1.35; }
.atelier-condition { color: var(--encre-douce); }
/* L'ABSENCE N'EST PAS UNE VALEUR BASSE : elle ne prend ni le gras du nombre ni
   la place d'un chiffre. Elle se lit comme une phrase, parce que c'en est une. */
.atelier-etape-absente { color: var(--encre-douce); font-style: italic; }
/* LA NAPPE EST SOUS SON ÉTAPE, EN RETRAIT : elle qualifie ce gain-là et pas le
   suivant. Et l'absence de nappe n'est pas un vide typographique — elle se lit
   comme une phrase, parce que c'en est une : une nappe vide dirait « ce centre
   n'a pas d'alternative », l'inverse du fait. */
.atelier-nappe { margin-top: 2px; font-size: 12px; color: var(--encre-douce); }
.atelier-nappe-absente { font-style: italic; }
.atelier-proximite { margin: 8px 0 0; }
/* Et la phrase qui interdit l'addition n'est pas une note de bas de bloc : elle
   a le même corps que le reste. Une réserve en petit se lit au second regard,
   et celle-ci doit arriver avant que le lecteur ait fait la somme. */
.atelier-sans-total { margin: 6px 0 0; }

.atelier-ratio {
    margin-top: 8px; padding-left: 9px;
    border-left: 2px solid var(--encre-pale);
}
.atelier-ratio-titre { margin: 0; font-size: 12px; line-height: 1.5; color: var(--encre); }
.atelier-repere {
    margin: 5px 0 0; font-size: 10.5px; line-height: 1.45; color: var(--encre-douce);
}
.atelier-plateau {
    margin: 10px 0 0; font-size: 10.5px; line-height: 1.5; color: var(--encre-douce);
}
.atelier-limites {
    margin-top: 14px; padding: 10px 16px 0; border-top: 1px solid var(--trait-pale);
}
/* LES DIX, REPLIÉES SUR L'OUVERTURE ET DÉPLIÉES SUR LA RÉPONSE. Le chevron du
   navigateur suffit à dire que ça s'ouvre ; un bouton dessiné par-dessus
   ajouterait un état à tenir. */
.atelier-limites-tete {
    font-size: 11px; font-weight: 600; color: var(--encre-douce); cursor: pointer;
    list-style-position: outside; padding: 2px 0;
}
.atelier-limites-tete:focus-visible { outline: 2px solid var(--encre); outline-offset: 2px; }
.atelier-limites-pli[open] .atelier-limites-tete { margin-bottom: 7px; }
.atelier-limites h3 {
    margin: 0 0 7px; font-size: 11px; font-weight: 600; color: var(--encre-douce);
}
.atelier-limite {
    margin: 0 0 6px; font-size: 10.5px; line-height: 1.5; color: var(--encre-pale);
}

/* ── LE CHOISISSEUR DE FOND ──────────────────────────────────────────────────

   Il vit dans le conteneur de la carte, comme le zoom. Un fond n'est pas une
   couche : on ne l'allume pas, il n'a ni poids ni provenance, il n'a donc rien
   à faire dans la pile. Il est le papier, pas ce qu'on pose dessus.

   CHAQUE BOUTON DIT À QUOI LE FOND SERT, sous son nom et en plus petit. Ce
   n'est pas un sous-titre décoratif : « Satellite » est une catégorie, « voir
   le sol tel qu'il est » est un fait, et c'est le fait qui permet de choisir. */
.fonds {
    /* AU-DESSUS DE CE QUE LEAFLET EMPILE. Ses contrôles montent à 1000 ; un
       choisisseur à 500 s'ouvrirait derrière eux. Et les deux surfaces neuves
       ne sont PAS au même niveau : la phrase du zoom remonté passe devant le
       choisisseur qu'elle commente — deux surfaces à égalité laisseraient le
       navigateur trancher par l'ordre du document, qui est ce qui change en
       premier. */
    position: absolute; left: 10px; bottom: 10px; z-index: 1020;
    display: flex; gap: 4px; flex-wrap: wrap; max-width: calc(100% - 20px);
    /* LA BOÎTE EST TRANSPARENTE, ELLE NE PREND PAS LE DOIGT : à 390, ses fonds
       passent sur trois lignes, elle prend toute la largeur et couvrait le zoom
       de Leaflet — visible, mais plus touchable (map-a-390, test_ecran_390.py).
       Seuls les fonds eux-mêmes se touchent. */
    pointer-events: none;
}
.fonds > * { pointer-events: auto; }
.fond {
    display: grid; gap: 1px; text-align: left; cursor: pointer;
    padding: 5px 8px; border: 1px solid var(--trait-pale); border-radius: 2px;
    background: var(--papier); color: var(--encre-douce);
    font: inherit; line-height: 1.2;
}
.fond:hover { border-color: var(--encre-pale); }
.fond.choisi { border-color: var(--encre); color: var(--encre); }
.fond-nom { font-size: 11px; font-weight: 600; }
/* À QUOI IL SERT, toujours rendu — jamais une infobulle. Un fait qu'il faut
   survoler pour avoir est un fait que le lecteur n'a pas au moment de choisir.
   C'est la règle de « à établir » n'est pas une origine, sur un autre objet. */
.fond-sert { font-size: 9.5px; color: var(--encre-pale); }
.fond.choisi .fond-sert { color: var(--encre-douce); }
/* LA VUE A BOUGÉ ET ELLE LE DIT. Une vue qui bouge sans le dire est
   indiscernable d'une vue qu'on a mal lue. */
.fonds-remonte {
    position: absolute; left: 10px; bottom: 58px; z-index: 1030; margin: 0;
    max-width: calc(100% - 20px); padding: 5px 8px;
    background: var(--papier); border-left: 2px solid var(--encre);
    font-size: 10.5px; line-height: 1.4; color: var(--encre);
}

/* À L'IMPRESSION, le choisisseur ne sort pas : on ne choisit pas un fond sur
   du papier. La règle vit avec les autres, plus bas. */

/* ═══ LA NOTE DE CHANGEMENT ═══════════════════════════════════════════════
   Pourquoi les chiffres de cette vue ne sont plus ceux d'hier.

   ELLE EST AU-DESSUS DU CHIFFRE, ET SON HÔTE NE RÉSERVE AUCUNE PLACE. Le
   conteneur est vide tant que le fichier n'est pas arrivé, et il le reste
   pour toujours si la note ne s'applique pas à cette vue. *Une place
   réservée pour une note qui ne viendra peut-être pas est un trou que le
   lecteur voit* — et un volet qui saute quand la note atterrit est pire
   qu'un volet sans note. */
.note-changement-hote:empty { display: none; }

.note-changement {
    border-left: 3px solid var(--reserve);
    background: var(--reserve-fond);
    padding: 12px 14px;
    margin: 0 0 16px;
    border-radius: 0 var(--r-grand) var(--r-grand) 0;
    font-size: 13px;
    line-height: 1.5;
}
.note-changement p { margin: 0 0 8px; }
.note-changement p:last-child { margin-bottom: 0; }

.note-changement-titre {
    font-weight: 600;
    color: var(--encre);
}

/* LA PHRASE EST PLUS GRANDE QUE LE RESTE, parce qu'elle doit être lue et que
   tout le reste n'existe que pour elle. C'est la seule hiérarchie de taille
   de ce bloc : en donner une seconde ferait deux phrases importantes, donc
   aucune. */
.note-changement-phrase {
    font-size: 14.5px;
    font-weight: 600;
    color: var(--encre);
}

/* LES TROIS CAUSES, SÉPARÉES ET SANS PUCE D'ALERTE. *« Nos données ont été
   mises à jour » laisse croire à une correction d'erreur* — les trois se
   lisent donc comme trois faits distincts, du même poids. */
/* LE RÉSUMÉ DES CAUSES EN UNE LIGNE — le volet a un budget, et trois causes
   nommées séparément le mangent. Elles le sont dans le détail, en bas. */
.note-changement-causes-court { color: var(--encre-douce); }

/* LE PLANCHER MONTE DANS LE VOLET, en une phrase. Le bloc qui l'explique reste
   en bas : *une phrase tient dans le budget, un bloc le mange.* */
.note-changement-plancher { color: var(--encre); }
.note-changement-lien {
    color: var(--etat);
    text-decoration: none;
    white-space: nowrap;
    font-weight: 600;
}
.note-changement-lien:hover { text-decoration: underline; }

/* LE DÉTAIL, EN BAS DU PANNEAU — là où sa hauteur ne dispute rien au chiffre.
   *Ce qui ne tient pas dans le budget du volet n'est pas supprimé : il est
   déplacé là où le budget n'existe pas.* */
.note-changement-detail-hote:empty { display: none; }
.note-changement-detail {
    border-top: 1px solid var(--trait-pale);
    padding-top: 14px;
    margin-top: 18px;
    font-size: 13px;
    color: var(--encre-douce);
}
.note-changement-detail h3 {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--encre-pale);
    margin: 0 0 10px;
}
.note-changement-detail p { margin: 0 0 8px; }
/* LA LIGNE QUI DÉCLARE L'EXCEPTION AU § 3. Le volet arrondit, ce tableau non —
   parce qu'un nombre arrondi ne se retrouve dans aucun champ. *Une exception
   tacite à une règle est une exception que le prochain lecteur prend pour un
   défaut, ou pire pour la règle.* */
/* LA TABLE DES VALEURS EXACTES — REPLIÉE, ET SANS ATTRIBUT `open`.
   Le repli est l'état par défaut de `<details>` : rien ici ne le force, et
   rien ne doit le défaire. *Un `details[open]` posé par la feuille de style
   n'existe pas ; un `display` qui l'ouvrirait serait un pli en trompe-l'œil,
   et un contrôle qui mesure la hauteur du contenu le trouverait vert.* */
.note-changement-source { margin: 10px 0 0; }
.note-changement-source > summary {
    cursor: pointer;
    font-size: 11.5px;
    color: var(--encre-pale);
    list-style: revert;
}
.note-changement-source > summary:hover { color: var(--encre-douce); }
/* LES LIGNES DU REPLI ONT LEUR PROPRE CLASSE. La règle disait
   `.note-changement-source .note-changement-avant-apres` : le bloc du repli
   restylait un composant qui ne lui appartient pas, et deux blocs se
   disputaient le même élément. *Qui édite le composant ne voyait pas qu'il
   changeait la taille d'un texte ailleurs.* Elles ne partagent plus que les
   chiffres tabulaires, qui sont une propriété du nombre, pas du bloc. */
.note-changement-brut {
    font-size: 11.5px;
    color: var(--encre-douce);
    font-variant-numeric: tabular-nums;
}

.note-changement-provenance {
    font-size: 11.5px;
    color: var(--encre-pale);
    font-style: italic;
}

.note-changement-causes {
    margin: 0 0 8px;
    padding-left: 18px;
    color: var(--encre-douce);
}
.note-changement-causes li { margin: 0 0 3px; }

/* LES NOMBRES VIENNENT APRÈS LA PHRASE — l'ordre est dans le module, pas ici.
   La feuille ne fait que ne pas le contredire : aucun `order`, aucun
   `flex-direction: column-reverse`. *Une mise en page qui réordonne ce que le
   DOM a ordonné met la raison d'être du bloc à la merci d'une ligne de CSS.* */
.note-changement-avant-apres {
    font-variant-numeric: tabular-nums;
    color: var(--encre);
}

.note-changement-direction {
    color: var(--encre-douce);
    font-style: italic;
}

/* LA CIRCULARITÉ EST DANS SON PROPRE BLOC, ET D'UNE AUTRE ENCRE. Les trois
   causes déplacent le nombre ; celle-ci ne le touche pas — elle dit comment
   il doit être lu. *La mettre dans la même liste en ferait une cause de
   plus, et un lecteur qui cherche « pourquoi le chiffre a bougé » la
   sauterait.* */
.note-changement-lecture {
    border-left: 3px solid var(--reserve);
    background: var(--reserve-fond);
    padding: 10px 12px;
    margin: 12px 0 0;
    border-radius: 0 var(--r-petit) var(--r-petit) 0;
    color: var(--encre-douce);
}
.note-changement-lecture-titre {
    font-weight: 600;
    color: var(--encre);
}
.note-changement-quand { font-style: italic; }

/* LA VENTILATION RÈGLE PAR RÈGLE — sans encadré : elle n'est pas une réserve,
   c'est la décomposition d'un total. *Un total qui ne dit pas d'où il vient se
   lit comme un résultat.* */
.note-changement-par-regle { margin: 12px 0 0; }
.note-changement-par-regle .note-changement-avant-apres {
    font-size: 11.5px;
    color: var(--encre-douce);
}

/* ELLE NE S'IMPRIME PAS, ET C'EST DÉLIBÉRÉ. Une feuille sortie aujourd'hui
   sera lue dans six mois, et « les chiffres ont changé le 17 septembre »
   y affirmera un lien qui n'existera plus — sans qu'aucune date servie ne
   puisse la retirer, puisque le papier ne relit rien. *Ce qui protège la
   note à l'écran — la comparaison des dates — n'existe pas sur le papier.*
   La feuille porte à la place, en pied, la date de la passe qui a produit
   ses chiffres. */

/* ══ LES FICHES IMPRIMABLES ══════════════════════════════════════════════════

   ÉCRITE DE ZÉRO. Le dépôt n'avait qu'un seul `@media print`, dans
   modelling.html : il masque la barre latérale et étale la carte en 100vh,
   derrière 94 lignes de cascade sur les `id` des cases à cocher et un titre en
   anglais. Il résout « imprimer la carte que je vois en ce moment ». Ce n'est
   pas une fiche : c'est une capture d'écran avec un titre calculé.

   AUCUNE RÈGLE ICI N'EST PROPRE À UN DOSSIER. C'est la condition de la tâche
   22 : les deux dossiers sortent leur fiche sans que la feuille sache lequel
   est lequel, et le troisième sortira la sienne sans qu'on y revienne.

   LA CONTRAINTE QUI LIE EST LA PLUS STRICTE DES DEUX USAGES. Un PDF ne perd
   rien à être lisible en gris ; un tirage perd tout à ne pas l'être. Donc tout
   est pensé pour le noir et blanc, et le PDF en hérite. */

/* À L'ÉCRAN, les fiches sont un aperçu : elles vivent dans le volet du dossier
   et gardent sa largeur. C'est volontairement PROCHE du rendu papier sans
   prétendre l'être — la tâche 22 dit de vérifier sur un aperçu avant
   impression, pas dans les outils de développement. */
.fiche {
    background: var(--papier); color: var(--encre);
    padding: 14px; margin-bottom: 14px;
    border: 1px solid var(--trait-pale); border-radius: 2px;
}
/* LE CHOIX DE LA FEUILLE QU'ON REGARDE. Il ne s'imprime pas : on ne choisit
   pas une feuille sur du papier, et le destinataire n'a pas à savoir laquelle
   était à l'écran quand on a lancé l'impression. */
.fiches-choix { margin-bottom: 12px; }
/* LA POIGNÉE DE LA PORTE. `Cmd+P` était le seul moyen de sortir la feuille, et
   il fallait le connaître. Le bouton est dans l'en-tête de l'outil, à côté du
   choix de la province — pas dans la feuille : ce qui sert à AGIR sur la feuille
   n'appartient pas à la feuille.

   Il est large et discret : c'est le dernier geste, pas le premier. Un bouton
   plein en tête de panneau ferait de l'impression le sujet de l'écran, alors que
   le sujet est la note qu'on relit avant de l'envoyer. */
.fiches-sortir {
    display: block; width: 100%; margin-top: 10px; padding: 7px 10px;
    font: inherit; font-size: 12px; text-align: center;
    color: var(--encre); background: transparent;
    border: 1px solid var(--trait); border-radius: 2px; cursor: pointer;
}
/* `--fond-doux` n'a jamais existé. Le bouton est transparent au repos, donc son
   survol n'avait AUCUN effet — et ça ne se voit pas : une variable absente se
   rabat sur l'héritage au lieu de casser. `--fond` est le fond de page, la
   teinte que ce survol voulait poser sur le papier du panneau. */
.fiches-sortir:hover { background: var(--fond); }
.fiches-sortir:focus-visible { outline: 2px solid var(--encre); outline-offset: 1px; }
.fiches-choix h3 {
    margin: 0 0 6px; font-size: 10px; font-weight: 600;
    letter-spacing: .05em; text-transform: uppercase; color: var(--encre-douce);
}
.fiches-provinces { display: flex; flex-wrap: wrap; gap: 4px; }
.fiches-province {
    padding: 3px 7px; font: inherit; font-size: 11px; cursor: pointer;
    border: 1px solid var(--trait-pale); border-radius: 2px;
    background: var(--papier); color: var(--encre-douce);
}
/* SURVOL, FOCUS ET CHOIX SE DISTINGUENT PAR TROIS CHOSES DIFFÉRENTES, pas par
   trois nuances de la même. Ils ne se distinguaient que par la teinte d'une
   bordure — `--encre-pale` contre `--encre` — et sur une capture on ne pouvait
   pas dire si « Haut-Ogooué » était survolé, au focus, ou choisi. *Trois états
   qui se ressemblent valent un seul état.* */
.fiches-province:hover { background: var(--fond); }
.fiches-province:focus-visible { outline: 2px solid var(--encre); outline-offset: 1px; }
.fiches-province.choisie {
    border-color: var(--encre); color: var(--encre); font-weight: 600;
}
/* LA FEUILLE REGARDÉE SE DISTINGUE À L'ÉCRAN — un filet, pas un fond : elle
   doit rester lisible comme les autres, puisque c'est la même feuille. */
.fiche.regardee { box-shadow: inset 3px 0 0 var(--encre); }

.fiche-tete { border-bottom: 1.5px solid var(--encre); padding-bottom: 7px; margin-bottom: 10px; }

/* LA SILHOUETTE NE COÛTE PAS UNE LIGNE DE HAUTEUR, et c'est la condition qui
   l'autorise sur une feuille qui débordait. Elle se pose dans le blanc que
   l'en-tête occupe DÉJÀ : l'en-tête devient une rangée, le texte garde toute la
   largeur qu'il veut, la forme prend ce qui reste à droite.

   `align-self: center` et non `flex-start` : centrée, elle ne peut pas dépasser
   vers le bas, quelle que soit la hauteur du texte à côté. Et elle n'a NI marge
   NI bordure — une marge verticale sur un enfant de rangée pousse la rangée, ce
   qui est exactement la ligne qu'on refuse de payer.

   Sa hauteur est bornée à celle que trois lignes de titre occupent de toute
   façon. Si le titre rétrécit un jour sous cette borne, c'est la forme qui
   rétrécit avec lui, pas l'en-tête qui grandit. */
.fiche-tete { display: flex; align-items: center; gap: 10px; }
.fiche-tete > :not(.fiche-silhouette) { min-width: 0; }
.fiche-entete-texte { flex: 1 1 auto; min-width: 0; }
.fiche-ancrage {
    flex: 0 0 auto; align-self: center;
    width: 104px; margin: 0; padding: 0; border: 0;
    display: flex; flex-direction: column; align-items: center; gap: 3px;
}
.fiche-silhouette { width: 40px; height: 43px; margin: 0; display: block; }
/* LA LÉGENDE HABITE LA PLACE QUE LA FORME A OUVERTE, elle ne s'ajoute pas au
   flux. Elle est sous l'objet qu'elle qualifie et non ailleurs dans la page :
   une légende posée sous l'objet se lit AVEC lui. */
.fiche-silhouette-note {
    margin: 0; font-size: 8.5px; line-height: 1.2; text-align: center;
    color: var(--encre-douce);
}
/* AUCUNE SECONDE TEINTE, ET LE MÊME REMPLISSAGE SUR LES NEUF. Un aplat ne peut
   se lire comme une mesure que s'il existe une échelle pour le lire ; il n'y en
   a aucune ici, donc il désigne. Les frontières intérieures ne sont pas
   tracées : neuf traits à quarante pixels ne montrent pas neuf provinces, ils
   montrent une forme sale. */
.silh-pays { fill: #dcd8d0; stroke: none; }
.silh-sujet { fill: #3a3a3a; stroke: none; }
.fiche-dossier {
    font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
    color: var(--encre-douce);
}
.fiche-province { margin: 2px 0 0; font-size: 19px; line-height: 1.15; }
.fiche-question { margin: 3px 0 0; font-size: 11px; color: var(--encre-douce); }
.fiche-ratio {
    margin: 6px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--encre);
}
/* OÙ AGIR DANS LA PROVINCE — le concret, et il passe devant les réserves.
   Chaque ligne porte ses DEUX nombres : « 100 % » vaut 7 517 habitants ici et
   en vaudrait 120 471 ailleurs, et sans l'effectif le lecteur ne sait pas si la
   ligne pèse. La barre est la même grille que le classement, en encre papier. */
.fiche-departements { margin-top: 12px; }
.fiche-departements h3, .fiche-place h3, .fiche-rangs h3 {
    margin: 0 0 6px; font-size: 10px; font-weight: 600;
    letter-spacing: .05em; text-transform: uppercase; color: var(--encre-douce);
}
.fiche-dep {
    display: grid; grid-template-columns: 1fr auto auto; gap: 2px 8px;
    align-items: baseline; margin-bottom: 6px;
}
.fiche-dep-nom { font-size: 11.5px; }
.fiche-dep-chiffres { font-size: 10.5px; color: var(--encre-douce); white-space: nowrap; }
.fiche-dep-part {
    font-size: 11.5px; text-align: right; font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.fiche-dep-barre {
    grid-column: 1 / -1; height: 3px; background: var(--trait-pale);
}
.fiche-dep-barre i { display: block; height: 100%; background: var(--encre-pale); }
/* CE QUI EXISTE AILLEURS — une ligne, sans encadré. L'arbitrage est tombé : le
   meilleur emplacement est payant, donc il ne MANQUE pas, il se trouve
   ailleurs. Un cadre en pointillés dirait « il manque quelque chose ici » ; une
   ligne dit « ça existe ». La forme suit la décision. */
.fiche-place { margin-top: 10px; }
.fiche-place-ligne {
    margin: 0; font-size: 10.5px; line-height: 1.5; color: var(--encre-douce);
}
.fiche-rangs { margin-top: 12px; }
.fiche-rang { margin: 0 0 3px; font-size: 11px; line-height: 1.45; }
.fiche-ecart { margin: 4px 0 0; font-size: 10.5px; line-height: 1.45; color: var(--encre-douce); }

.fiche-gardes { margin-top: 12px; padding-top: 8px; border-top: 1px solid var(--trait-pale); }
.fiche-gardes h3 {
    margin: 0 0 5px; font-size: 10px; font-weight: 600;
    letter-spacing: .05em; text-transform: uppercase; color: var(--encre-douce);
}
.fiche-garde { margin: 0 0 4px; font-size: 9.5px; line-height: 1.45; color: var(--encre-douce); }
.fiche-pied {
    margin-top: 12px; padding-top: 7px; border-top: 1px solid var(--trait-pale);
    font-size: 9px; line-height: 1.5; color: var(--encre-douce);
}
.fiche-couverture {
    margin-bottom: 12px; padding: 8px 10px;
    border-left: 2px solid var(--encre-pale); font-size: 11px; line-height: 1.5;
}
.fiche-couverture p { margin: 0; }
.fiche-couverture.manque { border-left-color: #d03b3b; }

/* ── LE PAPIER ───────────────────────────────────────────────────────────────

   A4 PORTRAIT, marges de 14 mm. Le format est déclaré : sans `@page`, le
   navigateur prend le format par défaut de l'imprimante, et une feuille conçue
   pour A4 sortant en Letter perd 18 mm en bas — soit le pied de provenance. */
/*
 * LE NUMÉRO DE PAGE, ET IL RÉPARE UN DÉFAUT QUE PERSONNE N'AVAIT NOMMÉ.
 * Arbitré par `35` le 18 sept. 2026, après la décision de NE PAS faire tenir
 * les feuilles en une page : serrer la typographie abîmerait sept feuilles
 * pour en sauver deux.
 *
 * *Une feuille de deux pages dont la seconde s'est perdue est indiscernable
 * d'une feuille d'une page* — et c'est là que le chiffre part sans ses
 * réserves, qui sont précisément ce qui l'accompagne à la fin.
 *
 * CE QUE CHROME SAIT FAIRE, MESURÉ AVANT D'ÊTRE ÉCRIT : les boîtes de marge
 * de `@page` fonctionnent (« 1 / 3 » apparaît bien dans le PDF). Ce qu'il ne
 * sait PAS faire : remettre le compteur à zéro par feuille — `counter-reset:
 * page` sur `.fiche` reste sans effet, vérifié. **La numérotation est donc
 * celle du DOCUMENT et non de la feuille**, ce qui sert le but visé au moins
 * aussi bien : une feuille manquante se voit, et une page aussi.
 */
@page {
    size: A4 portrait;
    margin: 14mm;
    @bottom-right {
        content: counter(page) " / " counter(pages);
        font-family: "GIA Texte", system-ui, sans-serif;   /* le pied imprimé, hors de « html body » : il demandait Plex à Google. Le nom en clair, une boîte de marge de @page ne lisant pas toujours les variables de :root */
        font-size: 7.5pt;
        color: #666;
    }
}

@media print {
    /* CE QUI NE S'IMPRIME PAS. Le rail, la carte, la pile, la barre du haut,
       la palette : rien de ce qui sert à NAVIGUER n'a de sens sur une feuille
       qu'on ne peut pas cliquer. La couverture non plus — elle s'adresse à
       celui qui imprime, pas à celui qui reçoit.

       ET LA LÉGENDE DE LA CARTE NON PLUS : il n'y a pas de carte sur les
       feuilles. Une légende sans sa carte est une promesse que le papier ne
       tient pas — et elle décrit une échelle que la feuille n'emploie pas,
       puisque celle du papier est en gris et la sienne en couleurs. */
    .bandeau, .rail, .pile, #carte, .voile, .etroit-seul,
    .fonds, .fonds-remonte, .fiches-choix, .fiches-legende, .fiches-sortir,
    .fiche-couverture, .porte-hote { display: none !important; }

    /* LE VOLET DEVIENT LA PAGE. Il est une colonne étroite à l'écran ; il rend
       ici toute la largeur utile, sans fond ni bordure — un aplat de fond
       imprimé boit l'encre sur toute la feuille. */
    html, body { background: #fff !important; }
    .corps { display: block !important; }
    .rail.dossier, #volet-dossier {
        display: block !important; position: static !important;
        width: auto !important; max-width: none !important;
        height: auto !important; overflow: visible !important;
        border: 0 !important; background: #fff !important; padding: 0 !important;
    }

    /* UNE FEUILLE PAR PAGE, ET PAS DE PAGE VIDE À LA FIN. `break-after` sur la
       dernière ferait sortir une page blanche — celle qu'on jette, et qui fait
       croire qu'il manque quelque chose. */
    .fiche {
        break-after: page; break-inside: avoid;
        border: 0; border-radius: 0; padding: 0; margin: 0;
        background: #fff; color: #000;
    }
    .fiche:last-child { break-after: auto; }
    /* ET LA FEUILLE REGARDÉE N'EST PAS MARQUÉE SUR LE PAPIER : le destinataire
       n'a pas à savoir laquelle était à l'écran quand on a imprimé. */
    /* CE QUI S'IMPRIME EST CE QUI EST CHOISI. `Cmd+P` sortait les dix-huit
       pages alors qu'une seule province était sélectionnée : l'outil dit « une
       note par province, à envoyer », au singulier, et le dernier geste avant
       l'envoi jetait seize feuilles sur dix-huit.

       Il reste donc autant de feuilles qu'il y a de dossiers prêts — deux
       aujourd'hui, la troisième viendra avec le troisième dossier — et pas une
       de plus. Pas de « tout imprimer » : personne ne l'a demandé.

       ET LA MARQUE, ELLE, NE S'IMPRIME PAS. Le filet du bord dirait au
       destinataire que sa feuille est celle qu'on regardait, ce qui ne veut
       rien dire une fois qu'elle a quitté l'écran. */
    .fiche:not(.regardee) { display: none !important; }
    .fiche.regardee { box-shadow: none; }

    /* ET QUAND LE VOLET N'EST PAS FAIT QUE DE FEUILLES.
       Le panneau des fiches ne contient que des feuilles, donc « le volet
       devient la page » lui suffit. Celui de l'Atelier porte la réponse, la
       pile des couches, la base de population et la méthode : imprimer y
       sortirait tout ce qui sert à NAVIGUER, sur la feuille qu'on envoie.
       *C'est le défaut des seize pages jetées sur dix-huit, refait à
       l'identique sur un autre écran.*
       La classe est posée par l'écran au moment où il montre la feuille ; sans
       feuille, rien n'est masqué et le volet s'imprime comme avant. */
    /* ET AUCUN DES DEUX NOMS NE DIT « ATELIER ».
       Le contrôle de la tâche 22 l'exige et il a rougi sur `feuille-atelier-hote` :
       *les dossiers sortent leur fiche sans que la feuille sache lequel est
       lequel.* La propriété est générale — « ce volet ne montre qu'une feuille,
       n'imprime qu'elle » — et le prochain écran qui en aura besoin la trouvera
       écrite plutôt que de la refaire à son nom. */
    .volet-feuille-seule > *:not(.feuille-hote) { display: none !important; }
    .feuille-hote { padding: 0 !important; }

    /* CE QUI NE SE COUPE PAS AU MILIEU. Un tableau coupé entre une ligne et sa
       valeur, un groupe à part séparé de son titre, un pied de provenance seul
       en haut d'une page : les trois se lisent comme des défauts d'impression,
       et deux d'entre eux changent le sens. */
    .fiche-tete, .fiche-pied, .groupe-a-part, .fiche-gardes,
    .fiche-departements, .fiche-place, .fiche-rangs,
    .prov, .gap-ligne, .fiche-dep { break-inside: avoid; }
    .fiche-tete, h1, h2, h3 { break-after: avoid; }

    /* LA FEUILLE DE L'ATELIER SUIT LES MÊMES RÈGLES, ET ELLE LES SUIT PARCE
       QU'ELLES ONT ÉTÉ ÉPROUVÉES SUR DU PAPIER — pas parce qu'elles sont
       plausibles. Les règles ci-dessus ont été corrigées après un tirage réel
       qui a sorti dix-huit feuilles pour deux provinces et séparé deux pieds
       de leur feuille. *Une règle recopiée d'un gabarit prouvé est une
       hypothèse faible ; une règle inventée pour un cas qu'on ne peut pas voir
       est une hypothèse sans support.*

       CELLES-CI N'ONT PAS ENCORE ÉTÉ ÉPROUVÉES ICI. Elles sont héritées, pas
       mesurées, et la suite de la feuille le dit à la fin de chaque exécution
       plutôt que de le laisser passer pour couvert.

       ET LES TROIS NOMBRES NE SE COUPENT PAS. C'est la même règle qu'à
       l'écran, et c'est la plus importante des quatre : le gain, la desserte
       et le plateau s'impriment ensemble ou pas du tout, et une coupure de
       page ferait par accident ce que la garde refuse de faire exprès — sortir
       un gain seul en haut d'une page, qui se lit comme une promesse. */
    ET AUCUN DE CES NOMS NE PORTE CELUI D'UN OUTIL. La feuille de style ne
       doit pas savoir quel outil l'a produite : c'est la condition de la tâche
       22, et une suite la vérifie. J'avais nommé mes blocs d'après l'Atelier,
       et le contrôle est tombé — en heurtant au passage une règle d'écran qui
       portait déjà ce nom-là. */
    /* LA NOTE DE CHANGEMENT NE S'IMPRIME PAS, et c'est délibéré. Une feuille
       sortie aujourd'hui sera lue dans six mois, et « les chiffres ont changé
       le 17 septembre » y affirmera un lien qui n'existera plus — sans qu'aucune
       date servie ne puisse la retirer, puisque le papier ne relit rien. *Ce qui
       la protège à l'écran — la comparaison des dates — n'existe pas sur le
       papier.* La feuille porte à la place, en pied, la date de la passe.

       ET ELLE EST ICI, DANS LE BLOC EXISTANT, PAS DANS UN SECOND `@media print`.
       Un second bloc posé plus haut devenait le premier que trouve le contrôle
       des fiches, qui lit « le » bloc d'impression et analysait alors ma règle
       d'une ligne à la place de la sienne : douze contrôles sont tombés d'un
       coup. *Le fichier n'a qu'un bloc d'impression — en ouvrir un second ne
       change pas le rendu et casse tout ce qui suppose qu'il n'y en a qu'un.* */
    .note-changement, .note-changement-hote,
    .note-changement-detail, .note-changement-detail-hote { display: none; }

    .fiche-chiffres, .fiche-marge, .fiche-refus,
    .fiche-marge-phrase { break-inside: avoid; }
    .fiche-marge, .fiche-refus { break-before: avoid; }

    /* LES TROIS PHRASES AU MÊME CORPS, JUSQUE SUR LE PAPIER. Celle qui tient et
       celle qui bascule ne se distinguent ni par la taille, ni par l'encre, ni
       par un encadré : une feuille qui a deux gabarits a deux classes de
       vérité, et le lecteur apprend en une fois laquelle il peut sauter. */
    .fiche-marge-phrase { font-size: 8.5pt; }

    /* LE PLAN TIENT D'UN SEUL BLOC. La colonne, l'échelle de la barre et le
       total sont un seul énoncé : séparés par une coupure de page, la barre
       devient un ornement sans unité et le total un nombre sans provenance.
       C'est la même règle que pour les trois nombres, pour la même raison. */
    .fiche-plan { break-inside: avoid; }
    .fiche-plan-ligne, .fiche-plan-echelle,
    .fiche-plan-arrondi, .fiche-plan-part { break-inside: avoid; }

    /* LA RÉSERVE DU PLAN NE SE SÉPARE PAS DE SES ÉTAPES. Au dos, elle se lirait
       comme une réserve du modèle ; sous la liste, elle dit que CETTE liste-ci
       n'est pas optimale. Une coupure de page entre les deux lui rend le sens
       qu'on vient de lui retirer. */
    .fiche-plan-reserve { font-size: 8.5pt; break-inside: avoid; }

    /* LA CONVENTION DE LA FEUILLE, ET LE RELEVÉ DU POINT.
       La feuille écrit des effectifs EXACTS quand l'écran arrondit à la
       centaine : les deux règles sont justes dans leur support, et la feuille
       le dit une fois plutôt que de laisser découvrir l'écart.
       Le relevé porte les quatre décimales du clic — onze mètres, pour une
       maille de 2 780. *En pied, c'est un relevé de machine ; en tête, c'était
       une affirmation sur le terrain.* Petit et gris : il situe, il n'affirme
       pas. */
    .fiche-convention, .fiche-releve {
        font-size: 7.5pt; color: #444; break-inside: avoid;
    }
    .fiche-convention { margin-top: 6pt; }

    /* LES BARRES SE COMPARENT, DONC ELLES S'ALIGNENT. Chaque ligne commence
       par sa barre, au bord gauche, sans retrait ni puce : c'est la seule
       façon que cinq longueurs se lisent d'un coup d'œil. Et les chiffres
       sont tabulaires, sinon « 1 137 » et « 2 316 » n'ont pas la même largeur
       et la colonne tremble. */
    .fiche-plan-ligne {
        font-size: 9pt;
        margin: 0.15em 0;
        text-indent: 0;
        font-variant-numeric: tabular-nums;
    }
    /* L'ÉCHELLE ET LA PART SONT PLUS PETITES QUE LES LIGNES, mais du même noir :
       elles disent ce qu'il faut pour lire les lignes, elles ne les commentent
       pas. Aucun encadré, aucune couleur — la feuille n'a qu'une classe de
       vérité. */
    .fiche-plan-echelle, .fiche-plan-arrondi { font-size: 8pt; }
    .fiche-plan-part { font-size: 9.5pt; }
    .fiche-chiffre-gain, .fiche-chiffre-desserte, .fiche-chiffre-plateau { font-size: 11pt; }
    .fiche-refus { font-size: 9pt; }

    /* LE PIED NE PART JAMAIS SEUL, ET C'EST BLOQUANT — pas cosmétique.
       MESURÉ SUR UN TIRAGE : deux feuilles sur neuf débordaient — Haut-Ogooué,
       onze départements, et Ngounié, neuf — et la page suivante ne portait QUE
       les quatre lignes de provenance. *Le pied est ce qui rend la feuille
       défendable : séparé d'elle, il devient une annexe, et une feuille dont le
       chiffre est page 1 et la provenance page 2 affirme sans ses conditions.*
       `break-inside: avoid` sur `.fiche` ne suffisait pas : un navigateur
       l'IGNORE quand le contenu dépasse la page — il ne peut pas l'honorer.
       `break-before: avoid` dit autre chose : ne coupe pas JUSTE AVANT ce
       bloc-ci, et il pousse ce qui précède plutôt que d'isoler ce qui suit. */
    .fiche-pied, .fiche-gardes, .groupe-a-part { break-before: avoid; }

    /* CE QUE CETTE RÈGLE-CI N'A PAS FAIT, ET CE QUE ÇA PROUVE — exactement.
       MESURÉ : posée le 15 sept. à 17 h 28 ; sur l'export de Vhiny à 22 h 12,
       quatre heures et demie plus tard, LE PIED PARTAIT TOUJOURS SEUL. Ce qui
       a réglé le cas n'est pas une règle de plus, c'est le CONTENU : 427
       caractères coupés sur la partie fixe, et le tirage est passé de vingt
       pages à dix-huit.

       ET LA CONCLUSION S'ARRÊTE LÀ. On a mesuré que la règle N'A PAS SUFFI sur
       un bloc qui déborde — pas qu'elle ne fait rien. *Un `break-before: avoid`
       n'est honorable que s'il reste un choix : quand le contenu qui précède
       remplit déjà la page, le moteur doit couper quelque part et la règle n'a
       rien à lui offrir.* Le support de `avoid` sur les coupures AVANT est par
       ailleurs connu pour être faible dans les moteurs WebKit/Blink.

       ELLE RESTE, ET CETTE MESURE RESTE AVEC ELLE. *La retirer ferait qu'on la
       reposerait un jour sans savoir ce qu'elle avait déjà coûté d'heures ;
       la laisser nue ferait croire que le débordement est traité.* **Si une
       feuille déborde, la sortie est de couper du contenu — et de le mesurer en
       caractères, poste par poste, plutôt que de rogner au jugé.** */

    /* ET LES DEUX EN-TÊTES DE TROP SUR LA PREMIÈRE PAGE DE CHAQUE LOT.
       La page 1 portait « Fiches », puis « Accès aux soins » en gris, PUIS
       « ACCÈS AUX SOINS » en surtitre de la feuille. Les pages suivantes n'ont
       que le surtitre : *la première feuille de chaque lot ne ressemblait donc
       pas aux autres, et c'est elle qu'on regarde en premier.* Le titre de
       l'outil et le libellé de section servent à naviguer ; la feuille porte
       déjà le nom de son dossier. */
    .dossier-tete, .fiches-titre { display: none !important; }

    /* LES APLATS SORTENT. Par défaut les navigateurs retirent les fonds à
       l'impression pour économiser l'encre — et emportent avec eux les marches
       de l'échelle, qui PORTENT une valeur. Les deux propriétés sont
       nécessaires : la seconde est le nom standard, la première ce que Chrome
       et Safari écoutent encore. */
    .fiche, .fiche * {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    /* LES CORPS DE TEXTE EN POINTS, PAS EN PIXELS. Un pixel n'a pas de taille
       sur du papier : le navigateur en invente une, et elle change d'un
       navigateur à l'autre. Le point en a une depuis toujours. */
    body { font-size: 10pt; }
    /* SUR LE PAPIER AUSSI, ET AUX MÊMES CONDITIONS. Les deux encres sont
       reprises ici parce que l'économie d'encre du navigateur emporte les fonds
       — et un aplat retiré laisserait la province introuvable, c'est-à-dire la
       silhouette réduite à un contour sans réponse. */
    .fiche-ancrage { width: 33mm; }
    .fiche-silhouette { width: 13mm; height: 14mm; }
    .fiche-silhouette-note { font-size: 6.5pt; }
    .silh-pays { fill: #dcd8d0 !important; }
    .silh-sujet { fill: #3a3a3a !important; }
    .fiche-province { font-size: 17pt; }
    .fiche-dossier { font-size: 7.5pt; }
    .fiche-question { font-size: 9pt; }
    /*
     * UN ÉCRAN SANS RIEN D'IMPRIMABLE LE DIT — mesuré le 18 sept. 2026 :
     * l'écran d'administration rendait 58 px de haut, une phrase orpheline au
     * sommet d'une page blanche, le bouton « Se connecter » imprimé à côté.
     *
     * *Un bouton sur du papier est une promesse qu'on ne peut pas tenir*, et
     * une phrase seule en haut d'une feuille se lit comme un bug plutôt que
     * comme un refus. Le bouton part, la phrase devient lisible.
     *
     * VÉRIFIÉ SUR UN VRAI PDF, avant et après, Chrome sans interface : avant,
     * la feuille portait « Se connecter » sous la phrase ; après, elle ne
     * porte plus que la phrase. *C'est la seule des trois règles écrites ce
     * jour-là dont la mesure ait montré un effet.*
     *
     * Ce qu'on ne décide PAS ici : ce que « imprimer un écran » devrait
     * produire quand il n'y a pas de fiche. C'est un arbitrage de design, il
     * est demandé, et une règle de style ne doit pas le trancher en douce.
     */
    /*
     * CE QUI NE S'IMPRIME JAMAIS, arbitré par `35` : rien de ce qui sert à
     * naviguer ou à cliquer. Le rail, la pile, la palette et la carte sont
     * déjà masqués plus haut ; s'ajoute ici le lien « Pourquoi → » de la note
     * de changement. *Une flèche sur du papier montre une porte qui n'existe
     * pas.* La silhouette remplace la carte et porte sa propre réserve.
     */
    /*
     * L'ORDRE IMPOSÉ SUR LE PAPIER — arbitré par `35` le 18 sept. 2026, après
     * un premier essai que la mesure a fait retirer : la consigne disait « le
     * classement » et la feuille en porte deux. L'arbitre a tranché, et la
     * raison n'est pas esthétique :
     *
     *   les départements disent OÙ AGIR — ce dont le lecteur a besoin pour
     *   employer le chiffre ; le rang parmi les neuf dit SI CETTE PROVINCE
     *   EST UNE PRIORITÉ, ce qui est du contexte.
     *
     * *Et le rang est une comparaison entre provinces, posée sur une feuille
     * qui n'en porte qu'une : placé avant les départements, il inviterait à
     * conclure sur les huit autres sans leurs feuilles.*
     *
     * Ce que ces règles déplacent RÉELLEMENT, le reste étant déjà dans cet
     * ordre : la silhouette. À l'écran elle est logée dans l'en-tête, à droite
     * du titre, donc elle arrive AVANT le chiffre. Le papier n'a pas de « à
     * droite » : tout se suit. L'en-tête cède son rôle de boîte
     * (`display: contents`) et ses enfants entrent dans le flux de la feuille.
     *
     * *Réordonner à l'impression plutôt que dans le DOM évite de déplacer à
     * l'écran une silhouette que personne n'a demandé d'y déplacer.*
     */
    .fiche {
        display: flex;
        flex-direction: column;
    }

    .fiche-tete { display: contents; }
    .fiche > * { order: 2; }              /* le chiffre et son ratio, collés */
    .fiche-entete-texte { order: 1; }     /* dossier, province, question */
    /* LE `figure` QUI PORTE LA SILHOUETTE ET SA RÉSERVE, et non le `svg`
       qu'il contient : c'est lui l'enfant de l'en-tête. Premier essai posé sur
       `.fiche-silhouette`, et la silhouette est remontée EN TÊTE de feuille,
       avant le titre du dossier. *Une règle qui vise le mauvais élément ne
       reste pas sans effet : elle en a un autre.* */
    .fiche-ancrage { order: 3; }
    .fiche-departements { order: 4; }     /* où agir */
    .groupe-a-part { order: 5; }          /* ce qui ne se classe pas, avec eux */
    .fiche-rangs { order: 6; }            /* si c'est une priorité : du contexte */
    .fiche-gardes { order: 7; }           /* les réserves, en entier */
    .fiche-pied { order: 8; }

    .note-changement-lien {
        display: none !important;
    }

    .chg-porte {
        display: none !important;
    }

    .chg-refus {
        font-size: 11pt;
        line-height: 1.5;
        max-width: 60ch;
        margin: 0;
    }

    .fiche-garde, .fiche-pied { font-size: 7pt; }

    /* LE LIEN N'EST PLUS UN LIEN. Souligner ce qu'on ne peut pas cliquer
       apprend au lecteur que la feuille est une capture d'écran. */
    a { text-decoration: none; color: inherit; }
}


/* ─── La porte ───────────────────────────────────────────────────────────────
 *
 * Elle est posée hors du flux et masquée par défaut : une porte fermée ne doit
 * pas déplacer d'un pixel l'écran de celui qui n'en a pas besoin. Rien ici ne
 * nomme un dossier — une règle d'impression propre à un dossier ferait rougir
 * test_v2_fiches.js, et elle aurait raison.
 */
.compte-barre { margin-left: auto; display: flex; align-items: center; gap: .5rem; }
.compte-nom { font-size: .85rem; opacity: .8; }
.compte-bouton {
    font: inherit; font-size: .85rem; padding: .25rem .7rem; cursor: pointer;
    border: 1px solid currentColor; border-radius: 3px; background: none;
    color: inherit;
}
/* LA PORTE A SA FEUILLE, css/porte.css (v1.6.4), partagée avec reset_password.html. */

/* LES COINS DU KIOSQUE SUR /v2 (v1.6.2) : boutons et champs à 10 px, les petites commandes
 * posées dans une ligne (l'œil, le retrait) à 7 px (K/base.css:96, 125 ; K/accent.css:53).
 * Les cartes et les panneaux gardent --r-grand et --r-petit (3 et 2 px ; 4 et 3 au Kiosque). */
.ajouter, .etroit-seul, .fiches-province, .fiches-sortir, .atelier-action, .compte-bouton,
.palette button, .dossier button:not(.oeil):not(.retirer) { border-radius: var(--gia-coin-bouton); }
.oeil, .retirer { border-radius: var(--gia-coin-imbrique); }
input[type="text"], input[type="email"], input[type="password"], input[type="search"], select, textarea { border-radius: var(--gia-coin-champ); }

/* LES BOUTONS DU COMPTE DANS L'EN-TÊTE UNIQUE (v1.6.2) : « Se connecter » bordeaux,
 * « Se déconnecter » neutre (css/marque.css). Plus précis que .compte-bouton, qu'ils
 * remplacent dans la barre à toutes les largeurs. */
.compte-barre .gia-bouton-principal, .compte-barre .gia-bouton-secondaire {
    min-height: 38px; height: auto; padding: 0.6rem 0.95rem; font: 500 0.84rem/1 var(--gia-texte);
    border-radius: var(--gia-coin-bouton);
}
.compte-barre .gia-bouton-principal { color: var(--gia-sur-bordeaux); background: var(--gia-bordeaux); border: 1px solid var(--gia-bordeaux); }
.compte-barre .gia-bouton-principal:hover { background: var(--gia-bordeaux-survol); border-color: var(--gia-bordeaux-survol); }
.compte-barre .gia-bouton-secondaire { color: var(--gia-encre); background: transparent; border: 1px solid var(--gia-filet-fort); }
/* LE MENU DU COMPTE (v1.6.6, c0, 26/10) : le nom, coupé au-delà d'environ 12 caractères, ouvre
 * une liste posée sous lui, hors du flux : elle ne déplace rien de la barre. */
.compte-menu { position: relative; display: flex; min-width: 0; }
.compte-nom {
    display: inline-flex; align-items: center; gap: 4px; min-width: 0; min-height: 38px;
    padding: 0 0.7rem; font: 500 0.84rem/1 var(--gia-texte); color: var(--gia-encre);
    background: transparent; border: 1px solid var(--gia-filet-fort);
    border-radius: var(--gia-coin-bouton); cursor: pointer;
}
.compte-nom-texte { max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.compte-fleche { font-size: 0.7em; opacity: .7; }
.compte-nom:focus-visible { outline: 2px solid var(--gia-bordeaux); outline-offset: 2px; }
.compte-liste {
    position: absolute; top: calc(100% + 6px); right: 0; z-index: 1150; min-width: 100%;
    display: flex; flex-direction: column; padding: 4px; background: var(--gia-papier);
    border: 1px solid var(--gia-filet-fort); border-radius: var(--gia-coin-bouton);
    box-shadow: 0 6px 18px rgba(15, 42, 58, .14);
}
/* « Se déconnecter » est une LIGNE de menu, pas un bouton bordé dans une boîte bordée (c0). Plus
 * précis que .compte-barre .gia-bouton-secondaire, qu'il défait ici. */
.compte-barre .compte-liste .compte-bouton {
    display: block; width: 100%; min-height: 36px; padding: 0 12px; text-align: left;
    white-space: nowrap; font: 500 0.84rem/36px var(--gia-texte); color: var(--gia-encre);
    background: transparent; border: 0; border-radius: var(--gia-coin-imbrique); cursor: pointer;
}
.compte-barre .compte-liste .compte-bouton:hover,
.compte-barre .compte-liste .compte-bouton:focus-visible { background: var(--gia-brume); outline: none; }
.compte-barre .compte-liste .compte-bouton:focus-visible { box-shadow: inset 0 0 0 2px var(--gia-bordeaux); }
.bandeau .gia-nav { margin-right: auto; }
/* Sur /v2, pas de bouton « Menu » : sous 900 px, la navigation est en tête du tiroir. */
.bandeau .gia-menu-bouton { display: none !important; }
.gia-nav-rail { display: none; }
@media (max-width: 900px) {
    .gia-nav-rail { display: flex; flex-direction: column; padding: 8px 16px 4px; border-bottom: 1px solid var(--gia-filet); }
    .gia-nav-rail a { font: 500 0.94rem/1 var(--gia-texte); color: var(--gia-encre-douce); text-decoration: none; padding: 12px 0; }
    .gia-nav-rail a[aria-current="page"] { color: var(--gia-encre); box-shadow: inset 3px 0 0 var(--gia-bordeaux); padding-left: 10px; }
    .gia-nav-rail a:focus-visible { outline: 2px solid var(--gia-bordeaux); outline-offset: 2px; border-radius: var(--gia-coin-focus); }
    /* Le bouton du compte, compact : 32 px de haut, sur une ligne. */
    .compte-barre .gia-bouton-principal, .compte-barre .gia-bouton-secondaire {
        min-height: 32px; padding: 0 10px; font-size: 0.78rem; white-space: nowrap; flex-shrink: 0;
    }
    .compte-nom { min-height: 32px; padding: 0 8px; font-size: 0.78rem; }
}

/* LA BARRE ÉTROITE AVEC LA MARQUE HODOLOGIC (v1.6.2). Le logo et « une
 * plateforme Hodologic » demandaient 179 px : à 390 px la barre mesurait 479 px
 * (mesuré le 25/10). Règles reprises de dev (v1.7, #24, e0 03/10), MISE EN PAGE
 * seule, sans la police de l'étape 2 : sous 900 px le sous-titre de la marque
 * cède (le nom accessible du lien reste « GIA, une plateforme Hodologic »), les
 * écarts passent à 12 et la porte prend la forme des deux boutons ; de 320 à
 * 359 px, les marges cèdent, et la marque se réduit à son logo. Ici, après la
 * règle du bouton du compte, qu'elles doivent emporter. Sous 320 px, rien n'est
 * promis (WCAG 1.4.10). test_marque_hodologic.py mesure la barre à 320 et 390. */
@media (max-width: 900px) {
    .bandeau { gap: 12px; }
    .compte-bouton {
        display: inline-flex; align-items: center; height: 24px; padding: 0 9px;
        font-size: 11px; white-space: nowrap; flex-shrink: 0;
    }
    .bandeau .gia-marque { gap: 7px; }
    .bandeau .gia-marque-sous { display: none; }
}
@media (max-width: 359px) {
    .bandeau { padding: 0 10px; gap: 6px; }
    .etroit-seul, .compte-bouton { padding: 0 6px; }
}
/* SOUS 390 PX, LA MARQUE SE RÉDUIT À SON LOGO (v1.6.3, 26/10). Le seuil était 359 : à 360,
 * le lien de la marque (logo et « GIA ») mesurait 78 px et la barre demandait 366 px en vue
 * liste, 383 en vue carte ; à 375, 383 en vue carte (mesuré par 96 puis 09, Chrome, is_mobile).
 * À 390 elle tient (390/390). Le nom accessible du lien porte toujours « GIA ». */
@media (max-width: 389px) {
    .bandeau .gia-marque { gap: 0; }
    .bandeau .gia-marque-nom { display: none; }
}
.porte-hote {
    position: fixed; inset: 0; display: grid; place-items: center;
    background: rgba(15, 42, 58, .5);   /* le voile marine du Kiosque */
    /* UNE GOUTTIÈRE RÉELLE. Sans ce padding, la porte mesurait 384 px dans un
     * écran de 390 : trois pixels de chaque côté, c'est-à-dire un panneau qui
     * touche les bords et qu'on lit comme un défaut d'affichage. Mesuré, pas
     * supposé. */
    padding: 20px; box-sizing: border-box;   /* 20 px, la marge du Kiosque (.auth-modal-backdrop) */
    /* AU-DESSUS DE LEAFLET, QUI MONTE À 1000. Écrit à 40 d'abord — la porte se
     * serait ouverte DERRIÈRE la carte, et le clic serait allé à la carte.
     * Le témoin de test_v2_carte.js l'a dit avant le navigateur ; les autres
     * surfaces flottantes sont à 1020, 1030, 1040, 1100 et 1200, et la porte
     * les couvre toutes puisqu'elle couvre l'écran.
     *
     * ET SOUS LA PALETTE, QUI EST À 1200. Écrit à 1300 ensuite, et un second
     * témoin l'a refusé : ⌘K est un dialogue et doit passer devant tout. Les
     * deux contrôles bornent donc cette valeur des DEUX côtés — au-dessus de
     * Leaflet à 1000, en dessous de la palette à 1200 — et il n'y avait qu'un
     * intervalle où la poser.
     *
     * ET AU-DESSUS DES NOUVEAUTÉS, QUI SONT À 1190 (v1.6.3, 26/10). À 1150, un
     * premier visiteur envoyé ici par modelling (?porte=modelling) voyait la
     * fenêtre des nouveautés couvrir la porte qu'il venait de demander : ni la
     * raison ni le formulaire n'étaient atteints (elementFromPoint, 1440 et 390).
     * La porte est un geste demandé, la note une information : elle reste
     * dessous, intacte, et se lit en refermant la porte. */
    z-index: 1195;
}
/* LA CARTE DE LA PORTE, son bandeau et ses champs : css/porte.css (v1.6.4, la porte du Kiosque). */
/* La phrase du refus d'observation qui MÈNE à la porte. Ce n'est pas un bouton :
 * offrir un bouton qui ne peut pas réussir est une promesse de plus, et cette
 * décision est écrite dans v2-dossier-chantiers.js. C'est la PHRASE qui ouvre. */
.obs-vers-porte {
    background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
    text-decoration: underline; color: inherit;
}

/* ══ L'OUTIL « POPULATION D'UNE ZONE » ═══════════════════════════════════
 *
 * Le panneau reprend la maquette de `35` : un intitulé pâle, un chiffre gros,
 * une ligne de faits dessous, et la provenance séparée d'un filet. Le chiffre
 * est un ENCADREMENT — « 1 200 – 4 900 » — et sa taille est ce qui le fait
 * lire en premier ; les réserves qui ne s'appliquent pas ne s'affichent pas.
 */
.zone-quoi {
    margin: 0 0 6px; font-size: 10.5px; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--encre-pale);
}
.zone-chiffre {
    margin: 0 0 2px; font-size: 27px; font-weight: 600; line-height: 1.12;
    letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.zone-petit { font-size: 15px; font-weight: 400; color: var(--encre-douce); }
.zone-apres { margin: 4px 0 0; font-size: 12.5px; color: var(--encre-douce); }
.zone-apres-carte {
    margin: 8px 0 0; font-size: 11.5px; font-style: italic;
    color: var(--encre-pale);
}
.zone-parce-que {
    margin: 13px 0 0; padding-top: 11px; border-top: 1px solid var(--trait-pale);
    font-size: 12px; line-height: 1.5; color: var(--encre-douce);
}
.zone-parce-que b { color: var(--encre); font-weight: 600;
                    font-variant-numeric: tabular-nums; }
/* Une réserve qui porte sur CE tracé-ci, et pas sur la méthode : encadrée
   comme un fait de ce résultat, pas rangée avec les limites générales. */
.zone-note {
    margin: 12px 0 0; padding: 9px 11px; font-size: 12px; line-height: 1.5;
    background: var(--fond); border: 1px solid var(--trait-pale);
    border-radius: var(--r-petit); color: var(--encre-douce);
}
.zone-note b { color: var(--encre); font-weight: 600; }
.zone-ouverture h2 { margin: 0 0 6px; font-size: 14px; }
.zone-quoi-outil, .zone-maille {
    margin: 0 0 10px; font-size: 12px; line-height: 1.5; color: var(--encre-douce);
}
.zone-maille { color: var(--encre-pale); }
.zone-limites {
    margin-top: 14px; padding-top: 10px; border-top: 1px solid var(--trait-pale);
}
.zone-limites h3 {
    margin: 0 0 6px; font-size: 10.5px; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--encre-pale); font-weight: 600;
}
.zone-limite { margin: 0 0 6px; font-size: 11.5px; line-height: 1.45;
               color: var(--encre-douce); }
.zone-source { margin: 12px 0 0; font-size: 10.5px; color: var(--encre-pale); }

.zone-commandes {
    display: flex; flex-wrap: wrap; gap: 7px; margin: 14px 0 0;
    padding-top: 12px; border-top: 1px solid var(--trait-pale);
}
.zone-btn {
    font: inherit; font-size: 12.5px; min-height: var(--controle);
    padding: 3px 11px; cursor: pointer;
    background: var(--papier); color: var(--encre);
    border: 1px solid var(--trait); border-radius: var(--r-petit);
}
.zone-btn.fort { background: var(--etat); color: var(--sur-etat);
                 border-color: var(--etat); }
.zone-btn:disabled { opacity: 0.45; cursor: default; }

/* LA BARRE DE COMMANDES POSÉE SUR LA CARTE.
 *
 * Elle existe parce que sous 900 px le volet passe DERRIÈRE la carte pendant
 * qu'on trace : des boutons rangés dans le volet seraient invisibles au moment
 * précis où ils servent. Elle est en haut — le bas est pris par le choisisseur
 * de fond, et deux surfaces qui se recouvrent se disputent le doigt.
 *
 * ET ELLE PASSE DEVANT TOUT CE QUI FLOTTE SUR LA CARTE — 1040, au-dessus du
 * choisisseur de fond (1020) et de la phrase du zoom remonté (1030). Elle est
 * la seule surface qui doit rester TOUCHABLE pendant un geste : une phrase qui
 * la recouvrirait d'un pixel ferait manquer « Fermer la zone », et le geste
 * manqué pose un point de plus. Elle reste sous le tiroir (1100) et sous le
 * voile de la palette (1200), qui sont des écrans entiers et non des commandes
 * de la carte. */
.commandes-sur-carte {
    position: absolute; top: 10px; left: 10px; right: 10px; z-index: 1040;
    display: flex; justify-content: center; pointer-events: none;
}
.zone-commandes-carte {
    pointer-events: auto;
    display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
    max-width: 100%; padding: 6px 8px;
    background: var(--papier); border: 1px solid var(--trait);
    border-radius: var(--r-grand);
    box-shadow: 0 1px 4px rgb(0 0 0 / 0.12);
}
.zone-commandes-etat {
    font-size: 11.5px; color: var(--encre-douce); padding: 0 4px;
    font-variant-numeric: tabular-nums;
}
/* Sur un écran étroit, la barre prend la largeur et ses boutons s'étalent :
   trois cibles de 28 px valent mieux qu'une ligne qui déborde. */
@media (max-width: 560px) {
    .zone-commandes-carte { width: 100%; }
    .zone-commandes-carte .zone-btn { flex: 1 1 auto; }
    .zone-commandes-etat { flex: 1 0 100%; text-align: center; }
}

/* ══ LES LIEUX DANS LA PALETTE ═══════════════════════════════════════════
 *
 * Deux sortes de réponse, pas deux catégories d'une même liste : une couche
 * s'ajoute à la pile et y reste, un lieu déplace la carte et ne laisse rien.
 * Le groupe les sépare ; la ligne, elle, garde exactement la même forme — trois
 * colonnes, même rythme — parce que l'œil parcourt une liste, pas deux.
 */
.resultat.lieu .etat { font-variant: small-caps; letter-spacing: 0.02em; }
/* La phrase qui explique un « rien trouvé » : elle n'est pas un échec, elle est
   un fait sur la donnée — une localité sur cinq n'a pas de nom. */
.vide-pourquoi {
    margin: 6px 14px 0; font-size: 11.5px; line-height: 1.45;
    color: var(--encre-douce);
}
.vide-pourquoi:last-child { margin-bottom: 12px; font-style: italic; }
/* La phrase des jumeaux : elle explique deux lignes identiques AU MOMENT du
   choix. La donner ailleurs — une console, une note de bas de page — c'est la
   donner à personne. */
.palette-note {
    margin: 4px 14px 10px; font-size: 11.5px; line-height: 1.45;
    color: var(--encre-douce); font-style: italic;
}
/* ══ CE QUI A PRODUIT UNE ALERTE — A13 ═══════════════════════════════════
 *
 * Toujours au même endroit sur l'alerte, jamais dans un glossaire : un second
 * endroit diverge, et celui qui lit une alerte n'y va pas. Le bloc est donc
 * discret mais pas caché — il ne se replie pas, il ne se survole pas.
 */
.alerte-regle {
    margin: 10px 0 0; padding: 9px 11px;
    background: var(--fond); border-left: 2px solid var(--trait);
    border-radius: 0 var(--r-petit) var(--r-petit) 0;
}
.alerte-regle h4 {
    margin: 0 0 4px; font-size: 10px; font-weight: 600; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--encre-pale);
}
.regle-phrase { margin: 0; font-size: 12px; line-height: 1.5; color: var(--encre); }
/* La réserve est en retrait ET en italique : elle ne dit pas la règle, elle dit
   ce que la règle ne peut pas faire. Une seconde phrase au même rang se lirait
   comme une seconde condition. */
.regle-reserve {
    margin: 5px 0 0; font-size: 11.5px; line-height: 1.45; font-style: italic;
    color: var(--encre-douce);
}
/* Une règle sans phrase se VOIT. Un bloc qui disparaît en silence quand sa
   donnée manque rend l'absence indiscernable de la normalité. */
.regle-absente { margin: 0; font-size: 11.5px; line-height: 1.45; color: var(--encre-douce); }
/* ══ CE QUE LA CARTE A APPRIS — écran d'administration ═══════════════════
 *
 * La limite des deux relevés est en TÊTE, avant tout nombre : une réserve
 * rangée en bas est une réserve qu'on lit après avoir conclu. Elle est donc
 * traitée comme un bloc à part entière, pas comme une note.
 */
.chg-limite {
    margin: 0 0 16px; padding: 11px 13px;
    background: var(--fond); border-left: 3px solid var(--encre);
}
.chg-limite h2 {
    margin: 0 0 5px; font-size: 11px; font-weight: 600; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--encre);
}
.chg-limite p { margin: 0; font-size: 12px; line-height: 1.5; color: var(--encre-douce); }
.chg-trouves {
    margin: 8px 0 0; font-size: 12px; line-height: 1.5; color: var(--encre-douce);
}
.chg-ligne {
    display: grid; grid-template-columns: 1fr auto auto; gap: 10px;
    align-items: baseline; padding: 5px 0;
    border-bottom: 1px solid var(--trait-pale); font-size: 12.5px;
}
.chg-ligne .ou { font-size: 10.5px; color: var(--encre-pale); }
.chg-ligne .val { font-variant-numeric: tabular-nums; font-weight: 600; }
.chg-inconnue { font-size: 10.5px; color: var(--encre-pale); font-style: italic; }
.chg-retraits { margin-top: 18px; }
.chg-phrase { margin: 0 0 10px; font-size: 12.5px; line-height: 1.55; }
.chg-note { margin: 8px 0 0; font-size: 11.5px; line-height: 1.45; color: var(--encre-douce); }
.chg-gardes { margin-top: 16px; padding-top: 10px; border-top: 1px solid var(--trait-pale); }
.chg-gardes h3 {
    margin: 0 0 6px; font-size: 10.5px; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--encre-pale); font-weight: 600;
}
.chg-garde { margin: 0 0 6px; font-size: 11.5px; line-height: 1.45; color: var(--encre-douce); }
.chg-source { margin: 12px 0 0; font-size: 10.5px; color: var(--encre-pale); }
/* Le refus n'est pas une page d'erreur : il dit lequel des deux il est, et il
   mène à la porte quand c'est la porte qui manque. */
.chg-refus p { margin: 0 0 10px; font-size: 13px; line-height: 1.55; }
.chg-porte {
    font: inherit; font-size: 12.5px; min-height: var(--controle); padding: 3px 11px;
    cursor: pointer; background: var(--etat); color: var(--sur-etat);
    border: 1px solid var(--etat); border-radius: var(--r-petit);
}
/* Une alerte non réexaminée : elle reste lisible et elle se distingue. Son
   filet est en tirets — *ce qui est en attente ne se peint pas comme ce qui est
   constaté*, et aucune couleur d'état ne lui est donnée, puisqu'on ne sait plus
   ce qu'elle vaut. */
.alerte.reportee { border-left-style: dashed; }

/* La barre de l'Atelier, posée sur la carte pendant l'attente d'un clic.
   Même gabarit que `.zone-commandes-carte` : les deux outils demandent la même
   chose à l'écran — une consigne, un état, une sortie — et deux gabarits
   différents pour un même rôle se désaccordent au premier changement. */
.atelier-commandes-carte {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 8px 12px; background: var(--fond); border: 1px solid var(--trait);
    border-radius: 6px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}
.atelier-commandes-etat { font-size: 13px; color: var(--encre); }
.atelier-commandes-annuler {
    border: 1px solid var(--trait); background: none; border-radius: 4px;
    padding: 4px 10px; cursor: pointer; font: inherit; font-size: 13px;
    color: var(--encre-pale);
}

/* « NOUVEAU DANS GIA » (v1.2) — d'après design/maquette-nouveautes.html (86,
   validée par e8). Les jetons sont ceux du site Hodologic (CHARTE-HODOLOGIC
   § 1), portés ici par la fenêtre seule : le reste de /v2 garde les siens.
   Dialogue modal sur un voile ; sur téléphone, une feuille qui monte du bas,
   dont le bouton reste en pied sans défiler. Cibles tactiles : 44 px. */
.nv-voile {
    /* Un seul jeu de jetons (§ 4 bis) : la fenêtre LIT ceux de :root. */
    --nv-bg: var(--papier); --nv-ink: var(--encre); --nv-ink-soft: var(--encre-douce); --nv-muted: var(--encre-pale);
    --nv-rule: var(--trait); --nv-green: var(--etat); --nv-green-hover: var(--etat-survol);
    --nv-on-green: var(--sur-etat); --nv-sand-ink: var(--reserve); --nv-r: var(--r-grand);
    --nv-sans: var(--gia-texte);
    /* Sous la palette (1200) : ⌘K est LE dialogue qui passe devant tout
       (test_v2_carte) ; au-dessus de la carte et des volets. */
    position: fixed; inset: 0; z-index: 1190;
    background: rgba(15, 42, 58, .42);
    display: flex; align-items: center; justify-content: center; padding: 32px 16px;
    box-sizing: border-box;
}
.nv-fen {
    width: 560px; max-width: 100%; max-height: 100%;
    background: var(--nv-bg); color: var(--nv-ink); font-family: var(--nv-sans);
    border-radius: var(--nv-r); box-shadow: 0 18px 48px rgba(15, 42, 58, .28);
    display: flex; flex-direction: column; overflow: hidden;
}
.nv-tete { position: relative; padding: 22px 24px 18px; border-bottom: 1px solid var(--nv-rule); }
.nv-surtitre { font-size: 12px; color: var(--nv-muted); letter-spacing: .02em; }
.nv-titre { font-family: var(--nv-sans); font-size: 17px; font-weight: 600; margin: 6px 0 0; outline: none; }
.nv-fermer {
    position: absolute; top: 10px; right: 10px; width: 44px; height: 44px;
    border: 0; border-radius: var(--nv-r); background: transparent;
    font-size: 22px; line-height: 1; color: var(--nv-ink); cursor: pointer;
}
.nv-corps { padding: 0 24px; overflow-y: auto; flex: 1 1 auto; }
.nv-chiffres {
    margin: 16px 0 4px; padding: 12px 14px; border-left: 2px solid var(--nv-sand-ink);
    font-size: 13.5px; color: var(--nv-ink-soft);
}
.nv-quoi { color: var(--nv-sand-ink); font-weight: 600; font-size: 13px; }
.nv-chiffres p { margin: 6px 0; line-height: 1.45; }
.nv-liens { display: flex; flex-wrap: wrap; gap: 0 16px; }
.nv-elements { list-style: none; margin: 0; padding: 0; }
.nv-elements li { padding: 14px 0; border-top: 1px solid var(--nv-rule); }
.nv-elements li:first-child { border-top: 0; }
.nv-elements h3 { font-size: 14.5px; font-weight: 600; margin: 0 0 4px; }
.nv-elements p { font-size: 13.5px; line-height: 1.45; color: var(--nv-ink-soft); margin: 0; }
.nv-lien {
    display: inline-flex; align-items: center; min-height: 44px;
    color: var(--nv-green); font-weight: 500; font-size: 13.5px; text-decoration: none;
}
.nv-lien:hover { color: var(--nv-green-hover); text-decoration: underline; }
.nv-pied {
    display: flex; align-items: center; gap: 16px; padding: 14px 24px;
    border-top: 1px solid var(--nv-rule); background: var(--nv-bg); flex-shrink: 0;
}
.nv-pied p { font-size: 12.5px; color: var(--nv-muted); margin: 0; flex: 1; line-height: 1.4; }
.nv-bouton {
    font: inherit; font-weight: 500; font-size: 14px; min-height: 44px; padding: 10px 18px;
    background: var(--nv-green); color: var(--nv-on-green); border: 0;
    border-radius: var(--nv-r); cursor: pointer; flex-shrink: 0;
}
.nv-bouton:hover { background: var(--nv-green-hover); }
/* « Nouveautés », en pied du rail. */
.rail-nouveautes { margin-top: auto; }
@media (max-width: 600px) {
    .nv-voile { align-items: flex-end; padding: 0; }
    .nv-fen {
        width: 100%; max-height: 88vh;
        border-radius: var(--nv-r) var(--nv-r) 0 0;
    }
    .nv-tete, .nv-corps, .nv-pied { padding-left: 16px; padding-right: 16px; }
}

/* LA LÉGENDE DU TEMPS DE ROUTE, maille par maille (v1.2). Une fonction la rend
   dans Accès aux soins ET dans la preuve d'une alerte « mal desservi »
   (v2-couche-temps.js). La hachure « aucune route » y porte son liseré clair,
   comme sur la carte. */
.legende-temps { margin: 12px 0; font-size: 12px; color: var(--encre-douce); }
.legende-temps-titre { font-weight: 600; color: var(--encre); margin-bottom: 6px; }
.legende-temps-cles { display: flex; flex-wrap: wrap; gap: 4px 12px; }
.legende-temps-cle { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.legende-temps-pastille {
    display: inline-block; width: 10px; height: 10px;
}
/* « Aucune route » : la hachure de la carte, en petit, sans anneau (e8). La
   couleur vient de AUCUNE_ROUTE (v2-couche-temps.js), posée en `color`. */
.legende-temps-hachure {
    background: repeating-linear-gradient(-45deg, currentColor 0 1px, #ffffff 1px 3.5px);
    box-shadow: 0 0 0 1px #ffffff;
}
.legende-temps-phrase { margin: 6px 0 0; line-height: 1.45; }

/* Un sujet de SURFACE au-dessus des mailles (une province de preuve) ne prend
   le pointeur que sur son trait : son aplat laisse les mailles répondre
   (e8, v1.2.1 — v2-carte.js, contourSeul). Plus spécifique que la règle de
   Leaflet (.leaflet-pane > svg path.leaflet-interactive). */
.leaflet-pane > svg path.leaflet-interactive.contour-seul { pointer-events: visibleStroke; }
/* La prise du trait : invisible, 12 px, sous le trait en tirets d'une province
   de preuve ; `stroke` et non `visibleStroke`, puisqu'elle ne se peint pas. */
.leaflet-pane > svg path.leaflet-interactive.prise-du-trait { pointer-events: stroke; }

/* CE QU'UNE COUCHE DIT D'ELLE-MÊME, SOUS SA LIGNE DE PILE (v1.3, la géologie) :
   ses réserves, puis sa légende dépliable (v2-legende.js). Alignées sur le
   texte de la ligne : 16 px de marge, 3 de bordure, l'œil (28) et l'écart (10). */
.entree-reserve {
    margin: 0 16px 4px 57px; font-size: 11px; line-height: 1.4; color: var(--encre-pale);
}
.legende-couche { margin: 0 16px 8px 57px; }
.legende-couche-bouton {
    border: 0; background: none; padding: 2px 0; cursor: pointer;
    font: inherit; font-size: 11px; color: var(--encre-douce); text-decoration: underline;
    text-underline-offset: 2px;
}
.legende-couche-bouton[aria-expanded="true"] { color: var(--encre); }
/* Dépliée : toutes les entrées, sans défilement interne (e8). */
.legende-couche-liste { list-style: none; margin: 4px 0 0; padding: 0; }
.legende-couche-entree { display: flex; align-items: flex-start; gap: 7px; margin: 0 0 5px; }
.legende-couche-titre {
    margin: 8px 0 4px; font-size: 10.5px; font-weight: 600; color: var(--encre-douce);
}
.legende-couche-titre:first-child { margin-top: 2px; }
.legende-couche-pastille {
    flex: 0 0 12px; width: 12px; height: 12px; margin-top: 2px;
    border-radius: 2px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.12);
}
/* La trame neutre des non attribuées, comme sur la carte : jamais une couleur. */
.legende-couche-trame-neutre {
    /* Variante A d'e8 : fine et claire, comme sur la carte. */
    background: repeating-linear-gradient(-45deg, rgba(148, 163, 184, 0.9) 0 0.75px, transparent 0.75px 5px);
}
/* UNE PASTILLE PAR STYLE DESSINÉ (e8) : côte à côte, et le motif de la case
   par-dessus sa couleur, dans l'ENCRE de la case (--encre, posée par la
   légende ; absente, l'encre commune). Vocabulaire du vecteur (7f, 26/09). */
.legende-couche-pastilles { display: flex; gap: 2px; flex: 0 0 auto; }
.legende-couche-pastille { --encre: rgba(15, 23, 42, 0.30); }
.legende-couche-motif-points {
    background-image: radial-gradient(var(--encre) 0.8px, transparent 1px),
                      radial-gradient(var(--encre) 0.8px, transparent 1px);
    background-size: 5px 5px; background-position: 0 0, 2.5px 2.5px;
}
.legende-couche-motif-cercles {
    background-image: radial-gradient(circle, transparent 1.2px, var(--encre) 1.3px 1.9px, transparent 2px);
    background-size: 7px 7px;
}
.legende-couche-motif-croix {
    background-image: repeating-linear-gradient(45deg, transparent 0 2.5px, var(--encre) 2.5px 3.2px, transparent 3.2px 6px),
                      repeating-linear-gradient(-45deg, transparent 0 2.5px, var(--encre) 2.5px 3.2px, transparent 3.2px 6px);
}
.legende-couche-motif-tirets_horizontaux {
    background-image: linear-gradient(90deg, var(--encre) 0 3px, transparent 3px);
    background-size: 5px 4px; background-repeat: repeat;
}
.legende-couche-motif-tirets {
    background-image: linear-gradient(90deg, var(--encre) 0 3px, transparent 3px);
    background-size: 7px 6px;
}
.legende-couche-motif-triangles {
    background-image: conic-gradient(from 150deg at 50% 25%, var(--encre) 0 60deg, transparent 60deg);
    background-size: 6px 6px;
}
.legende-couche-motif-traits_epars {
    background-image: linear-gradient(45deg, transparent 45%, var(--encre) 45% 55%, transparent 55%);
    background-size: 8px 8px;
}
/* plan_d_eau : la couleur seule, sans marque — aucune règle. */
/* L'en-tête « 12 unités ici, 76 en tout », et les RUBRIQUES de la légende
   imprimée, repliables (e8, 26/09) : le titre se clique, son compte suit. */
.legende-couche-entete { margin: 2px 0 6px; font-size: 10.5px; color: var(--encre-pale); }
.legende-couche-rubrique { cursor: pointer; }
.legende-couche-rubrique::before { content: '▾ '; }
.legende-couche-rubrique[aria-expanded="false"]::before { content: '▸ '; }
.legende-couche-compte { font-weight: 400; color: var(--encre-pale); }
/* METTRE EN ÉVIDENCE (e8) : la ligne est un bouton ; la choisie se marque. */
.legende-couche-choix {
    display: flex; align-items: flex-start; gap: 7px; width: 100%; padding: 2px 4px; margin: -2px -4px;
    border: 0; border-radius: 4px; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.legende-couche-choix:hover { background: var(--fond-survol, rgba(15, 23, 42, 0.05)); }
.legende-couche-choix[aria-pressed="true"] { background: rgba(15, 23, 42, 0.08); box-shadow: inset 2px 0 0 var(--encre); }
.legende-couche-tout-afficher {
    margin: 0 0 6px; padding: 2px 8px; border: 1px solid rgba(15, 23, 42, 0.2); border-radius: 4px;
    background: none; font: inherit; font-size: 11px; cursor: pointer;
}
.legende-couche-texte { display: flex; flex-direction: column; min-width: 0; }
/* Le nom sur une ou deux lignes, jamais tronqué. */
.legende-couche-nom { font-size: 11.5px; line-height: 1.3; overflow-wrap: anywhere; }
.legende-couche-mention,
.legende-couche-note { font-size: 10.5px; line-height: 1.3; color: var(--encre-pale); }
.legende-couche-pied {
    margin: 6px 0 0; font-size: 10.5px; line-height: 1.4; color: var(--encre-pale);
    overflow-wrap: anywhere;
}
/* « LIRE LES N AUTRES RÉSERVES » EST UNE CIBLE, PAS UN LIEN DANS UNE PHRASE :
 * seul sur sa ligne, il mesurait 158 × 20 px à 390. Il prend 24 px de haut,
 * comme les autres cibles du lot F (WCAG 2.5.8 ; e0, 78, 03/10). La taille de
 * sa police reste celle du bloc : la charte la change en v1.7. */
.reserves-plus { min-height: 24px; display: inline-flex; align-items: center; }
