/* Strata — thème sombre « instrument scientifique ».
   Le fond est neutre et désaturé pour que les couleurs portent uniquement de
   l'information : ambre = anomalie en relief, bleu = creux, vert = enclos. */

:root {
  --bg:        #0d1014;
  --panel:     #141a21;
  --panel-2:   #1a212a;
  --line:      #242e3a;
  --line-soft: #1c242e;
  --text:      #e4e9f0;
  --muted:     #8695a8;
  --dim:       #5f6d7e;

  --amber:     #e0a458;
  --amber-dim: #8a6532;
  --teal:      #5eaaa8;
  --blue:      #5b9bd5;
  --green:     #6fb98f;
  --red:       #d4674a;

  --radius: 7px;
  --sidebar-w: 336px;
  --details-w: 392px;

  /* ─── échelle typographique ───
     Toutes les tailles de texte de la feuille sont multipliées par cette
     valeur. Les espacements, eux, ne bougent pas : le texte grossit dans une
     mise en page qui tient. C'est ce qu'on veut d'un logiciel qu'on regarde
     huit heures d'affilée sur un écran qu'on n'a pas choisi.
     Réglable dans Réglages → Apparence. */
  --echelle-texte: 1;

  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
  --sans: 'Segoe UI', system-ui, -apple-system, sans-serif;
}

* { box-sizing: border-box; }

/* ─── barres de défilement ───
   Par défaut, le navigateur en dessine une claire : sur un fond sombre elle
   traverse le panneau comme un ruban blanc, et c'est la première chose que
   l'œil accroche. Elle devient ici une simple poignée qui se fond dans la
   bordure, et ne se remarque qu'au moment où l'on veut s'en servir.

   Deux syntaxes, non par précaution mais par nécessité : Firefox ne connaît
   que la première, les navigateurs Chromium que la seconde. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  /* La bordure transparente avec `background-clip` amincit la poignée sans
     réduire la zone cliquable : viser trois pixels à la souris est pénible. */
  background: var(--line);
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: 7px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--dim);
  border: 3px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-corner { background: transparent; }

html, body {
  margin: 0; height: 100%;
  background: var(--bg); color: var(--text);
  font: 14px/1.5 var(--sans);
  font-size: calc(14px * var(--echelle-texte));
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

#app {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr auto;
  height: 100%;
}

/* ─────────────────────────── barre latérale ─────────────────────────── */
#sidebar {
  background: var(--panel);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column;
  min-height: 0;
}

.brand {
  display: flex; align-items: center; gap: 14px;
  padding: 22px 18px 18px;
  border-bottom: 1px solid var(--line-soft);
}
.brand-mark {
  width: 44px; height: 44px; flex: none;
  fill: none; stroke: var(--muted); stroke-width: 1.4; stroke-linecap: round;
}
.brand-mark .brand-find { fill: var(--amber); stroke: none; }
/* ─── logotype ───
   « Strata » est la famille, « Archeo » la déclinaison. Le rapport de taille
   dit lequel des deux on retient : trois quarts d'écart, et une couleur qui
   sépare sans crier. Les futurs « Aménagement » et « Défense » se poseront
   dans le même gabarit sans qu'on y retouche.

   Il occupe désormais la largeur du panneau. C'est le seul endroit de l'écran
   où le nom du produit apparaît, et il était plus discret que les titres de
   section qui le suivent — un logotype qu'on ne remarque pas ne se retient
   pas, et ce nom doit se retenir. */
.brand h1 {
  margin: 0; display: flex; align-items: baseline; gap: 7px;
  font-weight: 600; line-height: 1;
}
.marque-famille {
  font-size: calc(29px * var(--echelle-texte)); letter-spacing: .045em; color: var(--text);
  font-weight: 650;
}
.marque-declinaison {
  font-size: calc(14px * var(--echelle-texte)); letter-spacing: .2em; text-transform: uppercase;
  color: var(--amber); font-weight: 500;
}
.brand p { margin: 7px 0 0; font-size: calc(11.5px * var(--echelle-texte)); color: var(--dim); }

/* ─── bloc « Lancer une analyse » ───
   Il ouvre chaque session. Les quatre sections qui le suivent — Campagnes,
   Analyses, Archives, Supprimés — rangent ce qui existe déjà ; celui-ci fait
   exister. Il ne doit donc pas se lire comme une cinquième section.

   Trois écarts suffisent, et pas un de plus : un fond légèrement soulevé, un
   filet ambre à gauche, un titre en pleine casse là où les sections sont en
   petites capitales grises. */
.bloc-lancer {
  margin: -16px -16px 14px;          /* déborde la marge du panneau */
  padding: 14px 16px 12px 14px;
  background: linear-gradient(180deg, #1b232d, #171e27);
  border-bottom: 1px solid var(--line);
  border-left: 2px solid var(--amber);
}
/* C'est la commande qui ouvre tout le reste : sans zone tracée, le logiciel
   n'a rien à montrer. Elle était au corps des titres de section, c'est-à-dire
   au même rang que « Archives » ou « Supprimés » — un rang qui ne dit pas
   qu'on commence par là. */
.bloc-lancer-titre {
  margin: 0 0 14px; display: flex; align-items: center; gap: 10px;
  font-size: calc(18px * var(--echelle-texte)); font-weight: 650;
  color: var(--text); letter-spacing: .005em; line-height: 1.2;
}
.ico-lancer {
  width: 21px; height: 21px; flex: none;
  fill: none; stroke: var(--amber); stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
/* Chercher un lieu et délimiter une emprise sont deux gestes successifs, pas
   une même commande en deux morceaux : l'écart le dit. */
.bloc-lancer .search { margin-bottom: 14px; }
.bloc-lancer .hint { margin: 10px 0 0; }
/* Vide, la consigne ne doit pas réserver sa place. */
.bloc-lancer .hint:empty { display: none; }

.search {
  display: flex; gap: 6px;
}
.search input {
  flex: 1; min-width: 0;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text);
  padding: 8px 10px; font: inherit; font-size: calc(13px * var(--echelle-texte));
}
.search input:focus { outline: none; border-color: var(--amber-dim); }
.search button {
  width: 34px; flex: none;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--muted);
  cursor: pointer; font-size: calc(15px * var(--echelle-texte));
}
.search button:hover { color: var(--amber); border-color: var(--amber-dim); }

/* Marges serrées : à 140 % de texte et panneau au minimum, « Réglages » était
   rogné. Les quelques pixels rendus ici lui suffisent, et personne ne voit la
   différence à taille normale. */
.tabs {
  display: flex; padding: 0 6px; gap: 2px;
  border-bottom: 1px solid var(--line);
}
.tab {
  flex: 1; min-width: 0; padding: 10px 2px;
  background: none; border: none; border-bottom: 2px solid transparent;
  color: var(--dim); font: inherit; font-size: calc(12.5px * var(--echelle-texte)); font-weight: 500;
  cursor: pointer; transition: color .12s;
}
.tab:hover { color: var(--muted); }
.tab.is-active { color: var(--amber); border-bottom-color: var(--amber); }

.panel { display: none; padding: 16px; overflow-y: auto; flex: 1; min-height: 0; }
.panel.is-active { display: block; }

/* ─────────────────────────── éléments communs ─────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 14px;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text);
  font: inherit; font-size: calc(13px * var(--echelle-texte)); cursor: pointer;
  transition: border-color .12s, background .12s;
}
/* Les livrables sont des liens de téléchargement, donc soulignés par défaut.
   Ils se présentent comme des boutons : le soulignement les fait passer pour
   du texte cliquable au milieu d'une pile de boutons. */
