/* GeoGardien — feuille de styles applicative.
   Les jetons de conception (couleurs, typographie, espacements, formes) sont
   dans tokens.css, chargé avant ce fichier. Aucune couleur ne doit être écrite
   en dur ici : elle échapperait au moteur de marque multi-tenant et resterait
   figée chez un client dont la charte est différente. */
/* Observatoire Orpaillage — feuille de style unique.
   Pas de framework : la page doit rester légère sur une connexion rurale, et
   toute règle ici est une règle que nous avons écrite et relue. */


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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--police);
  /* Sélectionne la chasse condensée de Bahnschrift lorsque le moteur passe par
     la FAMILLE plutôt que par le nom d'instance. Sans effet sur les replis, qui
     sont condensés par dessin et n'ont pas d'axe de chasse. */
  font-stretch: condensed;
  font-size: var(--t-base);
  line-height: var(--interligne);
  color: var(--encre);
  background: var(--fond);
}

/* Les titres passent en serif, le reste de l'interface garde la pile système.
   Ce contraste de genre — récit en serif, données en sans — donne à
   l'application une voix sans coûter un octet sur les tableaux et les listes,
   qui représentent l'essentiel du texte affiché. */
h1, h2, h3 {
  font-family: var(--police-titre);
  line-height: var(--interligne-titre);
  letter-spacing: var(--chasse-titre);
  margin: 0 0 var(--e-2);
  font-weight: 600;
  text-wrap: balance;   /* évite le mot orphelin en fin de titre ; ignoré ailleurs */
}
h1 { font-size: var(--t-2xl); }
h2 { font-size: var(--t-xl); }
h3 { font-size: var(--t-l); margin-top: var(--e-5); letter-spacing: 0; }
p { margin: 0 0 var(--e-3); }
a { color: var(--marque); }
a:hover { color: var(--marque-fort); }
code { font-family: var(--police-chiffres); font-size: .875em; }

/* Les nombres se lisent en colonne : chasse fixe et chiffres alignés, sinon
   les ordres de grandeur ne s'empilent pas et la comparaison visuelle est
   fausse. */
.num, td.num, th.num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

.saut-contenu {
  position: absolute; left: -9999px;
  background: var(--vert-fonce); color: var(--surface); padding: .6rem 1rem; z-index: 100;
}
.saut-contenu:focus { left: .5rem; top: .5rem; }

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

/* ── En-tête ─────────────────────────────────────────────────────────────── */

.entete {
  display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;
  padding: .65rem 1.25rem;
  background: var(--vert-fonce); color: var(--surface);
}
.entete a { color: var(--surface); text-decoration: none; }

.marque { display: flex; align-items: center; gap: .65rem; }
.marque__logo { width: 30px; height: 30px; color: var(--marque-bord); flex: none; }

/* Le symbole est peint par un MASQUE, pas recopié dans la page : le fichier ne
   fournit que sa forme, la couleur vient de `currentColor`. Deux raisons.
     • Le poids. Le tracé pèse 4,4 Ko compressés, quand la page d'accueil
       entière en fait 2,0 : l'inclure en ligne dans chaque page, comme le
       faisait l'ancien triangle, la triplerait — inacceptable en 2G.
       En masque, c'est une requête unique et mise en cache.
     • La marque. `background-color: currentColor` suit la couleur du tenant,
       exactement comme le faisait `fill="currentColor"` sur l'ancien tracé. */
.marque__logo--symbole {
  display: block;
  background-color: currentColor;
  -webkit-mask: url("/assets/img/logo-symbole.svg") center / contain no-repeat;
          mask: url("/assets/img/logo-symbole.svg") center / contain no-repeat;
}
/* Sans masque, `background-color` peindrait un carré plein de 30 px. On efface
   plutôt le symbole : le nom du produit reste écrit juste à côté, donc la
   marque tient toujours. Aucun navigateur sachant faire tourner cette
   application (service worker, modules ES) n'atterrit ici — c'est une ceinture,
   pas un cas attendu. */
@supports not ((mask-image: url("#")) or (-webkit-mask-image: url("#"))) {
  .marque__logo--symbole { display: none; }
}

/* Logo raster (branding tenant) : dimensionné en hauteur, ratio préservé.
   Pastille blanche pour rester lisible quelle que soit la couleur du bandeau. */
.marque__logo--img { width: auto; height: 34px; max-width: 150px; object-fit: contain;
  background: var(--surface); border-radius: var(--rayon); padding: 3px 6px; }
.marque strong { display: block; font-size: .98rem; letter-spacing: .01em; }
.marque small { display: block; font-size: .72rem; opacity: .78; }

.entete__nav { display: flex; gap: .25rem; flex-wrap: wrap; margin-left: auto; }
.entete__nav a {
  padding: .45rem .7rem; border-radius: var(--rayon);
  font-size: .9rem; opacity: .88;
}
.entete__nav a:hover { background: rgb(255 255 255 / 12%); opacity: 1; }
.entete__nav a[aria-current="page"] { background: rgb(255 255 255 / 18%); opacity: 1; font-weight: 600; }

.entete__compte { display: flex; align-items: center; gap: .75rem; }
.compte__nom { font-size: .85rem; text-align: right; line-height: 1.3; }

/* Application de terrain (PatrolSIG) : chrome minimal, sans navigation, teinté
   du bleu de l'appli agent ; la déconnexion reste alignée à droite. */
.entete--terrain { background: var(--etat-info-encre); }
.entete--terrain .marque__logo { color: var(--etat-info-doux); }
.entete--terrain .entete__compte { margin-left: auto; }
.compte__nom small { display: block; opacity: .72; font-size: .75rem; }

/* ── Bandeaux et messages ────────────────────────────────────────────────── */

.bandeau {
  padding: .6rem 1.25rem; font-size: .875rem;
  border-bottom: 1px solid var(--bord);
}
.bandeau--attention { background: var(--terre-clair); color: var(--etat-estime-encre); }
.bandeau--info { background: var(--bleu-clair); color: var(--etat-info-encre); }

.message {
  padding: .7rem .9rem; border-radius: var(--rayon);
  border-left: 4px solid; font-size: .9rem; margin: 0 0 1rem;
}
.message--attention { background: var(--terre-clair); border-color: var(--ambre); color: var(--etat-estime-encre); }
.message--info { background: var(--bleu-clair); border-color: var(--bleu); color: var(--etat-info-encre); }
.message--succes { background: var(--vert-clair); border-color: var(--vert); color: var(--marque-encre); }
.message--erreur { background: var(--rouge-clair); border-color: var(--rouge); color: var(--etat-critique-encre); }

/* ── Structure ───────────────────────────────────────────────────────────── */

.contenu {
  max-width: var(--largeur-max);
  margin: 0 auto; padding: 1.5rem 1.25rem 3rem;
}
body.public .contenu { max-width: 1080px; }

.page-entete {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 1.25rem;
}
.page-entete__sous { color: var(--encre-douce); font-size: .9rem; margin: 0; }
.page-entete__actions { display: flex; gap: .5rem; flex-wrap: wrap; }

.grille-2 {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
  gap: 1rem; margin-bottom: 1rem;
}

/* Bordure OU ombre, pas les deux. Un panneau cerné d'un filet et posé sur une
   ombre se détache deux fois du fond ; empilés à huit sur un tableau de bord —
   dix-neuf sur la page d'administration — ces cartes flottantes produisent
   exactement le rendu de gabarit que ce projet doit éviter. Le filet seul suffit
   à délimiter, et la page redevient dense et calme au lieu de bouillonner. */
.panneau {
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon-l); padding: var(--e-4);
}
/* Un titre de panneau n'est pas un titre de page. L'échelle globale porte h2 à
   28 px, juste sur une surface éditoriale ; au-dessus d'un tableau à 14 px, dans
   une page qui en empile huit, il crie. Le titre situe le panneau, il ne
   l'annonce pas. */
.panneau > h2 { font-size: var(--t-l); letter-spacing: 0; margin-bottom: var(--e-3); }
.panneau > h3 { font-size: var(--t-m); margin-top: var(--e-4); }

/* ── Titres de commande : la serif s'arrête ici ─────────────────────────────
   Dans une surface de COMMANDES, un h2 n'est pas un titre : c'est une étiquette
   de section, balisée en titre pour la navigation au lecteur d'écran. La
   distinction n'est pas typographique mais fonctionnelle — un titre porte la
   voix de la page, une étiquette range des contrôles.

   Sans cette règle, la display atterrissait sur des libellés de 11,8 px en
   capitales interlettrées : une serif à cette taille, dans ce traitement, se
   lit plus mal que la pile système. Elle y perdait sa raison d'être ET sa
   lisibilité. */
.panneau-carte h2, .panneau-carte h3,
.carte-outils h2, .carte-outils h3,
.carte-export h2, .carte-export h3,
.carte-resultats h2, .carte-resultats h3,
.carte-detection__entete h2,
.fiche-flottante h2, .fiche-flottante h3,
.legende h2, .legende h3,
.pil-filtres h2, .pil-filtres h3,
.pil-bloc h2, .pil-bloc h3,
.pil-kpi h2, .pil-kpi h3,
.panneau-section__titre,
.pil-filtres__titre, .pil-synthese__titre, .pil-plan__titre,
.carte-resultats__pied-titre {
  font-family: var(--police);
  font-weight: 650;
  /* La chasse resserrée des titres display n'a pas de sens sous 16 px : elle y
     colle les lettres au lieu de les tenir. Les règles propres à chaque
     étiquette (capitales interlettrées, par exemple) reprennent la main plus
     bas dans la feuille. */
  letter-spacing: normal;
}
.panneau__aide { color: var(--encre-douce); font-size: var(--t-s); }
.vide { color: var(--encre-tres-douce); font-style: italic; padding: .75rem 0; }

/* ── Indicateurs ─────────────────────────────────────────────────────────── */

/* Sept indicateurs de même taille ne disent pas lequel compte. Les deux qui
   répondent à « quelle est l'ampleur en ce moment » prennent la tête ; les
   autres tiennent une rangée compacte au-dessous. */
.indicateurs {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  gap: var(--e-3); margin-bottom: var(--e-6);
}
.carte-indicateur {
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon-l); padding: var(--e-3) var(--e-4);
}
.carte-indicateur__valeur {
  font-size: var(--t-xl); font-weight: 650; line-height: 1.1; margin: 0;
  color: var(--marque-fort); font-variant-numeric: tabular-nums;
}
.carte-indicateur__unite { font-size: var(--t-s); font-weight: 500; margin-left: .2rem; color: var(--encre-douce); }
.carte-indicateur__libelle { font-size: var(--t-s); color: var(--encre-douce); margin: var(--e-1) 0 0; }

@media (min-width: 48rem) {
  .carte-indicateur--tete { grid-column: span 2; padding: var(--e-4) var(--e-5); }
  .carte-indicateur--tete .carte-indicateur__valeur {
    font-family: var(--police-titre);
    font-size: var(--t-3xl); font-weight: 600; letter-spacing: var(--chasse-titre);
  }
  .carte-indicateur--tete .carte-indicateur__libelle { font-size: var(--t-base); }
}

/* Estimation : DEUX canaux, le filet tireté et l'étiquette. Le premier survit à
   une impression en noir et blanc, le second au daltonisme. La distinction
   mesure/estimation ne doit jamais tenir à la seule couleur — un chiffre dérivé
   repris pour un constat de terrain engage des moyens publics sur une géométrie. */
