/* ===========================================================================
   Gironde — suivi de l'incendie
   Parti pris : instrument éditorial. Le fond de carte reste neutre et froid ;
   toute la chaleur chromatique appartient au feu. Les moyens de lutte sont en
   cyan : la carte oppose visuellement le sinistre et la réponse humaine.
   =========================================================================== */

:root {
  /* --- socle --------------------------------------------------------- */
  --ink-000: #07070a;
  --ink-050: #0c0d11;
  --ink-100: #12141a;
  --ink-200: #1a1d25;
  --ink-300: #262a34;
  --ink-400: #363b48;

  --paper: #f4f1ec;
  --paper-dim: #a8a49d;
  --paper-mute: #6f6c67;

  /* --- échelle de braise : du charbon au coeur incandescent ---------- */
  --ember-000: #4a2410;
  --ember-100: #8c3208;
  --ember-200: #c8430a;
  --ember-300: #ef6316;
  --ember-400: #ff8c2b;
  --ember-500: #ffb648;
  --ember-600: #ffe1a0;

  /* --- réponse humaine ------------------------------------------------ */
  --ice-100: #0d3b45;
  --ice-200: #1a6f7f;
  --ice-300: #2fb3c9;
  --ice-400: #5ce0f0;
  --ice-500: #a8f2fb;

  /* --- catégories d'aéronefs ------------------------------------------ */
  --ac-amphibie: #5ce0f0;
  --ac-bombardier: #7d9bff;
  --ac-airtractor: #62f0c0;
  --ac-helico: #c79bff;
  --ac-militaire: #9aa6b8;
  --ac-coordination: #ffd166;

  /* foudre : violet électrique, distinct du feu comme de la réponse */
  --bolt: #b98cff;
  --bolt-hot: #e0c8ff;

  /* --- géométrie ------------------------------------------------------ */
  --r-sm: 4px;
  --r-md: 8px;
  --r-lg: 14px;
  --rail-w: 268px;
  --panel-w: 372px;
  --tl-h: 128px;

  --shadow-lift: 0 1px 2px rgba(0,0,0,.5), 0 8px 28px rgba(0,0,0,.44);
  --shadow-deep: 0 2px 6px rgba(0,0,0,.6), 0 24px 60px rgba(0,0,0,.5);

  --ease: cubic-bezier(.22,.61,.36,1);
  --ease-out: cubic-bezier(.16,1,.3,1);

  /* Registre typographique « instrument de bord ». Orbitron, très large et
     géométrique, ne tient que sur les titres et les grands chiffres ; Chakra
     Petch garde des formes techniques tout en restant lisible à 11 px, ce que
     ne fait pas Orbitron. */
  --font-display: "Orbitron", "Chakra Petch", sans-serif;
  --font-ui: "Chakra Petch", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: var(--ink-000);
  color: var(--paper);
  font-family: var(--font-ui);
  font-size: 14px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

button { font: inherit; color: inherit; cursor: pointer; }
a { color: inherit; }

::selection { background: var(--ember-300); color: #14100c; }

/* ---------------------------------------------------------------- carte */

#map { position: fixed; inset: 0; background: var(--ink-000); }

/* champ de vent : particules advectées, dessinées au-dessus de la carte */
#windCanvas {
  position: fixed; inset: 0; z-index: 1;
  pointer-events: none; opacity: 0;
  transition: opacity .6s var(--ease);
}
/* la toile ne se charge plus au fil du temps : elle peut donc être plus visible
   sans risquer de griser la carte */
#windCanvas.is-on { opacity: .78; }

/* léger assombrissement des bords : concentre le regard sur le sinistre */
.vignette {
  position: fixed; inset: 0; pointer-events: none; z-index: 2;
  background:
    radial-gradient(130% 96% at 50% 44%, transparent 42%, rgba(4,4,7,.42) 100%),
    linear-gradient(to bottom, rgba(4,4,7,.62) 0, transparent 15%, transparent 76%, rgba(4,4,7,.76) 100%);
}

.maplibregl-ctrl-attrib {
  background: rgba(8,9,12,.74) !important;
  color: var(--paper-mute) !important;
  font-size: 10px !important;
  font-family: var(--font-ui) !important;
  backdrop-filter: blur(6px);
}
.maplibregl-ctrl-attrib a { color: var(--paper-dim) !important; }
.maplibregl-ctrl-bottom-right { bottom: calc(var(--tl-h) + 4px) !important; z-index: 3 !important; }
.maplibregl-ctrl-group {
  background: rgba(14,16,21,.9) !important;
  border: 1px solid var(--ink-300) !important;
  box-shadow: var(--shadow-lift) !important;
}
.maplibregl-ctrl-group button + button { border-top-color: var(--ink-300) !important; }
.maplibregl-ctrl-group button span { filter: invert(1) brightness(1.4); }

/* ------------------------------------------------------------- bandeau */

.masthead {
  position: fixed; z-index: 12; top: 0; left: 0; right: 0;
  display: flex; align-items: center; gap: 14px;
  padding: 14px 20px 30px;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(6,6,9,.9) 0%, rgba(6,6,9,.55) 55%, transparent 100%);
}

.masthead-mark {
  width: 3px; height: 38px; flex: none; border-radius: 2px;
  background: linear-gradient(to bottom, var(--ember-600), var(--ember-300) 45%, var(--ember-100));
  box-shadow: 0 0 16px rgba(239,99,22,.55);
}

/* Le bandeau des couches occupe le centre : le sous-titre est borné pour ne
   jamais l'atteindre, et s'abrège par points de suspension. Sans cette borne
   il passait dessous à partir de 900 px de large. */
.masthead-text { min-width: 0; max-width: calc(50vw - 160px); overflow: hidden; }

/* Orbitron porte large : à 30 px le titre débordait sur la toolbar centrale */
.masthead h1 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 23px; font-weight: 600; letter-spacing: .04em;
  line-height: 1.06; text-transform: uppercase;
}

/* Le titre porte l'avertissement. Il ne doit pas pour autant *ressembler* à un
   bouton : c'est un titre, et le seul repère utile est qu'il réagisse au pointeur.
   Le style du navigateur est donc entièrement défait. */
.masthead-name {
  -webkit-appearance: none; appearance: none;
  padding: 0; margin: 0; border: 0; background: none;
  font: inherit; letter-spacing: inherit; text-transform: inherit;
  color: inherit; cursor: pointer; pointer-events: auto;
  text-align: left;
}
.masthead-name:hover { color: var(--ember-500); }
.masthead-name:focus-visible {
  outline: 1px solid var(--ember-400); outline-offset: 3px; border-radius: 2px;
}

.masthead-sub {
  margin: 1px 0 0;
  font-size: 11.5px; letter-spacing: .055em; text-transform: uppercase;
  color: var(--paper-mute); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.masthead-sub .sep { color: var(--ink-400); margin: 0 3px; }

.live {
  margin-left: auto; pointer-events: auto; flex: none;
  display: flex; align-items: center; gap: 7px;
  padding: 5px 11px 5px 9px;
  border: 1px solid var(--ink-300); border-radius: 100px;
  background: rgba(12,14,19,.82); backdrop-filter: blur(10px);
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .03em;
  color: var(--paper-dim); white-space: nowrap;
}
/* Pastille pulsée — voir `@keyframes onde` pour le pourquoi de ce montage.
   L'onde est un pseudo-élément derrière le disque, et non une ombre portée. */
.live-dot {
  position: relative;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--ember-400);
}
.live-dot::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: 50%; background: rgba(255,140,43,.6);
  animation: onde 2.6s var(--ease) infinite;
}
.live.is-stale .live-dot { background: var(--paper-mute); }
.live.is-stale .live-dot::after { animation: none; opacity: 0; }
/* Le bandeau ne signale plus le mode temps réel : il est permanent, il n'y a
   donc plus d'état à distinguer. Il ne dit que la fraîcheur des données. */
/* Onde qui s'écarte d'une pastille et s'efface.
 *
 *  Elle était obtenue en animant `box-shadow`, de zéro à sept pixels d'épaisseur.
 *  C'était la formulation la plus courte, et la plus coûteuse qui soit : une ombre
 *  portée n'est pas compositable, le navigateur devait donc repeindre l'élément à
 *  **chaque image de l'écran** — cent vingt fois par seconde sur un téléphone
 *  récent, indéfiniment, et pour chacune des pastilles affichées.
 *
 *  Pire, ces pastilles vivent dans des panneaux à `backdrop-filter` : un repaint
 *  à l'intérieur d'une surface floutée oblige à refaire le flou de toute la
 *  surface. Une pastille de six pixels faisait ainsi reflouter le volet entier,
 *  à la fréquence de l'écran. C'est la cause de l'échauffement qui restait après
 *  la correction de la pulsation du halo.
 *
 *  `transform` et `opacity` sont les deux seules propriétés que le compositeur
 *  sait animer seul, sans repeindre : l'onde est donc un disque à l'échelle 1 que
 *  l'on dilate. Le rendu est le même — l'ombre portée était elle aussi un anneau
 *  plein — mais le coût par image tombe à zéro côté processeur.
 *
 *  Facteur d'échelle : le disque fait six pixels de diamètre, l'ancienne ombre en
 *  ajoutait sept de chaque côté, soit vingt au total. D'où 20/6 ≈ 3,3.
 */
@keyframes onde {
  0%   { transform: scale(1);   opacity: .5; }
  70%  { transform: scale(3.3); opacity: 0; }
  100% { transform: scale(3.3); opacity: 0; }
}

/* ------------------------------------------- bandeau des couches (hud)
   Rangée flottante et centrée. Chaque bouton est un <label> portant sa case à
   cocher : l'état reste dans le formulaire, ce qui laisse intacts les
   écouteurs `change` qui pilotent les couches. La case elle-même est masquée
   sans être retirée du flux d'accessibilité — le focus clavier reste visible
   sur le bouton. */

.hud {
  position: fixed; z-index: 13;
  top: 15px; left: 50%; transform: translateX(-50%);
  display: flex; gap: 5px;
  padding: 5px;
  border: 1px solid var(--ink-300); border-radius: calc(var(--r-md) + 5px);
  background: rgba(9,10,14,.84); backdrop-filter: blur(14px) saturate(1.15);
  box-shadow: var(--shadow-deep), inset 0 1px 0 rgba(255,255,255,.04);
}

/* Bouton carré, icône seule. Les libellés en clair élargissaient le bandeau
   jusqu'à toucher le titre à gauche et le témoin à droite ; le nom court
   apparaît au survol, et le texte long reste dans le document pour nommer la
   case à cocher — masqué visuellement, pas retiré. */
.hud-btn {
  --neon: var(--paper-mute);
  position: relative;
  width: 40px; height: 40px; flex: none;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: var(--r-md);
  cursor: pointer; user-select: none;
  color: var(--paper-mute);
  transition: color .2s var(--ease), border-color .2s var(--ease),
              background .2s var(--ease), box-shadow .25s var(--ease);
}
.hud-btn input {
  position: absolute; inset: 0; opacity: 0; margin: 0;
  cursor: pointer; appearance: none;
}
.hud-btn:hover { color: var(--paper-dim); background: rgba(255,255,255,.04); }

.hud-ico { display: flex; }
.hud-ico svg { width: 20px; height: 20px; }

/* nom lisible par les lecteurs d'écran, invisible à l'oeil */
.hud-txt {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* infobulle : le libellé court, sous le bouton */
.hud-btn::after {
  content: attr(data-tip);
  position: absolute; top: calc(100% + 7px); left: 50%;
  transform: translateX(-50%) translateY(-3px);
  padding: 3px 7px;
  border: 1px solid var(--ink-300); border-radius: var(--r-sm);
  background: rgba(10,11,15,.95); backdrop-filter: blur(8px);
  color: var(--paper-dim);
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em;
  white-space: nowrap; pointer-events: none; opacity: 0;
  transition: opacity .16s var(--ease), transform .16s var(--ease);
}
.hud-btn:hover::after,
.hud-btn:has(input:focus-visible)::after {
  opacity: 1; transform: translateX(-50%) translateY(0);
}

/* allumé : l'icône passe au néon de sa couche */
.hud-btn:has(input:checked) {
  color: var(--neon);
  border-color: color-mix(in srgb, var(--neon) 40%, transparent);
  background: color-mix(in srgb, var(--neon) 11%, transparent);
  box-shadow: 0 0 13px -3px color-mix(in srgb, var(--neon) 55%, transparent);
}
.hud-btn:has(input:checked) .hud-ico svg {
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--neon) 80%, transparent));
}
.hud-btn:has(input:focus-visible) { outline: 1px solid var(--neon); outline-offset: 2px; }

/* Repli pour les navigateurs sans :has() ni color-mix() : la couleur de
   l'icône suffit à distinguer l'état allumé. */
@supports not (selector(:has(*))) {
  .hud-btn input:checked ~ .hud-ico { color: var(--neon); }
}

