/* ==========================================================================
   ARBITRAGES APPLIQUÉS À LA LIVRAISON — 2026-09-09
   Cette feuille est le fichier livré par l'atelier « Large », à deux
   différences près, décidées explicitement :

   1. --ink vaut #0F1320 et non #191330. Trois points d'écart, invisibles à
      l'œil, mais c'est le bleu nuit historique de la marque : le fil avec
      l'identité existante ne coûte rien et se garde.
   2. Le rouge #E60028 ne figure PAS dans cette feuille. La direction
      « Large » porte l'action en violet #6338E0 ; le rouge reste employé
      pour les seules suppressions en administration, via --e-danger.
      C'est un changement d'identité assumé, pas un oubli.

   COHABITATION — cette feuille ne remplace pas fluvoria-sg.css, elle vit à
   côté. Les deux ne peuvent PAS être chargées ensemble : elles stylent
   toutes deux html, body, *, h1, .btn, .rail et .vide, et déclarent des
   jetons de même nom (--line, --muted) avec des valeurs différentes. La
   séparation se fait donc par GABARIT, pas par cascade :

       base-sg.html    -> fluvoria-sg.css     (écrans pas encore repris)
       base-large.html -> fluvoria-large.css  (écrans repris)

   Un écran migré change son {% extends %} et rien d'autre. fluvoria-sg.css
   sera supprimée quand le dernier gabarit l'aura quittée, et pas avant.

   3. Le sélecteur du lien de rail est étendu à `.rail form button`, et
      `.rail form` passe en `display:contents`. La déconnexion est un POST —
      `/logout` n'accepte que POST, et un lien GET qui déconnecte se
      déclenche au préchargement du navigateur. Le livrable ne prévoyait pas
      d'action de rail en formulaire. Aucune classe nouvelle, aucune valeur
      dupliquée : le même composant accepte un second élément.

   AJOUT AU SYSTÈME — le menu du compte. Le livrable n'en prévoit pas et
   quatre destinations doivent partir du bandeau. Il est construit avec les
   valeurs existantes uniquement (--paper, --r-feuille, --sh, --r-ctl, --fill)
   et signalé comme un ajout, pas comme une reprise. Voir le bloc « AJOUT AU
   SYSTÈME » plus bas.

   POLICES — auto-hébergées, aucun appel sortant. Plus Jakarta Sans est la
   fonte variable (un fichier pour 400/600/700/800), IBM Plex Mono est en
   deux fichiers statiques. Sous-ensemble latin, comme Archivo.
   ========================================================================== */
/* Les @font-face sont dans `atomes.css` : la fiche les demande aussi, et
   elle se rend désormais sous une coquille qui ne charge pas ce fichier. */

/* ==========================================================================
   FLUVORIA — Direction « Large »  ·  fluvoria-large.css
   SIGNATURE : des feuilles blanches qui flottent sur un fond lilas, un rayon
   qui varie selon la hiérarchie, et un violet qui n'apparaît que trois fois
   par écran — le bouton d'action, les nombres-clés, la ligne sélectionnée.

   LES PARTIS PRIS
   1. Le fond est lilas pâle (#F4F2FB), teinté vers l'accent. Jamais un gris
      d'interface : c'est le fond qui signe, avant toute couleur d'accent.
   2. Le rayon EST la hiérarchie : 18 px les feuilles, 14 px le bouton
      principal, 11 px les vignettes, 10 px les commandes, plein rond les
      jetons et les onglets. Un rayon unique partout annulerait le système.
   3. Une seule ombre dans l'écran, portée par les feuilles. Tout le reste se
      sépare par un filet ou par le vide.
   4. Le violet a trois emplois, pas quatre : action, nombre-clé, sélection.
      Un quatrième besoin de violet signale une hiérarchie ratée.
   5. Plus Jakarta Sans 800 sur les titres et les villes, à −.03em. Plex Mono
      tabulaire pour les seuls chiffres qui se comparent.
   6. L'aération est structurelle : rang de 60 px, rail de 236 px, commandes
      de 40 px, bouton de 46 px. La densité se gagne au filtre, pas au
      tassement — un écran qui tasse est un écran qui filtre mal.

   CE QUE ÇA COÛTE
   Le rang de 60 px montre onze lignes là où un rang de 40 en montrerait
   dix-sept : les filtres et le plafond de 200 lignes ne sont pas des options.
   Le fond lilas oblige à vérifier chaque contraste deux fois — sur le fond ET
   sur la feuille. Et l'ombre unique demande de la discipline : dès qu'un
   deuxième objet en porte une, la feuille cesse de flotter.

   RETIRÉ AVANT LIVRAISON : le grand rayon en bas du bandeau. À cette échelle
   il ne se lisait plus comme un rayon de feuille mais comme un ornement.

   TECHNIQUE
   Aucun framework, aucune compilation. Polices auto-hébergeables (Plus
   Jakarta Sans 400/600/700/800, IBM Plex Mono 400/500). Icônes en sprite SVG
   inline en tête de gabarit ; chaque <svg class="ic"> porte width ET height
   en ATTRIBUTS — sans eux, un symbole se déploie à 300 px de haut le temps
   que la feuille charge. Nomenclature reprise de fluvoria-atelier-2.css.
   ========================================================================== */