.carte-indicateur--estime { border-style: dashed; border-color: var(--etat-estime-bord); }
.carte-indicateur__nature {
  display: inline-block; margin: var(--e-2) 0 0; padding: .1rem .4rem;
  background: var(--etat-estime-doux); color: var(--etat-estime-encre);
  border: 1px solid var(--etat-estime-bord);
  border-radius: var(--rayon); font-size: var(--t-xs); font-weight: 600;
  text-transform: uppercase; letter-spacing: .03em; cursor: help;
}

/* ── Tableaux ────────────────────────────────────────────────────────────── */

.tableau { width: 100%; border-collapse: collapse; font-size: .875rem; }
.tableau th, .tableau td {
  padding: .5rem .6rem; text-align: left; border-bottom: 1px solid var(--bord);
  vertical-align: top;
}
.tableau thead th {
  font-size: .76rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--encre-douce); font-weight: 640; border-bottom: 2px solid var(--bord-fort);
}
.tableau tbody tr:hover { background: var(--surface-douce); }
.tableau .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tableau .num--alerte { color: var(--rouge); font-weight: 640; }
.tableau--compact th, .tableau--compact td { padding: .35rem .5rem; font-size: .82rem; }
.tableau--liste { background: var(--surface); border: 1px solid var(--bord); border-radius: var(--rayon-l); }
.cellule-texte { max-width: 22rem; color: var(--encre-douce); }
.detail-preuve { max-width: 26rem; font-size: .8rem; color: var(--encre-douce); word-break: break-word; }

/* Les tableaux larges défilent dans leur propre conteneur : la page ne doit
   jamais défiler horizontalement sur un téléphone. */
.panneau > .tableau, .tableau--liste { display: table; }
@media (max-width: 720px) {
  .panneau, .contenu > .tableau--liste { overflow-x: auto; }
}

/* ── Étiquettes et badges ────────────────────────────────────────────────── */

.etiquette {
  display: inline-block; padding: .1rem .45rem; border-radius: 999px;
  font-size: .74rem; font-weight: 620; text-transform: lowercase;
  background: var(--surface-douce); color: var(--encre-douce);
  border: 1px solid var(--bord-fort); white-space: nowrap;
}
.etiquette--grande { font-size: .85rem; padding: .25rem .7rem; }

/* ── Deux axes, deux vocabulaires ───────────────────────────────────────────
   Ce composant rendait indistinctement deux choses de nature différente :
   l'ÉTAT d'un site observé, et l'ISSUE d'une décision humaine. La confusion
   produisait une contradiction visible en production — « actif » partageait la
   règle de « confirmé » et de « succès », donc le vert de marque, alors que la
   carte et la légende peignent un site actif en ROUGE (--etat-critique).

   Un agent voyait donc le même site en rouge sur la carte et en vert dans le
   tableau. Sur un produit dont l'objet est de hiérarchiser l'urgence, un site
   activement exploité et jamais traité est l'état le PLUS grave : lui donner la
   couleur du succès inverse la lecture.

   Les états d'un site suivent désormais exactement l'échelle de la carte. */
.etiquette--actif    { background: var(--etat-critique-doux); color: var(--etat-critique-encre); border-color: var(--etat-critique-bord); }
.etiquette--suspecte { background: var(--etat-estime-doux);   color: var(--etat-estime-encre);   border-color: var(--etat-estime-bord); }

/* Issue d'une décision : un acte accompli, pas un état du terrain. */
.etiquette--confirme, .etiquette--succes {
  background: var(--marque-doux); color: var(--marque-encre); border-color: var(--marque-bord);
}
/* En cours d'instruction — l'acte est engagé, pas terminé. */
.etiquette--nouveau, .etiquette--en_revue, .etiquette--planifie {
  background: var(--etat-suivi-doux); color: var(--etat-suivi-encre); border-color: var(--etat-suivi-bord);
}
.etiquette--rejete, .etiquette--echec {
  background: var(--rouge-clair); color: var(--etat-critique-encre); border-color: var(--etat-critique-bord);
}
/* ── États d'un compte ──────────────────────────────────────────────────────
   Trois états, trois couleurs, et surtout trois SENS distincts :
     actif     — vert   : le compte fonctionne ;
     désactivé — orange : suspension réversible, décidée côté client ;
     supprimé  — rouge  : départ définitif, décidé par l'éditeur.
   L'orange n'est pas un rouge atténué : il dit « en attente d'une décision »,
   là où le rouge dit « la décision est prise et ne se reprend pas ». Les deux
   partageaient auparavant la même étiquette rouge, ce qui revenait à présenter
   une suspension d'une journée comme un départ définitif. */
.etiquette--compte_actif {
  background: var(--marque-doux); color: var(--marque-encre); border-color: var(--marque-bord);
}
.etiquette--compte_desactive {
  background: var(--etat-suivi-doux); color: var(--etat-suivi-encre); border-color: var(--etat-suivi-bord);
}
.etiquette--compte_supprime {
  background: var(--rouge-clair); color: var(--etat-critique-encre); border-color: var(--etat-critique-bord);
}

.etiquette--rehabilite, .etiquette--sans_donnee, .etiquette--inactif, .etiquette--doublon {
  background: var(--bleu-clair); color: var(--etat-info-encre); border-color: var(--etat-info-doux);
}

.badge {
  display: inline-block; padding: .05rem .35rem; border-radius: var(--rayon);
  font-size: .68rem; font-weight: 680; text-transform: uppercase; letter-spacing: .03em;
}
.badge--croise { background: var(--vert-fonce); color: var(--surface); }
.alerte-aire { color: var(--terre); font-weight: 600; }

/* Badges de priorité de la file de revue */
.etiquette--croise { background: var(--vert-clair); color: var(--marque-encre); border-color: var(--marque-bord); }
.etiquette--aire   { background: var(--etat-estime-doux); color: var(--etat-estime-encre); border-color: var(--etat-estime-bord); }

/* Barre d'action par lot (revue des détections) */
.barre-lot {
  position: sticky; top: .5rem; z-index: 20;
  display: flex; gap: .6rem; align-items: center; flex-wrap: wrap;
  padding: .6rem .85rem; margin: 0 0 1rem;
  background: var(--surface); border: 1px solid var(--bord-fort);
  border-radius: var(--rayon-l);
  /* Seule ombre conservee de l'espace agent : cette barre est STICKY, elle
     passe reellement par-dessus la liste et doit s'en detacher. */
  box-shadow: var(--ombre-l);
}
.select-detection { width: 1.1rem; height: 1.1rem; vertical-align: middle; margin-right: .3rem; }
.lien-discret { font-size: .75rem; color: var(--encre-tres-douce); }

/* ── Boutons et formulaires ──────────────────────────────────────────────── */

.bouton {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .45rem .85rem; border-radius: var(--rayon); border: 1px solid transparent;
  font: inherit; font-size: .875rem; font-weight: 600; cursor: pointer;
  text-decoration: none; transition: background .12s, border-color .12s;
}
.bouton:disabled { opacity: .55; cursor: not-allowed; }
.bouton--principal { background: var(--vert); color: var(--surface); }
.bouton--principal:hover:not(:disabled) { background: var(--vert-fonce); color: var(--surface); }
.bouton--secondaire { background: var(--surface); color: var(--vert-fonce); border-color: var(--bord-fort); }
.bouton--secondaire:hover:not(:disabled) { background: var(--surface-douce); }
.bouton--discret {
  background: transparent; color: var(--encre-douce); border-color: var(--bord);
  font-size: .8rem; padding: .3rem .6rem;
}
.bouton--discret:hover:not(:disabled) { background: var(--surface-douce); color: var(--encre); }
.bouton--grand { padding: .7rem 1.4rem; font-size: 1rem; }
.bouton--large { width: 100%; }

.formulaire { display: flex; flex-direction: column; gap: .85rem; max-width: 34rem; }
.formulaire--inline { flex-direction: row; align-items: flex-end; flex-wrap: wrap; max-width: none; }
.formulaire--grille {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: .85rem; max-width: none;
}
.formulaire--grille button { grid-column: 1 / -1; justify-self: start; }
.champ--large { grid-column: 1 / -1; }

.champ { display: flex; flex-direction: column; gap: .25rem; }
.champ label { font-size: .82rem; font-weight: 600; color: var(--encre-douce); }
.champ__aide { font-size: .78rem; color: var(--encre-tres-douce); margin: 0; }
.champ input, .champ select, .champ textarea, .barre-filtres input, .barre-filtres select {
  padding: .45rem .6rem; border: 1px solid var(--bord-fort); border-radius: var(--rayon);
  font: inherit; font-size: .9rem; background: var(--surface); color: var(--encre);
  min-height: 2.4rem;
}
.champ textarea { resize: vertical; }
.champ__mdp { display: flex; gap: .4rem; }
.champ__mdp input { flex: 1; }

.formulaire__erreur {
  background: var(--rouge-clair); color: var(--etat-critique-encre); padding: .55rem .8rem;
  border-radius: var(--rayon); font-size: .85rem; margin: 0;
}

.barre-filtres {
  display: flex; gap: .75rem; align-items: flex-end; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon-l); padding: .85rem; margin-bottom: 1rem;
}

.bascule { display: flex; align-items: center; gap: .45rem; font-size: .875rem; cursor: pointer; padding: .2rem 0; }
.bascule input { width: 1.05rem; height: 1.05rem; accent-color: var(--vert); }

.groupe { border: 1px solid var(--bord); border-radius: var(--rayon); padding: .8rem; margin: 0 0 1rem; }
.groupe legend { font-size: .82rem; font-weight: 660; padding: 0 .35rem; color: var(--encre-douce); }

.repli-bloc { border: 1px solid var(--bord); border-radius: var(--rayon-l); padding: 1rem; background: var(--surface-douce); }
.repli-bloc h3 { margin-top: 0; }
.dessin-controles { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; margin: .6rem 0; }
.dessin-etat { font-size: .82rem; color: var(--encre-douce); }
.repli { margin-top: 1rem; border-top: 1px solid var(--bord); padding-top: .75rem; }
.repli summary { cursor: pointer; font-weight: 600; font-size: .9rem; color: var(--vert); }
.repli[open] summary { margin-bottom: .75rem; }

.definitions { display: grid; grid-template-columns: auto 1fr; gap: .3rem .9rem; font-size: .875rem; margin: 0; }
.definitions dt { color: var(--encre-douce); }
.definitions dd { margin: 0; font-variant-numeric: tabular-nums; }
/* ══ DataViz — poste de pilotage ═══════════════════════════════════════════
   Tableau de bord institutionnel : sobre, hiérarchisé, imprimable en A4 paysage.
   Espacement généreux, ombres légères, arrondis modérés — l'information
   prioritaire doit s'identifier immédiatement.

   PALETTE (variables préfixées --pil- pour ne pas entrer en conflit avec les
   couleurs de marque du tenant, injectées dynamiquement dans le gabarit). */

.pilotage {
  display: grid; grid-template-columns: 280px 1fr; gap: 24px;
  align-items: start; background: var(--pil-fond);
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  font-size: 14px; color: var(--pil-encre);
}
@media (max-width: 1100px) { .pilotage { grid-template-columns: 1fr; gap: 16px; } }