.btn { text-decoration: none; }
.btn:hover { border-color: var(--dim); background: #212a35; }

/* ─── livrables ───
   Un pictogramme par format, du même trait que le reste : on repère le PDF ou
   le GeoPackage à sa silhouette, sans relire toute la liste. */
/* La vue du nuage : pleine largeur du panneau, fond sombre pour qu'elle se
   fonde dans le cadre plutôt que d'y flotter. */
.vue-nuage {
  width: 100%; display: block; border-radius: var(--radius);
  background: #0a0c10; border: 1px solid var(--line-soft);
}

.livrables { display: flex; flex-direction: column; gap: 6px; }
.livrables .btn { justify-content: flex-start; gap: 10px; }
.ico-livrable {
  width: 17px; height: 17px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .9;
}
/* Flèche sortante des liens qui quittent le logiciel. Elle est poussée à
   droite et plus discrète : elle prévient, elle n'appelle pas. */
.ico-sortant {
  width: 13px; height: 13px; flex: none; margin-left: auto;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .5;
}
.btn:hover .ico-sortant { opacity: .85; }

/* Le pictogramme du nuage est fait de disques pleins, pas de traits : la
   règle commune les rendrait invisibles. Restreint à lui — le repère du
   Géoportail porte un cercle qui, lui, doit rester creux. */
.ico-nuage circle { fill: currentColor; stroke: none; }
.btn-primary {
  background: linear-gradient(180deg, #3a2f1c, #2a2317);
  border-color: var(--amber-dim); color: var(--amber);
}
.btn-primary:hover { background: linear-gradient(180deg, #4a3b22, #33291a); }
.btn-block { width: 100%; }
.btn-icon { font-size: calc(14px * var(--echelle-texte)); opacity: .85; }
.btn:disabled { opacity: .45; cursor: not-allowed; }

.hint {
  margin: 10px 0 16px; font-size: calc(11.5px * var(--echelle-texte)); line-height: 1.55; color: var(--dim);
}

.field { margin-bottom: 16px; }
.field > label {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: calc(12px * var(--echelle-texte)); font-weight: 500; color: var(--muted); margin-bottom: 6px;
}
.field > label b { color: var(--amber); font-family: var(--mono); font-size: calc(11.5px * var(--echelle-texte)); }
.field input[type=text], .field input[type=password] {
  width: 100%; background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text); padding: 8px 10px;
  font: inherit; font-size: calc(13px * var(--echelle-texte));
}
.field input:focus { outline: none; border-color: var(--amber-dim); }
.field small {
  display: block; margin-top: 6px; font-size: calc(11px * var(--echelle-texte)); line-height: 1.5; color: var(--dim);
}
.range-pair { display: flex; gap: 8px; }
.range-pair input { flex: 1; }

input[type=range] {
  width: 100%; height: 4px; appearance: none;
  background: var(--line); border-radius: 2px; outline: none;
}
input[type=range]::-webkit-slider-thumb {
  appearance: none; width: 14px; height: 14px; border-radius: 50%;
  background: var(--amber); cursor: pointer; border: 2px solid var(--panel);
}

hr { border: none; border-top: 1px solid var(--line-soft); margin: 18px 0; }

/* interrupteur */
.switch {
  display: flex; align-items: flex-start; gap: 10px;
  margin: 14px 0; cursor: pointer;
}
.switch input { display: none; }
.switch-track {
  flex: none; width: 34px; height: 19px; margin-top: 1px;
  background: var(--line); border-radius: 10px;
  position: relative; transition: background .15s;
}
.switch-thumb {
  position: absolute; top: 2px; left: 2px;
  width: 15px; height: 15px; border-radius: 50%;
  background: var(--dim); transition: transform .15s, background .15s;
}
.switch input:checked + .switch-track { background: var(--amber-dim); }
.switch input:checked + .switch-track .switch-thumb {
  transform: translateX(15px); background: var(--amber);
}
.switch input:disabled + .switch-track { opacity: .4; }
.switch-label { font-size: calc(12.5px * var(--echelle-texte)); line-height: 1.45; }
.switch-label em {
  display: block; font-style: normal; font-size: calc(11px * var(--echelle-texte)); color: var(--dim); margin-top: 2px;
}

/* ─────────────────────────── listes ─────────────────────────── */
.list { display: flex; flex-direction: column; gap: 8px; }

.card {
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 11px 12px; cursor: pointer;
  transition: border-color .12s;
}
.card:hover { border-color: var(--dim); }
.card.is-active { border-color: var(--amber); background: #21201a; }

.card-top {
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
}
.card-title {
  font-size: calc(13px * var(--echelle-texte)); font-weight: 550;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.card-meta {
  margin-top: 4px; font-size: calc(11px * var(--echelle-texte)); color: var(--dim);
  font-family: var(--mono);
}
.card-actions { display: flex; gap: 6px; margin-top: 9px; }
.card-actions .btn { padding: 5px 9px; font-size: calc(11.5px * var(--echelle-texte)); }

.pill {
  flex: none; font-size: calc(10px * var(--echelle-texte)); text-transform: uppercase; letter-spacing: .05em;
  padding: 2px 7px; border-radius: 20px;
  border: 1px solid var(--line); color: var(--dim);
}
.pill.ok      { color: var(--green); border-color: #2f4a3a; }
.pill.running { color: var(--amber); border-color: var(--amber-dim); }
.pill.fail    { color: var(--red);   border-color: #4a2f28; }

.empty {
  padding: 26px 12px; text-align: center;
  font-size: calc(12px * var(--echelle-texte)); color: var(--dim); line-height: 1.6;
}

/* ─────────────────────────── carte ─────────────────────────── */
#map-area { position: relative; min-width: 0; }
/* Le fond n'est plus noir mais gris ardoise. Il se voit à deux moments : entre
   deux tuiles qui n'ont pas fini d'arriver, et au-delà des bords de la
   couverture. Dans les deux cas, un gris se lit comme « rien ici pour
   l'instant » ; un noir se lit comme une panne. */
#map { position: absolute; inset: 0; background: #232b35; }
.leaflet-container { background: #232b35; font: inherit; }

/* ─── le socle en retrait ───
   Le plan IGN posé sous tous les fonds sert à ce que la carte ne s'arrête pas
   au bord de la couverture. Il ne doit jamais se lire comme une donnée : dès
   qu'un autre fond le recouvre, il est désaturé et assombri, et redevient un
   contour du monde plutôt qu'une carte concurrente.

   C'est la seule couche de la carte qui reçoive un filtre, et elle le peut
   parce qu'elle ne porte rien de ce qui est analysé. Les fonds sélectionnés,
   les couches de relief et les pictogrammes n'en reçoivent aucun — ce serait
   mentir sur ce que l'archéologue regarde. */
.socle-en-retrait .leaflet-socle-pane {
  filter: saturate(.18) brightness(.66);
}

/* ─── coutures entre tuiles ───
   Une tuile est posée à une position calculée en nombres réels, puis arrondie
   au pixel par le navigateur. Quand deux voisines s'arrondissent chacune de
   son côté, il reste entre elles une fraction de pixel par où l'on voit le
   fond : d'où le damier de lignes sur toute la carte.

   Première tentative : agrandir chaque tuile d'un demi-pixel pour qu'elles se
   chevauchent. Les lignes noires ont bien disparu — remplacées par des lignes
   claires, l'agrandissement faisant reproduire au navigateur le bord clair de
   chaque tuile. Le remède valait la maladie.

   Ce qui marche vraiment : demander au navigateur de composer chaque tuile sur
   sa propre couche graphique. Elle est alors positionnée au pixel entier du
   compositeur, et non arrondie à l'affichage — les voisines se touchent
   exactement, sans recouvrement ni écart, et sans déformer l'image. */
.leaflet-tile {
  will-change: transform;
  backface-visibility: hidden;
}

.leaflet-control-attribution {
  background: rgba(13,16,20,.82) !important; color: var(--dim) !important;
  font-size: calc(10px * var(--echelle-texte)) !important;
}
.leaflet-control-attribution a { color: var(--muted) !important; }
.leaflet-bar a {
  background: var(--panel) !important; color: var(--text) !important;
  border-bottom-color: var(--line) !important;
}
.leaflet-bar a:hover { background: var(--panel-2) !important; }

.map-drawing { cursor: crosshair !important; }

/* fond de plan */
/* ─────────────────────── frise chronologique ───────────────────────
   Sept boutons alignés ne disent pas qu'ils forment une suite dans le temps.
   Une réglette, si. */
.basemap-switch {
  position: absolute; top: 14px; right: 14px; z-index: 500;
  width: 460px; max-width: calc(100vw - 340px);
  padding: 10px 14px 8px;
  background: rgba(20, 26, 33, .94);
  border: 1px solid var(--line); border-radius: var(--radius);
  backdrop-filter: blur(6px);
  --avancee: 0%;
}

.frise-crans { display: flex; justify-content: space-between; gap: 2px; }
.frise-cran {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 2px 1px; background: none; border: none;
  color: var(--dim); font: inherit; cursor: pointer;
  transition: color .15s;
}
.frise-cran:hover { color: var(--muted); }
.frise-cran.is-active { color: var(--amber); }

.frise-point {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--line); transition: background .15s, transform .15s;
}
.frise-cran:hover .frise-point { background: var(--dim); }
.frise-cran.is-active .frise-point {
  background: var(--amber); transform: scale(1.5);
  box-shadow: 0 0 0 3px rgba(224, 164, 88, .18);
}

.frise-epoque {
  font-family: var(--mono); font-size: calc(10px * var(--echelle-texte));
  font-variant-numeric: tabular-nums; letter-spacing: 0;
  white-space: nowrap;
}
.frise-nom {
  font-size: calc(9px * var(--echelle-texte)); opacity: .62;
  overflow: hidden; text-overflow: ellipsis; max-width: 100%;
  white-space: nowrap;
}
.frise-cran.is-active .frise-nom { opacity: 1; }

/* Une couverture incomplète se signale sans occuper de place. */
.frise-cran.est-partiel .frise-point {
  background: transparent; box-shadow: inset 0 0 0 1.5px var(--line);
}
.frise-cran.est-partiel:hover .frise-point { box-shadow: inset 0 0 0 1.5px var(--dim); }
.frise-cran.est-partiel.is-active .frise-point {
  background: var(--amber); box-shadow: 0 0 0 3px rgba(224, 164, 88, .18);
}

/* Le curseur natif porte l'accessibilité — flèches, valeur annoncée — et
   reste invisible ; les crans ci-dessus en sont la représentation. */
.frise-rail {
  width: 100%; height: 3px; margin: 7px 0 3px; appearance: none;
  background: linear-gradient(to right,
    var(--amber-dim) 0%, var(--amber-dim) var(--avancee),
    var(--line) var(--avancee), var(--line) 100%);
  border-radius: 2px; outline: none; cursor: pointer;
}
.frise-rail::-webkit-slider-thumb {
  appearance: none; width: 13px; height: 13px; border-radius: 50%;
  background: var(--amber); border: 2px solid var(--panel); cursor: grab;
}
.frise-rail:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; }

.frise-legende {
  display: flex; justify-content: space-between;
  font-size: calc(9px * var(--echelle-texte)); color: var(--dim); text-transform: uppercase;
  letter-spacing: .06em;
}

@media (max-width: 1100px) {
  .basemap-switch { width: 340px; }
  .frise-nom { display: none; }
}

/* sélecteur de couches */
.layer-bar {
  position: absolute; top: 14px; left: 14px; z-index: 500; width: 268px;
  background: rgba(20,26,33,.95); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 11px 12px;
  backdrop-filter: blur(8px);
}
/* Un seul élément depuis le retrait de la croix : `space-between` n'avait
   plus rien à répartir et laissait le nom collé au bord. */
.layer-bar-head {
  display: flex; justify-content: center; align-items: center;
  font-size: calc(12px * var(--echelle-texte)); font-weight: 600; margin-bottom: 10px;
  text-align: center;
}
.layer-buttons { display: flex; flex-wrap: wrap; gap: 5px; }
.layer-buttons button {
  padding: 5px 9px; background: var(--panel); border: 1px solid var(--line);
  border-radius: 5px; color: var(--muted); font: inherit; font-size: calc(11.5px * var(--echelle-texte));
  cursor: pointer;
}
.layer-buttons button:hover { border-color: var(--dim); }
.layer-buttons button.is-active {
  background: #2a2317; border-color: var(--amber-dim); color: var(--amber);
}
.layer-opacity {
  display: flex; align-items: center; gap: 9px; margin-top: 11px;
  font-size: calc(11px * var(--echelle-texte)); color: var(--dim);
}
.layer-opacity input { flex: 1; }
.layer-help {
  margin: 9px 0 0; font-size: calc(11px * var(--echelle-texte)); line-height: 1.5; color: var(--dim);
  border-top: 1px solid var(--line-soft); padding-top: 8px;
}

/* tâches de fond */
.jobs {
  position: absolute; left: 14px; bottom: 14px; z-index: 500;
  display: flex; flex-direction: column; gap: 8px; width: 300px;
}
.job {
  background: rgba(20,26,33,.96); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 10px 12px;
  backdrop-filter: blur(8px);
}
.job-title { font-size: calc(12px * var(--echelle-texte)); font-weight: 550; }
.job-msg {
  font-size: calc(11px * var(--echelle-texte)); color: var(--dim); margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.job-bar {
  height: 3px; margin-top: 8px; background: var(--line); border-radius: 2px;
  overflow: hidden;
}
.job-bar span {
  display: block; height: 100%; background: var(--amber);
  transition: width .3s ease;
}
.job.is-fail .job-bar span { background: var(--red); }
.job.is-done .job-bar span { background: var(--green); }

/* ─────── temps écoulé et avancement chiffré ───────
   La barre de trois pixels dit « ça avance » sans dire de combien. Le chiffre
   le dit ; le chronomètre répond à la seule question qu'on se pose devant une
   attente longue : est-ce normal ? Les deux en chiffres tabulaires, sinon la
   ligne tressaute à chaque seconde qui change de largeur. */
.job-pied {
  display: flex; justify-content: space-between; margin-top: 5px;
  font-size: calc(10.5px * var(--echelle-texte));
  color: var(--dim); font-variant-numeric: tabular-nums;
}
.job-part { font-weight: 600; color: var(--amber); }
.job.is-done .job-part, .job.is-fail .job-part { color: var(--dim); }

/* ─────── quand la barre ne bouge plus ───────
   La récupération LiDAR chez l'IGN peut rester une minute sur la même
   fraction ; immobile, la barre se lit comme un blocage. Un balayage traverse
   alors la portion déjà acquise : il ne prétend pas à un avancement — la
   largeur, elle, n'a pas changé — il dit que le travail se poursuit. */
@keyframes strata-balayage {
  from { background-position: 0 0; }
  to   { background-position: 28px 0; }
}
.job-bar.est-bloquee span,
.progress-slim.est-bloquee span {
  background-image: repeating-linear-gradient(
    115deg, rgba(0,0,0,.26) 0 7px, rgba(0,0,0,0) 7px 14px);
  background-size: 28px 100%;
  animation: strata-balayage 1s linear infinite;
}

.toast {
  position: absolute; left: 50%; bottom: 22px; transform: translateX(-50%);
  z-index: 900; max-width: 560px;
  background: rgba(26,33,42,.97); border: 1px solid var(--line);
  border-left: 3px solid var(--amber);
  border-radius: var(--radius); padding: 11px 16px; font-size: calc(12.5px * var(--echelle-texte));
  backdrop-filter: blur(8px);
}
.toast.is-error { border-left-color: var(--red); }

/* ─────────────────────────── poignées de largeur ───────────────────────────
   Les panneaux latéraux n'ont pas la même largeur idéale selon le moment :
   on veut la carte en grand pendant qu'on cherche, la fiche en grand pendant
   qu'on lit. Une poignée à mi-hauteur de chaque bordure permet de trancher au
   coup par coup.

   Elle est posée sur la carte, non dans les panneaux : ceux-ci défilent, et
   une poignée qui défile avec son contenu serait introuvable dès qu'on a
   descendu la liste. */
.redim {
  position: absolute; top: 50%; translate: 0 -50%; z-index: 640;
  width: 15px; height: 62px;
  display: grid; place-items: center;
  cursor: ew-resize; touch-action: none;
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--dim);
  transition: background .15s, color .15s, border-color .15s;
}
/* Chaque poignée s'arrondit du côté de la carte : elle paraît sortir du
   panneau, ce qui dit à quoi elle est attachée. */
.redim-gauche { left: 0;  border-left: none;  border-radius: 0 6px 6px 0; }
.redim-droite { right: 0; border-right: none; border-radius: 6px 0 0 6px; }

.redim:hover, .redim:focus-visible, .redim.est-active {
  background: var(--panel); color: var(--text); border-color: var(--dim);
  outline: none;
}
.redim.est-active { border-color: var(--amber); color: var(--amber); }

/* Les deux flèches opposées, dessinées en CSS : deux chevrons dos à dos.
   Un caractère « ↔ » aurait dépendu de la police installée. */
.redim-fleches {
  position: relative; width: 9px; height: 9px; color: inherit;
}
.redim-fleches::before, .redim-fleches::after {
  content: ''; position: absolute; top: 1px;
  width: 5px; height: 5px;
  border-top: 1.5px solid currentColor; border-right: 1.5px solid currentColor;
}
.redim-fleches::before { left: 0;  rotate: -135deg; }   /* pointe à gauche */
.redim-fleches::after  { right: 0; rotate: 45deg; }     /* pointe à droite */

/* Pendant le glissement, le pointeur ne doit pas sélectionner du texte ni
   changer de forme en survolant la carte. */
body.redim-en-cours { user-select: none; cursor: ew-resize; }
body.redim-en-cours #map { pointer-events: none; }

/* ─────────────────────────── panneau de détail ─────────────────────────── */
#details {
  width: var(--details-w);
  background: var(--panel); border-left: 1px solid var(--line);
  overflow-y: auto; position: relative; min-height: 0;
}
.details-close {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  width: 26px; height: 26px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 5px;
  color: var(--dim); cursor: pointer; font-size: calc(13px * var(--echelle-texte)); line-height: 1;
}
/* Le retour se place juste à gauche de la fermeture, au même gabarit : deux
   sorties voisines, l'une d'un cran, l'autre de tout. */
.details-retour {
  position: absolute; top: 12px; right: 44px; z-index: 2;
  width: 26px; height: 26px; display: grid; place-items: center;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 5px;
  color: var(--dim); cursor: pointer; padding: 0;
}
.details-retour svg {
  width: 14px; height: 14px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.details-retour:hover { color: var(--text); border-color: var(--dim); }
.details-close:hover { color: var(--text); }

.detail-head { padding: 18px 18px 14px; border-bottom: 1px solid var(--line); }
.detail-head h2 { margin: 0 30px 5px 0; font-size: calc(16px * var(--echelle-texte)); font-weight: 600; }
.detail-head .sub { font-size: calc(11.5px * var(--echelle-texte)); color: var(--dim); font-family: var(--mono); }

.notice {
  margin: 14px 18px; padding: 10px 12px;
  border-radius: var(--radius); font-size: calc(11.5px * var(--echelle-texte)); line-height: 1.55;
  background: #2a2117; border: 1px solid var(--amber-dim); color: #e8c79a;
}
.notice.info { background: #16232b; border-color: #2c4756; color: #a9cbdc; }

.detail-section { padding: 14px 18px; border-bottom: 1px solid var(--line-soft); }
.detail-section h3 {
  margin: 0 0 10px; font-size: calc(11px * var(--echelle-texte)); font-weight: 600;
  text-transform: uppercase; letter-spacing: .07em; color: var(--dim);
}

.stats { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.stat {
  background: var(--panel-2); border: 1px solid var(--line-soft);
  border-radius: 5px; padding: 8px 10px;
}
.stat b { display: block; font-size: calc(16px * var(--echelle-texte)); font-family: var(--mono); color: var(--text); }
.stat span { font-size: calc(10.5px * var(--echelle-texte)); color: var(--dim); }

table.props { width: 100%; border-collapse: collapse; font-size: calc(12px * var(--echelle-texte)); }
table.props td { padding: 5px 0; vertical-align: top; }
table.props td:first-child { color: var(--dim); width: 44%; }
table.props td:last-child { font-family: var(--mono); font-size: calc(11.5px * var(--echelle-texte)); text-align: right; }

.bars { display: flex; flex-direction: column; gap: 8px; }
.bar-row { font-size: calc(11.5px * var(--echelle-texte)); }
.bar-row .bar-top { display: flex; justify-content: space-between; color: var(--muted); }
.bar-row .bar-top b { font-family: var(--mono); color: var(--text); font-weight: 500; }
.bar-track {
  height: 4px; margin-top: 4px; background: var(--line); border-radius: 2px;
  overflow: hidden;
}
.bar-track span { display: block; height: 100%; background: var(--teal); }

.flags { list-style: none; margin: 0; padding: 0; }
.flags li {
  font-size: calc(11.5px * var(--echelle-texte)); line-height: 1.5; color: var(--muted);
  padding-left: 15px; position: relative; margin-bottom: 4px;
}
.flags li::before {
  content: "▸"; position: absolute; left: 2px; color: var(--dim);
}

.quote {
  font-size: calc(12px * var(--echelle-texte)); line-height: 1.6; color: var(--muted);
  border-left: 2px solid var(--line); padding-left: 11px; font-style: italic;
}
.reasoning {
  font-size: calc(12px * var(--echelle-texte)); line-height: 1.55; color: var(--muted);
  background: var(--panel-2); border-radius: 5px; padding: 10px 12px;
}

select.status-select, textarea.note {
  width: 100%; background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text);
  padding: 8px 10px; font: inherit; font-size: calc(12.5px * var(--echelle-texte));
}
select.status-select:focus, textarea.note:focus {
  outline: none; border-color: var(--amber-dim);
}
textarea.note { margin-top: 8px; min-height: 66px; resize: vertical; }

.cand-row {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 18px; cursor: pointer;
  border-bottom: 1px solid var(--line-soft);
}
.cand-row:hover { background: var(--panel-2); }
.cand-row.is-active { background: #21201a; }
.cand-dot { flex: none; display: flex; align-items: center; }

/* ── pictogrammes de type ──
   Tracés au trait en `currentColor` : la couleur vient toujours du parent,
   jamais du pictogramme lui-même. */
.picto { display: block; }

/* Sur la carte, le pictogramme se pose sur une pastille sombre : sans elle,
   un trait clair disparaît sur une orthophoto claire. */
.picto-marker { background: none; border: none; }
.picto-chip {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%;
  background: rgba(12, 16, 22, .74);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .1);
  transition: transform .12s ease, box-shadow .12s ease;
}
.picto-marker:hover .picto-chip { transform: scale(1.12); }
.picto-marker.est-actif .picto-chip {
  background: rgba(12, 16, 22, .92);
  box-shadow: 0 0 0 2px currentColor;
}

.hypo-picto { flex: 0 0 auto; color: var(--amber); opacity: .78; }
.hypo.is-premiere .hypo-picto { opacity: 1; }
.cand-main { flex: 1; min-width: 0; }
.cand-name { font-size: calc(12.5px * var(--echelle-texte)); }
.cand-sub { font-size: calc(10.5px * var(--echelle-texte)); color: var(--dim); font-family: var(--mono); }
.cand-score {
  font-family: var(--mono); font-size: calc(12.5px * var(--echelle-texte)); color: var(--amber); flex: none;
}
/* Le style des lignes écartées est défini plus bas, avec celui des
   marqueurs : les deux doivent dire la même chose. */

/* ─────────────────────────── modale ─────────────────────────── */
.modal {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(6,8,11,.72); backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
}
.modal-card {
  width: 430px; max-width: calc(100vw - 32px);
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 10px; padding: 22px;
  box-shadow: 0 22px 60px rgba(0,0,0,.6);
}
.modal-card h2 { margin: 0 0 16px; font-size: calc(16px * var(--echelle-texte)); font-weight: 600; }
.modal-meta {
  margin: -8px 0 14px; font-size: calc(11.5px * var(--echelle-texte)); color: var(--dim); font-family: var(--mono);
}
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }

/* ─────────────────────────── mentions légales ─────────────────────────── */
.legal h3 { margin: 0 0 8px; font-size: calc(12px * var(--echelle-texte)); color: var(--muted); }
.legal p, .legal li { font-size: calc(11px * var(--echelle-texte)); line-height: 1.6; color: var(--dim); }
.legal ul { margin: 8px 0; padding-left: 16px; }
.legal .version { margin-top: 14px; font-family: var(--mono); font-size: calc(10px * var(--echelle-texte)); }

.hidden { display: none !important; }

/* ─────────────────────────── écrans étroits ─────────────────────────── */
@media (max-width: 1180px) {
  :root { --sidebar-w: 292px; --details-w: 320px; }
}
/* `dvh` et non `vh` : sur un mobile, `vh` est figé sur la hauteur que
   l'écran aurait sans barre d'adresse. Le panneau dépassait donc du bas
   tant que la barre était déployée, et le dernier livrable de la fiche
   passait sous elle. `dvh` suit la hauteur réellement visible. La ligne en
   `vh` est conservée au-dessus : elle sert aux navigateurs qui ignorent
   `dvh`, où elle vaut mieux que rien. */
@media (max-width: 900px) {
  #app { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  #sidebar { max-height: 44vh; max-height: 44dvh; }
  #details {
    position: absolute; inset: auto 0 0 0; width: 100%;
    height: 56vh; height: 56dvh;
    border-left: none; border-top: 1px solid var(--line);
  }
}

/* Pastille « déjà répertorié » sur les candidats correspondant à un monument protégé */
.badge-known {
  margin-left: 7px;
  padding: 1px 6px;
  border-radius: 3px;
  font-size: calc(10px * var(--echelle-texte));
  font-weight: 600;
  letter-spacing: .02em;
  vertical-align: middle;
  background: rgba(242, 183, 5, .16);
  color: #f2b705;
  border: 1px solid rgba(242, 183, 5, .35);
}

/* Planche de vérification : vues croisées d'un même candidat */
.vignettes {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.vignettes figure {
  margin: 0;
  border: 1px solid var(--line, #2a2f3a);
  border-radius: 5px;
  overflow: hidden;
  background: #12141a;
}
.vignettes img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  cursor: zoom-in;
  transition: transform .18s ease;
}
.vignettes img:hover { transform: scale(1.06); }
.vignettes figcaption {
  padding: 4px 6px;
  font-size: calc(10px * var(--echelle-texte));
  letter-spacing: .02em;
  color: var(--dim, #8b93a5);
  border-top: 1px solid var(--line, #2a2f3a);
}

/* Choix du mode d'analyse dans la modale */
.mode-choice { display: grid; gap: 7px; margin: 12px 0 4px; }
.mode-option {
  display: flex; gap: 9px; align-items: flex-start;
  padding: 9px 11px; border: 1px solid var(--line, #2a2f3a);
  border-radius: 6px; cursor: pointer; transition: border-color .15s;
}
.mode-option:hover { border-color: #4a5364; }
.mode-option:has(input:checked) { border-color: #f2b705; background: rgba(242,183,5,.06); }
.mode-option input { margin-top: 3px; }
.mode-option b { display: block; font-size: calc(12.5px * var(--echelle-texte)); }
.mode-option em {
  display: block; margin-top: 2px; font-style: normal;
  font-size: calc(11px * var(--echelle-texte)); line-height: 1.45; color: var(--dim, #8b93a5);
}
.mode-option input:disabled + span { opacity: .4; }

/* Barre d'avancement des campagnes */
.progress-slim {
  height: 3px; margin-top: 5px; border-radius: 2px;
  background: rgba(255,255,255,.09); overflow: hidden;
}
.progress-slim.big { height: 6px; margin-bottom: 10px; }
.progress-slim span {
  display: block; height: 100%; background: #f2b705;
  transition: width .4s ease;
}

/* La phase en cours, sous le nom de la zone. Elle change une dizaine de fois
   pendant une analyse — c'est ce qui distingue une attente d'un blocage. */
.card-phase {
  margin-top: 5px;
  font-size: calc(10.5px * var(--echelle-texte));
  color: var(--amber);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.card.est-en-analyse { border-color: rgba(242,183,5,.34); }

/* L'emprise en cours d'analyse respire sur la carte : c'est ce qui relie la
   fiche de gauche au rectangle qu'on regarde. Deux secondes et demie par
   cycle — assez lent pour n'être pas un clignotement. */
@keyframes strata-respire {
  50% { stroke-opacity: 1; stroke-width: 2.6; }
}
.emprise-en-analyse {
  stroke: #f2b705 !important;
  stroke-opacity: .55;
  animation: strata-respire 2.5s ease-in-out infinite;
}

/* Une animation d'attente qui ne peut pas être arrêtée devient une gêne pour
   qui y est sensible. L'information reste : le chiffre, la phase, la couleur. */
@media (prefers-reduced-motion: reduce) {
  .job-bar.est-bloquee span,
  .progress-slim.est-bloquee span,
  .emprise-en-analyse { animation: none; }
  .emprise-en-analyse { stroke-opacity: 1; }
}

.list-title {
  margin: 16px 0 6px; font-size: calc(10.5px * var(--echelle-texte)); font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; color: var(--dim, #8b93a5);
}

/* Planche des tracés linéaires : format paysage, une vue par ligne */
.vignettes.lineaires { grid-template-columns: 1fr; }
.vignettes .vignette.large img { aspect-ratio: 2 / 1; }

/* ═══════════ hypothèses typologiques ═══════════
   Le vert porte ce qui soutient, le rouge ce qui manque. Les deux sont
   toujours montrés : une nomination sans ses réserves serait crue. */
.hypo {
  padding: 8px 10px; margin-bottom: 7px;
  background: var(--panel-2); border: 1px solid var(--line);
  border-left: 3px solid var(--dim); border-radius: var(--radius);
}
.hypo.is-premiere { border-left-color: var(--amber); }
.hypo-tete { display: flex; align-items: center; gap: 8px; }
.hypo-nom { font-size: calc(12.5px * var(--echelle-texte)); font-weight: 600; color: var(--text); flex: 1; min-width: 0; }
.hypo-conf {
  font-family: var(--mono); font-size: calc(11px * var(--echelle-texte)); color: var(--amber); flex: 0 0 auto;
}
.hypo ul { margin: 5px 0 0; padding-left: 15px; }
.hypo li { font-size: calc(11px * var(--echelle-texte)); line-height: 1.45; }
.hypo-pour li { color: var(--green); }
.hypo-contre li { color: var(--red); }
.hypo-note {
  margin: 6px 0 0; font-size: calc(11px * var(--echelle-texte)); line-height: 1.45; color: var(--muted);
}
.hypo-conf-avec {
  margin: 5px 0 0; font-size: calc(10.5px * var(--echelle-texte)); line-height: 1.45; color: var(--dim);
  font-style: italic;
}

/* ═══════════ loupe : vignette en plein écran ═══════════
   L'image est affichée en `contain` et non recadrée : une vue de vérification
   tronquée ne sert à rien, c'est précisément ce qu'on vient regarder en grand. */
.loupe {
  position: fixed; inset: 0; z-index: 2000;
  display: grid; place-items: center;
  background: rgba(6, 8, 11, .93);
  backdrop-filter: blur(6px);
  padding: 48px 64px;
}
.loupe.hidden { display: none; }

.loupe-cadre { margin: 0; display: flex; flex-direction: column; gap: 12px;
  max-width: 100%; max-height: 100%; }
.loupe-cadre img {
  /* Le cadre est une colonne flexible : sans cela, l'image est étirée à sa
     largeur et le rapport hauteur/largeur se perd d'un ou deux pour cent —
     assez pour qu'un profil en travers mente sur sa pente. */
  align-self: center;
  /* La taille est posée par `ajusterLoupe()` : en CSS, `max-width` borne mais
     n'agrandit pas, et une vignette de 240 px restait à 240 px au milieu d'un
     écran vide. Aucune borne ici — elles rogneraient une taille déjà calculée
     pour tenir, et fausseraient le rapport hauteur/largeur. */
  object-fit: contain; border-radius: 6px;
  border: 1px solid var(--line);
  background: #0e1015;
  /* Le rendu 3D et les vignettes sont volontairement petits en pixels :
     l'interpolation lisse doit être remplacée par des pixels francs, sinon
     l'agrandissement invente du micro-relief qui n'existe pas. */
  image-rendering: pixelated;
}
.loupe-cadre figcaption {
  text-align: center; font-size: calc(12.5px * var(--echelle-texte)); color: var(--muted);
  letter-spacing: .01em;
}

.loupe-fermer, .loupe-nav {
  position: absolute; z-index: 1;
  background: rgba(20, 26, 33, .9); color: var(--text);
  border: 1px solid var(--line); border-radius: 8px;
  cursor: pointer; font: inherit; line-height: 1;
  transition: border-color .15s ease, background .15s ease;
}
.loupe-fermer:hover, .loupe-nav:hover { border-color: var(--amber); background: var(--panel-2); }
.loupe-fermer { top: 14px; right: 16px; width: 38px; height: 38px; font-size: calc(15px * var(--echelle-texte)); }
.loupe-nav { top: 50%; transform: translateY(-50%); width: 42px; height: 66px; font-size: calc(26px * var(--echelle-texte)); }
.loupe-nav.prec { left: 14px; }
.loupe-nav.suiv { right: 14px; }
.loupe-nav[disabled] { opacity: .25; cursor: default; }
.loupe-nav[disabled]:hover { border-color: var(--line); background: rgba(20, 26, 33, .9); }

@media (max-width: 640px) {
  .loupe { padding: 44px 12px; }
  .loupe-nav { width: 34px; height: 54px; font-size: calc(20px * var(--echelle-texte)); }
}

/* ═══════════ coordonnées d'un résultat ═══════════ */
.coord-bloc { display: flex; flex-direction: column; gap: 6px; }
.coord-ligne {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 9px; background: var(--panel-2);
  border: 1px solid var(--line); border-radius: var(--radius, 7px);
}
.coord-ligne .quoi {
  flex: 0 0 58px; font-size: calc(10.5px * var(--echelle-texte)); letter-spacing: .05em;
  text-transform: uppercase; color: var(--dim);
}
.coord-ligne .valeur {
  flex: 1; font-family: var(--mono); font-size: calc(12px * var(--echelle-texte)); color: var(--text);
  user-select: all; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.coord-copier {
  flex: 0 0 auto; padding: 4px 9px; font-size: calc(11px * var(--echelle-texte));
  background: none; color: var(--muted); cursor: pointer;
  border: 1px solid var(--line); border-radius: 5px;
  transition: color .15s ease, border-color .15s ease;
}
.coord-copier:hover { color: var(--amber); border-color: var(--amber); }
.coord-copier.fait { color: var(--green); border-color: var(--green); }
.lien-carte { display: flex; flex-direction: column; gap: 6px; margin-top: 9px; }

/* ═══════════ licence ═══════════ */
.lic-etat {
  padding: 9px 11px; margin-bottom: 8px;
  border: 1px solid var(--line); border-left-width: 3px;
  border-radius: var(--radius); background: var(--panel-2);
}
.lic-etat.is-ok   { border-left-color: var(--green); }
.lic-etat.is-eval { border-left-color: var(--amber); }
.lic-titre { font-size: calc(13px * var(--echelle-texte)); font-weight: 600; color: var(--text); }
.lic-sub {
  margin-top: 2px; font-size: calc(11.5px * var(--echelle-texte)); line-height: 1.45; color: var(--dim);
}
/* La référence est le numéro qu'on rappelle au support : elle doit se lire
   d'un coup d'œil et se sélectionner d'un double-clic. */
.lic-ref {
  margin-top: 5px; font-family: var(--mono); font-size: calc(11px * var(--echelle-texte));
  letter-spacing: 0.06em; color: var(--dim); user-select: all;
}
/* ─── choix d'apparence ───
   Deux pavés côte à côte plutôt qu'une case à cocher : on choisit entre
   deux choses, pas on active une option. */
.peau-choix { display: flex; gap: 7px; }
.peau-option {
  flex: 1; text-align: left; cursor: pointer;
  padding: 9px 10px; color: var(--muted);
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--radius); font: inherit;
  transition: border-color .15s, color .15s, background .15s;
}
.peau-option:hover { border-color: var(--dim); color: var(--text); }
.peau-option.is-active {
  border-color: var(--amber); color: var(--text); background: #21201a;
}
.peau-nom { display: block; font-size: calc(12.5px * var(--echelle-texte)); font-weight: 600; }
.peau-sub { display: block; margin-top: 2px; font-size: calc(10.5px * var(--echelle-texte)); color: var(--dim); }

/* Le dépôt de fichier est le geste principal : il occupe la place, la saisie
   manuelle se replie derrière un dépliant. */
.lic-depot {
  margin-top: 10px; padding: 18px 12px; text-align: center; cursor: pointer;
  border: 1.5px dashed var(--line); border-radius: var(--radius);
  background: var(--panel-2); transition: border-color .18s, background .18s;
}
.lic-depot:hover, .lic-depot:focus-visible, .lic-depot.est-survole {
  border-color: var(--accent); background: var(--panel);
}
.lic-depot.est-survole { border-style: solid; }
.lic-depot-titre { font-size: calc(12.5px * var(--echelle-texte)); font-weight: 600; color: var(--text); }
.lic-depot-sub { margin-top: 4px; font-size: calc(11px * var(--echelle-texte)); color: var(--dim); }
.lic-depot-sub code {
  font-family: var(--mono); font-size: calc(10.5px * var(--echelle-texte)); color: var(--text);
}

.lic-manuel { margin-top: 8px; }
.lic-manuel > summary {
  cursor: pointer; font-size: calc(11.5px * var(--echelle-texte)); color: var(--dim); padding: 4px 0;
  list-style: none;
}
.lic-manuel > summary::-webkit-details-marker { display: none; }
.lic-manuel > summary::before { content: '▸ '; }
.lic-manuel[open] > summary::before { content: '▾ '; }
.lic-manuel > summary:hover { color: var(--text); }
.lic-manuel #lic-poser { margin-top: 6px; }

#lic-texte {
  width: 100%; resize: vertical; font-family: var(--mono); font-size: calc(10.5px * var(--echelle-texte));
  /* Une clé se relit groupe par groupe : l'espacement des caractères et des
     lignes fait plus pour la vérification que n'importe quel message d'aide. */
  letter-spacing: 0.08em; line-height: 1.7; text-transform: uppercase;
  padding: 7px 8px; color: var(--text);
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--radius);
}
#lic-oter { margin-top: 6px; }

/* ═══════════ guide de lecture ═══════════
   Une légende doit se parcourir en diagonale : la pastille porte la couleur,
   le gras porte le nom, le reste s'efface. */
.lg-row {
  display: flex; gap: 9px; align-items: flex-start;
  padding: 7px 0; border-bottom: 1px solid var(--line-soft);
}
.lg-row:last-of-type { border-bottom: none; }
.lg-row b {
  display: block; font-size: calc(12.5px * var(--echelle-texte)); font-weight: 600; color: var(--text);
}
.lg-row em {
  display: block; margin-top: 2px; font-style: normal;
  font-size: calc(11.5px * var(--echelle-texte)); line-height: 1.5; color: var(--dim);
}
.lg-row-plain { padding-left: 2px; }
.lg-type { display: flex; align-items: flex-start; gap: 11px; padding-left: 2px; }
.lg-type-picto { flex: 0 0 26px; color: var(--amber); margin-top: 1px; }

/* La pastille imite la marque portée sur la carte : anneau pour une forme
   ponctuelle, segment pour un tracé. */
.lg-dot {
  flex: 0 0 auto; margin-top: 3px; display: block;
  width: 12px; height: 12px; border-radius: 50%;
}
.lg-dot.ring { background: none; border: 2px solid transparent; }
.lg-dot.line { width: 16px; height: 3px; border-radius: 2px; margin-top: 8px; }

.lg-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 4px; }
.lg-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 8px 3px 6px; font-size: calc(11px * var(--echelle-texte)); color: var(--muted);
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 20px;
}
.lg-chip .lg-dot { margin-top: 0; width: 9px; height: 9px; }

.lg-table td { padding: 5px 6px; font-size: calc(11.5px * var(--echelle-texte)); }
.lg-table td:first-child { color: var(--text); }
.lg-mono { font-family: var(--mono); color: var(--dim) !important; }
.lg-ok { color: var(--green); font-weight: 600; }
.lg-warn { color: var(--amber); }

/* Perspectives obliques : le rendu est déjà cadré sur son propre fond, donc
   `contain` plutôt que `cover` — un rognage couperait le repère du candidat. */
.vignettes .vignette.relief img {
  aspect-ratio: 2 / 1;
  object-fit: contain;
  background: #0e1015;
}

/* ── mises à jour ──
   Un bandeau, pas une fenêtre modale : l'information est utile, elle
   n'interrompt pas le travail en cours. */
.maj-banner {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin: 0 12px 10px; padding: 9px 11px;
  border: 1px solid rgba(242, 183, 5, .3);
  border-radius: 8px;
  background: rgba(242, 183, 5, .07);
  font-size: calc(11.5px * var(--echelle-texte)); line-height: 1.45;
}
.maj-banner span { flex: 1 1 100%; }
.maj-banner a, .maj-banner button {
  font: inherit; color: var(--amber); background: none;
  border: 1px solid rgba(242, 183, 5, .38); border-radius: 6px;
  padding: 3px 10px; cursor: pointer;
}
.maj-banner a:hover, .maj-banner button:hover { background: rgba(242, 183, 5, .14); }
.maj-banner .maj-fermer {
  flex: none; margin-left: auto; border: none; padding: 0 6px;
  font-size: calc(15px * var(--echelle-texte)); line-height: 1; color: var(--dim);
}

.maj-dispo {
  margin: 10px 0; padding: 10px 12px;
  border-left: 2px solid var(--amber);
  background: rgba(242, 183, 5, .06); border-radius: 0 6px 6px 0;
}
.maj-dispo b { font-size: calc(12.5px * var(--echelle-texte)); }
.maj-dispo .maj-date { font-family: var(--mono); font-size: calc(10.5px * var(--echelle-texte)); color: var(--dim); margin-left: 7px; }
.maj-dispo p { font-size: calc(11.5px * var(--echelle-texte)); margin: 5px 0 8px; }

/* Lien d'écoute dans la notice d'un réglage : c'est un bouton, mais il doit
   se lire comme un mot de la phrase qui l'entoure. */
.lien-essai {
  background: none; border: none; padding: 0; margin-left: 4px;
  font: inherit; color: var(--amber); cursor: pointer;
  text-decoration: underline; text-underline-offset: 2px;
}
.lien-essai:hover { color: var(--text); }

/* ═══════════════════ étoiles, bandeau de lecture, menus ═══════════════════ */

/* Cinq crans valent mieux que « 0,66 ». Le libellé qui les accompagne parle de
   netteté de forme, jamais de qualité ni de certitude : un score de Strata
   mesure une compatibilité géométrique, pas la probabilité d'un site. */
.etoiles { letter-spacing: 1px; white-space: nowrap; font-size: calc(19px * var(--echelle-texte));
  line-height: 1; }
.etoiles.sm { font-size: calc(13px * var(--echelle-texte)); letter-spacing: .5px; }
.etoiles .est-plein { color: currentColor; }
.etoiles .est-vide  { color: var(--line); }

.est-tres-net { color: var(--green); }
.est-net      { color: var(--amber); }
.est-partiel  { color: var(--amber-dim); }
.est-tenu     { color: var(--dim); }
.est-faible   { color: var(--dim); opacity: .75; }

/* Le bandeau de tête : l'information que l'utilisateur cherche en premier,
   avant d'entrer dans le détail des critères. */
.lecture {
  margin: 0 0 4px; padding: 13px 16px 12px;
  border-bottom: 1px solid var(--line-soft);
  border-left: 3px solid currentColor;
  background: linear-gradient(90deg, rgba(255, 255, 255, .028), transparent 60%);
}
.lecture-haut { display: flex; align-items: center; gap: 10px; }
.lecture-picto { flex: 0 0 26px; }
.lecture-nom {
  font-size: calc(14px * var(--echelle-texte)); font-weight: 600; line-height: 1.3; color: var(--text);
}
.lecture-bas {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px;
  margin-top: 9px;
}
.lecture-niveau { font-size: calc(12px * var(--echelle-texte)); font-weight: 600; }
.lecture-chiffre {
  font-family: var(--mono); font-size: calc(10.5px * var(--echelle-texte)); color: var(--dim);
}
.lecture-note {
  margin: 9px 0 0; font-size: calc(10.5px * var(--echelle-texte)); line-height: 1.5; color: var(--dim);
}
.lecture-note b { color: var(--muted); font-weight: 600; }

.bar-val { font-family: var(--mono); font-size: calc(11px * var(--echelle-texte)); margin-left: 5px; }
.cand-score { flex: none; }

/* ═══════════════════════════ animations ═══════════════════════════ */

/* Trois cents millisecondes : assez pour que l'œil suive un ordre, trop peu
   pour qu'on attende. Toutes sont désactivées si le poste demande une
   réduction du mouvement. */

@keyframes poser {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}
.bloc-apparait { animation: poser .3s cubic-bezier(.22, .8, .3, 1) both; }

/* Cent cinquante marqueurs surgissant d'un bloc forment une tache ; un semis
   qui se pose laisse voir où ils se groupent. */
@keyframes surgir {
  from { opacity: 0; transform: scale(.4); }
  60%  { opacity: 1; transform: scale(1.14); }
  to   { opacity: 1; transform: scale(1); }
}
.picto-apparait .picto-chip {
  animation: surgir .34s cubic-bezier(.2, .9, .3, 1.2) both;
  animation-delay: inherit;
}

/* Balayage de fin d'analyse : il dit *où* regarder au moment où les
   marqueurs s'y posent. */
@keyframes balayer {
  from { transform: translateX(-100%); opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  to   { transform: translateX(100%); opacity: 0; }
}
.balayage {
  position: absolute; inset: 0; z-index: 480; pointer-events: none;
  background: linear-gradient(100deg, transparent 38%,
    rgba(224, 164, 88, .16) 48%, rgba(224, 164, 88, .30) 50%,
    rgba(224, 164, 88, .16) 52%, transparent 62%);
  animation: balayer 1.1s ease-in-out both;
}

@media (prefers-reduced-motion: reduce) {
  .bloc-apparait, .picto-apparait .picto-chip, .balayage { animation: none; }
  .balayage { display: none; }
  .picto-chip { transition: none; }
}


/* ═══════════════════════ focalisation sur la carte ═══════════════════════
   Tant que tout a le même poids, la carte reste une nappe de points et l'œil
   n'a nulle part où se poser. Sélectionner réordonne la scène.

   Trois plans, et le plan intermédiaire porte une information : le voisinage.
   La proximité compte en archéologie — une motte flanquée d'un enclos peut
   avoir eu une basse-cour, une charbonnière isolée n'a pas le même sens que
   la vingtième d'un groupe. Le détecteur mesure déjà l'isolement ; ceci le
   rend visible. */

/* Plan 3 — le lointain s'efface, sans disparaître : on doit continuer à voir
   qu'il y a autre chose autour. */
.est-focalisee .picto-marker { opacity: .22; transition: opacity .22s ease; }
.est-focalisee .leaflet-overlay-pane path {
  opacity: .18; transition: opacity .22s ease;
}

/* Plan 2 — le voisinage, en demi-teinte. */
.est-focalisee .picto-marker.est-voisin { opacity: .78; }
.est-focalisee .leaflet-overlay-pane path.est-voisin { opacity: .7; }

/* Plan 1 — l'objet choisi, à pleine intensité et devant. */
.est-focalisee .picto-marker.est-actif { opacity: 1; z-index: 700 !important; }
.est-focalisee .leaflet-overlay-pane path.est-actif { opacity: 1; }

/* Le halo. Il désigne, il ne clignote pas : deux battements amples puis il
   se stabilise en anneau fixe. Un halo qui pulse indéfiniment finit par
   accrocher l'œil au mauvais moment, quand on lit le panneau de droite. */
@keyframes halo {
  0%   { box-shadow: 0 0 0 0 currentColor, 0 0 0 1px rgba(255,255,255,.14); }
  70%  { box-shadow: 0 0 0 14px transparent, 0 0 0 1px rgba(255,255,255,.14); }
  100% { box-shadow: 0 0 0 14px transparent, 0 0 0 1px rgba(255,255,255,.14); }
}
.est-focalisee .picto-marker.est-actif .picto-chip {
  transform: scale(1.28);
  background: rgba(12, 16, 22, .95);
  box-shadow: 0 0 0 2px currentColor, 0 0 16px -2px currentColor;
}
/* Le halo se pose sur la pastille et non sur le marqueur : la couleur du type
   est portée par la pastille, et `currentColor` doit la retrouver. */
.est-focalisee .picto-marker.est-actif .picto-chip::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  pointer-events: none;
  animation: halo 1.15s cubic-bezier(.2, .7, .3, 1) 2 both;
}

@media (prefers-reduced-motion: reduce) {
  .est-focalisee .picto-marker,
  .est-focalisee .leaflet-overlay-pane path { transition: none; }
  .est-focalisee .picto-marker.est-actif .picto-chip::after { animation: none; }
}

/* ═══════════════ plein écran, tracé libre, curseurs, choix ═══════════════ */

/* Bouton flottant sur la carte. Discret au repos, franc au survol : il ne doit
   pas concurrencer le relief, qui est le sujet. */
.bouton-flottant {
  position: absolute; top: 14px; left: 14px; z-index: 600;
  width: 32px; height: 32px; padding: 6px;
  background: rgba(20, 26, 33, .92); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--muted);
  cursor: pointer; backdrop-filter: blur(6px);
  transition: color .12s, border-color .12s;
}
.bouton-flottant:hover { color: var(--amber); border-color: var(--amber-dim); }
.bouton-flottant svg { width: 100%; height: 100%; display: block; }

/* En plein écran, la barre latérale se rétracte : chaque pixel rendu au
   relief est un pixel gagné. Elle revient au survol du bord gauche. */
.est-plein-ecran #sidebar {
  transition: margin-left .2s ease;
}
.est-plein-ecran .bouton-flottant { top: 14px; left: 14px; }

.paire-boutons { display: flex; gap: 6px; }
.paire-boutons .btn { flex: 1; padding: 9px 8px; font-size: calc(12.5px * var(--echelle-texte)); }

/* Curseurs. Le module `curseurs.js` décide *lequel*, la feuille de style
   décide *où* : la carte, le tracé, le reste. */
:root {
  /* Repli si `curseurs.js` n'a pas encore tourné. La carte au repos porte une
     flèche : c'est le tracé, et lui seul, qui appelle un réticule. */
  --curseur-carte: default;
  --curseur-trace: crosshair;
  --curseur-general: default;
  /* La main du système est le dernier vestige des interfaces de 2005, et elle
     cache une bonne part de ce qu'on fait glisser. */
  --curseur-deplacer: grab;
  --curseur-deplacer-serre: grabbing;
}
#map { cursor: var(--curseur-carte); }
/* Leaflet pose ses propres `grab` / `grabbing` sur le conteneur : il faut les
   reprendre nommément, sans quoi la main du système revient au premier
   glissement. */
/* Leaflet pose `grab` — la main ouverte — dès qu'une carte est déplaçable.
   Au repos on veut la flèche : on désigne bien plus souvent qu'on ne déplace,
   et la main annonce en permanence un geste qui n'est pas le geste courant.
   Elle se referme en revanche pendant le glissement, où elle dit exactement
   ce qui se passe. */
.leaflet-grab { cursor: var(--curseur-carte); }
#map.leaflet-drag-target,
.leaflet-dragging #map,
.leaflet-dragging .leaflet-grab { cursor: var(--curseur-deplacer-serre) !important; }
.map-drawing, .map-drawing .leaflet-container { cursor: var(--curseur-trace) !important; }
.leaflet-interactive { cursor: pointer; }

/* Menus déroulants des réglages : le `select` natif du système jure avec le
   reste, mais on le garde — il est accessible, et il s'ouvre correctement
   dans une fenêtre WebView2. On l'habille seulement. */
.field select {
  width: 100%; background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text);
  padding: 8px 10px; font: inherit; font-size: calc(13px * var(--echelle-texte)); cursor: pointer;
}
.field select:focus { outline: none; border-color: var(--amber-dim); }

/* ═══════════════ sections repliables, poignées, corbeille ═══════════════ */

/* Le chevron : un simple angle, pivoté de 90° à l'ouverture. C'est la
   convention que tout le monde connaît, et elle ne demande aucune légende. */
.chevron {
  flex: none; width: 14px; height: 14px;
  background: currentColor;
  -webkit-mask: no-repeat center / 10px 10px
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
  mask: no-repeat center / 10px 10px
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
  transform: rotate(90deg);
  transition: transform .16s cubic-bezier(.2, .8, .3, 1);
}
.est-repliee > .section-tete .chevron,
.est-repliee > .bloc-tete .chevron { transform: rotate(0deg); }

/* ─── sections de la colonne de gauche ─── */
.section { border-bottom: 1px solid var(--line-soft); }
.section:last-of-type { border-bottom: none; }

.section-tete {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 11px 2px; background: none; border: none;
  color: var(--muted); font: inherit; font-size: calc(11.5px * var(--echelle-texte)); font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; text-align: left;
  cursor: pointer; transition: color .12s;
}
.section-tete:hover { color: var(--text); }
.section-nom { flex: 1; }
.section-compte {
  font-family: var(--mono); font-size: calc(10.5px * var(--echelle-texte)); font-weight: 400;
  letter-spacing: 0; color: var(--dim);
  min-width: 16px; text-align: right;
}

.section-corps { padding-bottom: 14px; }
.section.est-repliee > .section-corps { display: none; }

/* La corbeille est une cible de dépôt : elle doit se signaler comme telle dès
   qu'un élément est saisi, sinon personne ne devine qu'on peut y jeter. */
.section.est-corbeille { border-top: 1px solid var(--line); margin-top: 4px; }
body.en-deplacement .section.est-corbeille {
  outline: 1px dashed var(--amber-dim); outline-offset: 2px; border-radius: 6px;
}
.section.est-corbeille.est-cible {
  outline: 2px dashed var(--amber); background: rgba(224, 164, 88, .07);
}

/* ─── blocs repliables du panneau de droite ─── */
.bloc-tete {
  display: flex; align-items: center; gap: 7px; width: 100%;
  padding: 0 0 8px; background: none; border: none;
  color: var(--muted); font: inherit; font-size: calc(11px * var(--echelle-texte)); font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; text-align: left;
  cursor: pointer;
}
.bloc-tete:hover { color: var(--text); }
.detail-section.est-repliee > .bloc-corps { display: none; }
.detail-section.est-repliee { padding-bottom: 6px; }


/* ─── cartes de la corbeille ─── */
.card.est-supprimee { cursor: default; opacity: .82; }
.card.est-supprimee:hover { opacity: 1; }
.card-meta.est-urgent { color: var(--red); font-weight: 600; }

.btn-mini {
  padding: 4px 9px; font-size: calc(11.5px * var(--echelle-texte)); margin-top: 8px;
}
.btn-danger { color: var(--red); border-color: #4a2f28; margin-top: 10px; }
.btn-danger:hover { background: rgba(212, 103, 74, .1); border-color: var(--red); }

/* ─── ce qui a été écarté ───
   L'opacité est déjà prise : elle porte la focalisation (lointain 0,22 /
   voisin 0,78 / choisi 1). Lui faire dire en plus « écarté » rendrait les deux
   signaux illisibles — et surtout, un objet écarté qu'on vient de sélectionner
   se serait effacé au moment précis où l'on veut le regarder.

   « Écarté » se dit donc par la MATIÈRE : couleur retirée, contour tireté,
   pastille creuse. On le voit, on sait qu'il est écarté, et il ne concurrence
   pas ce qui reste à examiner. */
.picto-chip.est-ecartee {
  filter: grayscale(1);
  background: rgba(12, 16, 22, .5);
  box-shadow: 0 0 0 1px currentColor inset;
  opacity: .7;
}
/* Sélectionné, il redevient pleinement visible : on le regarde. Il garde son
   gris, qui suffit à dire son état. */
.est-focalisee .picto-marker.est-actif .picto-chip.est-ecartee {
  opacity: 1;
  filter: grayscale(.7);
}

/* Dans les listes, même principe : le nom est barré plutôt qu'effacé. Une
   ligne à 42 % d'opacité se lisait comme un défaut d'affichage. */
.cand-row.is-dismissed { opacity: .72; }
.cand-row.is-dismissed .cand-name {
  text-decoration: line-through;
  text-decoration-color: var(--dim);
  text-decoration-thickness: 1px;
}
.cand-row.is-dismissed .cand-dot { filter: grayscale(1); }

/* ─── navigation d'une fiche à l'autre ───
   Examiner trente candidats coûtait trois gestes par candidat : fermer,
   retrouver la ligne, cliquer. C'est le geste le plus fréquent du logiciel ;
   il doit coûter une flèche. */
.nav-fiche {
  display: flex; align-items: center; gap: 4px;
  margin: -4px 34px 10px 0;
}
.nav-fleche {
  width: 24px; height: 24px; padding: 0; flex: none;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 5px; color: var(--muted);
  font-size: calc(15px * var(--echelle-texte)); line-height: 1; cursor: pointer;
  transition: color .12s, border-color .12s;
}
.nav-fleche:hover:not(:disabled) { color: var(--amber); border-color: var(--amber-dim); }
.nav-fleche:disabled { opacity: .3; cursor: default; }

.nav-rang {
  font-family: var(--mono); font-size: calc(12px * var(--echelle-texte)); color: var(--text);
  padding: 0 4px; min-width: 52px; text-align: center;
}
.nav-rang em { font-style: normal; color: var(--dim); margin: 0 1px; }
.nav-quoi {
  font-size: calc(10px * var(--echelle-texte)); color: var(--dim); text-transform: uppercase;
  letter-spacing: .06em; margin-left: 2px;
}

/* ═══════════ carte d'analyse : état, nom, poignée ═══════════ */

/* Un signe plutôt qu'un mot. « ANALYSÉE » répété sur chaque carte occupait un
   tiers de la largeur pour dire ce qui est vrai de presque toutes — une
   étiquette identique partout ne se lit plus, elle se contourne. */
.card-top { display: flex; align-items: center; gap: 8px; }
.card-title { flex: 1; min-width: 0; }

.etat {
  flex: none; width: 16px; height: 16px; display: block;
}
.etat svg { width: 100%; height: 100%; display: block; }
.etat.est-terminee  { color: var(--green); }
.etat.est-en-cours  { color: var(--amber); }
.etat.est-en-echec  { color: var(--red); }
.etat.est-attente   { color: var(--dim); }

/* Le sablier tourne lentement : assez pour dire que ça travaille, assez peu
   pour ne pas accrocher l'œil pendant qu'on lit ailleurs. */
@keyframes sablier { to { transform: rotate(180deg); } }
.etat.est-en-cours svg { animation: sablier 2.4s ease-in-out infinite alternate; }
@media (prefers-reduced-motion: reduce) {
  .etat.est-en-cours svg { animation: none; }
}

/* Crayon : discret au repos, il n'apparaît qu'au survol de la carte — le nom
   se lit bien plus souvent qu'il ne se corrige. */
.crayon {
  flex: none; width: 22px; height: 22px; padding: 3px;
  background: none; border: none; border-radius: 4px;
  color: var(--dim); cursor: pointer;
  opacity: 0; transition: opacity .13s, color .13s;
}
.card:hover .crayon { opacity: 1; }
.crayon:hover { color: var(--amber); background: rgba(255, 255, 255, .05); }
.crayon svg { width: 100%; height: 100%; display: block; }

/* Édition sur place : on corrige un mot, pas un formulaire. */
.champ-titre {
  flex: 1; min-width: 0;
  background: var(--bg); border: 1px solid var(--amber-dim);
  border-radius: 4px; color: var(--text);
  font: inherit; font-size: calc(13px * var(--echelle-texte)); font-weight: 550;
  padding: 2px 6px;
}
.champ-titre:focus { outline: none; border-color: var(--amber); }


/* ─── les trois boutons d'une carte ───
   Renommer, supprimer, ranger : trois gestes de même nature — ils agissent sur
   la fiche, pas sur son contenu — donc trois boutons de même famille. Révélés
   au survol : le nom se lit bien plus souvent qu'il ne se corrige, et au repos
   la carte ne montre que ce qu'on vient y chercher. */
.actions-carte {
  display: flex; align-items: center; gap: 1px; flex: none;
  margin: -3px -4px -3px 0;
  opacity: 0; transition: opacity .13s;
}
.card:hover .actions-carte,
.actions-carte:focus-within { opacity: 1; }

.action-carte {
  width: 24px; height: 24px; padding: 4px; flex: none;
  background: none; border: none; border-radius: 5px;
  color: var(--dim); cursor: pointer;
  transition: color .12s, background .12s;
}
.action-carte:hover { color: var(--amber); background: rgba(255, 255, 255, .06); }
.action-carte.est-danger:hover { color: var(--red); background: rgba(212, 103, 74, .12); }
.action-carte svg { width: 100%; height: 100%; display: block; }
.action-carte.poignee { cursor: grab; }
.action-carte.poignee svg { fill: currentColor; stroke: none; }
.action-carte.poignee:active { cursor: grabbing; }
/* Le clavier doit atteindre les trois : le contour ne suffit pas si le groupe
   est transparent, d'où le `:focus-within` plus haut. */
.action-carte:focus-visible { outline: 1px solid var(--amber); outline-offset: -1px; }

.card.est-deplacable { position: relative; }
.card.est-tiree { opacity: .35; }

/* ═══════════ finitions typographiques ═══════════
   Trois réglages qui ne se voient pas isolément et se remarquent tous
   ensemble. Ils viennent de l'audit des compétences de conception installées
   dans `.claude/skills/`.

   1. CHIFFRES TABULAIRES. Toutes les mesures du logiciel — diamètres,
      hauteurs, scores, pourcentages — s'alignent en colonne. Sans cela, un
      « 1 » plus étroit qu'un « 8 » fait danser une colonne de chiffres, et
      l'œil ne peut plus comparer deux lignes d'un coup.
   2. ÉQUILIBRE DES TITRES. `text-wrap: balance` répartit un titre sur ses
      lignes au lieu de laisser un mot seul en dernière ligne. `pretty` fait
      de même pour les paragraphes, en évitant les lignes veuves. */
h1, h2, h3, .card-title, .bloc-lancer-titre {
  text-wrap: balance;
}
p, .hint, li, figcaption, small, em {
  text-wrap: pretty;
}

/* Partout où un nombre se compare à un autre. */
.props, .stat b, .etoiles + b, .lg-mono, .coord-ligne .valeur,
.card-meta, .mesure-val, .barre-val, table, code, kbd, .lic-ref {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* ═══════════════════════ traduction ═══════════════════════
   Le contenu est masqué le temps que le catalogue arrive. Sans cela la page
   s'affiche en français une fraction de seconde puis bascule, et ce
   clignotement se voit — c'est la même raison qui fait poser le thème dans un
   script en tête de page.

   `visibility` et non `display` : la mise en page est calculée pendant
   l'attente, si bien que rien ne saute au moment où le texte apparaît.

   Ce sélecteur ne s'applique jamais en français, où aucun catalogue n'est
   chargé et où l'attribut n'est donc jamais posé. */
html[data-langue-attente] body { visibility: hidden; }

.champ-langue select {
  width: 100%;
  padding: 6px 8px;
}

/* Lecture régionale : ce que la forme désigne habituellement dans le pays. */
.hypo-locale {
  margin: 6px 0 0; padding: 6px 9px; border-left: 2px solid var(--teal);
  background: rgba(94,170,168,.07); color: var(--text);
  font-size: calc(12px * var(--echelle-texte)); line-height: 1.45;
}