:root{
  --ground:#F4F2FB; --paper:#FFFFFF; --sunk:#F8F7FD; --fill:#EEEBF8;
  --line:#EAE7F4; --line-2:#D9D4EC;
  --ink:#0F1320; --body:#453D63; --muted:#6B6389; --tert:#6B6389;
  /* --tert porte du texte de 13-14 px : libellés de mesures, valeurs absentes,
     décomptes, plafonds. Il doit donc tenir 4,5:1 sur les CINQ fonds où on le
     pose — paper, ground, sunk, accent-soft, panne-bg. #7C7498 n'y arrivait
     pas (3,71 à 4,37) ; #6B6389 passe partout (4,74 à 5,57). Le jeton garde
     son nom : il désigne un rang de hiérarchie, pas une valeur distincte. */
  --accent:#6338E0; --accent-deep:#4F2AC4; --accent-soft:#EFEAFD;
  --e-contact:#0E6E86; --e-ok:#15734F; --e-relance:#8A2E77; --e-warn:#9A5410;
  /* AJOUT AU SYSTÈME — la couleur des SUPPRESSIONS (2026-09-09).
     Le dossier « Large » donne quatre couleurs d'état et pas de cinquième :
     il ne dessine aucune action destructrice. L'arbitrage du 2026-09-09 en
     demande pourtant une — « le rouge, uniquement pour les suppressions
     admin ». Quatre écrans migrés employaient donc `var(--e-danger)` SANS
     REPLI sur une variable que rien ne déclarait : la couleur ne rendait
     rien, et une variable absente ne lève aucune erreur. Trouvé le 2026-09-09
     en cherchant ce motif dans tout le dépôt, pas à l'œil.

     La valeur n'est pas inventée : c'est `--red-2` de la charte. Le rouge
     principal `#E60028` a été mesuré et ÉCARTÉ — 4,78:1 sur blanc mais
     **4,02:1 sur son propre fond doux**, sous le seuil AA, dans l'usage même
     que l'arbitrage autorise. `#B8001F` donne 6,87:1 sur blanc et 5,78:1 sur
     le fond doux. Même famille, même charte, contraste tenu. */
  --e-danger:#B8001F; --danger-soft:#FDE6EA;
  /* AJOUT DU DOSSIER « fiche superposée » (2026-09-09) — le SEUL jeton
     nouveau qu'il demande. Une fenêtre modale doit se détacher plus
     franchement qu'une feuille : la règle « une seule ombre dans l'écran »
     vaut pour le PLAN de la page, et une fenêtre est au-dessus de ce plan. */
  --sh-fiche:0 2px 8px rgba(25,19,48,.10), 0 40px 90px -28px rgba(25,19,48,.46);
  /* Le fond et le filet d'un bandeau de PANNE. Ils viennent du bloc de
     jetons de la maquette (`--panne-bg`, `--panne-line`) et n'étaient pas
     encore déclarés : trois écrans les écrivaient en dur. */
  --panne-bg:#FDF3E8; --panne-line:#F0D5B0;
  /* L'encre au survol : `--ink` éclairci. Un bouton d'encre qui ne réagit
     pas au survol se lit comme désactivé. */
  --ink-2:#2A2447;
  --panne-bg:#FDF3E8; --panne-line:#F0D5B0;
  --src-lbc:#FFE7CF; --src-sl:#FFDCE4; --src-it:#D6E9FB; --src-fb:#DFE2FC; --src-ah:#D2F0E1;
  --src-ink:#3B3358;
  --font:'Plus Jakarta Sans',system-ui,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,monospace;
  --r-feuille:18px; --r-btn:14px; --r-vignette:11px; --r-ctl:10px; --r-jeton:999px;
  --sh:0 1px 2px rgba(25,19,48,.04), 0 8px 24px -10px rgba(25,19,48,.14);
  --t:140ms; --ease:cubic-bezier(.2,.7,.3,1);
  --rail-w:236px; --rang:60px; --ctl:40px; --btn:46px; --onglet:38px; --ic:19px;
}
*,*::before,*::after{box-sizing:border-box}
html{font:400 14.5px/1.5 var(--font);color:var(--body);background:var(--ground);-webkit-font-smoothing:antialiased}
body{margin:0}
h1{margin:0;font-size:34px;font-weight:800;letter-spacing:-.03em;color:var(--ink);line-height:1.05}
h2{margin:0;font-size:24px;font-weight:800;letter-spacing:-.03em;color:var(--ink);line-height:1.1}
h3{margin:0;font-size:17px;font-weight:800;letter-spacing:-.02em;color:var(--ink)}
a{color:var(--ink);text-decoration:none} a:hover{color:var(--accent-deep)}
button,input,select,textarea{font:inherit;color:inherit}
:focus{outline:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.masthead :focus-visible{outline-color:#fff}
/* Le mouvement répond à une action, jamais à une arrivée : pas de fondu-montée,
   pas de transition sur les cartes au chargement. */
@media (prefers-reduced-motion:reduce){*{transition-duration:1ms !important;animation-duration:1ms !important}}

/* Icônes — width/height en attributs sur chaque <svg>, cette règle ne fait
   que confirmer la taille une fois la feuille chargée. */
/* Mono : prix, surfaces, compteurs, parcelles. Jamais un libellé. */
.prix,.num{font-family:var(--mono);font-variant-numeric:tabular-nums;letter-spacing:-.02em}

/* Bandeau — encre pleine, sans rayon : il borde l'écran, il ne flotte pas */
.masthead{display:flex;align-items:center;gap:14px;height:64px;padding:0 24px;background:var(--ink)}
.masthead .marque{font-size:16px;font-weight:800;letter-spacing:-.02em;color:#fff}
.masthead .lieu{font-size:14px;color:#B4ADCE;padding-left:14px;border-left:1px solid #3A3157}
.masthead .palette{margin-left:auto;display:flex;align-items:center;gap:9px;height:36px;padding:0 16px;border-radius:var(--r-jeton);background:#2A2247;color:#B4ADCE;font-size:14px;transition:background var(--t) var(--ease),color var(--t) var(--ease)}
.masthead .palette:hover{background:#372D5C;color:#fff}
.masthead .compte{display:flex;align-items:center;gap:10px;margin-left:16px;color:#E6E2F2;font-size:14px;font-weight:600}
.masthead .avatar{width:32px;height:32px;border-radius:var(--r-vignette);background:var(--accent);color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700}


/* ── AJOUT AU SYSTÈME — menu du compte (2026-09-09) ─────────────────────────
   Le livrable place le compte dans le bandeau (nom + pastille) et s'arrête là.
   Or quatre destinations doivent partir de ce point — Paramètres, Extension,
   Abonnement, Déconnexion — et les étaler en permanence dans le rail les met
   au même rang que le travail du jour, ce qu'elles ne sont pas.

   Le menu ne fabrique aucune valeur nouvelle : c'est une feuille (--paper,
   --r-feuille, --sh, l'ombre unique du système) qui porte des lignes réglées
   comme les liens du rail. Il ne s'ouvre qu'au clic, comme la palette. La
   déconnexion y est un POST, pour la raison dite plus haut.
   ────────────────────────────────────────────────────────────────────────── */
/* `margin-left:auto` vivait sur `.masthead .palette`, retirée le 2026-09-09 :
   sans lui le compte remonterait se coller au nom du cabinet. */
.compte-zone{position:relative;display:flex;align-items:center;margin-left:auto}
.masthead .compte{border:0;font:inherit;cursor:pointer;background:none;
  border-radius:var(--r-jeton);padding:4px 6px 4px 12px;
  transition:background var(--t) var(--ease)}
.masthead .compte:hover{background:#2A2247}
.compte-menu{position:absolute;top:calc(100% + 12px);right:0;z-index:30;
  min-width:232px;padding:6px;background:var(--paper);
  border-radius:var(--r-feuille);box-shadow:var(--sh)}
.compte-menu[hidden]{display:none}
.compte-menu form{display:contents}
.compte-menu a,.compte-menu form button{display:flex;align-items:center;gap:12px;
  width:100%;height:42px;padding:0 12px;border:0;background:none;text-align:left;
  cursor:pointer;font-family:inherit;font-size:14.5px;font-weight:600;
  color:var(--body);border-radius:var(--r-ctl);
  transition:background var(--t) var(--ease),color var(--t) var(--ease)}
.compte-menu a:hover,.compte-menu form button:hover{background:var(--fill);color:var(--ink)}
.compte-menu .ic{color:var(--tert)}
.compte-menu .filet{display:block;height:1px;margin:6px 8px;background:var(--line)}


/* ── AJOUT AU SYSTÈME — la barre basse à quatre entrées (2026-09-09) ────────
   Le livrable est explicite : « sous 640 px, le rail devient une barre
   d'onglets basse de 64 px, QUATRE entrées », et sa maquette les nomme —
   Traiter, Messagerie, Explorer, Plus. Il ne dit pas ce que « Plus » ouvre.

   Ce que « Plus » ouvre ici : les entrées de rail restantes, dans une feuille
   au-dessus de la barre. Aucun lien n'est dupliqué — ce sont les MÊMES
   éléments, que `display:contents` laisse couler dans le rail au-dessus de
   640 px et qui deviennent une feuille en dessous. Un second jeu de liens
   aurait été une seconde liste à tenir à jour.
   ────────────────────────────────────────────────────────────────────────── */
.rail-secondaire{display:contents}
.rail .rail-plus{display:none;border:0;background:none;font:inherit;cursor:pointer;
  width:100%;text-align:left}

.cadre{display:flex;flex-direction:column;min-height:100vh}
.corps{flex:1;min-height:0;display:flex}

/* Rail — l'entrée active est une feuille blanche : c'est la seule chose du
   rail qui porte l'ombre, et son survol la laisse blanche. */
.rail{flex:none;width:var(--rail-w);padding:20px 14px;display:flex;flex-direction:column;gap:3px}
.rail .groupe{padding:16px 12px 6px;font-size:12.5px;font-weight:700;color:var(--tert)}
.rail form{display:contents}
.rail a,.rail form button,.rail .rail-plus{display:flex;align-items:center;gap:12px;height:42px;padding:0 12px;border:0;background:none;width:100%;text-align:left;cursor:pointer;font-family:inherit;border-radius:var(--r-ctl);color:var(--body);font-size:14.5px;font-weight:600;transition:background var(--t) var(--ease),color var(--t) var(--ease)}
.rail a .ic,.rail form button .ic,.rail .rail-plus .ic{color:var(--tert)}
.rail a:hover,.rail form button:hover,.rail .rail-plus:hover{background:var(--fill);color:var(--ink)}
.rail a[aria-current=page]{background:var(--paper);color:var(--ink);box-shadow:var(--sh)}
.rail a[aria-current=page]:hover{background:var(--paper)}
.rail a[aria-current=page] .ic{color:var(--accent)}
.rail .compteur{margin-left:auto;font-family:var(--mono);font-size:13px;font-weight:500;color:var(--tert)}
.rail a[aria-current=page] .compteur{color:var(--accent)}
.rail .avancement{margin-top:auto;padding:16px;border-radius:var(--r-feuille);background:var(--paper);box-shadow:var(--sh)}
.jauge{position:relative;display:block;height:7px;border-radius:var(--r-jeton);background:var(--fill);margin-top:10px}
.jauge>span{position:absolute;inset:0 auto 0 0;border-radius:var(--r-jeton);background:var(--accent)}

.travail{flex:1;min-width:0;display:flex;flex-direction:column;padding:20px 24px 24px 10px;gap:18px;overflow:auto}
.page-tete{display:flex;align-items:center;gap:22px}
.onglets{display:flex;gap:6px;margin-left:6px}
/* La bande d'onglets se BORNE, à toute largeur. Le titre et cinq onglets sur
   une ligne de flex dépassaient à 768 px comme à 390 px — « Sans suite » était
   coupé net — et le débordement, n'étant contenu par rien, faisait panoter la
   PAGE. Un débordement local se voit ; un débordement de page se confond avec
   un défilement normal, et c'est ce qui lui a permis de tenir.
   Quand les onglets tiennent, ces trois lignes ne changent rien : `auto` ne
   crée de zone de défilement que s'il y a de quoi défiler. */
.page-tete{min-width:0}
.onglets{min-width:0;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}
.onglets::-webkit-scrollbar{display:none}
.onglets a{flex:0 0 auto}

/* ── L'OMBRE DE DÉFILEMENT, POUR TOUTES LES BANDES ─────────────────────────
   Une bande qui défile coupait net à son bord : rien ne disait qu'il restait
   des onglets, des filtres ou des modèles au-delà. On la croit finie, et trois
   vues sur cinq deviennent introuvables. Constaté sur téléphone le 2026-09-09.

   Quatre couches de fond plutôt qu'un dégradé fixe. Les deux premières sont en
   `local` : elles défilent AVEC le contenu et viennent masquer l'ombre quand on
   atteint le bout. Les deux radiales sont en `scroll` : elles restent collées
   aux bords. Le tout s'ajuste seul — pas d'ombre quand il n'y a rien à défiler,
   donc jamais de fausse promesse, et rien à faire au redimensionnement. Un
   dégradé constant aurait estompé le dernier onglet même lorsqu'il est le
   dernier.

   Les couches `local` doivent porter LE FOND SOUS LA BANDE, sinon elles
   peignent une tache au lieu de masquer. D'où les deux déclinaisons : la
   plupart des bandes sont sur le fond de page, les jetons de modèle sont sur
   une feuille blanche. Une bande nouvelle rejoint l'une des deux listes.

   `.ex-filtres` est en `display:contents` hors du téléphone : il ne peint
   alors aucun fond, et cette règle y est simplement sans effet.            */
.onglets, .ex-barre .ex-filtres, .ms-files{
  --bande-fond:var(--ground); --bande-fond-0:rgba(244,242,251,0)}
/* La fenêtre de la fiche est une FEUILLE BLANCHE : ses trois bandes sont sur
   `--paper`, pas sur le fond de page. Classées d'abord avec les autres, elles
   peignaient une tache lilas au bord d'un en-tête blanc. */
.ms-modeles, .tr-modeles{
  --bande-fond:var(--paper);  --bande-fond-0:rgba(255,255,255,0)}
.onglets, .ex-barre .ex-filtres, .ms-files, .ms-modeles, .tr-modeles{
  background:
    linear-gradient(to right, var(--bande-fond) 34%, var(--bande-fond-0)) left center,
    linear-gradient(to left,  var(--bande-fond) 34%, var(--bande-fond-0)) right center,
    radial-gradient(farthest-side at 0% 50%, rgba(25,19,48,.14), rgba(25,19,48,0)) left center,
    radial-gradient(farthest-side at 100% 50%, rgba(25,19,48,.14), rgba(25,19,48,0)) right center;
  background-repeat:no-repeat;
  background-size:34px 100%, 34px 100%, 15px 100%, 15px 100%;
  background-attachment:local, local, scroll, scroll}
.onglets a{display:flex;align-items:center;gap:8px;height:var(--onglet);padding:0 16px;border-radius:var(--r-jeton);font-size:14px;font-weight:600;color:var(--muted);transition:background var(--t) var(--ease),color var(--t) var(--ease)}
.onglets a:hover{background:var(--fill);color:var(--ink)}
.onglets a[aria-current=page]{background:var(--ink);color:#fff}
.onglets .compteur{font-family:var(--mono);font-size:12.5px;opacity:.75}

.barre{display:flex;gap:10px;align-items:center}
.recherche{flex:1;display:flex;align-items:center;gap:10px;height:var(--ctl);padding:0 16px;border-radius:var(--r-ctl);background:var(--paper);color:var(--tert);font-size:14px;box-shadow:var(--sh)}
.filtre{height:var(--ctl);padding:0 15px;border-radius:var(--r-ctl);background:var(--paper);color:var(--body);font-size:14px;font-weight:600;display:flex;align-items:center;gap:8px;cursor:pointer;border:0;box-shadow:var(--sh);transition:color var(--t) var(--ease),background var(--t) var(--ease)}
.filtre:hover{color:var(--ink)}
.filtre[aria-pressed=true]{background:var(--accent-soft);color:var(--accent-deep);box-shadow:none}
.plan{display:flex;gap:18px;align-items:flex-start;flex:1;min-height:0}

/* Feuille — l'unique porteuse d'ombre */
.feuille{background:var(--paper);border-radius:var(--r-feuille);box-shadow:var(--sh)}

/* Registre — rang de 60 px : onze lignes visibles, pas dix-sept */
.registre{flex:1;min-width:0;overflow:hidden;container-type:inline-size}
.registre .thead,.registre .rang{display:grid;grid-template-columns:minmax(0,1fr) 132px 122px 46px;gap:18px;align-items:center;padding:0 22px}
.registre .thead{height:44px;font-size:12.5px;font-weight:700;color:var(--tert);border-bottom:1px solid var(--line)}
.registre .rang{height:var(--rang);border-bottom:1px solid var(--line);transition:background var(--t) var(--ease)}
.registre .rang:hover{background:var(--sunk)}
.registre .rang[aria-selected=true]{background:var(--accent-soft)}
.registre .ville{display:block;font-size:15.5px;font-weight:800;letter-spacing:-.025em;color:var(--ink)}
.registre .meta{display:block;font-size:13px;color:var(--muted)}
.registre .prix{font-size:14.5px;font-weight:600;color:var(--ink)}
.registre .rang[aria-selected=true] .prix{color:var(--accent-deep)}
.pied{padding:16px 22px;font-size:13px;color:var(--tert)}
/* Registre en colonne étroite (fiche latérale, tiroir, panneau de 352 px) :
   les quatre pistes fixes du registre large totalisent 354 px gouttières
   comprises — dans 352 px, minmax(0,1fr) se résout à 0 et la vignette sort de
   la boîte. Sous 400 px de large, on replie statut et prix. */
.registre.etroit .thead,.registre.etroit .rang{grid-template-columns:minmax(0,1fr) 46px;gap:14px}
/* Même classe de bug sur les listes à deux colonnes de texte (canaux, équipe) :
   une piste en `auto` se dimensionne sur son contenu le plus large — ici la
   ligne de détail secondaire — et prend sa largeur AVANT le minmax(0,1fr) du
   nom, qui se réduit jusqu'à tronquer l'identifiant de la ligne. La piste
   secondaire se borne toujours, et son texte reçoit l'ellipse. */
.liste-etat{display:grid;grid-template-columns:34px minmax(0,1fr) minmax(0,132px);gap:14px;align-items:center}
.liste-etat .detail{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (max-width:639px){.liste-etat{grid-template-columns:34px minmax(0,1fr) minmax(0,116px)}}
.registre.etroit .col-large{display:none}
@container (max-width:400px){
  .registre .thead,.registre .rang{grid-template-columns:minmax(0,1fr) 46px;gap:14px}
  .registre .col-large{display:none}
}
/* Vignette de source : fond de marque assez clair pour porter l'encre */
/* La variante PETITE, pour la ligne d'identité de la fiche superposée :
   26x20, la mesure de la maquette. Même fond, même encre, même famille —
   redéfinir une vignette ailleurs aurait donné deux composants à tenir. */

/* État — texte seul, couleur et graisse, casse de phrase */
.etat{font-size:14px;font-weight:700;color:var(--tert)}
/* ── Le badge « publication vérifiée » ──────────────────────────────────
   Ses RÈGLES vivent dans `crm_db.badge_publication_data` : quatre états, et
   quatre seulement — vérifiée en ligne, dépubliée, invérifiable, vérification
   bloquée. Jamais vérifiée ne donne RIEN, parce qu'une absence de verdict est
   une absence d'information, pas une anomalie à montrer.

   Ces quatre classes vivaient dans un `<style>` placé APRÈS `{% endmacro %}`
   dans `_badge_publication.html`, un fichier chargé par `{% from … import %}`.
   Jinja jette la sortie du corps d'un fichier importé : cette feuille n'a
   JAMAIS atteint une seule page. Les quatre états se rendaient donc
   identiques, en texte nu — la règle était appliquée dans la couche des
   données et perdue dans la couche voisine. Trouvé le 2026-09-09 en cherchant
   ce motif après les trois du lot 5. */
.pub-badge{display:inline-block;vertical-align:middle;padding:3px 9px;
  border-radius:var(--r-jeton);font-family:var(--mono);font-size:11px;
  font-weight:500;letter-spacing:.02em;white-space:nowrap}
.pub-ok{background:rgba(22,127,74,.12);color:var(--e-ok)}
.pub-ko{background:var(--danger-soft);color:var(--e-danger)}
.pub-na{background:var(--fill);color:var(--tert)}
.pub-wait{background:#FDF0E0;color:var(--e-warn)}

/* Fiche */
.fiche{width:352px;flex:none;overflow:hidden}
.fiche .tete{padding:24px 24px 20px}
.fiche .tete .sous{margin:6px 0 0;font-size:14px;color:var(--muted)}
.def{padding:4px 24px 20px;display:flex;flex-direction:column}
.def .l{display:flex;justify-content:space-between;align-items:center;gap:14px;padding:11px 0;border-top:1px solid var(--line);font-size:14px}
.def .l dt{color:var(--muted)}
.def .l dd{margin:0;color:var(--ink);font-weight:600;text-align:right}
.def .l dd.absent{color:var(--tert);font-weight:400}
.fiche .pied{padding:0 24px 24px}

/* Commandes — hauteur fixe, donc jamais de repli du libellé : c'est la rangée
   qui se replie (.vide .actions{flex-wrap:wrap}), pas la commande. */
.btn,.btn-secondaire,.btn-discret,.filtre,.onglets a,.masthead .palette{white-space:nowrap}
.btn{display:flex;align-items:center;justify-content:center;gap:9px;width:100%;height:var(--btn);border:0;border-radius:var(--r-btn);background:var(--accent);color:#fff;font-size:15px;font-weight:700;cursor:pointer;transition:background var(--t) var(--ease)}
.btn:hover{background:var(--accent-deep)}
.btn-secondaire{background:var(--paper);color:var(--ink);box-shadow:var(--sh);height:var(--ctl);border-radius:var(--r-ctl);font-size:14px;width:auto;padding:0 18px}
.btn-secondaire:hover{background:var(--sunk)}
.btn-discret{background:transparent;color:var(--muted);box-shadow:none;height:var(--ctl);border-radius:var(--r-ctl);font-size:14px;width:auto;padding:0 14px}
.btn-discret:hover{background:var(--fill);color:var(--ink)}
.btn[disabled]{background:var(--fill);color:var(--tert);cursor:not-allowed}
.btn[disabled]:hover{background:var(--fill)}

/* Champ — étiquette liée, jamais un placeholder en guise d'étiquette */
.champ{display:flex;flex-direction:column;gap:6px}
.champ label{font-size:13.5px;font-weight:600;color:var(--ink)}
.champ input,.champ select,.champ textarea{height:var(--ctl);border:1px solid var(--line-2);border-radius:var(--r-ctl);background:var(--paper);padding:0 14px;color:var(--ink);width:100%;transition:border-color var(--t) var(--ease)}
.champ textarea{height:auto;min-height:120px;padding:12px 14px;line-height:1.7;font-size:15.5px}
.champ input::placeholder{color:var(--tert)}
.champ input:focus-visible{border-color:var(--accent);outline:3px solid var(--accent-soft);outline-offset:0}
.champ .prix{text-align:right}
.champ .aide{font-size:13px;color:var(--muted)}
.champ.erreur input{border-color:var(--e-warn);background:var(--panne-bg)}
.champ.erreur .aide{color:var(--e-warn)}

/* Vide ≠ panne : le vide propose l'action suivante, la panne nomme la cause,
   l'heure du dernier succès et le moyen de réessayer. */
.vide{padding:56px 24px;text-align:center}
.vide h3{margin:0 0 6px}
.vide p{margin:0 auto;max-width:420px;font-size:14.5px;color:var(--muted)}
.vide .actions{margin-top:18px;display:flex;flex-wrap:wrap;gap:10px;justify-content:center}
.panne{display:flex;gap:12px;padding:18px 20px;border-radius:var(--r-feuille);background:var(--panne-bg);border:1px solid var(--panne-line)}
.panne .ic{color:var(--e-warn);margin-top:2px}
.panne strong{display:block;font-size:16px;font-weight:800;letter-spacing:-.02em;color:var(--ink)}
.panne p{margin:6px 0 0;font-size:14px;color:var(--body)}
.squelette{display:block;height:13px;border-radius:var(--r-jeton);background:var(--fill)}

@media (max-width:1023px){:root{--rail-w:76px} .rail a span:not(.compteur),.rail .groupe,.rail .avancement{display:none} .rail a{justify-content:center;padding:0} .fiche{width:300px}}
@media (max-width:639px){
  /* Cibles tactiles : onglets de file et boutons de bandeau compris — la
     navigation entre files est présente sur tous les écrans. */
  :root{--ctl:44px;--btn:48px;--rang:64px;--onglet:44px}
  .panne button{height:44px}
  .masthead{height:56px;padding:0 16px} .masthead .lieu,.masthead .palette,.masthead .compte span:not(.avatar){display:none}
  .corps{flex-direction:column}
  .travail{padding:16px 16px 76px}
  /* Rail en barre d'onglets basse, fiche en tiroir */
  .rail{position:fixed;inset:auto 0 0 0;width:auto;height:64px;flex-direction:row;padding:8px;gap:6px;background:var(--paper);box-shadow:0 -8px 24px -12px rgba(25,19,48,.18);z-index:20}
  .rail a{flex:1;flex-direction:column;gap:3px;height:100%;font-size:11.5px}
  .rail a[aria-current=page]{background:var(--accent-soft);box-shadow:none;color:var(--accent-deep)}
  .rail a[aria-current=page] .compteur{display:none}
  .plan{flex-direction:column}
  .fiche{position:fixed;left:0;right:0;bottom:64px;width:auto;max-height:72vh;overflow-y:auto;border-radius:var(--r-feuille) var(--r-feuille) 0 0;z-index:21}
  .registre .thead,.registre .rang{grid-template-columns:minmax(0,1fr) auto;gap:12px;padding:0 16px}
  .registre .col-large{display:none}
  input,select,textarea{font-size:16px}
}

/* ═══ LE TÉLÉPHONE — EXPLORER ET LE REGISTRE ══════════════════════════════
   Constaté sur un iPhone le 2026-09-09 : la page PANOTAIT. On perdait le bord
   gauche de tout l'écran — le titre lisait « lorer », le champ de recherche et
   les lignes étaient coupés des deux côtés. Trois causes distinctes, plus une
   perte d'information qu'aucune capture n'avait signalée.

   Ce bloc vient APRÈS le bloc mobile du livrable : à spécificité égale c'est
   l'ordre du fichier qui tranche, et plusieurs de ces règles corrigent les
   siennes.                                                                  */
@media (max-width:639px){

  /* ── 1. LE DÉBORDEMENT ────────────────────────────────────────────────────
     `.page-tete` posait le titre et cinq onglets sur UNE ligne de flex. Aucun
     des deux ne rétrécit sous son contenu : leur somme dépassait les 390 px,
     et comme rien n'encadrait ce débordement, c'est la PAGE ENTIÈRE qui
     devenait panotable. Un débordement local se serait vu ; un débordement de
     page se confond avec un défilement normal, et c'est pour ça qu'il a tenu.
     Le titre prend sa ligne, les onglets défilent dans leur PROPRE bande. */
  .page-tete{flex-direction:column;align-items:stretch;gap:12px}
  .page-tete h1{font-size:26px;line-height:1.1}

  /* Les marges négatives annulent le rembourrage de `.travail` : le premier et
     le dernier onglet touchent alors le bord de l'écran. Sans cela la bande
     semble buter avant la fin, et on croit qu'il n'y a plus rien à voir. */
  .onglets{margin:0 -16px;padding:0 16px;gap:8px;overflow-x:auto;
           scrollbar-width:none;-ms-overflow-style:none;
           scroll-snap-type:x proximity;overscroll-behavior-x:contain}
  .onglets::-webkit-scrollbar{display:none}
  .onglets a{flex:0 0 auto;scroll-snap-align:start}

  /* ── 2. LES FILTRES EN LIGNES DÉCHIQUETÉES ────────────────────────────────
     `flex-wrap:wrap` répartissait les six commandes en deux jetons, puis un
     seul, puis deux — trois lignes irrégulières qui mangeaient un tiers de
     l'écran. La recherche prend toute la largeur ; les filtres deviennent une
     bande qui défile, comme les onglets.

     ATTENTION À LA SPÉCIFICITÉ. Ces règles doivent battre celles du <style>
     d'`explorer.html`, qui est émis APRÈS cette feuille : à spécificité égale
     c'est lui qui gagne, où qu'on écrive. `.ex-filtres` seul (0,1,0) se
     faisait donc écraser par le `display:contents` de l'écran et la bande
     retombait en lignes déchiquetées — corrigé, puis re-cassé, puis remesuré.
     `.ex-barre .ex-filtres` (0,2,0) tranche sans dépendre de l'ordre. */
  .ex-barre{gap:10px}
  .ex-barre .recherche{flex:1 0 100%}
  .ex-barre .ex-filtres{flex:1 0 100%;display:flex;gap:8px;margin:0 -16px;
              padding:0 16px;overflow-x:auto;scrollbar-width:none;
              -ms-overflow-style:none;
              scroll-snap-type:x proximity;overscroll-behavior-x:contain}
  .ex-barre .ex-filtres::-webkit-scrollbar{display:none}
  .ex-barre .ex-filtres>*{flex:0 0 auto;scroll-snap-align:start}
  .ex-barre .ex-raz{flex:0 0 auto}
  .ex-barre .ex-total{flex:1 0 100%;margin-left:0;text-align:right}


  /* ── 3. LE PRIX N'EXISTAIT PAS SUR TÉLÉPHONE ──────────────────────────────
     `.col-large{display:none}` repliait le registre à deux pistes — le bien et
     la vignette — en emportant LE PRIX ET L'ÉTAT. Un agent qui parcourait ses
     569 annonces au téléphone ne voyait donc aucun prix et aucune action : la
     liste devenait un annuaire de villes. C'est la perte la plus coûteuse des
     trois, et la seule qu'aucune capture n'avait signalée, parce qu'une
     colonne absente ne laisse pas de trace — elle ne déborde pas, elle ne se
     chevauche pas, elle n'est simplement plus là.

     Le rang devient une CARTE à deux rangées, ce qui rend les quatre
     informations sans les serrer :

         ville ....................... prix
         état ........................ vignette                              */
  .registre .thead{display:none}          /* trois libellés de colonnes qui ne
                                             surmontent plus de colonnes */
  .registre .rang{
    height:auto;min-height:84px;padding:14px 16px;
    grid-template-columns:minmax(0,1fr) auto;
    grid-template-areas:"bien prix" "etat src";
    gap:6px 14px;align-items:center}
  .registre .rang>span:first-child{grid-area:bien;min-width:0}
  .registre .col-large{display:block}     /* annule le repli du bloc précédent */
  .registre .etat{grid-area:etat;justify-self:start;font-size:13px}
  .registre .prix{grid-area:prix;justify-self:end;white-space:nowrap;
                  font-family:var(--mono);font-variant-numeric:tabular-nums}
  .registre .src{grid-area:src;justify-self:end}

  /* ── 4. LE RAIL RECOUVRAIT LA DERNIÈRE LIGNE ──────────────────────────────
     La barre basse est fixe et haute de 64 px ; le rembourrage de 76 px ne
     laissait que 12 px, et l'indicateur d'accueil de l'iPhone mangeait le
     reste. `env(safe-area-inset-bottom)` vaut zéro là où il n'y a pas
     d'encoche : la règle est sans effet sur les appareils qui n'en ont pas. */
  /* ── 5. UN LIBELLÉ QUI NE SE REPLIE PAS FIXE UNE LARGEUR MINIMALE ─────────
     `white-space:nowrap` sur `.btn` donne au bouton une largeur minimale égale
     à son texte, et `width:100%` ne descend JAMAIS sous cette borne. « Envoyer
     et passer à la suivante » mesure 479 px : l'écran Traiter → Réponses
     débordait donc à 519 px de contenu pour 390 px de fenêtre, et panotait
     sous le doigt exactement comme Explorer. Trouvé par la mesure, pas à
     l'œil — la capture montrait un bouton coupé, ce qui se lit comme un
     cadrage serré et non comme un défaut.
     Sur téléphone le libellé se replie et le bouton prend la hauteur qu'il
     lui faut. Les jetons de filtre et les onglets gardent leur `nowrap` : ils
     vivent dans des bandes qui défilent, c'est leur raison d'être. */
  .btn,.btn-secondaire,.btn-discret{white-space:normal;height:auto;
    min-height:var(--btn);padding:10px 18px;line-height:1.25}

  /* Et les actions secondaires s'EMPILENT. Une rangée de trois donnait
     « Ouvrir dans la messagerie » replié sur trois lignes à côté de deux
     boutons tassés — trois largeurs différentes pour trois actions de même
     rang. Pleine largeur, elles se visent au pouce et se lisent d'un coup.
     `.tr-actions .tr-actions-sec` (0,2,0) : le <style> de `traiter.html` est
     émis après cette feuille, à spécificité égale c'est lui qui gagnerait. */
  .tr-actions .tr-actions-sec{flex-direction:column}

  .rail{height:auto;min-height:64px;
        padding:8px 8px calc(8px + env(safe-area-inset-bottom,0px))}
  .travail{padding:16px 16px calc(88px + env(safe-area-inset-bottom,0px))}
  .fiche{bottom:calc(64px + env(safe-area-inset-bottom,0px))}
}

/* ═══ LE TOUCHER ══════════════════════════════════════════════════════════
   Un doigt n'a pas de survol. iOS applique quand même `:hover` au toucher et
   le LAISSE COLLÉ jusqu'au toucher suivant : après avoir tapé une ligne, elle
   restait grisée comme si elle était encore sous le curseur, en concurrence
   visuelle avec la ligne réellement sélectionnée. On rend le survol aux seuls
   appareils qui pointent, et on donne au toucher son propre retour — immédiat,
   et qui s'efface tout seul.                                                */
@media (hover:none){
  .registre .rang:hover{background:none}
  .registre .rang[aria-selected=true]:hover,
  .registre .rang.on:hover{background:var(--accent-soft)}
  .registre .rang:active{background:var(--sunk)}
  .onglets a:hover{background:none;color:var(--muted)}
  .onglets a[aria-current=page]:hover{background:var(--ink);color:var(--paper)}
  .onglets a:active{background:var(--fill)}
}

/* « Plus » n'existe QUE dans la barre basse. Cette ligne vient après la règle
   groupée `.rail a, .rail form button, .rail .rail-plus` du bloc rail : sans
   elle, le bouton héritait de `display:flex` et apparaissait dans le rail de
   bureau, sous « Admin ». Vu à la capture. */
.rail .rail-plus{display:none}

/* ── AJOUT AU SYSTÈME (suite) — la barre basse, en FIN de feuille ───────────
   Ce bloc doit venir après les règles `.rail a` du livrable : à spécificité
   égale, c'est l'ordre du fichier qui tranche, et déclaré plus haut il se
   faisait écraser la hauteur et le rembourrage du bouton « Plus », qui
   sortait alors de l'alignement des trois autres onglets. Vu à la capture. */
@media (max-width:639px){
  .rail-secondaire{display:none;position:fixed;left:8px;right:8px;bottom:72px;z-index:22;
    flex-direction:column;padding:6px;background:var(--paper);
    border-radius:var(--r-feuille);box-shadow:var(--sh)}
  .rail-secondaire[data-ouvert]{display:flex}
  /* Dans la feuille, les entrées reprennent la forme d'un lien de rail —
     ligne, icône à gauche, libellé lisible — et non celle d'un onglet bas. */
  .rail-secondaire a{flex:none;flex-direction:row;justify-content:flex-start;
    gap:12px;height:42px;padding:0 12px;font-size:14.5px}
  .rail-secondaire a span:not(.compteur){display:inline}
  .rail-secondaire a[aria-current=page]{background:var(--accent-soft);color:var(--accent-deep)}
  /* Le rail tablette (76 px, icônes seules) masque les libellés à partir de
     1023 px. Sous 640 px ce n'est plus un rail mais une barre d'onglets, et
     la maquette du livrable y montre bien un libellé sous chaque icône : on
     les rend. Sans ceci, trois onglets muets voisinaient un « Plus » légendé,
     et l'ensemble se lisait de travers. Vu à la capture. */
  .rail a span:not(.compteur){display:inline}
  .rail .rail-plus{display:flex;flex:1;flex-direction:column;gap:3px;height:100%;
    font-size:11.5px;align-items:center;justify-content:center;text-align:center}
  .rail .rail-plus[aria-expanded=true]{background:var(--accent-soft);color:var(--accent-deep)}
}