/* ── Colonne de filtres ─────────────────────────────────────────────────── */
.pil-filtres {
  position: sticky; top: 16px; background: var(--pil-sidebar);
  border: 1px solid var(--pil-bord); border-radius: var(--pil-rayon);
  padding: 16px; box-shadow: var(--pil-ombre);
}
.pil-filtres__titre {
  font-size: 12px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--pil-encre-2); margin: 0 0 16px; font-weight: 700;
}
.pil-groupe { margin-bottom: 20px; }
.pil-groupe h3 {
  font-size: 12px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--pil-encre-2); margin: 0 0 8px; font-weight: 700;
}
.pil-champ { display: block; margin-bottom: 8px; color: var(--pil-encre-2); font-size: 13px; }
.pil-champ input, .pil-champ select {
  width: 100%; font-size: 13px; padding: 6px 8px; margin-top: 2px;
  border: 1px solid var(--pil-bord); border-radius: var(--pil-rayon-s);
  background: var(--pil-surface); color: var(--pil-encre);
}
/* Raccourcis de période : boutons, plus directs qu'une liste déroulante. */
.pil-raccourcis { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 8px; }
.pil-raccourcis button {
  flex: 1 1 auto; padding: 5px 8px; font-size: 12px; cursor: pointer;
  border: 1px solid var(--pil-bord); border-radius: var(--pil-rayon-s);
  background: var(--pil-surface); color: var(--pil-encre-2);
}
.pil-raccourcis button[aria-pressed="true"] {
  background: var(--pil-encre); border-color: var(--pil-encre); color: var(--surface); font-weight: 600;
}
.pil-cases { display: grid; gap: 6px; }
.pil-cases label {
  display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13px;
}
.pil-liste {
  width: 100%; font-size: 13px; padding: 4px; color: var(--pil-encre);
  border: 1px solid var(--pil-bord); border-radius: var(--pil-rayon-s);
  background: var(--pil-surface);
}
.pil-reset {
  width: 100%; font-size: 13px; padding: 8px; cursor: pointer;
  border: 1px solid var(--pil-bord); border-radius: var(--pil-rayon-s);
  background: var(--pil-surface); color: var(--pil-encre);
}
.pil-reset:hover { background: var(--pil-bord); }

/* Pastille de criticité — même code partout : filtres, carte, tableau, détail. */
.feu { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex: none; }
.feu--rouge  { background: var(--pil-critique); }
.feu--orange { background: var(--pil-suivi); }
.feu--vert   { background: var(--pil-maitrise); }

/* ── En-tête ────────────────────────────────────────────────────────────── */
.pil-entete {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 24px; flex-wrap: wrap; margin-bottom: 16px;
}
.pil-entete h1 { margin: 0 0 8px; font-size: 18px; color: var(--pil-encre); }
.pil-source { font-size: 12px; color: var(--pil-encre-2); text-align: right; }
.pil-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.pil-chip {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  background: var(--pil-surface); color: var(--pil-encre); border: 1px solid var(--pil-bord);
  border-radius: 999px; padding: 4px 10px; font-size: 12px; font-weight: 600;
}
.pil-chip:hover { border-color: var(--pil-encre-2); }
.pil-chip span { color: var(--pil-encre-2); }

/* ── Bandeau d'alerte (fond rouge à 10 % d'opacité) ─────────────────────── */
.pil-alerte {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  flex-wrap: wrap; background: var(--etat-critique-doux);
  border: 1px solid var(--etat-critique-bord); border-left: 4px solid var(--pil-critique);
  color: var(--etat-critique-encre); border-radius: var(--pil-rayon); padding: 12px 16px;
  font-size: 14px; margin-bottom: 24px;
}
.pil-alerte button {
  background: var(--pil-critique); color: var(--surface); border: 0; cursor: pointer;
  border-radius: var(--pil-rayon-s); padding: 6px 12px; font-size: 13px; font-weight: 600;
}

/* ── Indicateurs (chiffre dominant, variation, sparkline) ───────────────── */
.pil-kpis {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 16px; margin-bottom: 24px;
}
.pil-kpi {
  background: var(--pil-surface); border: 1px solid var(--pil-bord);
  border-radius: var(--pil-rayon); padding: var(--e-4); min-width: 0;
}
/* Le rouge etait ecrit en rgba() : hors jetons, il echappait au moteur de
   marque comme a tout controle de coherence — et ne suivait pas la correction
   de la palette d'etat. */
.pil-kpi--alerte { border-color: var(--etat-critique-bord); }
.pil-kpi__lib {
  margin: 0; font-size: 12px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--pil-encre-2); font-weight: 700;
}
.pil-kpi__ligne { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.pil-kpi__val {
  margin: 4px 0 0; font-size: 32px; font-weight: 700; line-height: 1.1;
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere; color: var(--pil-encre);
}
.pil-kpi--alerte .pil-kpi__val { color: var(--pil-critique); }
.pil-kpi__var { font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; }
.pil-kpi__var--hausse { color: var(--pil-maitrise); }
.pil-kpi__var--baisse { color: var(--pil-critique); }
.pil-kpi__sous { margin: 4px 0 0; font-size: 12px; color: var(--pil-encre-2); }
.pil-kpi__spark { display: block; width: 100%; height: 32px; margin-top: 8px; }

/* ── Blocs ──────────────────────────────────────────────────────────────── */
/* Filet OU ombre : la page de pilotage empile ces blocs, l'ombre les faisait
   tous flotter. Seul .pil-filtres, qui est STICKY, conserve la sienne. */
.pil-bloc {
  background: var(--pil-surface); border: 1px solid var(--pil-bord);
  border-radius: var(--pil-rayon); padding: var(--e-4);
  margin-bottom: var(--e-5);
}
.pil-bloc__entete {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 16px; flex-wrap: wrap; margin-bottom: 12px;
}
.pil-bloc h2 { margin: 0; font-size: 16px; color: var(--pil-encre); }
.pil-bloc h2 small { font-weight: 400; color: var(--pil-encre-2); font-size: 13px; }
.pil-aide { margin: 4px 0 0; font-size: 12px; color: var(--pil-encre-2); line-height: 1.45; }
.pil-actions { display: flex; gap: 8px; }
.pil-actions .bouton { font-size: 13px; border-radius: var(--pil-rayon-s); }
.pil-duo {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr));
  gap: 24px;
}
.pil-duo .pil-bloc { margin-bottom: 24px; }

/* ── Carte + panneau de détail ──────────────────────────────────────────── */
.pil-carte-zone { display: grid; grid-template-columns: 1fr 300px; gap: 16px; }
@media (max-width: 900px) { .pil-carte-zone { grid-template-columns: 1fr; } }
.pil-carte {
  height: 460px; border-radius: var(--pil-rayon); border: 1px solid var(--pil-bord);
  background: var(--pil-fond);
}
.pil-detail {
  border: 1px solid var(--pil-bord); border-radius: var(--pil-rayon);
  background: var(--pil-fond); padding: 16px; font-size: 13px;
  max-height: 460px; overflow-y: auto;
}
.pil-detail h3 {
  margin: 0 0 12px; font-size: 16px; display: flex; align-items: center; gap: 8px;
  color: var(--pil-encre);
}
.pil-detail__liste { display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; margin: 0 0 16px; }
.pil-detail__liste dt { color: var(--pil-encre-2); font-size: 12px; }
.pil-detail__liste dd { margin: 0; font-weight: 600; text-align: right; }
.pil-detail__actions { display: grid; gap: 8px; }
.pil-detail__actions .bouton { font-size: 13px; border-radius: var(--pil-rayon-s); text-align: center; }

/* ── Graphiques SVG ─────────────────────────────────────────────────────── */
.pil-graphe { width: 100%; overflow-x: auto; }
.pil-svg { width: 100%; height: auto; display: block; }
.pil-grille { stroke: var(--pil-bord); stroke-width: 1; }
.pil-diagonale { stroke: var(--pil-encre-2); stroke-width: 1.5; stroke-dasharray: 5 5; opacity: .6; }
.pil-axe { font-size: 11px; fill: var(--pil-encre-2); }
.pil-axe--titre { font-size: 12px; fill: var(--pil-encre-2); font-weight: 600; }
.pil-val { font-size: 11px; fill: var(--pil-encre); font-weight: 600; font-variant-numeric: tabular-nums; }
.pil-donut__total { font-size: 24px; font-weight: 700; fill: var(--pil-encre); }
.pil-barre-cliquable { cursor: pointer; transition: opacity .15s; }
.pil-barre-cliquable:hover { opacity: 1; }
.pil-barre-cliquable:focus { outline: 2px solid var(--pil-encre); outline-offset: 1px; }
.pil-legende { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 12px; font-size: 12px; }
.pil-legende__item { display: inline-flex; align-items: center; gap: 6px; color: var(--pil-encre-2); }
.pil-puce { width: 10px; height: 10px; border-radius: var(--rayon-micro); display: inline-block; }

/* ── Tableau de détail ──────────────────────────────────────────────────── */
.pil-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.pil-table thead th {
  text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--pil-encre-2); border-bottom: 2px solid var(--pil-bord);
  padding: 8px 10px; white-space: nowrap; background: var(--pil-surface);
}
.pil-table td {
  padding: 8px 10px; border-bottom: 1px solid var(--pil-bord); vertical-align: middle;
}
.pil-table tbody tr { cursor: pointer; }
/* Fond léger par criticité : la ligne se lit avant même d'être parcourue. */
/* Teintes de ligne : elles etaient ecrites en rgba() avec les ANCIENNES
   couleurs du pilotage (#DC3545, #F4A261, #2A9D8F). Elles ont donc echappe a
   l'unification, et le tableau gardait les teintes d'avant pendant que les
   etiquettes portaient les nouvelles. Les jetons « doux » sont opaques : ils
   s'impriment, la ou une couche alpha disparait. */
.pil-table tbody tr.feu-rouge  { background: var(--etat-critique-doux); }
.pil-table tbody tr.feu-orange { background: var(--etat-suivi-doux); }
.pil-table tbody tr.feu-vert   { background: var(--etat-maitrise-doux); }
.pil-table tbody tr:hover { background: var(--pil-sidebar); }
.pil-ligne--active { outline: 2px solid var(--pil-encre); outline-offset: -2px; }
.pil-table .num { text-align: right; font-variant-numeric: tabular-nums; }
/* Jauge intégrée : lecture du classement sans quitter la cellule. */
.pil-jauge { min-width: 92px; }
.pil-jauge__piste {
  display: block; height: 4px; background: var(--pil-bord); border-radius: 999px;
  margin-top: 3px; overflow: hidden;
}
.pil-jauge__piste span { display: block; height: 100%; background: var(--pil-encre); }
.pil-pagination {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 16px 0 4px; font-size: 13px; color: var(--pil-encre-2);
}
.pil-pagination button {
  background: var(--pil-surface); border: 1px solid var(--pil-bord); cursor: pointer;
  border-radius: var(--pil-rayon-s); padding: 5px 12px; font-size: 13px; color: var(--pil-encre);
}
.pil-pagination button:disabled { opacity: .45; cursor: default; }
.pil-pied {
  font-size: 12px; color: var(--pil-encre-2); padding: 8px 0 24px;
  text-align: center; line-height: 1.5;
}

/* ── Barre d'outils cartographiques ────────────────────────────────────────
   Conteneur partagé par les modules (mesure, sélection, export). Flottante en
   haut à droite de la carte, au-dessus des couches Leaflet. */
/* Une seule colonne de groupes, alignée à droite. Les groupes se suivent de
   haut en bas dans l'ordre d'usage : fond de carte, mesure, sélection, export.
   Le z-index dépasse celui des contrôles Leaflet (1000) : la barre est la
   couche d'interaction principale, rien ne doit passer devant. */
.carte-outils {
  position: absolute; top: .6rem; right: .6rem; z-index: 1100;
  display: flex; flex-direction: column; gap: .4rem; align-items: flex-end;
  /* Neuf outils empilés font environ 330 px : sur une fenêtre basse, la barre
     défile plutôt que de déborder sous la carte. Les menus déroulants sont
     rattachés au conteneur de la carte, pas à la barre : ce défilement ne les
     rogne donc pas. */
  max-height: calc(100% - 1.2rem); overflow-y: auto;
}
/* Groupes empilés verticalement : la barre reste sur une seule colonne de
   34 px, quel que soit le nombre d'outils. Disposés en ligne, les groupes de
   mesure et de sélection s'étalaient vers la gauche et mangeaient la carte —
   ce qui est justement ce qu'on veut regarder. Le séparateur passe donc du
   bord droit au bord inférieur. */