.hud-btn.c-smoke { --neon: #b9c2d0; }
.hud-btn.c-wind  { --neon: #8fe6f5; }
.hud-btn.c-bolt  { --neon: var(--bolt); }
.hud-btn.c-air   { --neon: var(--ice-400); }
/* Les marqueurs de passe sont passés au froid pour ne plus se confondre avec
   les points chauds : le bouton suit, sinon il annoncerait une couleur que la
   carte n'affiche plus. */
.hud-btn.c-rain  { --neon: #6fb6f0; }
.hud-btn.c-drops { --neon: var(--ice-500); }

/* légende chiffrée sous le bandeau, quand une couche en demande une */
.hud-note {
  position: fixed; z-index: 13; top: 62px; left: 50%;
  transform: translateX(-50%);
  margin: 0; padding: 4px 10px;
  border: 1px solid rgba(111,182,240,.3); border-radius: 100px;
  background: rgba(9,10,14,.9); backdrop-filter: blur(10px);
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .02em;
  color: #9ecdf4; white-space: nowrap; pointer-events: none;
}
.hud-note[hidden] { display: none; }

/* Écrans étroits : la barre se dresse le long du bord gauche.
 *
 *  En haut et à l'horizontale, elle partageait la même bande que le titre et les
 *  deux témoins, et sa hauteur de pile la plaçait par-dessus : sur un téléphone
 *  le titre se retrouvait tronqué à « GIRON » et la pastille « non officiel »
 *  disparaissait dessous. À la verticale contre le bord, elle rend tout l'en-tête
 *  au titre et occupe une colonne que la carte peut se permettre — la carte est
 *  panoramable, l'en-tête non.
 *
 *  `--hud-gutter` mesure la largeur de cette colonne. Les panneaux ne s'en
 *  écartent pas — ils prennent toute la largeur et passent par-dessus la barre
 *  quand ils sont ouverts, la barre étant centrée en hauteur, là où ils ne sont
 *  pas quand ils sont repliés. La mesure sert à ce qui doit, lui, la contourner :
 *  la légende de couche et la largeur maximale d'un menu.
 */
@media (max-width: 940px) {
  :root { --hud-gutter: 58px; }

  .hud {
    top: 50%; left: 10px; right: auto;
    transform: translateY(-50%);
    flex-direction: column;
    gap: 3px; padding: 4px;
  }
  .hud-btn { width: 34px; height: 34px; }
  .hud-ico svg { width: 17px; height: 17px; }

  /* L'infobulle passe à droite du bouton : sous lui se trouve désormais le
     bouton suivant, qu'elle recouvrirait. */
  .hud-btn::after {
    top: 50%; left: calc(100% + 7px);
    transform: translateY(-50%) translateX(-3px);
  }
  .hud-btn:hover::after,
  .hud-btn:has(input:focus-visible)::after {
    transform: translateY(-50%) translateX(0);
  }

  /* La légende de couche se pose au-dessus de la chronologie, seule bande
     restée libre : le haut revient au titre, le milieu gauche à la barre. */
  .hud-note {
    top: auto; bottom: calc(var(--tl-h) + 12px);
    left: calc(50% + var(--hud-gutter) / 2);
  }
}

/* ------------------------------------------------------------ rail
   Colonne d'instruments : un chiffre dominant, puis le détail. */

.rail {
  position: fixed; z-index: 11;
  top: 78px; left: 18px; width: var(--rail-w);
  max-height: calc(100vh - 78px - var(--tl-h) - 20px);
  display: flex; flex-direction: column;
  border: 1px solid var(--ink-300); border-radius: var(--r-lg);
  background: rgba(10,11,15,.86); backdrop-filter: blur(18px) saturate(1.1);
  box-shadow: var(--shadow-deep);
  overflow: hidden;
}

.rail-toggle {
  display: none; width: 100%; align-items: center; justify-content: space-between;
  padding: 11px 14px; background: none; border: 0;
  font-size: 11px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--paper-dim);
}
.rail-toggle svg { transition: transform .3s var(--ease); }
.rail.is-shut .rail-toggle svg { transform: rotate(-90deg); }
.rail.is-shut .rail-body { display: none; }

.rail-body { overflow-y: auto; padding: 4px 0 6px; }

.stat { padding: 18px 18px 15px; border-bottom: 1px solid var(--ink-200); }

.stat-figure {
  display: flex; align-items: baseline; gap: 6px;
  font-family: var(--font-mono); font-weight: 500;
  font-size: 38px; line-height: 1; letter-spacing: -.03em;
  color: var(--ember-500);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 34px rgba(255,182,72,.28);
}
.stat-unit {
  font-size: 13px; font-weight: 400; letter-spacing: .04em;
  color: var(--paper-mute);
}
.stat-caption {
  margin-top: 7px; font-size: 11.5px; line-height: 1.4; color: var(--paper-mute);
}
.stat-delta {
  margin-top: 8px; font-family: var(--font-mono); font-size: 11px;
  color: var(--ember-300); min-height: 15px;
}
.stat-delta:empty { display: none; }

/* Effort de lutte : le pendant du chiffre de surface, en cyan — la carte
   oppose partout le sinistre en braise et la réponse humaine en glace. Plus
   petit que les hectares : c'est une estimation, pas une mesure. */
.effort-figure {
  display: flex; align-items: baseline; gap: 6px;
  font-family: var(--font-mono); font-weight: 500;
  font-size: 26px; line-height: 1; letter-spacing: -.02em;
  color: var(--ice-400);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 28px rgba(92,224,240,.24);
}
.effort-unit {
  font-family: var(--font-ui); font-size: 10.5px; font-weight: 500;
  letter-spacing: .06em; text-transform: uppercase; color: var(--paper-mute);
}
.effort-note {
  margin-top: 7px; font-family: var(--font-mono); font-size: 10.5px;
  color: var(--paper-dim);
}
.effort-est { margin-top: 5px; font-size: 9.5px; color: var(--paper-mute); }

.block { padding: 14px 18px; border-bottom: 1px solid var(--ink-200); }
.block:last-child { border-bottom: 0; }

.block-title {
  margin: 0 0 10px;
  font-size: 10px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--paper-mute);
}

.muted { color: var(--paper-mute); font-size: 12px; margin: 0; }

/* foyers ------------------------------------------------------------- */

.massifs { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }

.massif {
  display: flex; align-items: center; gap: 9px;
  padding: 5px 7px; margin: 0 -7px; border-radius: var(--r-sm);
  cursor: pointer; transition: background .18s var(--ease);
}
.massif:hover { background: rgba(255,140,43,.09); }

.massif-bar {
  width: 3px; flex: none; border-radius: 2px;
  background: var(--ember-300);
  box-shadow: 0 0 9px rgba(239,99,22,.5);
}
.massif-name {
  flex: 1; min-width: 0; font-size: 12.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.massif-ha {
  font-family: var(--font-mono); font-size: 11.5px;
  color: var(--paper-dim); font-variant-numeric: tabular-nums;
}

/* couches ------------------------------------------------------------ */

.layers { display: grid; gap: 1px; }

/* `position: relative` n'est pas décoratif ici, il corrige le sursaut du rail.
   La case est en `position: absolute` pour disparaître sans disparaître de
   l'arbre. Sans ancêtre positionné, son bloc conteneur devenait `#rail` — le
   seul `position: fixed` au-dessus d'elle. Elle ne suivait donc pas le
   défilement de `#railBody` : les sept cases s'empilaient sous le rail, qui
   débordait de 145 px, et donner la mise au point à l'une d'elles faisait
   défiler `#rail` lui-même pour la ramener dans la vue — en emportant le chiffre
   d'en-tête. D'où un saut au clic sur toutes les couches sauf les premières,
   déjà dans la boîte visible. L'étiquette redevenue bloc conteneur, la case
   défile avec le corps et `#rail` ne déborde plus du tout. */
.sw {
  position: relative;
  display: flex; align-items: center; gap: 9px;
  padding: 5px 7px; margin: 0 -7px; border-radius: var(--r-sm);
  cursor: pointer; user-select: none;
  transition: background .18s var(--ease);
}
.sw:hover { background: rgba(255,255,255,.035); }
.sw input { position: absolute; opacity: 0; pointer-events: none; }

.sw-box {
  position: relative; width: 26px; height: 15px; flex: none;
  border-radius: 100px; background: var(--ink-300);
  transition: background .22s var(--ease);
}
.sw-box::after {
  content: ""; position: absolute; top: 2.5px; left: 2.5px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--paper-mute);
  transition: transform .24s var(--ease-out), background .22s var(--ease);
}
.sw input:checked + .sw-box { background: var(--ice-200); }
.sw input:checked + .sw-box::after { transform: translateX(11px); background: var(--ice-500); }
.sw input:focus-visible + .sw-box { outline: 2px solid var(--ice-300); outline-offset: 2px; }

.sw-txt { flex: 1; font-size: 12.5px; color: var(--paper-dim); }
.sw input:checked ~ .sw-txt { color: var(--paper); }

.key { width: 12px; height: 3px; flex: none; border-radius: 2px; opacity: .85; }
.key-burn  { background: linear-gradient(90deg, var(--ember-100), var(--ember-400)); }
.key-hot   { background: var(--ember-500); }
.key-heat  { background: linear-gradient(90deg, var(--ember-000), var(--ember-600)); }
.key-effis { background: repeating-linear-gradient(90deg, var(--paper-dim) 0 3px, transparent 3px 6px); }
.key-air   { background: var(--ice-400); }
.key-sat   { background: #6b7a52; }
.key-smoke { background: linear-gradient(90deg, #4a4f5c, #b9c2d0); }
.key-wind  { background: linear-gradient(90deg, #2f6f7f, #8fe6f5); }
.key-bolt  { background: var(--bolt); }
.key-drops { background: linear-gradient(90deg, var(--ice-500), var(--ice-300)); }
.key-dropheat { background: linear-gradient(90deg, var(--ice-100), var(--ice-500)); }
.key-field { background: #ff6ec7; box-shadow: 0 0 6px rgba(255,110,199,.5); }

/* Mise en garde d'une couche interprétative : elle rapproche deux mesures, elle
   ne conclut pas. Visible seulement quand la couche est allumée. */
.layers-warn {
  margin: 8px 0 0; padding: 7px 9px; border-radius: var(--r-sm);
  background: rgba(92,224,240,.06);
  font-size: 10px; line-height: 1.45; color: var(--paper-dim);
}
.layers-warn[hidden] { display: none; }
.layers-warn b { color: var(--ice-400); font-weight: 600; }

/* renvoi vers le bandeau, pour qu'on ne cherche pas une couche disparue */
.layers-note {
  margin: 8px 0 0; padding: 0 2px;
  font-size: 10px; line-height: 1.4; color: var(--paper-mute);
}

.sources p { font-size: 10.5px; line-height: 1.55; color: var(--paper-mute); }

/* conditions : vent dominant et pic de fumée à l'instant affiché */

.cond { display: grid; gap: 9px; }

.cond-row { display: flex; align-items: center; gap: 10px; }

.cond-arrow {
  width: 26px; height: 26px; flex: none; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--ink-300); background: rgba(92,224,240,.07);
  color: var(--ice-400);
}
.cond-arrow svg { width: 13px; height: 13px; transition: transform .5s var(--ease-out); }

.cond-main {
  font-family: var(--font-mono); font-size: 13px; color: var(--paper);
  font-variant-numeric: tabular-nums;
}
.cond-sub { font-size: 10.5px; color: var(--paper-mute); margin-top: 1px; }

.cond-pm {
  display: flex; align-items: baseline; gap: 7px;
  padding-top: 8px; border-top: 1px solid var(--ink-200);
}
.cond-pm-val {
  font-family: var(--font-mono); font-size: 15px; font-variant-numeric: tabular-nums;
}
.cond-pm-lab { font-size: 10.5px; color: var(--paper-mute); flex: 1; }
.pm-good { color: #6fd39a; }
.pm-mid  { color: var(--ember-500); }
.pm-bad  { color: var(--ember-300); }
.pm-vbad { color: #ff5a4d; }

/* --------------------------------------------------------- panneau droit */

.panel {
  position: fixed; z-index: 11;
  top: 78px; right: 18px; width: var(--panel-w);
  max-height: calc(100vh - 78px - var(--tl-h) - 20px);
  display: flex; flex-direction: column;
  border: 1px solid var(--ink-300); border-radius: var(--r-lg);
  background: rgba(10,11,15,.88); backdrop-filter: blur(18px) saturate(1.1);
  box-shadow: var(--shadow-deep);
  overflow: hidden;
  transition: transform .4s var(--ease-out), opacity .3s var(--ease);
}
.panel.is-shut { transform: translateX(calc(100% + 26px)); opacity: 0; pointer-events: none; }

.tabs {
  display: flex; align-items: stretch; flex: none;
  border-bottom: 1px solid var(--ink-200);
  background: rgba(255,255,255,.018);
}

.tab {
  position: relative; padding: 12px 15px; background: none; border: 0;
  font-size: 11px; font-weight: 500; letter-spacing: .085em; text-transform: uppercase;
  color: var(--paper-mute);
  transition: color .2s var(--ease);
}
.tab::after {
  content: ""; position: absolute; left: 15px; right: 15px; bottom: -1px; height: 2px;
  background: var(--ember-400); border-radius: 2px;
  transform: scaleX(0); transform-origin: left;
  transition: transform .3s var(--ease-out);
}
.tab:hover { color: var(--paper-dim); }
.tab.is-on { color: var(--paper); }
.tab.is-on::after { transform: scaleX(1); }

.tab-count {
  display: inline-block; margin-left: 5px; padding: 1px 5px;
  border-radius: 100px; background: var(--ink-300);
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0;
  color: var(--paper-dim);
}
.tab.is-on .tab-count { background: rgba(255,140,43,.17); color: var(--ember-500); }

.panel-close {
  margin-left: auto; padding: 0 14px; background: none; border: 0;
  color: var(--paper-mute); transition: color .2s var(--ease);
}
.panel-close:hover { color: var(--paper); }

.panel-open {
  position: fixed; z-index: 11; top: 78px; right: 18px;
  width: 34px; height: 34px; display: none;
  align-items: center; justify-content: center;
  border: 1px solid var(--ink-300); border-radius: 50%;
  background: rgba(10,11,15,.9); backdrop-filter: blur(10px);
  color: var(--paper-dim); box-shadow: var(--shadow-lift);
}
.panel.is-shut ~ .panel-open { display: flex; }

.tabpane { display: none; min-height: 0; flex: 1; flex-direction: column; }
.tabpane.is-on { display: flex; }

.pane-scroll {
  overflow-y: auto; overscroll-behavior: contain;
  padding: 5px 0 8px;
  min-height: 120px;
}

.rail-body::-webkit-scrollbar, .pane-scroll::-webkit-scrollbar { width: 8px; }
.rail-body::-webkit-scrollbar-thumb, .pane-scroll::-webkit-scrollbar-thumb {
  background: var(--ink-300); border-radius: 8px; border: 2px solid transparent;
  background-clip: content-box;
}
.pane-scroll::-webkit-scrollbar-thumb:hover { background: var(--ink-400); background-clip: content-box; }

/* chronologie fine des rotations ------------------------------------- */

.air-head {
  display: flex; align-items: center; gap: 12px; flex: none;
  padding: 14px 16px 12px;
  background: rgba(92,224,240,.045);
}

.air-play {
  width: 24px; height: 24px; flex: none;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--ink-400); border-radius: 50%;
  background: rgba(16,18,24,.9); color: var(--ice-400);
  transition: border-color .2s var(--ease), color .2s var(--ease);
}
.air-play:hover { border-color: var(--ice-300); }
.air-play .ico-pause { display: none; }
.air-play.is-playing .ico-play { display: none; }
.air-play.is-playing .ico-pause { display: block; }

.air-scrub {
  position: relative; flex: 1; min-width: 0; height: 22px;
  cursor: crosshair; touch-action: none;
  border-bottom: 1px solid var(--ink-300);
}
.air-scrub:focus-visible { outline: 2px solid var(--ice-300); outline-offset: 3px; }

/* repères : une marque par passe détectée dans la fenêtre */
.air-marks { position: absolute; inset: 0; }
.air-mark {
  position: absolute; bottom: 0; width: 2px; border-radius: 1px;
  transform: translateX(-1px);
}
.air-mark.k-largage { background: var(--ember-400); height: 13px; box-shadow: 0 0 6px rgba(255,140,43,.6); }
.air-mark.k-ecopage { background: var(--ice-400); height: 9px; box-shadow: 0 0 6px rgba(92,224,240,.5); }

.air-head-line {
  position: absolute; top: -2px; bottom: -1px; left: 100%;
  width: 1px; background: var(--ice-500);
  box-shadow: 0 0 8px rgba(168,242,251,.8);
  pointer-events: none;
}
.air-head-line::after {
  content: ""; position: absolute; left: 50%; bottom: -3px;
  width: 6px; height: 6px; margin-left: -3px; border-radius: 50%;
  background: var(--ice-500); box-shadow: 0 0 8px rgba(168,242,251,.9);
}

.air-time {
  flex: none; font-family: var(--font-mono); font-size: 12px;
  color: var(--ice-400); font-variant-numeric: tabular-nums;
}

/* La rangée de durées collait au curseur des rotations : elle en paraissait le
   prolongement. Un peu d'air l'en détache. */
.air-sub {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 8px 16px 13px;
  border-bottom: 1px solid var(--ink-200);
  font-size: 10.5px; color: var(--paper-mute);
}
.air-sub #airRange {
  flex: 1; font-family: var(--font-mono); font-size: 9.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Boutons de durée : un groupe serré à gauche, chacun cerné. La bordure était
   transparente au repos, si bien qu'on ne voyait un bouton qu'une fois
   sélectionné — les deux autres passaient pour du texte. */
.air-zoom { display: flex; gap: 4px; flex: none; }
.air-zoom button {
  padding: 3px 9px;
  border: 1px solid var(--ink-300); border-radius: var(--r-sm);
  background: rgba(255,255,255,.02);
  font-family: var(--font-mono); font-size: 9.5px;
  color: var(--paper-mute);
  transition: color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}
.air-zoom button:hover {
  color: var(--paper-dim); border-color: var(--ink-400);
  background: rgba(255,255,255,.05);
}
.air-zoom button.is-on {
  color: var(--ice-400); border-color: rgba(92,224,240,.45);
  background: rgba(92,224,240,.12);
}

/* « tous » : première ligne du menu, même gabarit que les rôles en dessous */
.air-all {
  display: flex; align-items: center; gap: 7px;
  padding: 4px 7px; border-radius: var(--r-sm);
  font-size: 10.5px; cursor: pointer; user-select: none;
}
.air-all:hover { background: rgba(255,255,255,.045); }
/* même correction que pour `.sw` : sans cela la case s'ancre sur le volet */
.air-all { position: relative; }
.air-all input { position: absolute; opacity: 0; pointer-events: none; }
.air-all span {
  position: relative; padding-left: 17px; color: var(--paper-mute);
  transition: color .2s var(--ease);
}
.air-all span::before {
  content: ""; position: absolute; left: 0; top: 50%;
  width: 11px; height: 11px; margin-top: -5.5px;
  border: 1px solid var(--ink-400); border-radius: 3px;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.air-all input:checked + span { color: var(--ice-400); }
.air-all input:checked + span::before {
  border-color: var(--ice-400); background: var(--ice-400);
  box-shadow: inset 0 0 0 2px rgba(12,14,19,.97);
}
.air-all input:focus-visible + span::before { outline: 1px solid var(--ice-400); outline-offset: 1px; }

/* filtres par rôle ---------------------------------------------------- */

/* ------------------------------------------- filtres en menu déroulant
   Le bouton « tous » et les six pastilles de rôle occupaient deux rangées
   entières du volet. Fondus dans un déroulant : rien ne disparaît, la place est
   rendue à la liste, et le libellé du bouton résume l'état une fois fermé —
   un menu doit abriter un réglage, pas le cacher. */

.air-drop { position: relative; flex: none; margin-left: auto; }

.air-drop-btn {
  display: flex; align-items: center; gap: 6px;
  padding: 3px 8px;
  border: 1px solid var(--ink-300); border-radius: var(--r-sm);
  background: rgba(255,255,255,.02);
  font-size: 10px; color: var(--paper-mute); white-space: nowrap;
  transition: color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}
.air-drop-btn:hover { color: var(--paper-dim); border-color: var(--ink-400); }
.air-drop-btn.is-set {
  color: var(--ice-400); border-color: rgba(92,224,240,.4);
  background: rgba(92,224,240,.1);
}
.air-drop-chev { transition: transform .2s var(--ease); }
.air-drop-btn.is-open .air-drop-chev { transform: rotate(180deg); }

.air-drop-menu {
  position: absolute; z-index: 5; right: 0; top: calc(100% + 6px);
  min-width: 196px; padding: 9px;
  border: 1px solid var(--ink-400); border-radius: var(--r-md);
  background: rgba(12,14,19,.97); backdrop-filter: blur(14px);
  box-shadow: var(--shadow-deep);
}
.air-drop-menu[hidden] { display: none; }
.air-drop-sep { height: 1px; margin: 8px 0; background: var(--ink-300); }

/* les rôles en colonne dans le menu : une ligne par rôle, plus lisible que
   des pastilles qui se bousculent sur deux rangs */
.air-filters { display: flex; flex-direction: column; gap: 3px; }

.air-chip {
  display: flex; align-items: center; gap: 7px; width: 100%;
  padding: 4px 7px; border-radius: var(--r-sm);
  border: 1px solid transparent; background: none; text-align: left;
  font-size: 10.5px; color: var(--paper-mute);
  transition: color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}
.air-chip:hover { background: rgba(255,255,255,.045); }
.air-chip i {
  width: 6px; height: 6px; border-radius: 50%; flex: none;
  background: currentColor; opacity: .5;
}
.air-chip:hover { color: var(--paper-dim); }
/* Libellé et compteur collés, en pastille, comme les onglets du volet : les deux
   se lisent alors comme un seul objet. Le compteur était renvoyé à l'extrémité
   droite de la ligne, ce qui obligeait l'oeil à traverser un vide pour le
   rattacher à son rôle. */
.air-chip-lab { flex: none; }
.air-chip .n {
  flex: none; padding: 1px 6px; border-radius: 100px;
  background: var(--ink-300); color: var(--paper-dim);
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0; opacity: 1;
}
.air-chip.is-on .n { background: rgba(255,255,255,.1); color: var(--paper); }
.air-chip.is-on { color: var(--paper); background: rgba(255,255,255,.05); }

/* rôle sans aucun appareil sur la période : la ligne reste, pour dire qu'il n'y
   en a pas, mais l'isoler donnerait une carte vide — donc pas cliquable */
.air-chip.is-empty { color: var(--ink-400); cursor: default; }
.air-chip.is-empty:hover { background: none; }
.air-chip.is-empty i { opacity: .25; }
.air-chip.is-empty .n { background: rgba(255,255,255,.04); color: var(--ink-400); }
.air-chip.is-on i { opacity: 1; }
.air-chip .n { font-family: var(--font-mono); font-size: 9.5px; opacity: .65; }

/* fiche d'un aéronef suivi -------------------------------------------- */

.air-detail { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.air-detail[hidden] { display: none; }

.det-top {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 10px 16px; border-bottom: 1px solid var(--ink-200);
  background: rgba(92,224,240,.05);
}
.det-back {
  width: 24px; height: 24px; flex: none; border: 0; border-radius: 50%;
  background: rgba(255,255,255,.06); color: var(--paper-dim);
  display: flex; align-items: center; justify-content: center;
}
.det-back:hover { color: var(--paper); }
.det-title { flex: 1; min-width: 0; }
.det-call {
  font-family: var(--font-mono); font-size: 14px; color: var(--paper);
}
.det-sub { font-size: 10.5px; color: var(--paper-mute); }

.det-follow {
  padding: 3px 9px; border-radius: 100px; flex: none;
  border: 1px solid rgba(92,224,240,.35); background: rgba(92,224,240,.1);
  font-size: 10px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ice-400);
}
.det-follow.is-on { background: var(--ice-400); color: #06222a; border-color: var(--ice-400); }

/* deux boutons dans un en-tête étroit : on resserre, et le titre cède la place */
.det-top .det-follow { padding: 3px 7px; font-size: 9.5px; }
.det-top .det-title { min-width: 0; }

.det-scroll { overflow-y: auto; min-height: 0; }

.det-photo { display: block; width: 100%; height: auto; background: var(--ink-200); }
.det-credit {
  padding: 5px 16px 0; font-size: 9.5px; color: var(--paper-mute); text-align: right;
}

.det-grid {
  display: grid; grid-template-columns: auto 1fr; gap: 5px 12px;
  padding: 12px 16px;
}
.det-k { font-size: 10.5px; color: var(--paper-mute); white-space: nowrap; }
.det-v {
  font-family: var(--font-mono); font-size: 11.5px; color: var(--paper);
  font-variant-numeric: tabular-nums;
}

.det-role {
  margin: 0 16px 12px; padding: 8px 10px;
  border-radius: var(--r-sm);
  background: rgba(92,224,240,.07);
  font-size: 11.5px; line-height: 1.45; color: var(--paper-dim);
}

/* aéronefs ------------------------------------------------------------ */

.ac {
  display: grid; grid-template-columns: 22px 1fr auto; gap: 3px 10px;
  align-items: center;
  padding: 10px 16px;
  border-bottom: 1px solid rgba(255,255,255,.045);
  cursor: pointer; transition: background .18s var(--ease);
}
.ac:hover { background: rgba(92,224,240,.07); }
.ac:last-child { border-bottom: 0; }

.ac-glyph {
  grid-row: span 2; width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: rgba(92,224,240,.12);
  color: var(--ice-400);
}
.ac-glyph svg { width: 13px; height: 13px; }

.ac-top { display: flex; align-items: baseline; gap: 7px; min-width: 0; }
.ac-call {
  font-family: var(--font-mono); font-size: 12.5px; font-weight: 500;
  color: var(--paper); letter-spacing: .01em;
}
.ac-reg { font-family: var(--font-mono); font-size: 10.5px; color: var(--paper-mute); }
/* La ligne de détail passe à la ligne plutôt que d'être coupée. Tronquée par
   des points de suspension, elle perdait justement la fin — distance au foyer
   et heure du relevé. Deux lignes coûtent quelques pixels et n'escamotent
   rien. */
/* Point vert pulsé : l'appareil est capté à l'instant même. Il ne s'affiche
   qu'au présent — sur un instant passé, « en direct » n'aurait aucun sens. */
.ac-live {
  width: 6px; height: 6px; border-radius: 50%; flex: none;
  /* aligné sur la hauteur d'x du texte voisin, non sur sa ligne de base : un
     disque n'a pas de jambage, et la ligne de base le posait trop haut */
  align-self: center; margin-top: 1px;
  position: relative;
  background: #4ade80;
}
/* Une pastille par appareil en vol : c'était la plus coûteuse des trois, animée
   autant de fois qu'il y a de lignes dans la liste. Voir `@keyframes onde`. */
.ac-live::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: 50%; background: rgba(74,222,128,.7);
  animation: onde 1.6s var(--ease) infinite;
}
.ac-sub {
  font-size: 11px; line-height: 1.35; color: var(--paper-mute);
}

.ac-phase {
  grid-row: span 2; justify-self: end;
  padding: 3px 8px; border-radius: 100px;
  font-size: 10px; letter-spacing: .05em; text-transform: uppercase;
  border: 1px solid transparent; white-space: nowrap;
}
.ph-largage    { background: rgba(239,99,22,.16);  color: var(--ember-400); border-color: rgba(239,99,22,.35); }
.ph-ecopage    { background: rgba(92,224,240,.14); color: var(--ice-400);   border-color: rgba(92,224,240,.32); }
.ph-transit    { background: rgba(255,255,255,.05); color: var(--paper-mute); }
.ph-rotation   { background: rgba(255,255,255,.05); color: var(--paper-dim); }
.ph-sol        { background: rgba(255,255,255,.04); color: var(--paper-mute); }
.ph-aérodrome  { background: rgba(255,255,255,.05); color: var(--paper-mute); }
.ph-approche   { background: rgba(125,155,255,.14); color: var(--ac-bombardier); border-color: rgba(125,155,255,.34); }
.ph-stationnaire,
.ph-basse      { background: rgba(255,209,102,.13); color: var(--ac-coordination); }

.drops { padding: 12px 16px 6px; }
.drops-title {
  font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--paper-mute); margin: 0 0 9px;
}

/* en-tête des passes : le libellé, et le choix de la période à sa droite */
/* Même retrait que la liste au-dessus : les deux sections tombent sur la même
   verticale. La plage horaire passe **sous** le titre : sur la même ligne, elle
   se serrait contre le sélecteur et l'ensemble finissait par se couper. */
.drops-head {
  display: grid; grid-template-columns: 1fr auto; align-items: start;
  gap: 2px 8px;
  padding: 4px 16px 9px;
  border-top: 1px solid var(--ink-200);
  margin-top: 8px;
}
.drops-head .sect-title {
  display: block; padding: 12px 0 0; white-space: nowrap;
}
.drops-head .sect-title span {
  display: block; margin-top: 3px;
  font-size: 9.5px; letter-spacing: .02em;
}
.drops-head select { grid-row: 1; grid-column: 2; align-self: center; }
.drops-head[hidden] { display: none; }
.drops-head .sect-title { margin: 0; flex: 1; }

/* Titres de section, colorés pour séparer les blocs du volet. Tous en gris, on
   ne voyait pas où finissait la liste des appareils et où commençaient les
   passes : la teinte fait le travail que la seule graisse ne faisait pas. */
.sect-title {
  display: flex; align-items: baseline; gap: 7px;
  margin: 0; padding: 12px 16px 8px;
  font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
}
.sect-title span {
  font-family: var(--font-mono); font-size: 9.5px; font-weight: 400;
  letter-spacing: .02em; color: var(--paper-mute); text-transform: none;
}
.s-air { color: var(--ice-400); }
.drops-head select {
  flex: none; padding: 2px 5px;
  border: 1px solid var(--ink-300); border-radius: var(--r-sm);
  background: var(--ink-100); color: var(--paper-dim);
  font-family: var(--font-mono); font-size: 9.5px;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.drops-head select:hover { color: var(--paper); border-color: var(--ink-400); }
.drops-head select:focus-visible { outline: 1px solid var(--ice-400); }
/* ------------------------------------------- passes groupées par appareil
   Un accordéon par appareil. À plat, cinquante passes entrelacées de quatre
   machines ne se lisaient pas ; l'en-tête porte le bilan, le détail s'ouvre à
   la demande. */

.dg { border-bottom: 1px solid rgba(255,255,255,.045); }
.dg:last-child { border-bottom: 0; }

/* L'en-tête porte deux commandes : replier le groupe, et cibler l'appareil.
   Deux boutons frères — un bouton dans un bouton n'est pas du HTML valide, et
   confier le repli à un <div> aurait coûté l'accès au clavier. */
.dg-row { display: flex; align-items: stretch; }
.dg-row .dg-head { flex: 1; min-width: 0; }

.dg-aim {
  flex: none; width: 34px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: 0; background: none; color: var(--paper-mute);
  transition: color .18s var(--ease), background .18s var(--ease);
}
.dg-aim:hover:not(:disabled) { color: var(--ice-400); background: rgba(92,224,240,.09); }
.dg-aim:focus-visible { outline: 1px solid var(--ice-400); outline-offset: -2px; }
.dg-aim:disabled { color: var(--ink-400); cursor: default; }

.dg-head {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 12px 16px 10px; border: 0; background: none; text-align: left;
  font-size: 11.5px; color: var(--paper-dim);
  transition: background .16s var(--ease);
}
.dg-head:hover { background: rgba(255,255,255,.035); }
.dg-head:focus-visible { outline: 1px solid var(--ice-400); outline-offset: -2px; }

.dg-chev {
  flex: none; color: var(--paper-mute);
  transition: transform .25s var(--ease);
}
.dg.is-open .dg-chev { transform: rotate(90deg); }

.dg-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }

.dg-who {
  flex: none; font-family: var(--font-mono); font-size: 11px;
  letter-spacing: .03em; color: var(--paper);
}
.dg-tally { flex: 1; font-size: 10.5px; color: var(--paper-mute); }
.dg-tally b { font-weight: 600; }

/* cadence de rotation : le rythme de la machine, d'un coup d'oeil */
.dg-cad {
  flex: none; padding: 1px 6px; border-radius: 100px;
  border: 1px solid var(--ink-300);
  font-family: var(--font-mono); font-size: 9.5px; color: var(--paper-mute);
}
.dg-last {
  flex: none; font-family: var(--font-mono); font-size: 10px;
  color: var(--paper-mute);
}

/* Frise de la vacation. Visible accordéon replié : c'est là qu'on lit le
   rythme, et surtout les trous — un appareil parti ravitailler laisse une plage
   vide qu'aucun décompte ne montre. */
.dg-strip {
  position: relative; height: 14px; margin: 0 16px 12px 33px;
  border-radius: 2px;
  background:
    linear-gradient(to right, rgba(255,255,255,.05), rgba(255,255,255,.05))
    center / 100% 1px no-repeat;
}
.dg-tick {
  position: absolute; top: 2px; width: 2px; height: 10px;
  margin-left: -1px; border-radius: 1px;
}
.dg-tick.t-largage { background: var(--ember-400); box-shadow: 0 0 5px rgba(255,140,43,.7); }
.dg-tick.t-ecopage { background: var(--ice-400); box-shadow: 0 0 5px rgba(92,224,240,.6); }

/* Repli par la grille : `0fr` → `1fr` anime une hauteur qu'on ne connaît pas
   d'avance, là où `max-height` demanderait une valeur arbitraire. Sur un
   navigateur qui n'anime pas cette propriété, le repli reste instantané —
   jamais cassé. */
.dg-body {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .25s var(--ease);
}
.dg.is-open .dg-body { grid-template-rows: 1fr; }
.dg-body > div { overflow: hidden; }

.dg-body .drop { padding: 6px 16px 6px 33px; border-bottom: 0; }
.dg-body .drop:hover { background: rgba(255,255,255,.04); }
.dg-body .drop-time { flex: none; }
.dg-body .drop-what { flex: 1; }
.dg-body .drop-alt {
  flex: none; font-family: var(--font-mono); font-size: 10px;
  color: var(--paper-mute);
}
/* état vide : le sélecteur reste au-dessus, donc on dit quoi en faire */
.dg-none {
  margin: 0; padding: 4px 16px 10px;
  font-size: 10.5px; line-height: 1.45; color: var(--paper-mute);
}

.dg-more {
  margin: 2px 0 8px; padding: 0 16px 0 33px;
  font-size: 10px; color: var(--paper-mute);
}
.drop {
  display: flex; align-items: baseline; gap: 8px;
  padding: 5px 0; font-size: 11.5px;
  border-bottom: 1px solid rgba(255,255,255,.035);
}
.drop:last-child { border-bottom: 0; }
.drop-time { font-family: var(--font-mono); font-size: 10.5px; color: var(--paper-mute); flex: none; }
.drop-who  { font-family: var(--font-mono); font-size: 11px; color: var(--paper-dim); flex: none; }
.drop-what { flex: 1; min-width: 0; color: var(--paper-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.drop-what .em { color: var(--ember-400); }
.drop-what .ic { color: var(--ice-400); }

/* état vide : explique pourquoi, sans dramatiser */
.empty { padding: 30px 22px; text-align: center; }
.empty-mark {
  width: 34px; height: 34px; margin: 0 auto 13px;
  border: 1px solid var(--ink-300); border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-400);
}
.empty-title { font-size: 13px; color: var(--paper-dim); margin: 0 0 5px; }
.empty-note { font-size: 11.5px; line-height: 1.55; color: var(--paper-mute); margin: 0; }

/* actus --------------------------------------------------------------- */

.news-head {
  display: flex; align-items: center; gap: 8px; flex: none;
  padding: 9px 16px; border-bottom: 1px solid var(--ink-200);
  background: rgba(255,140,43,.045);
}
.news-filter { flex: 1; font-size: 11px; color: var(--paper-dim); }
.news-filter strong { color: var(--ember-500); font-weight: 500; }
.news-refresh {
  width: 22px; height: 22px; border: 0; border-radius: 50%;
  background: rgba(255,255,255,.05); color: var(--paper-dim);
  font-size: 13px; line-height: 1;
  transition: transform .5s var(--ease-out), color .2s var(--ease);
}
.news-refresh:hover { color: var(--paper); }
.news-refresh.is-spin { transform: rotate(360deg); }

.art {
  display: block; padding: 12px 16px; text-decoration: none;
  border-bottom: 1px solid rgba(255,255,255,.045);
  transition: background .18s var(--ease);
}
.art:hover { background: rgba(255,255,255,.035); }
.art:last-child { border-bottom: 0; }

.art-meta {
  display: flex; align-items: center; gap: 7px; margin-bottom: 5px;
  font-size: 10.5px;
}
.art-age {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--ember-400); flex: none;
}
.art-age.is-fresh { color: var(--ember-600); }
.art-src {
  color: var(--paper-mute); letter-spacing: .02em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.art-dot { color: var(--ink-400); flex: none; }

.art-local {
  flex: none; padding: 1px 5px; border-radius: 100px;
  border: 1px solid rgba(92,224,240,.3); background: rgba(92,224,240,.1);
  font-size: 9px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ice-400);
}

.art-title {
  font-size: 13.5px; line-height: 1.36; color: var(--paper);
  font-weight: 400; margin: 0;
}
.art:hover .art-title { color: var(--ember-600); }

.art-sum {
  margin: 5px 0 0; font-size: 11.5px; line-height: 1.45; color: var(--paper-mute);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* ------------------------------------------------------------ timeline
   Le curseur EST la courbe de progression : on lit la montée en même
   temps qu'on la parcourt. */

.timeline {
  position: fixed; z-index: 12; left: 0; right: 0; bottom: 0;
  height: var(--tl-h);
  display: flex; align-items: center; gap: 16px;
  padding: 0 22px 12px;
  background: linear-gradient(to top, rgba(6,6,9,.96) 34%, rgba(6,6,9,.8) 72%, transparent 100%);
}

.play {
  width: 42px; height: 42px; flex: none; margin-top: 16px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--ink-400); border-radius: 50%;
  background: rgba(16,18,24,.92);
  color: var(--ember-500);
  transition: border-color .22s var(--ease), transform .22s var(--ease-out), box-shadow .3s var(--ease);
}
.play:hover {
  border-color: var(--ember-300); transform: scale(1.06);
  box-shadow: 0 0 22px rgba(239,99,22,.28);
}
.play .ico-pause { display: none; }
.play.is-playing .ico-play { display: none; }
.play.is-playing .ico-pause { display: block; }

.tl-main { flex: 1; min-width: 0; margin-top: 14px; }

.tl-readout {
  display: flex; align-items: baseline; gap: 8px; margin-bottom: 7px;
  font-family: var(--font-mono); font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}
/* Mention de nature, devant la date : elle dit de quoi cette date est celle.
   En police d'interface et non en mono — c'est une phrase, pas une valeur — et dans
   le gris de second plan, la date restant le chiffre qu'on vient lire. */
.tl-kicker {
  font-family: var(--font-ui); font-size: 10px; letter-spacing: .01em;
  color: var(--paper-mute); white-space: nowrap;
  /* Elle cède la première si la ligne manque de place : c'est la mention qui peut
     s'abréger, jamais la date ni la surface, qui sont ce qu'on vient lire. */
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
.tl-date, .tl-sep, .tl-ha { flex: none; }
.tl-date { color: var(--paper); letter-spacing: .01em; }
.tl-sep { color: var(--ink-400); }
.tl-ha { color: var(--ember-500); }

.tl-track {
  position: relative; height: 40px; cursor: crosshair;
  border-bottom: 1px solid var(--ink-300);
  touch-action: none;
}
.tl-track:focus-visible { outline: 2px solid var(--ice-300); outline-offset: 3px; border-radius: 2px; }

.tl-chart { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

.tl-head {
  position: absolute; top: -3px; bottom: -1px; left: 0;
  width: 1px; background: var(--ember-600);
  box-shadow: 0 0 11px rgba(255,225,160,.85);
  pointer-events: none;
  transition: left .09s linear;
}
.tl-head::after {
  content: ""; position: absolute; left: 50%; bottom: -3.5px;
  width: 7px; height: 7px; margin-left: -3.5px;
  border-radius: 50%; background: var(--ember-600);
  box-shadow: 0 0 12px rgba(255,225,160,.9);
}
.tl-head.is-drag { transition: none; }

.tl-axis {
  position: relative; height: 15px; margin-top: 3px;
  font-family: var(--font-mono); font-size: 9.5px; color: var(--paper-mute);
}
.tl-tick { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap; }
.tl-tick::before {
  content: ""; position: absolute; left: 50%; top: -4px;
  width: 1px; height: 3px; background: var(--ink-400);
}

.tl-speed { display: flex; gap: 3px; flex: none; margin-top: 16px; }
.tl-speed button {
  padding: 4px 8px; border: 1px solid transparent; border-radius: var(--r-sm);
  background: none; font-family: var(--font-mono); font-size: 10.5px;
  color: var(--paper-mute);
  transition: color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}
.tl-speed button:hover { color: var(--paper-dim); }
.tl-speed button.is-on {
  color: var(--ember-500); border-color: rgba(255,140,43,.28);
  background: rgba(255,140,43,.09);
}

/* ------------------------------------------------------------- infobulle */

.tip {
  position: fixed; z-index: 30; pointer-events: none;
  padding: 8px 11px; max-width: 260px;
  border: 1px solid var(--ink-400); border-radius: var(--r-md);
  background: rgba(10,11,15,.95); backdrop-filter: blur(12px);
  box-shadow: var(--shadow-lift);
  font-size: 11.5px; line-height: 1.45;
  opacity: 0; transform: translateY(3px);
  transition: opacity .16s var(--ease), transform .16s var(--ease);
}
.tip.is-on { opacity: 1; transform: translateY(0); }
.tip-h {
  font-family: var(--font-mono); font-size: 11.5px; font-weight: 500;
  color: var(--ember-500); margin-bottom: 3px;
}
.tip-h.is-air { color: var(--ice-400); }
.tip-r { color: var(--paper-dim); display: flex; gap: 8px; justify-content: space-between; }
.tip-r span:last-child { font-family: var(--font-mono); color: var(--paper); }

/* Vitesse et altitude en deux cadrans. Alignées en lignes de texte parmi les
   autres, elles se lisaient comme des états civils ; côte à côte, on les compare
   d'un coup d'oeil — à 250 km/h et 900 m l'appareil transite, à 150 km/h et
   60 m il est en passe. */
.gauges { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 7px; }
.gauge {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 8px; border-radius: var(--r-sm);
  border: 1px solid var(--ink-300);
  background: rgba(92,224,240,.05);
}
.gauge svg { width: 17px; height: 17px; flex: none; }
.gauge > div { min-width: 0; display: flex; flex-direction: column; }
.gauge-v {
  font-family: var(--font-mono); font-size: 12px; line-height: 1.15;
  color: var(--paper); font-variant-numeric: tabular-nums;
}
.gauge-k {
  font-size: 8.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--paper-mute);
}
.g-spd { color: var(--ice-400); }
.g-alt { color: var(--ac-airtractor); }

/* ------------------------------------------------- témoignages de terrain
   La source est vérifiée, les images non : l'avertissement est en tête du volet,
   pas en note de bas de page. Jaune de signalement, la teinte réservée à ce qui
   demande un jugement du lecteur. */

.field-warn {
  flex: none; margin: 0; padding: 11px 16px;
  border-bottom: 1px solid var(--ink-200);
  background: rgba(255,209,102,.06);
  font-size: 10.5px; line-height: 1.45; color: var(--paper-dim);
}
.field-warn b { color: var(--ac-coordination); font-weight: 600; }

.fld {
  padding: 12px 16px; cursor: pointer;
  border-bottom: 1px solid rgba(255,255,255,.045);
  transition: background .16s var(--ease);
}
.fld:hover { background: rgba(255,209,102,.06); }
.fld:last-child { border-bottom: 0; }

.fld-top { display: flex; align-items: baseline; gap: 7px; }
.fld-place {
  flex: 1; font-size: 12px; color: var(--paper); font-weight: 600;
}
.fld-pin {
  flex: none; font-family: var(--font-mono); font-size: 11px;
  color: var(--ac-coordination);
}
.fld-date {
  flex: none; font-family: var(--font-mono); font-size: 9.5px;
  color: var(--paper-mute);
}
.fld-text {
  margin: 5px 0 0; font-size: 11.5px; line-height: 1.45; color: var(--paper-dim);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.fld-by { margin-top: 6px; font-size: 10px; color: var(--paper-mute); }

/* carte de lecture, dans le panneau vidéo */
/* ------------------------------------------- carte d'un témoignage de terrain
   Elle prend les proportions de la vidéo, calculées à l'ouverture : cinq de ces
   séquences sont en paysage — jusqu'à 2,46 de rapport — et deux en portrait. Un
   format unique en aurait rogné ou bordé la moitié. */
.vid.is-field {
  top: 84px; bottom: auto;
  right: calc(var(--panel-w) + 30px);
}
.vid.is-field .vid-box {
  width: var(--vid-w, 640px); height: var(--vid-h, 360px);
  aspect-ratio: auto;
}
.vid.is-field .vid-body { scroll-snap-type: none; overflow: hidden; }
/* La vidéo occupe seule la carte : ni titre, ni bandeaux dégradés, ni pastilles.
   Sur une séquence de cinq secondes, l'habillage tenait plus de place que
   l'image. Ne reste que le bouton de fermeture, sans fond. */
.vid.is-field .vid-note,
.vid.is-field .vid-dots { display: none; }
.vid.is-field .vid-head {
  background: none; padding: 8px 8px 0; pointer-events: none;
}
.vid.is-field .vid-head > div:first-child { display: none; }
.vid.is-field .vid-close {
  pointer-events: auto; opacity: 0;
  background: rgba(8,9,12,.62); backdrop-filter: blur(6px);
  transition: opacity .18s var(--ease);
}
.vid.is-field .vid-box:hover .vid-close,
.vid.is-field .vid-close:focus-visible { opacity: 1; }

/* Attribution et réserve, en une bande qui n'apparaît qu'au survol :
   l'habillage disparaît, le crédit non — c'est le minimum dû à qui a filmé. */
.fld-credit {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  padding: 20px 12px 9px;
  background: linear-gradient(to top, rgba(4,5,8,.92), transparent);
  font-size: 10.5px; pointer-events: none;
  opacity: 0; transition: opacity .18s var(--ease);
}
.vid.is-field .vid-box:hover .fld-credit { opacity: 1; }
.fld-where { color: var(--paper); font-weight: 600; }
.fld-who { color: var(--paper-mute); font-family: var(--font-mono); font-size: 9.5px; }
.fld-warn {
  margin-left: auto; padding: 1px 7px; border-radius: 100px;
  border: 1px solid rgba(255,209,102,.35);
  font-size: 9px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ac-coordination);
}

.fld-item { display: flex; align-items: center; justify-content: center; }
.fld-video { width: 100%; height: 100%; object-fit: contain; background: #000; }

/* Flèches flottantes du carrousel, posées sur les bords de la vidéo. Elles ne se
   montrent qu'au survol de la carte : sur une séquence de cinq secondes, deux
   pastilles permanentes au milieu de l'image gênent plus qu'elles ne servent. */
.fld-nav {
  position: absolute; top: 50%; z-index: 3;
  width: 34px; height: 34px; margin-top: -17px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255,255,255,.18); border-radius: 50%;
  background: rgba(8,9,12,.62); backdrop-filter: blur(6px);
  color: var(--paper); font-size: 19px; line-height: 1;
  opacity: 0; transition: opacity .18s var(--ease), background .18s var(--ease);
}
.vid-box:hover .fld-nav { opacity: 1; }
.fld-nav:hover { background: rgba(8,9,12,.85); }
.fld-nav:focus-visible { opacity: 1; outline: 1px solid var(--ice-400); }
.fld-nav.p-prev { left: 10px; }
.fld-nav.p-next { right: 10px; }


.fld-card {
  width: 100%; max-height: 100%; overflow-y: auto;
  padding: 18px 16px; text-align: center;
}
.fld-quote {
  margin: 0 0 12px; font-size: 12.5px; line-height: 1.5; color: var(--paper);
}
.fld-meta { font-size: 10.5px; color: var(--paper-mute); margin-bottom: 14px; }
.fld-play {
  padding: 7px 14px; border-radius: 100px;
  border: 1px solid rgba(255,209,102,.45); background: rgba(255,209,102,.12);
  font-size: 11px; color: var(--ac-coordination);
}
.fld-play:disabled { opacity: .6; }
.fld-link {
  display: block; margin-top: 10px; font-size: 10.5px; color: var(--ice-400);
}
.fld-caveat {
  margin: 16px auto 0; max-width: 300px;
  font-size: 9.5px; line-height: 1.5; color: var(--paper-mute);
}
.fld-embed { margin-bottom: 12px; }
.tip-h.is-field { color: var(--ac-coordination); }

/* ----------------------------------------------------------------- foudre */

.alert {
  display: grid; grid-template-columns: 26px 1fr; gap: 3px 11px;
  padding: 12px 16px;
  border-bottom: 1px solid rgba(255,255,255,.045);
  background: rgba(239,99,22,.06);
  cursor: pointer; transition: background .18s var(--ease);
}
.alert:hover { background: rgba(239,99,22,.12); }

.alert-mark {
  grid-row: span 3; width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: rgba(185,140,255,.15); color: var(--bolt);
}
.alert-mark svg { width: 14px; height: 14px; }

.alert-title { font-size: 12.5px; color: var(--ember-500); font-weight: 500; }
.alert-where { font-size: 12.5px; color: var(--paper); }
.alert-detail {
  font-family: var(--font-mono); font-size: 10.5px; color: var(--paper-mute);
}

.bolt-head {
  display: flex; align-items: center; gap: 8px; flex: none;
  padding: 9px 16px; border-bottom: 1px solid var(--ink-200);
  background: rgba(185,140,255,.05);
  font-size: 11px; color: var(--paper-dim);
}
.bolt-live {
  position: relative;
  width: 6px; height: 6px; border-radius: 50%; flex: none;
  background: var(--bolt);
}
.bolt-live::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: 50%; background: color-mix(in srgb, var(--bolt) 60%, transparent);
  animation: onde 2.6s var(--ease) infinite;
}
.bolt-live.is-off { background: var(--paper-mute); }
.bolt-live.is-off::after { animation: none; opacity: 0; }

.strike {
  display: flex; align-items: baseline; gap: 9px;
  padding: 7px 16px; font-size: 11.5px;
  border-bottom: 1px solid rgba(255,255,255,.035);
}
.strike-time {
  font-family: var(--font-mono); font-size: 10.5px; color: var(--bolt); flex: none;
}
.strike-pos { font-family: var(--font-mono); font-size: 10.5px; color: var(--paper-mute); }

/* ------------------------------------------------- vignette d'aéronef */

.photo-card {
  position: fixed; z-index: 40; width: 280px;
  border: 1px solid var(--ink-400); border-radius: var(--r-md);
  background: rgba(10,11,15,.96); backdrop-filter: blur(12px);
  box-shadow: var(--shadow-deep);
  overflow: hidden; pointer-events: none;
  opacity: 0; transform: translateX(6px) scale(.98);
  transition: opacity .2s var(--ease), transform .2s var(--ease-out);
}
.photo-card.is-on { opacity: 1; transform: translateX(0) scale(1); }

.photo-card img {
  display: block; width: 100%; height: auto;
  background: var(--ink-200);
}

.photo-meta {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 10px 9px;
  border-top: 1px solid var(--ink-200);
}
.photo-who {
  font-family: var(--font-mono); font-size: 11.5px; color: var(--ice-400);
}
.photo-by { font-size: 10px; color: var(--paper-mute); }

.ac.has-photo .ac-call::after {
  content: "";
  display: inline-block; width: 4px; height: 4px; margin-left: 5px;
  border-radius: 50%; background: var(--ice-300); opacity: .55;
  vertical-align: middle;
}

/* ----------------------------------------------- menu contextuel et mesure */

.ctx {
  position: fixed; z-index: 45; min-width: 186px;
  padding: 5px; display: none;
  border: 1px solid var(--ink-400); border-radius: var(--r-md);
  background: rgba(12,14,19,.97); backdrop-filter: blur(12px);
  box-shadow: var(--shadow-deep);
}
.ctx.is-on { display: block; }

.ctx-item {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 9px; border: 0; border-radius: var(--r-sm);
  background: none; text-align: left;
  font-size: 12.5px; color: var(--paper-dim);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.ctx-item:hover { background: rgba(255,255,255,.06); color: var(--paper); }
.ctx-item svg { width: 13px; height: 13px; flex: none; opacity: .8; }

.ctx-sep { height: 1px; margin: 4px 6px; background: var(--ink-300); }

.ctx-coord {
  padding: 6px 9px 7px;
  font-family: var(--font-mono); font-size: 10.5px; color: var(--paper-mute);
}

/* étiquettes de distance, repositionnées à chaque déplacement de carte */

.measure-labels { position: fixed; inset: 0; z-index: 6; pointer-events: none; }

.measure-label {
  position: absolute; transform: translate(-50%, -50%);
  padding: 2px 7px; border-radius: 100px; white-space: nowrap;
  border: 1px solid rgba(168,242,251,.4);
  background: rgba(8,20,26,.9);
  font-family: var(--font-mono); font-size: 10.5px;
  color: var(--ice-500);
  font-variant-numeric: tabular-nums;
}
.measure-label.is-total {
  border-color: var(--ice-400); background: var(--ice-400);
  color: #05202a; font-weight: 500;
}

.measure-bar {
  position: fixed; z-index: 14; left: 50%; bottom: calc(var(--tl-h) + 14px);
  transform: translateX(-50%);
  display: flex; align-items: center; gap: 12px;
  padding: 8px 12px;
  border: 1px solid var(--ink-400); border-radius: 100px;
  background: rgba(12,14,19,.95); backdrop-filter: blur(12px);
  box-shadow: var(--shadow-deep);
}
.measure-bar[hidden] { display: none; }

.measure-total {
  font-family: var(--font-mono); font-size: 15px; color: var(--ice-400);
  font-variant-numeric: tabular-nums;
}
.measure-hint { font-size: 10.5px; color: var(--paper-mute); }

.measure-undo, .measure-close {
  padding: 3px 9px; border-radius: 100px; border: 1px solid var(--ink-400);
  background: none; font-size: 10.5px; color: var(--paper-dim);
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.measure-undo:hover, .measure-close:hover {
  color: var(--paper); border-color: var(--paper-mute);
}
.measure-close { color: var(--ice-400); border-color: rgba(92,224,240,.35); }

@media (max-width: 940px) {
  .measure-hint { display: none; }
}

/* ------------------------------------------------- vidéos d'illustration */

/* Panneau flottant, accolé à gauche du volet de droite. Il occupait auparavant
   tout l'écran derrière un voile sombre : consulter une vidéo coupait alors la
   carte et la liste des passes, alors que c'est précisément ce qu'on veut
   garder sous les yeux. Le conteneur épouse son contenu, donc rien n'intercepte
   les clics ailleurs — la carte reste manipulable pendant la lecture. */
/* Les bornes verticales sont **exactement** celles du volet de droite : même
   `top`, et une hauteur qui reprend son `max-height`. Fixées à la main — 84 px
   de haut, 620 px de haut maximum — la carte vidéo restait six pixels plus
   basse et nettement plus courte que son voisin. */
.vid {
  position: fixed; z-index: 40;
  top: 78px; bottom: calc(var(--tl-h) + 20px);
  right: calc(var(--panel-w) + 30px);
  display: flex;
}
.vid[hidden] { display: none; }

/* Format court : la carte est un 9:16 strict, et l'habillage flotte au-dessus
   de la vidéo plutôt que de rogner sa hauteur — comme dans un fil de formats
   courts. Sans cela l'en-tête écrasait le cadre et le rapport se perdait. */
.vid-box {
  position: relative;
  aspect-ratio: 9 / 16;
  height: 100%;
  border: 1px solid var(--ink-300); border-radius: var(--r-lg);
  background: #000;
  box-shadow: var(--shadow-deep), 0 0 0 1px rgba(92,224,240,.08);
  overflow: hidden;
}

/* volet réduit : le panneau reprend la place libérée */
body:has(.panel.is-shut) .vid { right: 22px; }

/* Écrans étroits : le panneau viendrait couvrir le rail. Il se replie alors
   contre le volet, en plus petit. Le décalage part du bord de l'écran, il doit
   donc franchir la largeur du volet **et** ses 18 px de marge : mesuré à
   +14 px, le panneau mordait de quatre pixels sur le volet. */
@media (max-width: 1180px) {
  .vid { right: calc(var(--panel-w) + 26px); }
}

/* Sous 940 px le volet devient un tiroir en bas et le rail occupe le haut :
   il n'y a plus de colonne libre à sa gauche. Le panneau se centre alors sur
   la carte, ce qui reste le seul espace disponible. */
/* ─────────────────────  la vidéo sur un écran étroit  ──────────────────────
   Le cadre était un 9:16 fixe, quelle que soit la vidéo : une séquence tournée
   en paysage s'y retrouvait en une bande minuscule cernée de noir, au milieu de
   l'écran. La forme suit donc l'orientation de la vidéo regardée — la classe est
   posée par le script, qui sait laquelle est à l'écran.

   Paysage : toute la largeur, dans la moitié haute, en gardant le rapport de
   l'image. On ne remplit pas la moitié au forceps, ce qui l'étirerait ; on prend
   la plus grande taille possible sans la déformer, et la moitié basse de la carte
   reste visible dessous.

   Portrait : aussi grand que la place le permet, en-tête et chronologie déduits. */
@media (max-width: 940px) {
  .vid, body:has(.panel.is-shut) .vid {
    top: 68px; bottom: auto; left: 0; right: 0;
    transform: none;
    padding: 0 10px;
    justify-content: center; align-items: flex-start;
  }

  /* Le carrousel garde son cadre 9:16, on ne fait qu'en augmenter la hauteur.
   *
   *  Une version précédente changeait la forme du cadre selon l'orientation de la
   *  vidéo regardée. Elle a cassé la mise en page des cartes : deux légendes se
   *  retrouvaient empilées en bas, celles de deux vidéos différentes, et les
   *  autres n'en avaient plus. Le carrousel repose sur des cartes de la hauteur
   *  exacte du cadre — c'est ce qui fait qu'une carte occupe une page et une
   *  seule —, et une hauteur dérivée d'un rapport d'image ne le lui garantit pas.
   *
   *  Une séquence paysage reste donc cernée de noir dans un cadre vertical, ce qui
   *  était le choix d'origine et qui est documenté : le lecteur la centre lui-même,
   *  avec des commandes à la bonne échelle. Un carrousel peut mêler les deux
   *  orientations ; lui donner une forme par carte demanderait de reprendre le
   *  mécanisme de pagination, ce que cette correction ne fera pas à la légère. */
  .vid-box { height: min(70vh, calc(100vh - 68px - var(--tl-h) - 28px)); }

  /* Le témoignage garde ses dimensions calculées par le script, mais il faut
     défaire son ancrage : au large il se pose à gauche du volet
     (`right: --panel-w + 30px`), et cette règle-là est plus spécifique que celle
     du panneau générique — sur un téléphone elle le repoussait contre le bord
     gauche, dans une bande de trente pixels. */
  .vid.is-field {
    top: 68px; bottom: auto; left: 0; right: 0;
    justify-content: center;
  }

  /* Crédit et fermeture toujours visibles, sur le seul critère de la largeur.
     La règle `(hover: none)` plus bas couvre le cas général du tactile, mais s'en
     remettre à elle seule laissait le crédit invisible sur les appareils qui
     déclarent un pointeur fin tout en étant tenus à la main. Sur un écran de cette
     taille, rien ne justifie de cacher l'attribution derrière un survol. */
  .vid.is-field .fld-credit,
  .vid.is-field .vid-close,
  .vid.is-field .fld-nav { opacity: 1; }

  /* Et il passe en haut du lecteur. Rendu permanent, il tombait sur les commandes
     natives de la vidéo — lecture, progression, plein écran — et l'attribution se
     lisait par-dessus la barre de défilement. Le haut est libre, à l'exception du
     bouton de fermeture, dont on réserve la place à droite. Le dégradé se
     retourne pour rester lisible sur l'image. */
  .vid.is-field .fld-credit {
    top: 0; bottom: auto;
    padding: 9px 52px 20px 12px;
    background: linear-gradient(to bottom, rgba(4,5,8,.92), transparent);
  }
}

/* Appareils sans survol : le crédit d'une séquence et le bouton de fermeture
   étaient révélés au passage du pointeur. Sur un écran tactile il n'y a pas de
   pointeur : ils ne se montraient jamais. On ne savait donc ni qui avait filmé —
   c'est le minimum dû à l'auteur — ni comment refermer, d'où le réflexe de taper
   la carte, que l'on prend désormais au mot. */
@media (hover: none) {
  .vid.is-field .fld-credit { opacity: 1; }
  .vid.is-field .vid-close { opacity: 1; }
  /* Les flèches de navigation entre témoignages, pour la même raison : révélées
     au survol, elles ne se montraient jamais sous un doigt. */
  .vid.is-field .fld-nav { opacity: 1; }
}

.vid-head {
  position: absolute; z-index: 4; left: 0; right: 0; top: 0;
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 14px 26px;
  background: linear-gradient(to bottom, rgba(4,5,8,.92) 20%, transparent);
  pointer-events: none;
}
.vid-head .vid-close { pointer-events: auto; }
/* Le titre porte la teinte de la manoeuvre : braise pour un largage, glace pour un
   écopage. C'est la grammaire de toute l'interface — le feu à la braise, l'eau à la
   glace — et elle vaut mieux ici qu'un cyan unique, qui disait « aérien » là où l'on
   sait déjà qu'on regarde un aéronef, sans distinguer les deux gestes. */
.vid-kind {
  font-family: var(--font-mono); font-size: 13px;
  color: var(--ice-400);
}
.vid-kind.k-largage { color: var(--ember-400); }
.vid-kind.k-ecopage { color: var(--ice-400); }
/* Sous-titre en blanc : il porte l'appareil, le lieu, l'heure et l'altitude — tout
   ce que disait l'infobulle recouverte par le lecteur. Dans le gris de second plan,
   ces quatre données se lisaient comme une mention légale. */
.vid-who { font-size: 11px; color: var(--paper); margin-top: 2px; }

.vid-close {
  margin-left: auto; width: 26px; height: 26px; flex: none;
  display: flex; align-items: center; justify-content: center;
  border: 0; border-radius: 50%;
  background: rgba(255,255,255,.06); color: var(--paper-dim);
}
.vid-close:hover { color: var(--paper); }

/* l'avertissement reste lisible en flottant, sur son propre fond */
/* Réserve posée sous l'en-tête du lecteur.
 *
 *  Elle courait d'un bord à l'autre du cadre, à dix pixels de chaque côté : elle
 *  se lisait comme une bande collée aux arêtes, et rien ne la rattachait au titre
 *  qu'elle commente. Ses bords s'alignent maintenant sur la marge de l'en-tête —
 *  quatorze pixels, comme le titre juste au-dessus — et sa largeur est plafonnée :
 *  au large, une réserve de deux lignes n'a pas à traverser six cents pixels. */
.vid-note {
  position: absolute; z-index: 4; left: 14px; right: 14px; top: 62px;
  max-width: 420px;
  margin: 0; padding: 6px 9px; border-radius: var(--r-sm);
  background: rgba(8,9,12,.82); backdrop-filter: blur(6px);
  font-size: 10px; line-height: 1.4; color: var(--paper-dim);
  pointer-events: none;
}

/* Défilement vertical accroché : une vidéo occupe toute la carte, on passe à
   la suivante d'un geste, comme dans un fil de formats courts. */
.vid-body {
  position: absolute; inset: 0;
  overflow-y: auto; overscroll-behavior: contain;
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
}
.vid-body::-webkit-scrollbar { display: none; }

.vid-item {
  position: relative; height: 100%;
  scroll-snap-align: start; scroll-snap-stop: always;
  background: #000;
}

.vid-frame {
  position: absolute; inset: 0;
  overflow: hidden; background: #000;
}

/* Le lecteur occupe toute la carte, sans exception.
   Une version antérieure dimensionnait le cadre selon l'orientation présumée de
   la vidéo, déduite d'oEmbed — qui renvoie en réalité 200×113 pour tout le
   monde. Résultat : un format vertical se retrouvait enfermé dans un cadre
   paysage de 290 pixels de haut, réduit à une bande minuscule, avec les
   commandes YouTube démesurées par-dessus.

   Le lecteur reçoit donc simplement les dimensions de la carte, en 9:16. Une
   vidéo verticale la remplit bord à bord ; une vidéo paysage est centrée par
   YouTube lui-même, avec des commandes à la bonne échelle. */
.vid-frame iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border: 0;
}

/* vidéo que son auteur n'autorise pas hors de YouTube */
.vid-out {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 7px;
  padding: 24px; text-align: center;
}
.vid-out p { margin: 0; font-size: 12.5px; color: var(--paper-dim); }
.vid-out span { font-size: 11px; color: var(--paper-mute); }
.vid-out a { font-size: 11px; color: var(--ice-400); }


/* vignette affichée avant la mise en lecture */
.vid-poster[hidden] { display: none; }
.vid-poster {
  position: absolute; inset: 0; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.vid-poster img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: .55;
}
.vid-play {
  position: relative; width: 54px; height: 54px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255,255,255,.5); background: rgba(8,9,12,.6);
  backdrop-filter: blur(4px); color: #fff;
}
.vid-poster:hover .vid-play { background: rgba(8,9,12,.8); }

.vid-cap {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  padding: 22px 12px 11px;
  background: linear-gradient(to top, rgba(4,5,8,.92), transparent);
  font-size: 11px; color: var(--paper);
  pointer-events: none;
}
.vid-cap .vid-act {
  padding: 1px 6px; border-radius: 100px; flex: none;
  font-size: 9.5px; letter-spacing: .05em; text-transform: uppercase;
}

/* repère de position dans le fil */
.vid-dots {
  position: absolute; right: 4px; top: 50%; z-index: 3;
  transform: translateY(-50%);
  /* le conteneur laisse passer, seules les pastilles prennent le clic : la
     colonne ne doit pas barrer le bord droit de la vidéo */
  display: grid; gap: 0; pointer-events: none;
}

/* Boutons, et non voyants : c'est le recours quand un lecteur capte la molette.
   Le point visible reste un point de cinq pixels — il est dessiné en `::before`,
   la surface cliquable étant portée par le bouton, qui l'entoure sans paraître. */
.vid-dot {
  width: 15px; height: 15px; padding: 0; border: 0; cursor: pointer;
  background: none; pointer-events: auto;
  display: grid; place-items: center;
  -webkit-appearance: none; appearance: none;
}
.vid-dot::before {
  content: ''; width: 5px; height: 5px; border-radius: 50%;
  background: rgba(255,255,255,.28);
  transition: background .25s var(--ease), transform .25s var(--ease);
}
.vid-dot:hover::before { background: rgba(255,255,255,.55); }
.vid-dot.is-on::before { background: var(--ice-400); transform: scale(1.4); }
.vid-dot:focus-visible { outline: 1px solid var(--ice-400); outline-offset: -2px; }
.vid-act.a-largage { background: rgba(239,99,22,.16); color: var(--ember-400); }
.vid-act.a-ecopage { background: rgba(92,224,240,.14); color: var(--ice-400); }
.vid-act.a-general { background: rgba(255,255,255,.06); color: var(--paper-mute); }
/* signale ce qui n'est pas un format court plein cadre : un extrait tronqué, ou
   une vidéo paysage cernée de bandes noires. Mieux vaut le dire que laisser
   croire à un défaut d'affichage. */
.vid-crop {
  flex: none; padding: 1px 5px; border-radius: 100px;
  border: 1px solid rgba(255,255,255,.2);
  font-size: 9px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--paper-mute);
}
.vid-cred { margin-left: auto; flex: none; font-size: 10px; color: var(--paper-dim); }

.vid-empty { padding: 22px 4px; text-align: center; }
.vid-empty p { margin: 0 0 5px; font-size: 12.5px; color: var(--paper-dim); }
.vid-empty span { font-size: 11px; color: var(--paper-mute); }

/* la passe cliquable se signale */
.drop { cursor: pointer; transition: background .16s var(--ease); }
.drop:hover { background: rgba(255,255,255,.04); }

/* Passe dont la vidéo est ouverte. Le repère de la carte porte déjà son anneau,
   mais la liste comptant jusqu'à soixante lignes, on perdait de vue laquelle on
   venait d'ouvrir. Un liseré plutôt qu'un fond : la ligne reste lisible et
   l'oeil la retrouve sans que la liste se mette à clignoter. */
.drop.is-sel {
  background: rgba(92,224,240,.07);
  box-shadow: inset 2px 0 0 var(--ice-400);
}

/* --------------------------------------------------------------- amorçage */

.boot {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  background: var(--ink-000);
  transition: opacity .7s var(--ease), visibility .7s;
}
.boot.is-done { opacity: 0; visibility: hidden; }
/* L'écran d'attente reste dans le document, seulement masqué : sa pastille
   continuait donc de respirer indéfiniment sous un voile invisible, entretenant
   le compositeur pour rien. */
.boot.is-done .boot-mark { animation: none; }

.boot-inner { text-align: center; }

.boot-mark {
  width: 46px; height: 46px; margin: 0 auto 20px; border-radius: 50%;
  background: radial-gradient(circle at 50% 55%, var(--ember-600), var(--ember-300) 38%, var(--ember-100) 62%, transparent 74%);
  animation: breathe 2.3s var(--ease) infinite;
}
@keyframes breathe {
  0%, 100% { transform: scale(.86); opacity: .55; }
  50%      { transform: scale(1.06); opacity: 1; }
}

.boot-title {
  margin: 0 0 6px; font-family: var(--font-display); font-size: 21px; font-weight: 400;
}
.boot-step {
  margin: 0; font-family: var(--font-mono); font-size: 11px;
  color: var(--paper-mute); letter-spacing: .02em;
}

/* Jauge d'avancement. Largeur fixe : calée sur l'étape la plus longue, elle ne
   se redimensionne pas à chaque changement de libellé. */
.boot-gauge {
  width: 210px; height: 2px; margin: 16px auto 8px;
  background: var(--ink-300); border-radius: 2px; overflow: hidden;
}
.boot-bar {
  width: 0; height: 100%;
  background: linear-gradient(to right, var(--ember-200), var(--ember-400));
  /* la transition suit la mesure : les étapes ne durent pas toutes le même
     temps, un déplacement lissé vaut mieux qu'un saut sec */
  transition: width .45s var(--ease);
}
.boot-pct {
  margin: 0; font-family: var(--font-mono); font-size: 10.5px;
  color: var(--ember-400); letter-spacing: .08em;
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------- icônes d'aéronefs
   Les aéronefs ne sont plus des éléments HTML mais une couche cartographique
   (voir `registerAircraftIcons` dans app.js). Il n'y a donc plus rien à styler
   ici : positions, orientation et halo sont rendus par la carte, dans le même
   système de coordonnées que les trajectoires.

   Conserver ce parti pris. Un marqueur HTML est positionné par MapLibre via
   `position: absolute` et un `transform` réécrit à chaque image ; la moindre
   règle CSS posant `position` ou `transform` sur sa racine le désolidarise du
   terrain, et le décalage — constant en pixels écran — donne l'illusion que
   l'icône glisse au zoom. */

/* --------------------------------------------------------------- écrans */

@media (max-width: 1180px) {
  :root { --panel-w: 330px; --rail-w: 244px; }
}

@media (max-width: 940px) {
  :root { --tl-h: 116px; }

  .masthead { padding: 11px 14px 26px; }
  .masthead h1 { font-size: 24px; }
  .masthead-sub { font-size: 10px; }

  /* La borne servait à ne pas atteindre la barre de couches, qui occupait le
     centre de l'en-tête. Celle-ci étant passée sur le côté, elle n'a plus
     d'objet — et sur un téléphone elle valait moins que zéro, ce qui écrasait
     le titre à « GIRON ». */
  .masthead-text { max-width: none; }

  /* Le rail et le tiroir s'arrêtent au couloir de la barre de couches. Sans
     cela le rail déplié passait dessous, et la barre — plus haute dans la pile —
     flottait par-dessus son contenu. */
  /* Toute la largeur disponible. Le couloir de la barre des couches ne leur est
     plus retiré : ces deux panneaux sont ce qu'on vient lire, et les amputer de
     cinquante-huit pixels sur trois cent quatre-vingt-treize se payait sur chaque
     ligne de texte. Repliés ils n'occupent que le haut, où la barre — centrée en
     hauteur — n'est pas ; ouverts, ils passent par-dessus elle. */
  .rail, .panel { left: 10px; right: 10px; }

  /* Ouverts, ils dominent la barre des couches. Repliés, ils lui laissent la
     place : on doit pouvoir basculer une couche sans refermer un panneau qui ne
     recouvre rien. */
  .rail:not(.is-shut), .panel:not(.is-shut) { z-index: 15; }

  .rail {
    top: 66px; width: auto;
    max-height: none;
  }

  /* Le bouton du rail et la barre d'onglets du volet doivent se lire comme deux
     barres de même famille. Le premier n'avait pas le léger éclaircissement du
     second et portait un gris de second plan : posés l'un sous l'autre, la
     situation paraissait enfoncée et éteinte à côté des onglets. */
  .rail-toggle {
    padding: 12px 12px;
    background: rgba(255,255,255,.018);
    color: var(--paper);
    font-size: 10px; font-weight: 500; letter-spacing: .05em;
  }
  .rail-toggle { display: flex; }
  /* 46 vh laissaient les foyers coupés au milieu alors que le bas de l'écran
     restait vide : la borne datait du temps où le tiroir pouvait être ouvert en
     même temps. Ils s'excluent désormais, le rail peut donc respirer. */
  .rail-body { max-height: 58vh; }

  /* Le volet devient le pair du rail : même colonne, même cadre, empilé juste
     dessous. Il était un tiroir montant du bas, ce qui en faisait un objet d'une
     autre nature — on ne voyait pas que les deux ne peuvent pas être ouverts en
     même temps. Sa barre d'onglets tient le rôle que le bouton « Situation »
     tient pour le rail : toujours visible, elle ouvre et referme. */
  .panel {
    /* `--rail-h` est renseignée depuis le script, à la hauteur réelle du rail :
       déplié, il grandit, et le volet doit descendre d'autant. Le CSS ne sait pas
       mesurer un frère en position fixe. La valeur de repli couvre le cas où le
       script n'a pas encore mesuré. */
    top: calc(66px + var(--rail-h, 38px) + 8px); bottom: auto;
    width: auto;
    max-height: 58vh;
    border: 1px solid var(--ink-300);
    border-radius: var(--r-lg);
  }
  /* Replié, seule la barre d'onglets subsiste — le volet ne quitte plus l'écran.
     Il faut défaire les trois propriétés de la règle générale, et non la seule
     translation : au large le volet replié sort du cadre et s'efface, si bien
     qu'il restait invisible et intouchable ici, correctement placé mais à
     `opacity: 0`. */
  .panel.is-shut {
    transform: none; opacity: 1; pointer-events: auto;
    overflow: hidden;
  }
  .panel.is-shut .tabpane { display: none; }
  .panel.is-shut .tabs { border-bottom: 0; }

  /* Le bouton flottant d'ouverture n'a plus d'objet : la barre d'onglets ne
     disparaît jamais, c'est elle qu'on touche pour déplier. Sélecteur aligné sur
     celui qui l'affiche au large — `.panel.is-shut ~ .panel-open` — sinon la
     spécificité de ce dernier l'emporte et le bouton reste là. */
  .panel-open,
  .panel.is-shut ~ .panel-open { display: none; }

  /* Les deux chevrons doivent dire la même chose, de la même façon : replié, il
     montre où le panneau va s'ouvrir — vers le bas ; ouvert, où il va se refermer
     — vers le haut. Les deux icônes de départ ne pointent pas du même côté, l'une
     vers le bas et l'autre vers la droite, d'où deux rotations différentes pour un
     même résultat à l'écran. Et la même couleur : le volet portait un gris de
     second plan là où le rail portait du blanc. */
  .rail-toggle svg, .panel-close { color: var(--paper); }

  .rail.is-shut .rail-toggle svg { transform: none; }
  .rail:not(.is-shut) .rail-toggle svg { transform: rotate(180deg); }
  .panel.is-shut .panel-close svg { transform: rotate(90deg); }
  .panel:not(.is-shut) .panel-close svg { transform: rotate(-90deg); }
  .panel-close svg { transition: transform .3s var(--ease); }

  /* Même place, exactement.
   *
   *  Les deux chevrons vivent dans des barres qui n'avaient ni la même hauteur —
   *  trente-six pixels de marges contre une rangée d'onglets étirée — ni la même
   *  marge à droite : douze pixels pour le rail, dix pour le volet. À l'oeil, l'un
   *  paraissait plus haut et plus rentré que l'autre.
   *
   *  Les deux barres reçoivent donc la même hauteur et le même retrait, et chacune
   *  centre son chevron. Le retrait est porté par la marge intérieure du bouton,
   *  non par celle de la barre : c'est le bouton qu'on touche, il doit rester assez
   *  large pour le doigt. */
  .rail-toggle, .tabs { min-height: 42px; }
  .rail-toggle { padding: 0 0 0 12px; align-items: center; }

  /* Treize pixels du bord droit dans les deux cas. Le retrait est posé sur le
     chevron du rail — dont la barre n'a plus de marge à droite — et sur la marge
     intérieure du bouton du volet, qui doit rester assez large pour le doigt.
     Aucune largeur n'est imposée au dessin lui-même : la lui donner l'étirerait,
     ses dimensions étant portées par ses attributs. */
  .rail-toggle > svg { margin-right: 13px; flex: none; }
  .panel-close {
    padding: 0 13px;
    display: flex; align-items: center;
  }

  /* Le couloir prend 58 px au tiroir : la barre d'onglets n'y tenait plus et le
     compteur passait sous son libellé. On resserre plutôt que d'abréger les
     libellés, qui nomment les trois volets. */
  .tab { padding: 12px 10px; font-size: 10px; letter-spacing: .05em; }
  .tab::after { left: 10px; right: 10px; }
  .tab-count { margin-left: 4px; padding: 1px 4px; font-size: 9.5px; }

  /* Le détail d'un appareil passe à la ligne — c'est voulu, le tronquer perdrait
     sa fin. On lui rend donc de la largeur au lieu de le couper : marges
     resserrées et pastille d'état plus discrète. */
  .ac { padding: 10px 12px; gap: 3px 8px; }
  .ac-phase { font-size: 9px; padding: 3px 6px; letter-spacing: .04em; }

  /* La chronologie garde toute la largeur : la barre est centrée en hauteur, et
     ne descend pas jusqu'à elle sur un écran en portrait. */
  .timeline { gap: 11px; padding: 0 12px 10px; }
  .play { width: 36px; height: 36px; }
  .tl-speed button { padding: 4px 6px; }
}

@media (max-width: 560px) {
  /* La vitesse reste réglable : seul le bouton actif s'affiche, et le toucher
     passe au suivant. Masquer le groupe entier, comme avant, ne laissait que la
     vitesse la plus lente — plus d'une minute pour rejouer l'épisode. Les trois
     boutons ne tiennent pas ici : ils prennent soixante-dix pixels que la date et
     la surface réclament déjà. */
  .tl-speed button:not(.is-on) { display: none; }
  .tl-speed button.is-on { padding: 6px 7px; font-size: 11px; }

  /* Treize pixels manquaient à la ligne pour porter la mention, la date, la
     surface et ce bouton. Ils sont pris là où ils ne se voient pas : deux pixels
     sur chacun des trois écarts, un demi-point sur la mention. Sans cela l'ellipse
     rongeait la mention de deux caractères — « relevé satellite d… ». */
  .tl-readout { gap: 5px; }
  .tl-kicker { font-size: 9.5px; }
  .masthead-sub { display: none; }
  .masthead h1 { font-size: 17px; }
  .live { font-size: 9.5px; padding: 4px 9px 4px 7px; }
}

/* ===========================================================================
   Bilan de l'épisode — page plein écran

   Elle ne se superpose pas à la carte, elle la remplace : ce sont deux façons
   de regarder le même épisode, et elles ne se lisent pas ensemble. Même
   grammaire chromatique que la carte — la braise au feu, la glace à la lutte —
   pour qu'aucun apprentissage ne soit nécessaire en passant de l'une à l'autre.
   =========================================================================== */

.stats {
  position: fixed; inset: 0; z-index: 80;
  display: flex; flex-direction: column;
  background: var(--ink-000);
}
.stats[hidden] { display: none; }

.st-open {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; padding: 9px 12px;
  border: 1px solid var(--ink-300); border-radius: var(--r-sm);
  background: rgba(255,140,43,.07);
  font-size: 11.5px; font-weight: 600; letter-spacing: .04em;
  color: var(--ember-400);
  transition: background .2s var(--ease), border-color .2s var(--ease);
}
.st-open:hover { background: rgba(255,140,43,.14); border-color: rgba(255,140,43,.4); }

.st-top {
  display: flex; align-items: center; gap: 16px; flex: none;
  padding: 14px 26px;
  border-bottom: 1px solid var(--ink-200);
  background: rgba(10,11,15,.96);
}
.st-title { flex: 1; min-width: 0; }
.st-title h2 {
  margin: 0; font-family: var(--font-display);
  font-size: 19px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
}
.st-title p {
  margin: 2px 0 0; font-size: 10.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--paper-mute);
}

.st-tabs { display: flex; gap: 4px; flex: none; }
.st-tabs button {
  padding: 5px 12px;
  border: 1px solid var(--ink-300); border-radius: var(--r-sm);
  background: rgba(255,255,255,.02);
  font-size: 10.5px; color: var(--paper-mute); white-space: nowrap;
  transition: color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}
.st-tabs button:hover { color: var(--paper-dim); border-color: var(--ink-400); }
.st-tabs button.is-on {
  color: var(--ember-400); border-color: rgba(255,140,43,.45);
  background: rgba(255,140,43,.12);
}

.st-btn {
  width: 30px; height: 30px; flex: none;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--ink-300); border-radius: var(--r-sm);
  background: none; color: var(--paper-mute); font-size: 13px;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.st-btn:hover { color: var(--paper); border-color: var(--ink-400); }

.st-body {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 20px 26px 40px;
}

/* --- chiffres de tête ---------------------------------------------------
   Un chiffre par carte, sa légende au-dessus et sa nuance en dessous : jamais
   un nombre seul, toujours ce à quoi il se compare. */
.st-cards {
  display: grid; gap: 10px; margin-bottom: 24px;
  grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
}
.st-card {
  padding: 13px 15px;
  border: 1px solid var(--ink-200); border-radius: var(--r-md);
  background: rgba(255,255,255,.014);
}

.st-k {
  font-size: 9.5px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--paper-mute);
}
.st-v {
  display: flex; align-items: baseline; gap: 6px; margin-top: 7px;
  font-family: var(--font-mono); font-weight: 500;
  font-size: 27px; line-height: 1; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.t-em .st-v { color: var(--ember-500); }
.t-ic .st-v { color: var(--ice-400); }
.t-bo .st-v { color: var(--bolt-hot); }
.t-ne .st-v { color: var(--paper); }
.st-u {
  font-family: var(--font-ui); font-size: 10px; font-weight: 500;
  letter-spacing: .06em; text-transform: uppercase; color: var(--paper-mute);
}
.st-n { margin-top: 6px; font-size: 10.5px; line-height: 1.4; color: var(--paper-mute); }

/* --- blocs et graphiques ------------------------------------------------ */

.st-block {
  padding: 16px 18px; margin-bottom: 16px;
  border: 1px solid var(--ink-200); border-radius: var(--r-md);
  background: rgba(255,255,255,.012);
}
.st-block h3 {
  margin: 0; font-size: 11px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--paper);
}
.st-block .st-h2 { margin-top: 22px; }
.st-sub {
  margin: 5px 0 12px; max-width: 76ch;
  font-size: 10.5px; line-height: 1.5; color: var(--paper-mute);
}

.st-cols { display: grid; gap: 16px; grid-template-columns: 1fr 1fr; }
.st-cols .st-block { margin-bottom: 0; }

.st-svg { display: block; width: 100%; height: 190px; }
.st-svg + .st-svg { height: 90px; margin-top: 6px; }
.st-grid line { stroke: rgba(255,255,255,.07); stroke-width: 1; }
/* Graduations des axes.
 *
 *  Elles étaient en mono à neuf pixels, dans le gris de second plan : sur un
 *  téléphone, « 53 838 » devenait une suite de traits. La police à chasse fixe
 *  était un choix de cohérence — les chiffres du bilan sont en mono — mais elle
 *  s'écroule à cette taille, ses fûts étant plus étroits que ceux d'une
 *  proportionnelle à corps égal.
 *
 *  Les graduations passent donc à la police d'interface, plus haute d'oeil, en
 *  onze pixels et dans un gris plus clair. `font-variant-numeric` garde les
 *  chiffres alignés en colonnes, ce que la mono donnait gratuitement et qui
 *  importe ici : on lit une échelle, pas une phrase. */
.st-ax {
  fill: var(--paper-dim);
  font-family: var(--font-ui); font-size: 11px;
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
}
.st-ax.is-day { fill: var(--paper-dim); }

/* --- tableaux -----------------------------------------------------------
   Chiffres en chasse fixe et alignés à droite : deux colonnes de nombres ne se
   comparent que si les unités tombent l'une sous l'autre. */
.st-tab { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.st-tab th {
  padding: 0 8px 7px; text-align: left;
  border-bottom: 1px solid var(--ink-300);
  font-size: 9px; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--paper-mute);
}
.st-tab td {
  padding: 6px 8px; border-bottom: 1px solid rgba(255,255,255,.04);
  color: var(--paper);
}
.st-tab tr:last-child td { border-bottom: 0; }
.st-tab .n {
  text-align: right; font-family: var(--font-mono);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.st-tab .w { width: 22%; }
.st-tab .st-dim { color: var(--paper-mute); }
.st-dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-right: 7px; vertical-align: baseline;
}

.st-bar {
  display: block; height: 6px; border-radius: 3px;
  background: rgba(255,255,255,.05); overflow: hidden;
}
.st-bar i { display: block; height: 100%; border-radius: 3px; }

/* --- faits de captation ------------------------------------------------- */
.st-facts {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
}
.st-fact {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  padding: 8px 11px; border-radius: var(--r-sm);
  background: rgba(255,255,255,.025);
  font-size: 10.5px; color: var(--paper-mute);
}
.st-fact b {
  font-family: var(--font-mono); font-size: 12px; color: var(--paper);
  font-variant-numeric: tabular-nums;
}

.st-none {
  margin: 0; padding: 14px 0; text-align: center;
  font-size: 10.5px; color: var(--paper-mute);
}
td.st-none { padding: 18px 8px; }

.st-foot {
  margin: 22px 0 0; max-width: 96ch;
  font-size: 10px; line-height: 1.6; color: var(--paper-mute);
}
.st-foot b { color: var(--paper-dim); font-weight: 600; }

@media (max-width: 1080px) {
  .st-cols { grid-template-columns: 1fr; }
  .st-body { padding: 16px 14px 32px; }
  .st-top { padding: 12px 14px; gap: 10px; flex-wrap: wrap; }
}

/* --- survol des graphiques -----------------------------------------------
   Bandes transparentes, repère vertical et infobulle à nous. Le `<title>` de
   SVG attendrait une seconde, ne se stylerait pas et ne porterait qu'une seule
   valeur : ici les séries d'un même instant s'affichent ensemble, puisque c'est
   leur rapprochement qui informe. */

.st-hit-r { fill: transparent; cursor: crosshair; }
.st-hit-r:hover { fill: rgba(255,255,255,.035); }
.st-cursor {
  stroke: rgba(255,255,255,.4); stroke-width: 1;
  stroke-dasharray: 2 3; pointer-events: none;
}

.st-tip {
  position: fixed; z-index: 90; pointer-events: none;
  min-width: 148px; padding: 8px 10px;
  border: 1px solid var(--ink-400); border-radius: var(--r-md);
  background: rgba(10,11,15,.97); backdrop-filter: blur(10px);
  box-shadow: var(--shadow-lift);
  opacity: 0; transform: translateY(3px);
  transition: opacity .12s var(--ease), transform .12s var(--ease);
}
.st-tip.is-on { opacity: 1; transform: translateY(0); }
.st-tip-h {
  font-family: var(--font-mono); font-size: 10.5px; color: var(--paper);
  margin-bottom: 5px;
}
.st-tip-r {
  display: flex; align-items: center; gap: 7px;
  font-size: 10.5px; color: var(--paper-mute);
}
.st-tip-r i { width: 7px; height: 7px; border-radius: 2px; flex: none; }
.st-tip-r span { flex: 1; }
.st-tip-r b {
  font-family: var(--font-mono); color: var(--paper);
  font-variant-numeric: tabular-nums;
}

.notice {
  position: fixed; z-index: 60; inset: 0;
  display: flex; align-items: center; justify-content: center; padding: 22px;
  background: rgba(6,6,9,.74); backdrop-filter: blur(6px);
}
.notice[hidden] { display: none; }

/* Le filet de couleur sur l'arête haute était le même dispositif que celui écarté
   partout ailleurs, simplement pivoté d'un quart de tour — le balayage ne cherchait
   que les bordures gauches et l'avait manqué. Le crochet d'angle prend sa place. */
.notice-card {
  position: relative;
  width: min(520px, 100%); max-height: 100%; overflow-y: auto;
  padding: 26px 28px 24px;
  border: 1px solid var(--ink-300); border-radius: 4px;
  background: var(--ink-050);
  box-shadow: 0 24px 70px rgba(0,0,0,.62);
  --accent: var(--ember-300);
}
.notice-card::before {
  content: '';
  position: absolute; top: 0; left: 0;
  width: 11px; height: 11px;
  border-top: 1.5px solid var(--accent);
  border-left: 1.5px solid var(--accent);
  border-top-left-radius: inherit;
  pointer-events: none;
}
.notice-kicker {
  margin: 0 0 6px;
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ember-400);
}
.notice-title {
  margin: 0 0 14px;
  font-family: var(--font-display); font-size: 19px; font-weight: 600;
  line-height: 1.25; color: var(--paper);
}
.notice-card p { margin: 0 0 11px; font-size: 13px; line-height: 1.62; color: var(--paper-dim); }
.notice-card strong { color: var(--paper); font-weight: 600; }
.notice-strong {
  padding: 11px 13px;
  background: rgba(74,36,16,.28); color: var(--paper) !important;
}
.notice-ok {
  margin-top: 6px; width: 100%; padding: 11px; cursor: pointer;
  border: 1px solid var(--ink-400); border-radius: 3px;
  background: var(--ink-200);
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--paper);
  transition: background .18s var(--ease), border-color .18s var(--ease);
}
.notice-ok:hover { background: var(--ink-300); border-color: var(--ember-300); }

/* ─────────────────────────────  panneau de mesures  ─────────────────────────
   Affiché uniquement avec `?diag` dans l'adresse. Posé au-dessus de tout, y
   compris de l'écran d'attente : on veut le voir pendant la collecte, qui est
   justement le moment où la page travaille le plus. */
.diag {
  position: fixed; z-index: 90; top: 6px; left: 6px;
  padding: 7px 9px; border-radius: 4px;
  border: 1px solid var(--ice-300);
  background: rgba(2,3,5,.92);
  font-family: var(--font-mono); font-size: 10px; line-height: 1.5;
  color: var(--ice-400); white-space: pre; pointer-events: none;
  /* aucun flou ici : ce panneau ne doit pas fausser ce qu'il mesure */
}

/* ───────────────────  groupes dépliants de la barre des couches  ───────────
   Les onze couches sont réunies dans la barre, groupées par sujet. Un groupe est
   un bouton qui ouvre un menu d'interrupteurs — les mêmes `.sw` que portait le
   rail, avec leur pastille de couleur : la lecture ne change pas, seul l'endroit.

   Le libellé est écrit dans le menu, et non porté par une infobulle au survol :
   sur un téléphone il n'y a pas de survol, et une barre d'icônes muette n'est
   utilisable que par qui l'a écrite. */

.hud-grp { position: relative; display: flex; }

/* Un groupe est un `button`, une bascule un `label` : il faut retirer au premier
   le fond, la bordure et la marge intérieure que le navigateur lui donne, sans
   quoi les deux ne se ressembleraient pas dans la même barre. */
.hud-drop {
  -webkit-appearance: none; appearance: none;
  padding: 0; margin: 0; font: inherit;
  background: none; color: var(--paper-mute);
}

/* Un bouton de groupe se distingue d'une bascule : trois quarts de cercle en
   bas à droite, comme un coin replié, plutôt qu'un chevron qui prendrait la
   place de l'icône. */

/* Ce qui est allumé dans le groupe, en points : un point par couche en service.
   Un chiffre demandait à être lu, et à cette taille il se lisait mal ; des points
   se comptent d'un regard, et trois ou quatre suffisent à couvrir un groupe. */
.hud-dots {
  position: absolute; left: 0; right: 0; bottom: 3px;
  display: flex; gap: 2px; justify-content: center;
  pointer-events: none;
}
.hud-dots i {
  width: 3px; height: 3px; border-radius: 50%;
  background: var(--neon);
  box-shadow: 0 0 3px color-mix(in srgb, var(--neon) 70%, transparent);
}

/* Le menu. Sous le bouton au large, à sa droite quand la barre est verticale. */
.hud-menu {
  position: absolute; z-index: 14;
  top: calc(100% + 8px); left: 50%; transform: translateX(-50%);
  width: 232px; padding: 9px 10px 10px;
  border: 1px solid var(--ink-300); border-radius: var(--r-md);
  background: rgba(9,10,14,.96); backdrop-filter: blur(14px) saturate(1.15);
  box-shadow: var(--shadow-deep), inset 0 1px 0 rgba(255,255,255,.04);
}
.hud-menu[hidden] { display: none; }

.hud-menu-h {
  margin: 0 0 6px; padding: 0 6px;
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--neon);
}

/* Cible tactile confortable dans le menu : au doigt, 26 px de haut se ratent. */
.hud-menu .sw { padding: 9px 6px; }
.hud-menu .sw-txt { font-size: 12px; }

.hud-btn.c-fire  { --neon: var(--ember-400); }
.hud-btn.c-meteo { --neon: #8fe6f5; }
.hud-btn.c-sat   { --neon: #a9bd84; }
.hud-btn.c-field { --neon: #ff6ec7; }

/* Un groupe dont une couche est allumée s'annonce comme tel, sans attendre
   qu'on l'ouvre — même traitement qu'une bascule allumée. */
.hud-grp.is-lit .hud-drop {
  color: var(--neon);
  border-color: color-mix(in srgb, var(--neon) 40%, transparent);
  background: color-mix(in srgb, var(--neon) 11%, transparent);
  box-shadow: 0 0 13px -3px color-mix(in srgb, var(--neon) 55%, transparent);
}
.hud-grp.is-lit .hud-ico svg {
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--neon) 80%, transparent));
}

@media (max-width: 940px) {
  /* Barre verticale : le menu s'ouvre à côté, pas dessous — dessous se trouve le
     bouton suivant. Et il ne doit pas dépasser du bord droit de l'écran. */
  .hud-menu {
    top: 50%; left: calc(100% + 8px); transform: translateY(-50%);
    width: min(230px, calc(100vw - var(--hud-gutter) - 22px));
  }
  /* Un menu de quatre lignes fait plus de deux cents pixels : centré sur un
     bouton proche d'un bord, il sortirait de l'écran. On le laisse glisser. */
  .hud-menu { max-height: calc(100vh - 140px); overflow-y: auto; }
}

/* ─────────────────  la page de bilan sur un téléphone  ─────────────────────
   Elle a été dessinée en pleine largeur : un en-tête d'une seule ligne, des
   cartes à cent quatre-vingt-seize pixels de large minimum, des tableaux à
   plusieurs colonnes. Sur un écran de quatre cents pixels, l'en-tête se
   repliait n'importe comment, les cartes s'empilaient en une colonne
   interminable et les tableaux débordaient sans qu'on puisse les atteindre. */
@media (max-width: 700px) {
  /* En-tête sur deux rangs, et non replié au hasard : le titre et les deux
     boutons d'abord, les périodes ensuite sur toute la largeur. L'ordre
     d'affichage est imposé par `order`, ce qui évite de dépendre de l'ordre du
     document — les boutons y sont écrits après les onglets. */
  .st-top { flex-wrap: wrap; gap: 8px 10px; padding: 10px 14px; }
  .st-title { order: 1; }
  .st-btn { order: 1; }
  .st-tabs {
    order: 2; flex-basis: 100%;
    overflow-x: auto; scrollbar-width: none;
  }
  .st-tabs::-webkit-scrollbar { display: none; }
  .st-tabs button { flex: none; }

  .st-title h2 { font-size: 15px; }
  .st-title p { font-size: 9px; }

  /* Deux cartes par rang. À une seule, les huit chiffres de tête formaient une
     colonne qu'il fallait dérouler avant d'atteindre le premier graphique. */
  .st-cards {
    gap: 8px; margin-bottom: 18px;
    grid-template-columns: repeat(auto-fit, minmax(142px, 1fr));
  }
  .st-card { padding: 10px 11px; }
  .st-v { font-size: 21px; margin-top: 5px; }
  .st-k { font-size: 9px; }

  .st-body { padding: 14px 12px 32px; }
  .st-block { padding: 13px 13px; }

  /* Les tableaux gardent toutes leurs colonnes et défilent dans leur bloc. En
     masquer aurait été plus net à l'oeil, mais c'est retirer une donnée à qui
     vient la lire — un bilan n'a pas de colonne décorative. */
  .st-block { overflow-x: auto; }
  .st-tab { min-width: 330px; }

  .st-svg { height: 150px; }
  .st-svg + .st-svg { height: 70px; }
}

/* ──────────  « effort par appareil » replié en cartes sur téléphone  ────────
   Sept colonnes — appareil, modèle, largages, écopages, cadence, volume, part —
   ne tiennent pas sur quatre cents pixels, et les faire défiler latéralement
   revient à cacher la moitié d'un bilan derrière un geste qu'on ne devine pas.

   Chaque ligne se replie donc en carte. Le tableau reste un tableau : c'en est un,
   et le remplacer par des `div` aurait coûté sa structure aux lecteurs d'écran
   pour un simple besoin de mise en page. C'est la grille qui replie, en plaçant
   les sept cellules dans des zones nommées.

   Ce que la carte donne à lire, dans l'ordre : qui et combien — l'indicatif et le
   volume, les deux seules valeurs qu'on cherche d'abord — puis le modèle, puis la
   part en barre pleine largeur, puis les trois nombres de détail avec leur nom,
   l'en-tête du tableau ne pouvant plus les porter. */
@media (max-width: 700px) {
  /* la règle générale des tableaux ne s'applique plus à celui-ci */
  .st-air { min-width: 0; }
  .st-air, .st-air tbody { display: block; }
  .st-air thead { display: none; }

  .st-air tr {
    display: grid;
    grid-template-columns: auto auto auto 1fr;
    grid-template-areas:
      "qui    qui    qui    vol"
      "modele modele modele modele"
      "part   part   part   part"
      "larg   ecop   cad    .";
    gap: 3px 12px;
    padding: 11px 0 12px;
    border-bottom: 1px solid rgba(255,255,255,.055);
  }
  .st-air tbody tr:last-child { border-bottom: 0; }

  .st-air td { display: block; border: 0; padding: 0; }

  .st-air td:nth-child(1) {
    grid-area: qui;
    font-family: var(--font-mono); font-size: 12.5px; color: var(--paper);
  }
  .st-air td:nth-child(2) { grid-area: modele; font-size: 10.5px; }
  .st-air td:nth-child(3) { grid-area: larg; }
  .st-air td:nth-child(4) { grid-area: ecop; }
  .st-air td:nth-child(5) { grid-area: cad; }
  .st-air td:nth-child(6) {
    grid-area: vol; text-align: right;
    font-family: var(--font-mono); font-size: 13px; color: var(--ice-400);
  }
  .st-air td:nth-child(7) { grid-area: part; width: auto; margin: 3px 0 1px; }

  /* Les trois nombres de détail portent leur nom, l'en-tête ayant disparu. Le nom
     passe devant en petit : « 5 largages » se lit seul, « 5 » ne dit rien. */
  .st-air td[data-l] {
    font-family: var(--font-mono); font-size: 11px; text-align: left;
    color: var(--paper-dim); white-space: nowrap;
  }
  .st-air td[data-l]::after {
    content: ' ' attr(data-l);
    font-family: var(--font-ui); font-size: 9.5px; letter-spacing: .04em;
    color: var(--paper-mute);
  }

  /* Une seule ligne pour dire qu'il n'y a rien : elle ne se replie pas. */
  .st-air td.st-none { grid-area: qui / qui / part / part; text-align: left; }
}

/* ══════════════════  l'accent de couleur : un crochet d'angle  ══════════════
   Sept blocs portaient un filet de couleur sur leur bord gauche — cartes du
   bilan, encarts de réserve, alerte de foudre, rôle d'un appareil. C'est le
   dispositif le plus employé du web, et le seul élément de cette interface qui ne
   parlait pas sa langue : partout ailleurs, l'information tient à des filets d'un
   pixel, des micro-libellés en capitales mono et des halos de néon.

   Le crochet d'angle dit la même chose autrement : deux filets qui marquent un
   coin, comme une croix de repère sur un plan ou un coin de viseur. Il appartient
   au vocabulaire d'un tableau de bord, il ne coûte qu'un pseudo-élément, et il
   laisse la bordure du bloc intacte — là où le filet gauche la remplaçait sur un
   côté, ce qui déséquilibrait le cadre.

   La sémantique de couleur ne change pas : braise pour le feu, glace pour la
   lutte aérienne, violet pour la foudre. Elle passe par une seule variable, ce
   qui permet d'accentuer un bloc sans écrire de règle.

   Sur les cartes du bilan, le micro-libellé prend en plus la teinte : c'est lui
   qui nomme le chiffre, c'est donc sur lui que la couleur travaille le mieux. */

/* Le crochet a besoin d'un ancêtre positionné. `.vid-note` en est un déjà — elle
   est en `absolute` sur le cadre du lecteur — et **ne doit pas figurer ici** : la
   déclaration l'aurait ramenée dans le flux, en pleine largeur, où ses décalages
   `left` et `right` ne servent plus qu'à la pousser hors du cadre par la droite.
   C'est ce qui la faisait toucher le bord de la vidéo. */
.st-card, .layers-warn, .det-role, .field-warn, .alert, .notice-strong {
  position: relative;
}

.st-card::before, .layers-warn::before, .det-role::before, .field-warn::before,
.alert::before, .vid-note::before, .notice-strong::before {
  content: '';
  position: absolute; top: 0; left: 0;
  width: 9px; height: 9px;
  border-top: 1.5px solid var(--accent, var(--ink-400));
  border-left: 1.5px solid var(--accent, var(--ink-400));
  /* le crochet suit l'arrondi du bloc plutôt que de le couper au carré */
  border-top-left-radius: inherit;
  pointer-events: none;
}

/* Ces cinq encarts ne reçoivent pas de cadre.
 *
 *  Un premier essai leur en donnait un, au motif qu'un crochet sur un bloc sans
 *  bordure paraîtrait posé dans le vide. C'était mal regarder : ils portent tous
 *  déjà un fond teinté, qui les détache assez du panneau. Le cadre ajouté n'y
 *  apportait qu'un trait de plus, et sur la note posée par-dessus une vidéo il
 *  refermait un rectangle là où l'on cherchait une marque discrète. Le crochet
 *  suffit à dire l'accent, le fond suffit à dire le bloc. */
.layers-warn, .det-role, .field-warn, .notice-strong { border-radius: var(--r-sm); }

.st-card.t-em  { --accent: var(--ember-400); }
.st-card.t-ic  { --accent: var(--ice-400); }
.st-card.t-bo  { --accent: var(--bolt); }
.st-card.t-ne  { --accent: var(--paper-mute); }
.layers-warn   { --accent: var(--ice-300); }
.det-role      { --accent: var(--ice-300); }
.field-warn    { --accent: var(--ac-coordination); }
.alert         { --accent: var(--ember-300); }
.vid-note      { --accent: var(--ember-400); }
.notice-strong { --accent: var(--ember-300); }

/* Le libellé de la carte prend la teinte de son accent. C'est là que la couleur
   sert : elle dit de quelle moitié de l'épisode le chiffre parle — le feu ou la
   lutte — avant même qu'on ait lu le mot. */
.st-card .st-k { color: var(--accent, var(--paper-mute)); opacity: .85; }

/* L'alerte de foudre garde un cadre ouvert : elle vit dans une liste, un cadre
   fermé par élément ferait une pile de boîtes. Le crochet suffit à la marquer. */
.alert::before { border-top-left-radius: 0; }

/* ──────────────────  bouton d'une infobulle punaisée  ───────────────────────
   L'infobulle reste transparente aux gestes : elle ne doit jamais intercepter ce
   qui est destiné à la carte, sous peine de rendre inatteignable ce qu'elle
   recouvre. Seul le bouton les reprend — même montage que les pastilles du fil de
   vidéos sous leur colonne inerte.

   Il n'apparaît que sur une infobulle punaisée, c'est-à-dire ouverte au clic. Au
   survol il serait hors d'atteinte : l'infobulle s'effacerait avant qu'on y
   arrive. */
.tip-act {
  -webkit-appearance: none; appearance: none;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; margin-top: 9px; padding: 7px 10px;
  border: 1px solid rgba(92,224,240,.4); border-radius: var(--r-sm);
  background: rgba(92,224,240,.1);
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .05em;
  text-transform: uppercase; color: var(--ice-400);
  cursor: pointer; pointer-events: auto;
  transition: background .18s var(--ease), border-color .18s var(--ease);
}
.tip-act:hover { background: rgba(92,224,240,.2); border-color: var(--ice-300); }
.tip-act:focus-visible { outline: 1px solid var(--ice-400); outline-offset: 2px; }

/* Punaisée, l'infobulle se distingue : elle attend une action au lieu de
   commenter un survol. Un filet un peu plus net y suffit. */
.tip.is-pinned { border-color: rgba(92,224,240,.35); }

@media (max-width: 940px) {
  /* Au doigt, la cible passe à quarante pixels de haut. */
  .tip-act { padding: 11px 10px; font-size: 11px; }
}