.carte-outils__groupe {
  display: flex; flex-direction: column; background: rgb(255 255 255 / 96%);
  border: 1px solid var(--bord); border-radius: var(--rayon);
  box-shadow: 0 1px 5px rgb(0 0 0 / 25%); overflow: hidden;
}
.carte-outil {
  width: 34px; height: 34px; display: grid; place-items: center; cursor: pointer;
  background: transparent; border: 0; border-bottom: 1px solid var(--bord);
  color: var(--encre-douce); padding: 0;
}
.carte-outils__groupe .carte-outil:last-child { border-bottom: 0; }
.carte-outil svg { width: 19px; height: 19px; }
.carte-outil:hover { background: var(--surface-douce); color: var(--vert-fonce); }
.carte-outil[aria-pressed="true"] { background: var(--vert-fonce); color: var(--surface); }
.carte-outil:focus-visible { outline: 2px solid var(--vert); outline-offset: -2px; }

/* Bandeau de mesure : le résultat courant, lisible sans quitter la carte. */
.carte-mesure-etat {
  position: absolute; left: .6rem; top: .6rem; z-index: 600;
  background: rgb(255 255 255 / 96%); border: 1px solid var(--bord);
  border-left: 3px solid var(--terre); border-radius: var(--rayon);
  padding: .4rem .7rem; font-size: .82rem; font-weight: 600;
  box-shadow: 0 1px 5px rgb(0 0 0 / 20%); max-width: 22rem;
}
/* Curseur en croix pendant une mesure ou une sélection : le geste attendu est
   explicite avant même d'avoir lu l'infobulle du bouton. */
.carte--mesure,
.carte--selection { cursor: crosshair; }

/* Menu de choix du fond de carte, aligné sous son bouton. */
.carte-fonds {
  position: absolute; right: var(--gouttiere-outils); top: .6rem; z-index: 1200;
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon); box-shadow: 0 4px 14px rgb(0 0 0 / 22%);
  padding: .25rem; display: flex; flex-direction: column; min-width: 9.5rem;
}
.carte-fonds[hidden] { display: none; }
.carte-fonds__choix {
  background: transparent; border: 0; border-radius: var(--rayon);
  padding: .38rem .55rem; text-align: left; cursor: pointer;
  font-size: .84rem; color: var(--encre);
}
.carte-fonds__choix:hover { background: var(--surface-douce); }
.carte-fonds__choix[aria-checked="true"] {
  background: var(--vert-clair); color: var(--vert-fonce); font-weight: 650;
}
.carte-fonds__choix[aria-checked="true"]::before { content: '✓ '; }

/* ── Panneau d'export cartographique ───────────────────────────────────────
   Ouvert par le bouton d'export, sous la barre d'outils. Volontairement étroit :
   il ne doit pas masquer la carte qu'on s'apprête à exporter. */
/* Ancré en BAS : le groupe d'export ferme la colonne d'outils, son panneau doit
   s'ouvrir à hauteur de son bouton. Ouvert en haut, il obligeait l'œil à
   remonter toute la barre après un clic tout en bas. */
.carte-export {
  position: absolute; right: var(--gouttiere-outils); bottom: .6rem;
  z-index: 1200; width: 18rem;
  max-height: calc(100% - 1.2rem); overflow-y: auto;
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon); box-shadow: 0 4px 16px rgb(0 0 0 / 25%);
  padding: .8rem;
}

/* Périmètre de l'atlas : trois portées exclusives, le menu déroulant
   n'étant actif que sous l'option qui le concerne. */
.carte-export__perimetre {
  margin: .7rem 0 0; padding: .5rem .6rem;
  border: 1px solid var(--bord); border-radius: var(--rayon);
}
.carte-export__perimetre legend {
  font-size: .76rem; font-weight: 700; color: var(--encre-douce); padding: 0 .3rem;
}
.carte-export__perimetre select {
  width: 100%; margin: .1rem 0 .35rem 1.35rem; max-width: calc(100% - 1.35rem);
  padding: .3rem .4rem; font: inherit; font-size: .8rem;
  border: 1px solid var(--bord-fort); border-radius: var(--rayon);
}
.carte-export__perimetre select:disabled { opacity: .5; }
.carte-export[hidden] { display: none; }
.carte-export h2 { font-size: .92rem; margin: 0 0 .6rem; }
.carte-export__champ { display: block; margin-bottom: .6rem; }
.carte-export__champ span {
  display: block; font-size: .76rem; font-weight: 600;
  color: var(--encre-douce); margin-bottom: .2rem;
}
.carte-export__champ input {
  width: 100%; padding: .35rem .5rem; font: inherit; font-size: .84rem;
  border: 1px solid var(--bord-fort); border-radius: var(--rayon);
}
.carte-export .bascule { font-size: .82rem; }
.carte-export__actions {
  display: flex; flex-direction: column; gap: .35rem;
  margin-top: .7rem; padding-top: .7rem; border-top: 1px solid var(--bord);
}
.carte-export__actions .bouton { width: 100%; font-size: .82rem; }
.carte-export__etat {
  margin: .6rem 0 0; font-size: .76rem; color: var(--encre-douce); min-height: 1.1rem;
}
.carte-export__etat--succes { color: var(--vert); font-weight: 600; }
.carte-export__etat--erreur { color: var(--rouge); font-weight: 600; }

/* Jauge de progression : l'atlas prend jusqu'à une minute, l'utilisateur doit
   voir que le travail avance et non que l'application est figée. */
.carte-export__jauge {
  height: 5px; background: var(--surface-douce); border-radius: var(--rayon-micro);
  overflow: hidden; margin-top: .4rem;
}
.carte-export__jauge[hidden] { display: none; }
.carte-export__jauge span {
  display: block; height: 100%; width: 0; background: var(--vert);
  transition: width .2s ease;
}

/* ── Panneau des résultats d'une requête spatiale ──────────────────────────
   Ancré à droite, sous la barre d'outils. Hauteur bornée : le tableau défile
   dans le panneau, jamais la page. */
/* Les résultats vivent DANS le panneau latéral, en section comme les autres.
   Flottants au-dessus de la carte, ils masquaient précisément la zone qu'on
   venait de sélectionner — et entraient en concurrence avec la barre d'outils
   pour le même coin de l'écran. */
.carte-resultats {
  display: flex; flex-direction: column;
  border: 1px solid var(--bord); border-radius: var(--rayon);
  background: var(--surface); overflow: hidden; max-height: 26rem;
}
.carte-resultats[hidden] { display: none; }
.carte-resultats__entete {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  padding: .55rem .75rem; border-bottom: 1px solid var(--bord);
  background: var(--surface-douce);
}
.carte-resultats__entete h2 { margin: 0; font-size: .95rem; }
.carte-resultats__fermer {
  background: transparent; border: 0; cursor: pointer; font-size: 1.4rem; line-height: 1;
  color: var(--encre-douce); padding: 0 .25rem;
}
.carte-resultats__fermer:hover { color: var(--rouge); }
.carte-resultats__resume {
  margin: 0; padding: .45rem .75rem; font-size: .8rem; font-weight: 600;
  color: var(--encre-douce);
}
.carte-resultats__onglets {
  display: flex; gap: .25rem; padding: 0 .75rem; border-bottom: 1px solid var(--bord);
}
.carte-resultats__onglet {
  background: transparent; border: 0; border-bottom: 2px solid transparent;
  padding: .4rem .6rem; cursor: pointer; font-size: .82rem; color: var(--encre-douce);
}
.carte-resultats__onglet:hover { color: var(--vert-fonce); }
.carte-resultats__onglet[aria-selected="true"] {
  color: var(--vert-fonce); border-bottom-color: var(--vert-fonce); font-weight: 700;
}
.carte-resultats__aide,
.carte-resultats__alerte,
.carte-resultats__erreur {
  margin: .5rem .75rem 0; padding: .4rem .6rem; font-size: .78rem;
  border-radius: var(--rayon); border-left: 3px solid;
}
.carte-resultats__aide   { background: var(--surface-douce); border-color: var(--bord);
                           color: var(--encre-douce); }
.carte-resultats__alerte { background: var(--terre-clair); border-color: var(--ambre);
                           color: var(--etat-estime-encre); }
.carte-resultats__erreur { background: var(--rouge-clair); border-color: var(--rouge);
                           color: var(--etat-critique-encre); }

/* Le tableau prend la place restante et défile seul, dans les deux sens :
   une colonne « Forêt classée » ne doit pas élargir le panneau. */
.carte-resultats__table { flex: 1; overflow: auto; margin-top: .5rem; }
.carte-resultats__table table { width: 100%; border-collapse: collapse; font-size: .78rem; }
.carte-resultats__table th {
  position: sticky; top: 0; z-index: 1; text-align: left; white-space: nowrap;
  background: var(--surface-douce); border-bottom: 1px solid var(--bord);
  padding: .35rem .5rem; font-size: .74rem; text-transform: uppercase;
  letter-spacing: .02em; color: var(--encre-douce);
}
.carte-resultats__table td {
  padding: .3rem .5rem; border-bottom: 1px solid var(--bord);
  white-space: nowrap; max-width: 12rem; overflow: hidden; text-overflow: ellipsis;
}
.carte-resultats__table tbody tr { cursor: pointer; }
.carte-resultats__table tbody tr:hover { background: var(--surface-douce); }
.carte-resultats__table tbody tr[aria-current="true"] {
  background: var(--rouge-clair); box-shadow: inset 3px 0 0 var(--rouge);
}
.carte-resultats__table tbody tr:focus-visible { outline: 2px solid var(--vert); outline-offset: -2px; }
.carte-resultats__pied {
  padding: .5rem .75rem; border-top: 1px solid var(--bord); background: var(--surface-douce);
}
.carte-resultats__pied-titre {
  margin: 0 0 .35rem; font-size: .76rem; font-weight: 600; color: var(--encre-douce);
}
/* Quatre formats sur une grille : à des largeurs de panneau différentes, ils
   se répartissent sur une ou deux lignes sans qu'aucun ne devienne illisible. */
.carte-resultats__formats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(6.2rem, 1fr)); gap: .35rem;
}
.carte-resultats__formats .bouton { width: 100%; font-size: .8rem; padding: .3rem .4rem; }

/* Sur écran étroit, le panneau occupe le bas de la carte plutôt que sa droite :
   30 rem de large ne laisseraient rien voir du contexte cartographique. */
/* Sur écran étroit, la colonne d'outils occupe toute la hauteur du bord droit :
   les panneaux s'arrêtent avant elle plutôt que de la recouvrir — sans quoi le
   bouton qui a ouvert le panneau se retrouve sous le panneau lui-même. */
@media (max-width: 40rem) {
  .carte-resultats { top: auto; left: .6rem; height: 55%; width: auto; }
  .carte-export   { left: .6rem; width: auto; }
}
.mesure-etiquette {
  background: var(--terre); color: var(--surface); border-radius: var(--rayon);
  padding: .1rem .4rem; font-size: .74rem; font-weight: 700; white-space: nowrap;
  box-shadow: 0 1px 3px rgb(0 0 0 / 35%); width: auto !important;
}

/* Vignettes des photos de constat dans les rapports de patrouille.
   Une photo vaut le déplacement qu'elle documente : elle doit être visible
   depuis le rapport, sans avoir à ouvrir chaque constat un par un. */
.vignettes { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .5rem; }
.vignette {
  width: 84px; height: 84px; object-fit: cover; display: block;
  border: 1px solid var(--bord); border-radius: var(--rayon);
  background: var(--surface-douce);
}
.vignette--mini { width: 32px; height: 32px; border-radius: var(--rayon); }
.vignette-fig { margin: 0; width: 84px; }
.vignette-fig figcaption {
  font-size: .68rem; color: var(--encre-douce); line-height: 1.25;
  margin-top: .15rem; text-align: center;
}
.vignette-fig figcaption small { display: block; color: var(--encre-pale); }

/* Galerie repliée : le compte est visible d'emblée, les photos à la demande. */
.galerie > summary {
  display: flex; align-items: center; gap: .4rem; cursor: pointer;
  list-style: none; white-space: nowrap;
}
.galerie > summary::-webkit-details-marker { display: none; }
.galerie__compte {
  font-size: .78rem; font-weight: 600; color: var(--vert);
  text-decoration: underline; text-underline-offset: 2px;
}
.galerie[open] > summary .galerie__compte { color: var(--encre-douce); }
.galerie > summary:hover .galerie__compte { color: var(--vert-fonce); }

/* Réservé aux lecteurs d'écran (légende de tableau). */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Impression A4 paysage : la page doit rester lisible sans perte d'information. */
@media print {
  .pil-filtres, .pil-actions, .pil-pagination { display: none; }
  .pilotage { grid-template-columns: 1fr; background: var(--surface); }
  .pil-bloc { break-inside: avoid; box-shadow: none; }
}

/* Rose des vents de l'application terrain : l'aiguille rouge pointe le NORD et
   tourne à l'inverse du cap de l'appareil. */
.rose-vents {
  width: 52px; padding: 3px 0 2px; background: rgb(255 255 255 / 94%);
  display: flex; flex-direction: column; align-items: center; line-height: 1;
}
.rose-vents svg { width: 34px; height: 34px; display: block; }
.rose__fond { fill: var(--fond); stroke: var(--bord-fort); stroke-width: 1.5; }
.rose__aiguille { transform-origin: 50% 50%; transition: transform .25s ease-out; }
.rose__cap {
  font-size: .64rem; font-weight: 700; color: var(--encre);
  font-variant-numeric: tabular-nums; margin-top: 1px;
}

/* Guidage vers la cible d'une mission (application terrain).
   Lisibilité en plein soleil : contrastes francs, chiffres larges. */
.guidage {
  border: 2px solid var(--bord-fort); border-radius: var(--rayon);
  padding: .7rem .8rem; margin-bottom: .75rem; background: var(--surface);
}
.guidage__entete {
  display: flex; align-items: baseline; justify-content: space-between; gap: .6rem;
}
.guidage__cible { font-weight: 700; }
.guidage__distance { font-size: 1.5rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.guidage__barre {
  height: 8px; border-radius: 999px; background: var(--bord); overflow: hidden; margin: .5rem 0 .4rem;
}
.guidage__barre span { display: block; height: 100%; background: var(--vert); transition: width .4s; }
.guidage__etat { margin: 0; font-size: .85rem; color: var(--encre-douce); }
.guidage--proche { border-color: var(--marque); background: var(--vert-clair); }
.guidage--proche .guidage__etat { color: var(--marque-encre); font-weight: 600; }
.guidage--loin { border-color: var(--ambre); background: var(--terre-clair); }
.guidage--loin .guidage__etat { color: var(--etat-estime-encre); font-weight: 700; }
.guidage--loin .guidage__barre span { background: var(--ambre); }

/* Prévisualisation du site ciblé par une mission de patrouille. */
.apercu-site {
  border: 1px solid var(--bord); border-radius: var(--rayon);
  background: var(--surface-douce); padding: .7rem; display: grid; gap: .7rem;
}
.apercu-site__carte {
  height: 260px; border-radius: var(--rayon); border: 1px solid var(--bord);
  background: var(--surface);
}
.apercu-site__infos { margin: 0; }

/* Liste d'indices : les paires « libellé / valeur » s'enroulent librement.
   (Épingler les dt sur la ligne 1 et les dd sur la ligne 2 créait autant de
   colonnes que d'indices — donc un débordement dès qu'ils se sont multipliés.) */
.definitions--ligne { display: flex; flex-wrap: wrap; gap: .55rem .9rem; }
.definitions--ligne .definitions__paire { min-width: 7.5rem; flex: 0 1 auto; }
.definitions--ligne dt { font-size: .76rem; text-transform: uppercase; letter-spacing: .03em; }
.definitions--ligne dd { font-weight: 600; }

/* ── Pastilles ───────────────────────────────────────────────────────────── */

.pastille { display: inline-block; width: .7rem; height: .7rem; border-radius: 50%; flex: none; }
.pastille--sites, .pastille--actif { background: var(--etat-critique); }
.pastille--suspecte { background: var(--etat-estime); }
.pastille--rehabilite { background: var(--etat-info); }
.pastille--detections, .pastille--detection { background: var(--source-satellite); }
.pastille--signalements, .pastille--signalement { background: var(--source-citoyen); }
.pastille--interventions { background: var(--marque); }

.legende { display: flex; gap: 1rem; flex-wrap: wrap; list-style: none; padding: 0; margin: .5rem 0 0;
           font-size: .8rem; color: var(--encre-douce); }
.legende li { display: flex; align-items: center; gap: .35rem; }

/* ── Graphique ───────────────────────────────────────────────────────────── */

.graphique { width: 100%; min-height: 220px; }
.graphique svg { width: 100%; height: auto; display: block; }

/* ── Hotspots ────────────────────────────────────────────────────────────── */

.liste-hotspots { list-style: none; padding: 0; margin: 0; counter-reset: rang; }
.liste-hotspots li { border-bottom: 1px solid var(--bord); }
.liste-hotspots li:last-child { border-bottom: 0; }
.hotspot { display: flex; gap: .8rem; align-items: center; padding: .55rem .2rem; text-decoration: none; color: inherit; }
.hotspot:hover { background: var(--surface-douce); }
.hotspot__score {
  flex: none; width: 2.6rem; height: 2.6rem; border-radius: 50%;
  display: grid; place-items: center; font-weight: 700; font-size: .9rem;
  background: var(--vert-clair); color: var(--vert-fonce); font-variant-numeric: tabular-nums;
}
.hotspot__corps { display: flex; flex-direction: column; gap: .05rem; min-width: 0; }
.hotspot__corps small { font-size: .78rem; color: var(--encre-douce); }

/* ── Files de travail ───────────────────────────────────────────────────────
   Ce bloc répond à la seule question que se pose un agent en ouvrant la page :
   qu'est-ce qui m'attend ? Il était en BAS, sous sept indicateurs, deux
   graphiques, trois tableaux et un avertissement de cinq lignes. Il ouvre
   désormais la page.

   La distinction entre le tableau de bord et la page de pilotage autorise cette
   posture : /dataviz répond à « comment allons-nous », /tableau-de-bord à
   « que dois-je faire ». Deux publics, deux ordres de lecture. */
.files { display: grid; gap: var(--e-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
.file {
  display: grid; gap: var(--e-1);
  padding: var(--e-4) var(--e-5);
  border: 1px solid var(--marque-bord);
  border-left: 3px solid var(--marque);
  border-radius: var(--rayon);
  text-decoration: none; color: inherit; background: var(--marque-voile);
  transition: background var(--transition), border-color var(--transition);
}
.file:hover { background: var(--marque-doux); border-color: var(--marque); color: inherit; }
.file__nombre {
  font-family: var(--police-titre);
  font-size: var(--t-2xl); font-weight: 600; line-height: 1;
  color: var(--marque-fort);
  font-variant-numeric: tabular-nums lining-nums;
}
.file__libelle { font-size: var(--t-s); color: var(--encre-douce); }

/* Une file vide est une bonne nouvelle : elle ne doit pas réclamer l'attention
   au même titre qu'une file de douze. Sans cette distinction, un tableau de
   bord entièrement traité a l'air aussi urgent qu'un tableau de bord saturé —
   et l'agent cesse de lire le bloc. */
.file--vide {
  border-color: var(--bord); border-left-color: var(--bord-fort);
  background: var(--surface);
}
.file--vide .file__nombre { color: var(--encre-pale); font-family: var(--police); font-weight: 650; }
.file--vide:hover { background: var(--surface-douce); border-color: var(--bord-fort); }

/* ── Carte ───────────────────────────────────────────────────────────────── */

/* ── Page carte ────────────────────────────────────────────────────────────
   La carte prend la place, le panneau se replie. Les commandes occupaient
   auparavant une colonne fixe à gauche pendant que les résultats d'une
   sélection flottaient à droite par-dessus la carte : deux zones concurrentes
   pour un même travail. Tout est réuni à droite, dans un panneau repliable. */
.page-carte {
  display: grid;
  grid-template-columns: 1fr var(--panneau-carte, 380px);
  gap: .75rem;
  align-items: stretch;
}
/* Replié : il ne reste que le rail du bouton de bascule. */
.page-carte[data-panneau="replie"] { --panneau-carte: 2.4rem; }

@media (max-width: 900px) {
  /* Sous cette largeur, deux colonnes ne laissent lire ni l'une ni l'autre :
     le panneau repasse sous la carte, sur toute la largeur. */
  .page-carte { grid-template-columns: 1fr; }
  .page-carte[data-panneau="replie"] { --panneau-carte: auto; }
}

.panneau-carte {
  position: relative; display: flex; min-width: 0;
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon-l); overflow: hidden;
  max-height: min(78vh, 780px);
}
.panneau-carte__contenu {
  flex: 1; min-width: 0; overflow-y: auto; overflow-x: hidden;
  padding: .9rem 1rem 1rem;
}
.page-carte[data-panneau="replie"] .panneau-carte__contenu { display: none; }

/* Bouton de bascule : un rail vertical le long du bord gauche du panneau,
   toujours atteignable, y compris panneau replié. */
.panneau-carte__bascule {
  flex: none; width: 2.3rem; display: flex; flex-direction: column;
  align-items: center; gap: .5rem; padding: .6rem 0;
  background: var(--surface-douce); border: 0;
  border-right: 1px solid var(--bord); cursor: pointer; color: var(--encre-douce);
}
.panneau-carte__bascule:hover { background: var(--vert-clair); color: var(--vert-fonce); }
.panneau-carte__bascule svg { width: 18px; height: 18px; transition: transform .15s ease; }
.page-carte[data-panneau="replie"] .panneau-carte__bascule svg { transform: rotate(180deg); }
.panneau-carte__bascule-texte {
  font-size: .72rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; writing-mode: vertical-rl;
}
@media (max-width: 900px) {
  .panneau-carte { max-height: none; }
  .panneau-carte__bascule { width: auto; flex-direction: row; justify-content: center;
    padding: .45rem; border-right: 0; border-bottom: 1px solid var(--bord); }
  .panneau-carte { flex-direction: column; }
  .panneau-carte__bascule svg { transform: rotate(90deg); }
  .page-carte[data-panneau="replie"] .panneau-carte__bascule svg { transform: rotate(-90deg); }
  .panneau-carte__bascule-texte { writing-mode: horizontal-tb; }
}

.panneau-section { padding-bottom: .8rem; margin-bottom: .8rem; border-bottom: 1px solid var(--bord); }
.panneau-section:last-child { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }
.panneau-section__titre {
  font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--encre-tres-douce); margin: 0 0 .5rem;
}

/* ── Hauteur de la surface cartographique ──────────────────────────────────
   « 78vh, plafonné à 780 px » était une valeur magique, fausse aux deux bouts :
   sur un grand écran la carte restait petite alors que la place abondait ;
   sur mobile, `vh` compte la hauteur SANS la barre d'outils rétractable du
   navigateur, si bien qu'une partie de la carte passait sous le pli — or
   l'agent de terrain est précisément sur mobile.

   `dvh` suit la hauteur réellement disponible. Le repli en `vh` reste déclaré
   AVANT : sur une WebView ancienne qui ignore `dvh`, la déclaration suivante
   est simplement écartée et la carte garde une hauteur valide, au lieu de
   s'effondrer à zéro. La borne basse (24rem) garantit une carte utilisable
   même sur un écran très court en paysage. */
.carte-conteneur { position: relative; min-width: 0; }
.carte {
  height: clamp(24rem, calc(100vh - 10.5rem), 60rem);
  border-radius: var(--rayon-l);
  border: 1px solid var(--bord); background: var(--surface-douce);
}
.panneau-carte { max-height: clamp(24rem, calc(100vh - 10.5rem), 60rem); }

@supports (height: 100dvh) {
  .carte { height: clamp(24rem, calc(100dvh - 10.5rem), 60rem); }
  .panneau-carte { max-height: clamp(24rem, calc(100dvh - 10.5rem), 60rem); }
}
.carte--fiche { height: 320px; }

/* ── Indicateur de performance ─────────────────────────────────────────────
   Placé au-dessus de l'échelle de Leaflet, en gris et en petit : il rend
   compte du coût de la vue sans jamais réclamer l'attention. */
.carte-perf {
  position: absolute; left: .6rem; bottom: 2.6rem; z-index: 500; margin: 0;
  background: rgb(255 255 255 / 88%); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: .15rem .45rem;
  font-size: .7rem; font-variant-numeric: tabular-nums; color: var(--encre-tres-douce);
}
.carte-perf[hidden] { display: none; }
.carte-perf--lent { color: var(--ambre); border-color: var(--ambre); }

/* ── Légende dynamique ─────────────────────────────────────────────────────
   Reconstruite après chaque chargement : elle décrit ce qui est à l'écran,
   effectifs compris, et non un jeu de symboles figé dans le gabarit. */
.legende__liste { list-style: none; margin: 0; padding: 0; }
.legende__entree {
  display: flex; align-items: center; gap: .5rem;
  padding: .18rem 0; font-size: .82rem;
}
.legende__texte { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.legende__effectif {
  font-variant-numeric: tabular-nums; font-weight: 650; font-size: .78rem;
  color: var(--encre-douce);
}
.legende__note { font-size: .72rem; color: var(--encre-tres-douce); }
.legende__vide { font-size: .82rem; color: var(--encre-tres-douce); font-style: italic; margin: 0; }

.legende__symbole { flex: none; width: 16px; height: 16px; }
.legende__symbole--polygone {
  background: color-mix(in srgb, var(--teinte) 30%, transparent);
  border: 2px solid var(--teinte); border-radius: var(--rayon-micro);
}
.legende__symbole--contour { border: 2px solid var(--teinte); border-radius: var(--rayon-micro); }
.legende__symbole--point {
  background: var(--teinte); border: 2px solid var(--surface); border-radius: 50%;
  box-shadow: 0 0 0 1px var(--teinte);
}
.legende__symbole--pastille {
  background: var(--teinte); border-radius: 50%; opacity: .85;
}
.legende__symbole--ligne {
  height: 0; border-top: 3px solid var(--teinte); align-self: center;
}

/* ── Recherche ─────────────────────────────────────────────────────────────
   Motif « combobox » écrit à la main : champ, liste, navigation au clavier. */
.recherche { position: relative; }
.recherche__champ {
  width: 100%; padding: .4rem .55rem; font: inherit; font-size: .85rem;
  border: 1px solid var(--bord-fort); border-radius: var(--rayon);
}
.recherche__liste {
  position: absolute; z-index: 20; left: 0; right: 0; top: calc(100% + 2px);
  list-style: none; margin: 0; padding: .2rem; max-height: 15rem; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon); box-shadow: 0 6px 18px rgb(0 0 0 / 18%);
}
.recherche__liste[hidden] { display: none; }
.recherche__option {
  display: flex; align-items: center; gap: .5rem; padding: .35rem .45rem;
  border-radius: var(--rayon); cursor: pointer;
}
.recherche__option[aria-selected="true"] { background: var(--vert-clair); }
.recherche__icone { flex: none; color: var(--vert); }
.recherche__icone svg { width: 17px; height: 17px; display: block; }
.recherche__libelle { min-width: 0; }
.recherche__libelle strong { display: block; font-size: .84rem; font-weight: 650; }
.recherche__libelle small {
  display: block; font-size: .74rem; color: var(--encre-tres-douce);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.recherche__etat { margin: .3rem 0 0; font-size: .75rem; color: var(--encre-tres-douce); }
.recherche__etat[hidden] { display: none; }
.recherche__etat--erreur { color: var(--rouge); }
.recherche__etat--alerte { color: var(--ambre); }

/* Sélecteur de fond de carte : l'icône Leaflet par défaut n'étant pas vendorée,
   on affiche un pictogramme « burger » ☰.
   La variante tactile de Leaflet (.leaflet-touch …, plus spécifique) impose
   44 px : on surcharge les DEUX sélecteurs, sinon le bouton se déforme et le
   pictogramme se décentre. */
.leaflet-control-layers-toggle,
.leaflet-touch .leaflet-control-layers-toggle {
  background-image: none !important;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.25rem; line-height: 1; color: var(--vert-fonce);
  text-decoration: none;
}
.leaflet-control-layers-toggle::before { content: "\2630"; }
.leaflet-control-layers { border-radius: var(--rayon); }
.leaflet-control-layers-list { font-size: .85rem; }
.leaflet-control-layers label { display: flex; align-items: center; gap: .35rem; }

/* Flèche du nord géographique. */
.carte-nord {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  width: 34px; padding: 4px 0 5px; background: rgb(255 255 255 / 94%);
  font-size: .72rem; font-weight: 700; color: var(--encre-douce); line-height: 1;
}
.carte-nord svg { width: 15px; height: 19px; display: block; }
.carte-nord span { margin-top: 2px; }

.fiche-flottante {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 900;
  width: min(340px, calc(100vw - 2rem));
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon-l); padding: 1rem; box-shadow: var(--ombre-l);
}

/* ── Détections ──────────────────────────────────────────────────────────── */

.liste-detections { display: grid; gap: .85rem; margin-bottom: 1.5rem; }
/* Un article par detection, potentiellement des dizaines a la suite : c'est
   l'element le PLUS repete de l'espace agent. La meme regle qu'ailleurs vaut ici
   avec le plus de force — filet ou ombre, pas les deux. */
.carte-detection {
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon-l); padding: var(--e-4);
}
.carte-detection[data-traite] { opacity: .5; }
.carte-detection__entete { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.carte-detection__entete h2 { font-size: 1rem; margin: 0; }
.carte-detection__meta { font-size: var(--t-s); color: var(--encre-douce); margin: 0; }

/* ── Priorité décomposée ────────────────────────────────────────────────────
   La file est priorisée, mais toutes les cartes se ressemblaient : le score
   tenait en fin de ligne grise, entre le capteur et la date. Rien ne disait
   pourquoi une détection venait avant une autre.

   La barre montre les TROIS TERMES de la formule du modèle, dans leurs
   proportions réelles. Un rang élevé obtenu par corroboration indépendante
   (terrain, aire protégée) et un rang élevé obtenu par la seule confiance de
   l'algorithme n'appellent pas la même instruction — et se distinguent
   désormais sans lire un chiffre.

   Chaque terme porte la couleur de son ORIGINE : satellite pour la confiance,
   citoyen pour le croisement terrain. La couleur répond ici à « d'où vient
   cette corroboration », ce qui est précisément le rôle des jetons --source-*.

   La couleur ne porte pas seule : les étiquettes « croisé terrain » et
   « aire protégée » restent affichées au-dessus, et la barre expose sa
   décomposition complète en aria-label. */
.priorite {
  display: flex; align-items: center; gap: var(--e-2);
  margin: var(--e-2) 0 0; font-size: var(--t-xs); color: var(--encre-pale);
}
.priorite__rang { white-space: nowrap; font-variant-numeric: tabular-nums; }
.priorite__barre {
  display: flex; flex: 0 1 9rem; height: 6px;
  background: var(--surface-douce);
  border: 1px solid var(--bord);
  border-radius: var(--rayon-pilule); overflow: hidden;
}
.priorite__part { display: block; height: 100%; }
.priorite__part--conf    { background: var(--source-satellite); }
.priorite__part--aire    { background: var(--etat-estime); }
.priorite__part--terrain { background: var(--source-citoyen); }
.priorite__valeur {
  font-variant-numeric: tabular-nums; color: var(--encre-douce); font-weight: 640;
}

/* ── Score de priorité d'un site, décomposé ─────────────────────────────────
   Le score était la première ligne d'une liste de définitions, au même rang que
   la superficie. C'est pourtant lui qui décide de l'engagement de moyens de
   terrain : il ouvre la fiche, et il s'explique.

   Chaque terme montre son APPORT RÉEL rapporté à son maximum (« 7,4 / 30 ») :
   un poids fort peu rempli et un poids faible saturé se distinguent, ce qu'un
   pourcentage unique masquerait. Les jauges partagent une échelle relative à
   chaque poids, jamais au total — sinon le terme à 10 points paraîtrait
   toujours négligeable devant celui à 30. */
.score {
  display: flex; gap: var(--e-5); align-items: flex-start; flex-wrap: wrap;
  padding-bottom: var(--e-4); margin-bottom: var(--e-4);
  border-bottom: 1px solid var(--bord);
}
.score__valeur {
  font-family: var(--police-titre);
  font-size: var(--t-3xl); font-weight: 600; line-height: 1;
  letter-spacing: var(--chasse-titre);
  color: var(--marque-fort); margin: 0;
  font-variant-numeric: tabular-nums lining-nums;
}
.score__sur { font-size: var(--t-m); color: var(--encre-pale); letter-spacing: normal; }
.score__corps { flex: 1 1 16rem; min-width: 0; }
.score__titre { font-size: var(--t-s); margin: 0 0 var(--e-2); color: var(--encre-douce); }
.score__parts { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--e-1); }
.score__part {
  display: grid; grid-template-columns: minmax(0, 1fr) 4.5rem auto;
  align-items: center; gap: var(--e-2); font-size: var(--t-xs);
}
/* Un terme qui n'apporte rien reste AFFICHÉ, en retrait : savoir qu'un critère
   ne joue pas est une information, l'escamoter laisserait croire à un oubli. */
.score__part--nul { color: var(--encre-pale); }
.score__part-libelle { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.score__jauge {
  display: block; height: 5px; background: var(--surface-douce);
  border: 1px solid var(--bord); border-radius: var(--rayon-pilule); overflow: hidden;
}
.score__jauge > span { display: block; height: 100%; background: var(--marque); }
.score__part--nul .score__jauge > span { background: var(--bord-fort); }
.score__part-apport { font-variant-numeric: tabular-nums; white-space: nowrap; font-weight: 640; }
.score__part-max { color: var(--encre-pale); font-weight: 400; }
.score__note { font-size: var(--t-xs); color: var(--encre-pale); margin: var(--e-2) 0 0; }

/* ── Sommaire d'une page longue ─────────────────────────────────────────────
   L'administration empile huit sections sur près de huit cents lignes, sans
   plan : on y arrivait par le haut et on cherchait au défilement.

   Ce sommaire est fait de LIENS, pas d'onglets : il fonctionne sans JavaScript,
   ne masque rien, et l'impression de la page conserve toutes les sections. Sur
   une console d'administration consultée depuis des postes hétérogènes, c'est
   le compromis qui ne se retourne jamais contre l'utilisateur.

   Les sections sont réunies par NATURE — ce qui donne accès, ce qui règle le
   dispositif, ce qui en rend compte — parce que c'est ainsi qu'on les cherche :
   on vient « changer un seuil », pas « ouvrir la troisième section ». */
.sommaire {
  display: flex; flex-wrap: wrap; gap: var(--e-5) var(--e-6);
  padding: var(--e-4); margin-bottom: var(--e-5);
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon-l);
}
.sommaire__groupe { display: grid; gap: var(--e-2); align-content: start; }
.sommaire__titre {
  font-size: var(--t-xs); font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--encre-pale);
}
.sommaire__liste {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--e-1) var(--e-3);
}
.sommaire__liste a {
  display: inline-block; padding: var(--e-1) var(--e-2);
  font-size: var(--t-s); font-weight: 600;
  color: var(--marque-fort); text-decoration: none;
  border: 1px solid var(--marque-bord); border-radius: var(--rayon);
  background: var(--marque-voile);
  transition: background var(--transition), border-color var(--transition);
}
.sommaire__liste a:hover { background: var(--marque-doux); border-color: var(--marque); }

/* La section visée ne doit pas se coller au bord haut de la fenêtre : sans
   cette marge de défilement, son titre affleure et l'œil croit avoir manqué
   l'ancre. */
[id^="admin-"] { scroll-margin-top: var(--e-5); }
.carte-detection__actions { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: .9rem; }

.jauge { min-width: 8rem; margin: 0; }
.jauge__valeur { font-weight: 680; font-size: .95rem; font-variant-numeric: tabular-nums; }
.jauge__barre { display: block; height: 6px; background: var(--surface-douce); border-radius: var(--rayon-micro); overflow: hidden; }
.jauge__barre span { display: block; height: 100%; background: var(--vert); }

/* ── Accueil public ──────────────────────────────────────────────────────── */

/* ── Accueil public ─────────────────────────────────────────────────────────
   Mise en page éditoriale asymétrique (7/5), et non deux colonnes égales : le
   propos et l'action occupent la colonne large, les deux notes qui les
   encadrent — l'anonymat, la consigne — tiennent le rail étroit. La marche à
   suivre court ensuite sur toute la largeur.

   Sur mobile tout se replie dans l'ordre de lecture du gabarit, qui est celui
   de la décision : de quoi s'agit-il, que faire, ce qui lève l'obstacle, ce qui
   gouverne l'action, puis le détail. */
.accueil {
  display: grid;
  gap: var(--e-6);
  max-width: var(--largeur-max);
}

@media (min-width: 62rem) {
  .accueil {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--e-8);
    row-gap: var(--e-8);
    align-items: start;
  }
  .accueil__ouverture { grid-column: 1; }
  .accueil__notes     { grid-column: 2; }
  .accueil .marche    { grid-column: 1 / -1; }
}

.accueil__ouverture h1 {
  font-size: clamp(var(--t-2xl), 5.5vw, var(--t-3xl));
  color: var(--marque-fort);
  max-width: 16ch;          /* un titre qui court sur toute la largeur ne se lit pas */
  margin-bottom: var(--e-4);
}

.accueil__actions {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--e-5);
  margin-top: var(--e-5);
}

/* Une seule action dominante. Deux boutons de même poids obligent à choisir
   avant d'avoir compris ; le suivi d'un signalement ne concerne que ceux qui en
   ont déjà déposé un, et se contente d'un lien affirmé. */
.lien-appuye {
  font-weight: 600;
  color: var(--marque-fort);
  text-decoration: underline;
  text-underline-offset: .25em;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--marque-bord);
  transition: text-decoration-color var(--transition);
}
.lien-appuye:hover { text-decoration-color: currentColor; }

.accueil__notes { display: grid; gap: var(--e-5); align-content: start; }

/* L'anonymat quitte la pastille verte pour un bandeau à filet : c'est la
   promesse qui lève l'obstacle au signalement, elle se lit comme une clause,
   pas comme une décoration. */
.garantie--bandeau {
  background: var(--marque-voile);
  border-radius: 0;
  border-left: 3px solid var(--marque);
  padding: var(--e-4);
  font-size: var(--t-base);
}

/* Aside éditorial. Le filet remplace l'encadré : un bloc cerné de tous côtés
   s'écarte du texte, un filet l'y rattache tout en le distinguant. */
.note { border-left: 3px solid var(--bord-fort); padding-left: var(--e-4); }
.note__titre { font-size: var(--t-l); margin: 0 0 var(--e-2); }
.note__texte { color: var(--encre-douce); margin: 0; }

/* Consigne de sécurité physique — uniquement quand le public peut signaler,
   c'est-à-dire quand quelqu'un risque de se déplacer (cf. le gabarit).
   La teinte est empruntée à l'échelle des états, sans collision de sens : le
   vocabulaire d'état (« actif », « suivi », « maîtrisé ») décrit des SITES et
   n'apparaît que dans l'espace agent. Un citoyen n'en voit jamais. */
.note--consigne {
  border-left-color: var(--etat-suivi);
  background: var(--etat-suivi-doux);
  padding: var(--e-4);
}
.note--consigne .note__titre { color: var(--etat-suivi-encre); }
.note--consigne .note__texte { color: var(--etat-suivi-encre); }

/* Note d'estimation — même registre que l'étiquette « Estimation » portée par
   les indicateurs. Une seule idée, une seule forme : partout où l'application
   affiche un chiffre calculé plutôt que constaté, elle le dit de la même
   manière. Le filet tireté est le second canal, lisible à l'impression. */
.note--estime {
  border-left-style: dashed;
  border-left-color: var(--etat-estime);
  background: var(--etat-estime-doux);
  color: var(--etat-estime-encre);
  padding: var(--e-3) var(--e-4);
  font-size: var(--t-s);
  margin: 0 0 var(--e-4);
}

/* ── Marche à suivre ────────────────────────────────────────────────────────
   Une succession, pas un catalogue : trois colonnes égales effaceraient
   l'enchaînement, qui est justement l'information. Les chiffres pendent dans
   la marge, reliés par un filet vertical. */
.marche { border-top: 1px solid var(--bord); padding-top: var(--e-6); }
.marche__titre {
  font-size: var(--t-l); font-weight: 500; color: var(--encre-douce);
  margin: 0 0 var(--e-6);
}
.marche__liste {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--e-6);
  max-width: 60ch;
}
.marche__etape {
  display: grid; grid-template-columns: 3rem 1fr;
  gap: var(--e-4);
  position: relative;
}
.marche__numero {
  font-family: var(--police-titre);
  font-size: var(--t-2xl);
  line-height: 1;
  color: var(--marque);
  font-variant-numeric: lining-nums;
}
/* Le filet qui relie une étape à la suivante — la seule chose qui dise
   « ensuite » sans l'écrire. */
.marche__etape::before {
  content: '';
  position: absolute; left: 1.05rem; top: 2.4rem;
  bottom: calc(var(--e-6) * -1);
  width: 1px; background: var(--marque-bord);
}
.marche__etape:last-child::before { display: none; }
.marche__etape-titre { font-size: var(--t-m); margin: 0 0 var(--e-1); }
.marche__texte { color: var(--encre-douce); margin: 0; }

@media (min-width: 62rem) {
  .marche {
    display: grid;
    grid-template-columns: minmax(0, 3fr) minmax(0, 9fr);
    column-gap: var(--e-8);
  }
  .marche__titre { grid-column: 1; margin: 0; }
  .marche__liste { grid-column: 2; }
}

.chapo {
  font-size: var(--t-m);
  line-height: 1.6;
  color: var(--encre-douce);
  max-width: 46ch;   /* mesure de lecture : au-delà, l'œil perd la ligne suivante */
  margin: 0;
}
.garantie {
  display: flex; gap: .7rem; align-items: flex-start;
  background: var(--vert-clair); border-radius: var(--rayon-l);
  padding: .85rem 1rem; font-size: .88rem; color: var(--marque-encre);
}
.garantie--compacte { font-size: .85rem; padding: .7rem .85rem; }
.garantie__icone { width: 26px; height: 26px; flex: none; color: var(--vert); }
.installer { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; margin: .75rem 0; }
/* Dans l'application INSTALLÉE (lancée en PWA), l'invite d'installation n'a
   plus lieu d'être : on la masque de façon fiable et immédiate, quel que soit
   le comportement du JavaScript ou du type d'installation. */
@media (display-mode: standalone), (display-mode: minimal-ui), (display-mode: fullscreen) {
  #installer-app { display: none !important; }
}
.installer__texte { line-height: 1.4; }
.installer__aide { display: block; width: 100%; font-size: .85rem; margin-top: .35rem; opacity: .92; }

/* ── Connexion, suivi, erreur ────────────────────────────────────────────── */

/* ── Fond de marque : accueil et connexion ────────────────────────────────
   Le symbole sert de MASQUE, comme dans le bandeau : le fichier est le même,
   déjà téléchargé et mis en cache. Ces deux fonds ne coûtent donc ni une
   requête ni un octet de plus, et leur couleur suit le tenant.

   Le masque découpe l'image AU CADRE de l'élément : une position négative
   sort le globe du champ sans jamais déborder de la page, donc sans créer de
   défilement horizontal.

   Contraste mesuré du corps de texte sur la zone la plus teintée : 12,9:1 sur
   l'accueil, 13,0:1 sur la connexion — WCAG AA en demande 4,5. */

/* Accueil — sceau d'angle, ancré au BLOC D'OUVERTURE et non à toute la page.
   La raison tient à la grille : `.accueil` est en deux colonnes, et celle de
   droite porte les encadrés de garantie et de sécurité. Un sceau calé sur le
   coin de la page tombait donc exactement derrière ces cartes, qui sont
   opaques — il n'en restait rien.
   Posé sur `.accueil__ouverture`, il occupe la partie droite du bloc de titre,
   qui est vide : le titre est borné à 16ch et le chapô plus étroit encore. */
.accueil__ouverture { position: relative; z-index: 0; }
.accueil__ouverture::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-color: var(--marque); opacity: .07;
  -webkit-mask-image: url("/assets/img/logo-symbole.svg");
          mask-image: url("/assets/img/logo-symbole.svg");
  -webkit-mask-repeat: no-repeat;         mask-repeat: no-repeat;
  -webkit-mask-size: 330px;               mask-size: 330px;
  -webkit-mask-position: right -110px top -46px;
          mask-position: right -110px top -46px;
}

/* Connexion — halo. La carte ne fait que 34 rem au milieu d'une page large :
   le dégradé occupe ce vide, le symbole lui donne un centre. Le dégradé est
   porté par le corps de page, sans quoi il serait enfermé dans la carte. */
/* Sans `background-attachment: fixed` : il fait repeindre le dégradé à chaque
   défilement, ce qui se voit sur les terminaux modestes que vise ce produit.
   Le fond du corps de page est propagé au canevas, il remplit donc la fenêtre
   même quand la page est plus courte qu'elle. */
body[data-page="connexion"] {
  background: radial-gradient(120% 90% at 50% 12%, var(--marque-voile) 0%, var(--fond) 62%);
}
body[data-page="connexion"] .contenu { position: relative; z-index: 0; }
body[data-page="connexion"] .contenu::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-color: var(--marque); opacity: .05;
  -webkit-mask-image: url("/assets/img/logo-symbole.svg");
          mask-image: url("/assets/img/logo-symbole.svg");
  -webkit-mask-repeat: no-repeat;         mask-repeat: no-repeat;
  -webkit-mask-size: 300px;               mask-size: 300px;
  -webkit-mask-position: center 44%;      mask-position: center 44%;
}

/* Petit écran : la surface PRINCIPALE de cette application, pas une réduction
   du bureau. À 375 px, un symbole de 380 px couvre l'écran entier — il cesse
   d'être un filigrane pour devenir du bruit derrière le texte. On le réduit,
   on le repousse hors cadre, et on baisse encore l'opacité : un écran tenu à
   bout de bras en plein soleil ne rend pas les nuances d'un écran de bureau. */
@media (max-width: 560px) {
  .accueil__ouverture::before {
    opacity: .05;
    -webkit-mask-size: 200px;             mask-size: 200px;
    -webkit-mask-position: right -74px top -34px;
            mask-position: right -74px top -34px;
  }
  body[data-page="connexion"] .contenu::before {
    opacity: .038;
    -webkit-mask-size: 170px;             mask-size: 170px;
    -webkit-mask-position: center 22%;    mask-position: center 22%;
  }
}

/* Sans masque, `background-color` peindrait un aplat de marque en travers de
   la page. On efface plutôt le fond : la marque tient déjà par le bandeau. */
@supports not ((mask-image: url("#")) or (-webkit-mask-image: url("#"))) {
  .accueil__ouverture::before,
  body[data-page="connexion"] .contenu::before { display: none; }
}

/* À l'impression, un filigrane ne fait que consommer de l'encre. */
@media print {
  .accueil__ouverture::before,
  body[data-page="connexion"] .contenu::before { display: none; }
  body[data-page="connexion"] { background: none; }
}

.connexion, .suivi, .erreur { max-width: 34rem; margin: 2rem auto; }
.connexion__intro, .suivi__intro { color: var(--encre-douce); font-size: .9rem; }
.connexion__aide { margin-top: 1.5rem; font-size: .85rem; color: var(--encre-douce); }
.erreur { text-align: center; }
.erreur__code { font-size: 3.5rem; font-weight: 700; color: var(--bord-fort); margin: 0; line-height: 1; }
.erreur__message { color: var(--encre-douce); }

.fiche-suivi { background: var(--surface); border: 1px solid var(--bord); border-radius: var(--rayon-l); padding: 1.25rem; margin-top: 1.25rem; }
.fiche-suivi__code { font-family: var(--police-chiffres); font-size: 1.15rem; font-weight: 700; margin: 0 0 .5rem; }

/* Saisie d'un code de suivi : même chasse fixe que son affichage, et un
   interlettrage large. C'est le seul champ de l'application qu'on remplit en
   recopiant caractère par caractère. */
.champ__code {
  font-family: var(--police-chiffres);
  letter-spacing: .08em;
  text-transform: uppercase;
}
.fiche-suivi__date { font-size: .8rem; color: var(--encre-tres-douce); margin: .5rem 0 0; }

/* ── Signalement citoyen (PWA) ───────────────────────────────────────────── */

.signaler { max-width: 40rem; margin: 0 auto; }
.signaler .formulaire { max-width: none; }
.facultatif { font-weight: 400; color: var(--encre-tres-douce); text-transform: none; }

.choix-pictos { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: .6rem; }
.picto {
  display: flex; flex-direction: column; align-items: center; gap: .4rem;
  padding: .9rem .5rem; border: 2px solid var(--bord-fort); border-radius: var(--rayon-l);
  cursor: pointer; text-align: center; background: var(--surface);
  transition: border-color .12s, background .12s;
}
.picto svg { width: 46px; height: 46px; color: var(--encre-douce); }
.picto span { font-size: .85rem; font-weight: 600; line-height: 1.25; }
.picto input { position: absolute; opacity: 0; width: 0; height: 0; }
.picto:has(input:checked) { border-color: var(--vert); background: var(--vert-clair); }
.picto:has(input:checked) svg { color: var(--vert-fonce); }
.picto:has(input:focus-visible) { outline: 3px solid var(--bleu); outline-offset: 2px; }

.position { display: flex; flex-direction: column; gap: .6rem; }
.position__etat { font-size: .85rem; color: var(--encre-douce); margin: 0; }
.position__etat--ok { color: var(--vert); font-weight: 600; }
.position__etat--erreur { color: var(--rouge); font-weight: 600; }
.position__manuelle { display: grid; gap: .6rem; }

.etat-reseau { font-size: .84rem; padding: .5rem .8rem; border-radius: var(--rayon); margin-bottom: 1rem; }
.etat-reseau--hors-ligne { background: var(--terre-clair); color: var(--etat-estime-encre); }
.etat-reseau--en-ligne { background: var(--vert-clair); color: var(--marque-encre); }

.apercu-photo img { max-width: 100%; border-radius: var(--rayon); margin-top: .5rem; }

.file-attente {
  background: var(--terre-clair); border-radius: var(--rayon-l);
  padding: 1rem; margin-top: 1.5rem; color: var(--etat-estime-encre);
}
.file-attente ul { margin: .5rem 0 1rem; padding-left: 1.2rem; font-size: .85rem; }

.confirmation {
  background: var(--vert-clair); border-radius: var(--rayon-l);
  padding: 1.25rem; margin-top: 1.5rem; text-align: center; color: var(--marque-encre);
}
.code-signalement {
  font-family: ui-monospace, monospace; font-size: 1.5rem; font-weight: 700;
  letter-spacing: .05em; margin: .5rem 0 1rem;
}

/* ── Pied ────────────────────────────────────────────────────────────────── */

.pied {
  border-top: 1px solid var(--bord); padding: 1.25rem;
  font-size: .8rem; color: var(--encre-tres-douce); text-align: center;
  background: var(--surface);
}
.pied p { margin: 0 0 .25rem; }


/* ══ COUCHE D'ANALYSE DU RAPPORT DE PILOTAGE ═══════════════════════════════
   Constats calculés par le serveur, affichés sous chaque visuel et repris
   dans la synthèse de fin. Le constat, sa lecture et la recommandation sont
   visuellement distincts : les fondre laisserait croire que l'interprétation
   est mesurée alors qu'elle est déduite. */

.pil-notes { margin-top: 12px; display: grid; gap: 10px; }
.pil-notes[hidden] { display: none; }

.pil-constat {
  border: 1px solid var(--pil-bord); border-left: 4px solid var(--pil-encre-2);
  border-radius: var(--pil-rayon-s); padding: 10px 12px; background: var(--pil-surface);
}
.pil-constat--critique  { border-left-color: var(--pil-critique); }
.pil-constat--attention { border-left-color: var(--pil-suivi); }
.pil-constat--favorable { border-left-color: var(--pil-maitrise); }
.pil-constat--neutre    { border-left-color: var(--pil-encre-2); }

.pil-constat__entete {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px;
}
/* Un signe typographique, pas seulement une couleur : le rapport est imprimé
   en noir et blanc dans la plupart des services, où rouge et vert deviennent
   deux gris identiques. */
.pil-constat__marque {
  flex: none; width: 18px; height: 18px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 12px; font-weight: 700; color: var(--surface); background: var(--pil-encre-2);
}
.pil-constat--critique  .pil-constat__marque { background: var(--pil-critique); }
.pil-constat--attention .pil-constat__marque { background: var(--pil-suivi); }
.pil-constat--favorable .pil-constat__marque { background: var(--pil-maitrise); }

.pil-constat__gravite {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--pil-encre-2);
}
.pil-constat__echeance, .pil-constat__fiabilite {
  font-size: 11px; color: var(--pil-encre-2);
  border: 1px solid var(--pil-bord); border-radius: 999px; padding: 1px 8px;
}
.pil-constat__fiabilite { margin-left: auto; }

.pil-constat__constat { margin: 0 0 6px; font-size: 14px; font-weight: 600;
  color: var(--pil-encre); line-height: 1.45; }
.pil-constat__lecture { margin: 0 0 6px; font-size: 13px; color: var(--pil-encre-2);
  line-height: 1.5; }
.pil-constat__action  { margin: 0; font-size: 13px; color: var(--pil-encre); line-height: 1.5; }
.pil-constat__action strong { color: var(--pil-critique); }
.pil-constat--favorable .pil-constat__action strong { color: var(--pil-maitrise); }

/* ── Synthèse ───────────────────────────────────────────────────────────── */
.pil-synthese__resume { font-size: 15px; font-weight: 600; margin: 0 0 4px; }
.pil-synthese__garantie {
  font-size: 12px; color: var(--pil-encre-2); margin: 0 0 16px; font-style: italic;
}
.pil-synthese__titre {
  font-size: 15px; margin: 24px 0 12px; padding-top: 16px;
  border-top: 1px solid var(--pil-bord);
}
.pil-constats { display: grid; gap: 10px; }

/* Trois colonnes d'échéance : la lecture se fait de gauche à droite, du plus
   urgent au plus lointain. */
.pil-plan { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; }
.pil-plan__colonne {
  border: 1px solid var(--pil-bord); border-radius: var(--pil-rayon-s);
  padding: 12px; background: var(--pil-fond);
}
.pil-plan__titre {
  margin: 0 0 10px; font-size: 12px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--pil-encre-2);
}
.pil-plan__liste { margin: 0; padding-left: 18px; display: grid; gap: 10px; }
.pil-plan__action { font-size: 13px; line-height: 1.45; }
.pil-plan__action::marker { font-weight: 700; color: var(--pil-encre-2); }
.pil-plan__action--critique::marker { color: var(--pil-critique); }
.pil-plan__texte { display: block; color: var(--pil-encre); }
.pil-plan__fondement {
  display: block; margin-top: 3px; font-size: 11.5px; color: var(--pil-encre-2);
}
.pil-plan__vide, .pil-vide {
  font-size: 13px; color: var(--pil-encre-2); font-style: italic; margin: 0;
}
.pil-table--objectifs { width: 100%; }
.pil-ligne--ecart { background: color-mix(in srgb, var(--pil-critique) 8%, transparent); }
/* Cible fixée sur un indicateur que ce périmètre ne permet pas de calculer :
   la ligne le dit, plutôt que d'afficher un écart nul trompeur. */
.pil-ligne--note td {
  font-size: 12px; font-style: italic; color: var(--pil-encre-2);
  padding-top: 0; border-top: 0;
}

/* ── Impression du rapport (A4) ─────────────────────────────────────────────
   Le rapport est fait pour être posé sur une table de réunion. Les commandes
   disparaissent, les blocs ne se coupent plus au milieu, et la synthèse
   commence sur une page neuve — c'est elle qu'on lit à voix haute. */
@media print {
  @page { size: A4 portrait; margin: 14mm 12mm; }

  .pil-filtres, .pil-actions, .pil-chips, .pil-pagination,
  .pil-bloc__entete .pil-aide { display: none !important; }

  .pil-page, .pil-corps { display: block !important; }
  .pil-duo { display: block !important; }

  .pil-bloc, .pil-constat, .pil-plan__colonne {
    break-inside: avoid; box-shadow: none; border-color: var(--bord-fort);
  }
  .pil-bloc { margin-bottom: 10mm; }

  #pil-bloc-synthese { break-before: page; }
  .pil-synthese__titre { break-after: avoid; }
  .pil-plan { grid-template-columns: 1fr; }

  /* Les aplats de couleur ne survivent pas à l'impression par défaut : on
     force leur rendu, faute de quoi les repères de gravité disparaissent. */
  .pil-constat__marque, .pil-ligne--ecart {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .pil-constat { border-left-width: 3px; }

  body { background: var(--surface); font-size: 11pt; }
}

/* ── Impression ──────────────────────────────────────────────────────────── */

@media print {
  .entete, .pied, .barre-filtres, .page-entete__actions, .bouton { display: none !important; }
  .panneau { break-inside: avoid; box-shadow: none; }
  body { background: var(--surface); }
}

/* ── Mouvement réduit ────────────────────────────────────────────────────── */

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