/* ==========================================================================
   RADAR//X · NOYAU — feuille de style unique
   Bureau 1280–1920 px · tablette 768–1279 px · téléphone 390 px (Mini App Telegram)
   Mouvement : seules transform et opacity sont animées (plus grid-template-rows
   pour l'insertion du journal, et stroke-dashoffset pour deux petits tracés SVG).
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Variables (§8 du plan) — thème sombre uniquement, imposé aussi dans Telegram
   -------------------------------------------------------------------------- */
:root {
  color-scheme: dark;

  /* fonds */
  --fond: #050813;
  --scene: #060A18;
  --panneau: rgba(10, 16, 36, .78);
  --panneau-plein: #0A1126;
  --tuile: #0F1834;
  --selection: #16224A;

  /* lignes */
  --ligne: #1A2750;
  --ligne-2: #2A3C73;
  --bord: rgba(76, 125, 255, .16);
  --bord-fort: rgba(76, 125, 255, .32);
  --equerre: #3FE0FF;

  /* textes */
  --texte: #EAF0FF;
  --texte-2: #A9B6D9;
  --texte-3: #6E7DA8;
  --eteint: #46557F;

  /* anneaux ① à ⑤ */
  --a1: #E6EEFF;
  --a2: #5B8CFF;
  --a3: #3FE0FF;
  --a4: #FFD166;   /* or = ALERTE, et rien d'autre */
  --a5: #2BFFA3;

  /* matière du noyau */
  --violet: #7B5CFF;
  --magenta: #B64DFF;
  --or-matiere: #FFC24B;
  --flux-mort: #3A4660;
  --nebuleuse: #24307A;
  --treillis: #2C55B8;
  --poussiere: #5B4FC8;

  /* états */
  --gain: #2BFFA3;
  --attention: #FFB23F;
  --danger: #FF4D6A;
  --refuse: #4A5878;
  --inconnu: #A9B6D9;
  --telegram: #2AABEE;
  --migre: #4FF0D2;
  --hype: #FF6BD5;

  /* agents */
  --ag-chef: #FFF1C9;
  --ag-guetteur: #8FB8FF;
  --ag-ecran: #5B8CFF;
  --ag-hypes: #FF6BD5;
  --ag-risque: #FF5470;
  --ag-x: #E8ECF4;
  --ag-surveillant: #FF9F43;
  --ag-bilan: #2EE6A6;
  --ag-radar: #6B7A99;
  --ag-telegram: #2AABEE;

  /* polices */
  --f-titre: "Space Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --f-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* courbes */
  --sortie: cubic-bezier(.2, .8, .2, 1);
  --expo: cubic-bezier(.16, 1, .3, 1);

  /* rayons : petits, pour que les équerres tombent sur les coins */
  --r-panneau: 6px;
  --r-scene: 8px;

  /* marges sûres : Telegram (plein écran) d'abord, sinon l'encoche de l'appareil */
  --inset-haut: calc(var(--tg-safe-area-inset-top, env(safe-area-inset-top, 0px)) + var(--tg-content-safe-area-inset-top, 0px));
  --inset-bas: calc(var(--tg-safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)) + var(--tg-content-safe-area-inset-bottom, 0px));
  --inset-g: var(--tg-safe-area-inset-left, env(safe-area-inset-left, 0px));
  --inset-d: var(--tg-safe-area-inset-right, env(safe-area-inset-right, 0px));
  --g-g: calc(16px + var(--inset-g));
  --g-d: calc(16px + var(--inset-d));
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

html {
  background: var(--fond);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  color: var(--texte);
  font: 400 13px/1.45 var(--f-titre);
  font-variant-numeric: tabular-nums slashed-zero;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}

/* décor de fond : lueur de nébuleuse + trame de points (fixe, jamais animé) */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(1100px 560px at 50% -12%, rgba(44, 85, 184, .17), transparent 62%),
    radial-gradient(800px 640px at 92% 108%, rgba(123, 92, 255, .08), transparent 60%),
    radial-gradient(700px 520px at 4% 70%, rgba(63, 224, 255, .035), transparent 60%),
    radial-gradient(rgba(76, 125, 255, .055) 1px, transparent 1.3px) 0 0 / 24px 24px;
}

/* cadre doré du moment ALERTE (body.flash-alerte, 2 pulsations en 1,6 s) */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  opacity: 0;
  box-shadow: inset 0 0 0 2px var(--a4), inset 0 0 60px rgba(255, 209, 102, .35);
}
body.flash-alerte::after { animation: flash-page 1.6s ease-in-out; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-appearance: none;
  appearance: none;
}
a { color: inherit; text-decoration: none; }
b, strong { font-weight: 600; }
code {
  font: 500 .95em var(--f-mono);
  white-space: nowrap;
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(127, 156, 217, .12);
  color: var(--texte);
}
::selection { background: var(--selection); color: var(--texte); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--a3); outline-offset: 2px; }

* { scrollbar-width: thin; scrollbar-color: #24336A transparent; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #1F2D5A; border-radius: 8px; border: 2px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background-color: #2A3C73; }

/* couleurs utilitaires (posées par app.js) */
.gain { color: var(--gain); }
.attention, .ambre { color: var(--attention); }
.danger { color: var(--danger); }
.inconnu { color: var(--inconnu); }
.refuse { color: var(--refuse); }
.vide { color: var(--texte-3); font: 400 12px/1.45 var(--f-mono); }

.sans-js {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 24px;
  z-index: 95;
  width: max-content;
  max-width: calc(100% - 32px);
  margin: 0 auto;
  padding: 10px 16px;
  border-radius: 10px;
  background: var(--panneau-plein);
  border: 1px solid var(--ligne-2);
  color: var(--texte-2);
  font: 500 12px/1.4 var(--f-mono);
}

/* --------------------------------------------------------------------------
   3. Grille de la page (bureau ≥ 1280 px, §10)
   -------------------------------------------------------------------------- */
.app {
  position: relative;
  z-index: 1;
  overflow-x: clip;
}
#tete { grid-area: tete; }
#kpis { grid-area: kpi; }
#equipage { grid-area: equipage; }
#scene { grid-area: scene; }
#journal { grid-area: journal; }
#reussite { grid-area: reussite; }
#alertes { grid-area: alertes; }
#entonnoir { grid-area: entonnoir; }
#hypes { grid-area: hypes; }
#frise { grid-area: frise; }
#pied { grid-column: 1 / -1; }

@media (min-width: 1280px) {
  .app {
    max-width: 1920px;
    margin: auto;
    padding: 16px 24px 32px;
    display: grid;
    gap: 16px;
    grid-template-columns: clamp(300px, 20vw, 384px) minmax(0, 1fr) clamp(340px, 22vw, 432px);
    grid-template-rows: 56px 88px clamp(560px, calc(100vh - 232px), 820px) 400px 112px;
    grid-template-areas:
      "tete tete tete"
      "kpi kpi kpi"
      "equipage scene journal"
      "reussite alertes entonnoir"
      "hypes frise frise";
  }
}

/* tablette et petit portable : deux colonnes */
@media (min-width: 768px) and (max-width: 1279.98px) {
  .app {
    padding: 16px 20px 28px;
    display: grid;
    gap: 14px;
    grid-template-columns: minmax(0, 1fr) clamp(280px, 34vw, 360px);
    grid-template-rows: 56px auto clamp(480px, 62vw, 640px) 340px 400px 460px 112px;
    grid-template-areas:
      "tete tete"
      "kpi kpi"
      "scene equipage"
      "alertes alertes"
      "entonnoir reussite"
      "journal journal"
      "frise hypes";
  }
}

/* --------------------------------------------------------------------------
   4. En-tête
   -------------------------------------------------------------------------- */
#tete {
  position: relative;
  display: flex;
  align-items: center;
  gap: 20px;
  min-width: 0;
  padding: 0 2px;
  overflow: hidden;
}
/* filet bas et reflet qui le parcourt lentement */
#tete::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--ligne-2) 18%, var(--ligne-2) 82%, transparent);
  opacity: .8;
}
#tete::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  z-index: 1;
  background: linear-gradient(90deg, transparent 0, rgba(63, 224, 255, .9) 7%, transparent 14%) no-repeat;
  animation: reflet 9s linear infinite;
  pointer-events: none;
}

#marque {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: none;
}
#logo-noyau { flex: none; display: block; overflow: visible; }
#logo-noyau .logo-orbite { transform-origin: 14px 14px; animation: tourne 14s linear infinite; }
#logo-noyau .logo-halo { transform-origin: 14px 14px; animation: respire 3.2s ease-in-out infinite; }
#titre {
  margin: 0;
  font: 700 18px/1 var(--f-titre);
  letter-spacing: .08em;
  color: var(--texte);
  white-space: nowrap;
}
#titre b {
  font-weight: 700;
  margin: 0 .03em;
  color: var(--a3);
  text-shadow: 0 0 14px rgba(63, 224, 255, .55);
}
#marque p {
  margin: 0 0 0 4px;
  padding-left: 12px;
  border-left: 1px solid var(--ligne-2);
  font: 400 11px/1.2 var(--f-mono);
  letter-spacing: .04em;
  color: var(--texte-3);
  white-space: nowrap;
}

#etats {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  min-width: 0;
}

/* pastilles d'état : .ok / .ko / .ambre / .attente */
.pastille {
  position: relative;
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 11px 0 23px;
  border-radius: 999px;
  border: 1px solid var(--ligne-2);
  background: rgba(10, 16, 36, .62);
  color: var(--texte-2);
  font: 700 10px/1 var(--f-mono);
  letter-spacing: .09em;
  text-transform: uppercase;
  white-space: nowrap;
  -webkit-user-select: none;
  user-select: none;
  --pt: var(--texte-3);
}
span.pastille { cursor: default; }
.pastille::before,
.pastille::after {
  content: "";
  position: absolute;
  left: 10px;
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--pt);
}
.pastille::before { box-shadow: 0 0 8px var(--pt); }
.pastille::after { opacity: 0; }
@media (hover: hover) {
  button.pastille:hover { border-color: rgba(63, 224, 255, .4); color: var(--texte); }
}
.pastille.attente { --pt: var(--texte-3); color: var(--texte-3); }
.pastille.attente::before { animation: veille 1.6s ease-in-out infinite; box-shadow: none; }
.pastille.ok { --pt: var(--gain); border-color: rgba(43, 255, 163, .28); color: var(--texte-2); }
.pastille.ok::before { animation: none; }
.pastille.ok::after { animation: onde 2s var(--sortie) infinite; }
.pastille.ambre {
  --pt: var(--attention);
  border-color: rgba(255, 178, 63, .45);
  background: rgba(255, 178, 63, .07);
  color: #FFC97A;
}
.pastille.ambre::before { animation: none; }
.pastille.ko {
  --pt: var(--danger);
  border-color: rgba(255, 77, 106, .55);
  background: rgba(255, 77, 106, .09);
  color: #FF9AAB;
  animation: secousse 300ms ease-in-out 1;
}
.pastille.ko::before { animation: none; }
#p-telegram.ok { --pt: var(--telegram); border-color: rgba(42, 171, 238, .36); }

#p-maj {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 4px;
  font: 400 11px/1 var(--f-mono);
  color: var(--texte-3);
  white-space: nowrap;
}
#p-maj b { font-weight: 500; color: var(--texte-2); }
.compte-a-rebours { display: block; flex: none; overflow: visible; }
.compte-a-rebours circle { fill: none; stroke-width: 2; }
.compte-a-rebours .car-fond { stroke: var(--ligne-2); }
/* se vide en 4 s ; app.js relance l'animation à chaque réponse */
.compte-a-rebours .car-arc {
  stroke: var(--a3);
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 0;
  transform: rotate(-90deg);
  transform-origin: 8px 8px;
  animation: car-vide 4s linear forwards;
}
body.fige .compte-a-rebours .car-arc { stroke: var(--attention); }
body.fige #p-maj b { color: var(--attention); }

#horloge-bloc {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  flex: none;
  padding-left: 18px;
  border-left: 1px solid var(--ligne);
}
#horloge {
  display: block;
  font: 500 22px/1 var(--f-mono);
  letter-spacing: .02em;
  color: var(--texte);
}
/* deux-points qui clignotent à 1 Hz : app.js peut les envelopper dans <i> */
#horloge i, #horloge .dp { font-style: normal; animation: deux-points 1s steps(1) infinite; }
#date {
  font: 400 11px/1 var(--f-mono);
  color: var(--texte-3);
  letter-spacing: .03em;
}

/* --------------------------------------------------------------------------
   5. Panneaux (style commun, §7)
   -------------------------------------------------------------------------- */
.panneau {
  position: relative;
  isolation: isolate;
  min-width: 0;
  min-height: 0;
  padding: 14px;
  border-radius: var(--r-panneau);
  background: var(--panneau);
  border: 1px solid var(--bord);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .04);
}
/* bordure renforcée au survol (fondu d'opacité, 150 ms) */
.panneau::before {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: 4;
  border-radius: inherit;
  border: 1px solid var(--bord-fort);
  opacity: 0;
  pointer-events: none;
  transition: opacity 150ms ease;
}
/* équerres d'angle de 10 px, 1 px, cyan à 40 %, qui s'allument au survol (posées sur la bordure) */
.panneau::after {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: 4;
  pointer-events: none;
  opacity: .4;
  transition: opacity 150ms ease;
  background:
    linear-gradient(var(--equerre), var(--equerre)) left top / 10px 1px,
    linear-gradient(var(--equerre), var(--equerre)) left top / 1px 10px,
    linear-gradient(var(--equerre), var(--equerre)) right top / 10px 1px,
    linear-gradient(var(--equerre), var(--equerre)) right top / 1px 10px,
    linear-gradient(var(--equerre), var(--equerre)) left bottom / 10px 1px,
    linear-gradient(var(--equerre), var(--equerre)) left bottom / 1px 10px,
    linear-gradient(var(--equerre), var(--equerre)) right bottom / 10px 1px,
    linear-gradient(var(--equerre), var(--equerre)) right bottom / 1px 10px;
  background-repeat: no-repeat;
}
@media (hover: hover) {
  .panneau:hover::before,
  .panneau:hover::after { opacity: 1; }
}

.panneau > h2 {
  margin: 0 0 10px;
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
  font: 700 11px/1.2 var(--f-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--texte-3);
  white-space: nowrap;
}
.panneau > h2 .n { color: var(--n, var(--a3)); }
.panneau > h2 small {
  margin-left: auto;
  padding-left: 8px;
  overflow: hidden;
  text-overflow: ellipsis;
  font: 400 10.5px/1.2 var(--f-mono);
  letter-spacing: .03em;
  text-transform: none;
  color: var(--eteint);
}
#scene { --n: var(--a1); }
#equipage { --n: var(--a2); }
#journal { --n: var(--a3); }
#reussite { --n: var(--a5); }
#alertes { --n: var(--a4); }
#entonnoir { --n: var(--a3); }
#hypes { --n: var(--hype); }
#frise { --n: var(--a1); }

/* placeholders tant que app.js n'a rien écrit */
#journal-liste:empty::before,
#entonnoir-etapes:empty::before,
#alertes-cartes:empty::before {
  content: "connexion au radar…";
  display: block;
  padding: 14px;
  font: 400 11.5px/1.4 var(--f-mono);
  color: var(--eteint);
  animation: attente 1.6s ease-in-out infinite;
}
#entonnoir-etapes:empty::before { padding: 14px 0; }

/* --------------------------------------------------------------------------
   6. KPI (6 tuiles, odomètre, §7)
   -------------------------------------------------------------------------- */
#kpis {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 12px;
  min-width: 0;
}
#kpis:empty::before {
  content: "";
  grid-column: 1 / -1;
  height: 88px;
  border-radius: var(--r-panneau);
  border: 1px solid var(--bord);
  background: linear-gradient(90deg, rgba(15, 24, 52, .5), rgba(22, 34, 74, .75), rgba(15, 24, 52, .5));
  animation: attente 1.6s ease-in-out infinite;
}

.kpi {
  --c: var(--a2);
  position: relative;
  isolation: isolate;
  height: 88px;
  min-width: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "num label label"
    "val val spark"
    "sous sous sous";
  column-gap: 6px;
  align-items: center;
  padding: 11px 14px 9px;
  border-radius: var(--r-panneau);
  background: var(--panneau);
  border: 1px solid var(--bord);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .04);
  overflow: hidden;
  cursor: default;
  -webkit-user-select: none;
  user-select: none;
}
#kpi-nes { --c: var(--a1); }
#kpi-suivi { --c: var(--a2); }
#kpi-candidats { --c: var(--a3); }
#kpi-alertes { --c: var(--a4); }
#kpi-surveilles { --c: var(--ag-surveillant); }
#kpi-pic { --c: var(--a5); }

/* bordure haute de 3 px dans la couleur de la tuile, à 60 % */
.kpi::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 3px;
  z-index: 1;
  background: var(--c);
  opacity: .6;
  box-shadow: 0 0 14px var(--c);
}
/* lueur douce venue du haut */
.kpi::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(120% 90% at 50% -10%, var(--c), transparent 62%);
  opacity: .055;
  transition: opacity 250ms ease;
  pointer-events: none;
}
@media (hover: hover) {
  .kpi:hover { border-color: var(--bord-fort); }
  .kpi:hover::after { opacity: .12; }
}
.kpi.brille::before { animation: kpi-brille 400ms ease-out; }
.kpi.brille::after { animation: kpi-lueur 400ms ease-out; }
.kpi.rebond,
body.flash-alerte #kpi-alertes { animation: rebond 560ms var(--sortie); }

.kpi-num {
  grid-area: num;
  font: 700 10px/1 var(--f-mono);
  color: var(--c);
}
.kpi-label {
  grid-area: label;
  margin: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 600 11px/1.2 var(--f-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--texte-3);
}
.kpi-valeur {
  grid-area: val;
  min-width: 0;
  align-self: center;
  font: 600 34px/1.1 var(--f-titre);
  letter-spacing: -.01em;
  color: var(--texte);
  white-space: nowrap;
  transition: opacity 600ms ease;
}
.kpi-valeur small {
  margin-left: .12em;
  font-size: .5em;
  font-weight: 500;
  color: var(--texte-3);
  letter-spacing: 0;
}
#kpi-alertes .kpi-valeur { color: var(--a4); text-shadow: 0 0 22px rgba(255, 209, 102, .25); }
#kpi-pic .kpi-valeur { color: var(--texte); }
.kpi-sous {
  grid-area: sous;
  margin: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 500 12px/1.25 var(--f-titre);
  color: var(--texte-3);
}
.kpi-sous.danger { color: var(--danger); }
.kpi-sous.ambre { color: var(--attention); }
.kpi-spark {
  grid-area: spark;
  align-self: end;
  width: 120px;
  height: 28px;
  display: block;
  overflow: visible;
}
.kpi-spark :is(polyline, path, line):not([stroke]) {
  fill: none;
  stroke: var(--c);
  stroke-width: 1.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.kpi-spark :is(polyline, path, line, circle) { vector-effect: non-scaling-stroke; }
.kpi-spark circle:not([fill]) { fill: var(--c); }
.kpi-spark circle:last-of-type {
  transform-box: fill-box;
  transform-origin: center;
  animation: point-spark 1.6s ease-in-out infinite;
}
.kpi-badge {
  position: absolute;
  right: 12px;
  top: 12px;
  z-index: 2;
  font: 700 11px/1 var(--f-mono);
  color: var(--c);
  opacity: 0;
  pointer-events: none;
}
.kpi-badge.monte { animation: badge-monte 900ms var(--sortie) forwards; }

/* 8 crans des alertes du jour */
.crans {
  grid-area: spark;
  align-self: center;
  display: flex;
  gap: 4px;
  padding-right: 2px;
}
.crans i {
  display: block;
  width: 7px;
  height: 16px;
  border-radius: 2px;
  transform: skewX(-14deg);
  background: rgba(255, 209, 102, .07);
  box-shadow: inset 0 0 0 1px rgba(255, 209, 102, .32);
}
.crans i.plein {
  background: var(--a4);
  box-shadow: 0 0 10px rgba(255, 209, 102, .45);
}

/* odomètre : chaque chiffre fait 1em de haut ; app.js décale .odo-chiffres
   de translateY(-n em) ou translateY(-n × 10 %) */
.odo {
  display: inline-flex;
  align-items: flex-start;
  height: 1em;
  line-height: 1;
  overflow: hidden;
  vertical-align: -.08em;
}
.odo-col {
  position: relative;
  display: inline-block;
  height: 1em;
  overflow: hidden;
}
.odo-chiffres {
  display: flex;
  flex-direction: column;
  transition: transform 900ms var(--expo);
}
body.ouverture .odo-chiffres { transition-duration: 1.2s; }
.odo-chiffres > span {
  display: block;
  height: 1em;
  line-height: 1em;
  text-align: center;
}
.odo-sep {
  display: inline-block;
  height: 1em;
  line-height: 1em;
  white-space: pre;
}

/* --------------------------------------------------------------------------
   7. Équipage (8 cartes d'agents, §5)
   -------------------------------------------------------------------------- */
#equipage {
  display: flex;
  flex-direction: column;
  padding: 12px 10px 10px;
}
#equipage > h2 { margin: 0 4px 8px; }
#agents-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
#agents-liste:empty::before {
  content: "";
  flex: 1;
  border-radius: 8px;
  background: repeating-linear-gradient(180deg, rgba(15, 24, 52, .55) 0 64px, transparent 64px 68px);
  animation: attente 1.6s ease-in-out infinite;
}

.agent {
  --c: var(--texte-3);
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  padding: 6px 10px 5px 14px;
  border-radius: 8px;
  background: rgba(15, 24, 52, .42);
  border: 1px solid rgba(76, 125, 255, .1);
  overflow: hidden;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
#agents-liste > .agent {
  flex: 1 1 0;
  min-height: 56px;
  container-type: size;
  container-name: agent;
}
#ag-chef, .agent[data-cle="chef"] { --c: var(--ag-chef); }
#ag-guetteur, .agent[data-cle="guetteur"] { --c: var(--ag-guetteur); }
#ag-ecran, .agent[data-cle="ecran"] { --c: var(--ag-ecran); }
#ag-hypes, .agent[data-cle="hypes"] { --c: var(--ag-hypes); }
#ag-risque, .agent[data-cle="risque"] { --c: var(--ag-risque); }
#ag-x, .agent[data-cle="x"] { --c: var(--ag-x); }
#ag-surveillant, .agent[data-cle="surveillant"] { --c: var(--ag-surveillant); }
#ag-bilan, .agent[data-cle="bilan"] { --c: var(--ag-bilan); }

/* barre gauche de 3 px dans la couleur de l'agent */
.agent::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--c);
  opacity: .85;
}
/* balayage de couleur quand l'agent agit (.balaye, 1,2 s) */
.agent::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(90deg, var(--c), transparent 75%);
  opacity: 0;
  pointer-events: none;
}
.agent.balaye::after { animation: balaye-carte 1.2s var(--sortie); }
@media (hover: hover) {
  .agent:hover { background: var(--tuile); border-color: rgba(76, 125, 255, .26); }
}
.agent:focus-visible { outline-offset: -2px; }

.agent-tete {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  height: 15px;
  flex: none;
}
.agent-point {
  position: relative;
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--c);
  box-shadow: 0 0 6px var(--c);
}
.agent-point::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--c);
  opacity: 0;
}
.agent-nom {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 600 13px/1 var(--f-titre);
  color: var(--texte);
}
.agent-badge {
  flex: none;
  padding: 3px 4px 2px;
  border-radius: 4px;
  border: 1px solid transparent;
  font: 700 9px/1 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--texte-2);
  background: rgba(169, 182, 217, .07);
}
.agent-tete > .tag { margin-left: auto; font-size: 9px; padding: 2px 4px; }
.agent-tete > .agent-age { margin-left: 6px; }
.agent-tete > :not(.tag) + .agent-age { margin-left: auto; }
.agent-age {
  flex: none;
  font: 400 10px/1 var(--f-mono);
  color: var(--texte-3);
  white-space: nowrap;
  transition: opacity 600ms ease;
}
.agent-role {
  margin: 0;
  flex: none;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 400 10.5px/1.15 var(--f-mono);
  color: var(--texte-3);
}
.agent-msg {
  margin: 0;
  min-height: 0;
  flex: 0 1 auto;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
  font: 400 11.5px/1.32 var(--f-mono);
  color: var(--texte-2);
}
.agent-extra {
  order: 3;
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font: 500 10.5px/1.1 var(--f-mono);
  color: var(--texte-3);
  white-space: nowrap;
  overflow: hidden;
}
.agent-extra.ambre { color: var(--attention); }
.jauge {
  position: relative;
  flex: 1 1 auto;
  min-width: 40px;
  height: 4px;
  border-radius: 2px;
  background: rgba(42, 60, 115, .55);
  overflow: hidden;
}
.jauge > i {
  display: block;
  height: 100%;
  width: var(--p, 100%);
  border-radius: inherit;
  transform-origin: left center;
  background: linear-gradient(90deg, var(--a2), var(--a3));
}
.jauge.ambre > i, .jauge.haut > i { background: var(--attention); }
.agent-frise {
  order: 4;
  display: block;
  flex: none;
  width: 100%;
  height: 10px;
  margin-top: auto;
  border-radius: 2px;
  background: rgba(5, 8, 19, .35);
}

/* états (data-etat posé par app.js) */
.agent[data-etat="travail"] { border-color: rgba(43, 255, 163, .16); }
.agent[data-etat="travail"]::before { opacity: 1; box-shadow: 0 0 12px var(--c); }
.agent[data-etat="travail"] .agent-point::after { animation: ping 1.2s var(--sortie) infinite; }
.agent[data-etat="travail"] .agent-badge {
  color: var(--gain);
  background: rgba(43, 255, 163, .14);
  border-color: rgba(43, 255, 163, .3);
}
.agent[data-etat="pret"] .agent-badge { color: var(--texte-2); }
.agent[data-etat="attente"] .agent-point { opacity: .45; box-shadow: none; }
.agent[data-etat="attente"] .agent-badge {
  color: var(--texte-3);
  background: transparent;
  border-color: rgba(110, 125, 168, .26);
}
.agent[data-etat="silencieux"] .agent-point {
  background: var(--attention);
  box-shadow: 0 0 8px var(--attention);
  animation: veille 2.4s ease-in-out infinite;
}
.agent[data-etat="silencieux"] .agent-badge {
  color: var(--attention);
  background: rgba(255, 178, 63, .12);
  border-color: rgba(255, 178, 63, .38);
  animation: veille 2.4s ease-in-out infinite;
}
.agent[data-etat="pause"] .agent-point {
  background: transparent;
  box-shadow: inset 0 0 0 1.5px var(--texte-3);
}
.agent[data-etat="pause"] .agent-badge {
  color: var(--texte-2);
  background: transparent;
  border: 1px dashed rgba(169, 182, 217, .55);
}
.agent[data-etat="pause"] .agent-msg { opacity: .6; }
.agent[data-etat="horsligne"] { opacity: .78; }
.agent[data-etat="horsligne"]::before { background: #4A5470; box-shadow: none; }
.agent[data-etat="horsligne"] .agent-point { background: #4A5470; box-shadow: none; }
.agent[data-etat="horsligne"] .agent-badge {
  color: var(--danger);
  background: rgba(255, 77, 106, .12);
  border-color: rgba(255, 77, 106, .42);
}

/* cartes basses (hauteur de la boîte de contenu), avec la ligne du rôle (12 px + 3) :
   rôle + deux lignes + frise = 77 px ; rôle + une ligne + frise = 62 px (≈ 1440 × 900) ;
   avec la jauge (Chef, Agent X) : la frise part d'abord, puis le rôle */
@container agent (max-height: 76px) {
  .agent-msg { -webkit-line-clamp: 1; }
}
@container agent (max-height: 90px) {
  .agent:has(> .agent-extra) .agent-msg { -webkit-line-clamp: 1; }
}
@container agent (max-height: 75.5px) {
  .agent:has(> .agent-extra) .agent-frise { display: none; }
}
@container agent (max-height: 60.5px) {
  .agent:has(> .agent-extra) .agent-role { display: none; }
  .agent-frise { display: none; }
}
@container agent (max-height: 50px) {
  .agent-role { display: none; }
}
/* carte étroite (colonne de 300 px) : le nom passe avant la puce du dernier tag */
@container agent (max-width: 300px) {
  .agent-tete > .tag { display: none; }
  .agent-tete > .agent-age { margin-left: auto; }
}

/* --------------------------------------------------------------------------
   8. Tags (journal, cartes, étiquettes) — §8 : texte, fond 14 %, bordure 35 %
   -------------------------------------------------------------------------- */
[data-tag="SCAN"]     { --t: #7F9CD9; --tf: rgba(127, 156, 217, .14); --tb: rgba(127, 156, 217, .35); }
[data-tag="HYPE"]     { --t: #FF6BD5; --tf: rgba(255, 107, 213, .14); --tb: rgba(255, 107, 213, .35); }
[data-tag="CANDIDAT"] { --t: #3FE0FF; --tf: rgba(63, 224, 255, .14);  --tb: rgba(63, 224, 255, .35); }
[data-tag="PISTE"]    { --t: #FFF1C9; --tf: rgba(255, 241, 201, .14); --tb: rgba(255, 241, 201, .35); }
[data-tag="RISQUE"]   { --t: #FF8A3D; --tf: rgba(255, 138, 61, .14);  --tb: rgba(255, 138, 61, .35); }
[data-tag="REJET"]    { --t: #8A93A8; --tf: rgba(138, 147, 168, .14); --tb: rgba(138, 147, 168, .35); }
[data-tag="DANGER"]   { --t: #FF5A36; --tf: rgba(255, 90, 54, .14);   --tb: rgba(255, 90, 54, .35); }
[data-tag="BILAN"]    { --t: #2EE6A6; --tf: rgba(46, 230, 166, .14);  --tb: rgba(46, 230, 166, .35); }
[data-tag="TELEGRAM"] { --t: #2AABEE; --tf: rgba(42, 171, 238, .14);  --tb: rgba(42, 171, 238, .35); }
[data-tag="SYSTEME"]  { --t: #6B7A99; --tf: rgba(107, 122, 153, .14); --tb: rgba(107, 122, 153, .35); }
[data-tag="MIGRE"],
[data-tag="MIGRÉ"]    { --t: #4FF0D2; --tf: rgba(79, 240, 210, .14);  --tb: rgba(79, 240, 210, .35); }
[data-tag="VETO"]     { --t: #FF3B5C; --tf: rgba(255, 59, 92, .22);   --tb: rgba(255, 59, 92, .5); }
[data-tag="ALERTE"]   { --t: #FFD166; --tf: rgba(255, 209, 102, .22); --tb: rgba(255, 209, 102, .5); }
[data-tag="ERREUR"]   { --t: #FFFFFF; --tf: #FF3B5C; --tb: #FF3B5C; --acc: #FF3B5C; }

.tag {
  position: relative;
  isolation: isolate;
  display: inline-block;
  flex: none;
  max-width: 100%;
  padding: 2px 6px;
  border-radius: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
  font: 700 10.5px/1.25 var(--f-mono);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--t, var(--texte-2));
  background: var(--tf, rgba(169, 182, 217, .1));
  box-shadow: inset 0 0 0 1px var(--tb, rgba(169, 182, 217, .3));
}
/* flash du fond à l'arrivée (45 % → 14 %) */
.tag::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--t, var(--texte-2));
  opacity: 0;
  pointer-events: none;
}
.ligne.neuve .tag::before,
.tag.neuve::before { animation: tag-flash 1.2s var(--sortie); }
.tag[data-tag="ERREUR"]::before { background: #FFFFFF; }

/* --------------------------------------------------------------------------
   9. Journal en direct (§7)
   -------------------------------------------------------------------------- */
#journal {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: 44px minmax(0, 1fr);
  padding: 0;
  overflow: visible;
}
#journal > h2 {
  margin: 0;
  padding: 0 0 0 14px;
  align-self: center;
  overflow: hidden;
}
#journal-filtre {
  align-self: center;
  margin-right: 10px;
  display: inline-flex;
  padding: 2px;
  gap: 2px;
  border-radius: 8px;
  border: 1px solid var(--ligne);
  background: rgba(5, 8, 19, .55);
}
#journal-filtre button {
  height: 24px;
  padding: 0 10px;
  border-radius: 6px;
  font: 700 10px/24px var(--f-mono);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--texte-3);
  white-space: nowrap;
}
@media (hover: hover) {
  #journal-filtre button:hover { color: var(--texte-2); }
}
#journal-filtre button[aria-pressed="true"] {
  color: var(--texte);
  background: var(--selection);
  box-shadow: inset 0 0 0 1px rgba(91, 140, 255, .35);
}
#journal-liste {
  grid-column: 1 / -1;
  grid-row: 2;
  list-style: none;
  margin: 0;
  padding: 0 0 8px;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  border-top: 1px solid var(--ligne);
  border-radius: 0 0 calc(var(--r-panneau) - 1px) calc(var(--r-panneau) - 1px);
  transition: opacity 600ms ease;
}
#journal-nouveaux {
  position: absolute;
  z-index: 3;
  top: 54px;
  left: 0;
  right: 0;
  width: max-content;
  margin-inline: auto;
  height: 26px;
  padding: 0 12px;
  border-radius: 999px;
  border: 1px solid rgba(63, 224, 255, .5);
  background: rgba(8, 13, 30, .95);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .45), 0 0 16px rgba(63, 224, 255, .18);
  font: 700 10.5px/24px var(--f-mono);
  letter-spacing: .05em;
  color: var(--a3);
  animation: descend 320ms var(--sortie);
}

/* une ligne : heure | tag | point de l'agent | message | répétition */
.ligne {
  --acc: var(--t, var(--texte-3));
  position: relative;
  display: grid;
  grid-template-columns: 52px 64px minmax(0, 1fr) auto;
  grid-template-rows: 1fr;
  column-gap: 6px;
  align-items: start;
  padding: 5px 12px 5px 15px;
  border-bottom: 1px solid rgba(26, 39, 80, .55);
  overflow: hidden;
}
.ligne > * { min-height: 0; min-width: 0; }
.ligne[data-tag="ERREUR"] { --acc: #FF3B5C; }
@media (hover: hover) {
  .ligne:hover { background-color: rgba(15, 24, 52, .75); }
}
.ligne-h {
  font: 400 11px/18px var(--f-mono);
  color: var(--eteint);
  white-space: nowrap;
}
.ligne > .tag { justify-self: start; max-width: 64px; margin-top: 1px; padding: 2px 5px; letter-spacing: 0; }
.ligne-point {
  position: absolute;
  left: 5px;
  top: 11px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--c, var(--c-ag, var(--ag-radar)));
  box-shadow: 0 0 6px var(--c, var(--c-ag, transparent));
}
.ligne[data-agent="chef"] { --c-ag: var(--ag-chef); }
.ligne[data-agent="guetteur"] { --c-ag: var(--ag-guetteur); }
.ligne[data-agent="ecran"] { --c-ag: var(--ag-ecran); }
.ligne[data-agent="hypes"] { --c-ag: var(--ag-hypes); }
.ligne[data-agent="risque"] { --c-ag: var(--ag-risque); }
.ligne[data-agent="x"] { --c-ag: var(--ag-x); }
.ligne[data-agent="surveillant"] { --c-ag: var(--ag-surveillant); }
.ligne[data-agent="bilan"] { --c-ag: var(--ag-bilan); }
.ligne[data-agent="telegram"] { --c-ag: var(--ag-telegram); }
.ligne-msg {
  margin: 0;
  font: 400 12.5px/1.45 var(--f-mono);
  color: var(--texte-2);
  overflow-wrap: anywhere;
}
.ligne-msg b, .ligne-msg strong { color: var(--texte); font-weight: 500; }
.ligne-rep {
  align-self: start;
  margin-top: 1px;
  padding: 0 5px;
  border-radius: 4px;
  background: rgba(127, 156, 217, .13);
  font: 700 10px/16px var(--f-mono);
  color: var(--texte-2);
  white-space: nowrap;
  animation: pop 420ms var(--sortie);
}

/* insertion : la ligne s'ouvre (0fr → 1fr, 220 ms) puis glisse (−6 → 0, 180 ms) */
.ligne.neuve {
  animation:
    ligne-ouvre 220ms var(--sortie) both,
    ligne-glisse 180ms 180ms var(--sortie) backwards;
}

/* routine : atténuée, une seule ligne */
.ligne.routine { padding-block: 3px; }
.ligne.routine .ligne-point { top: 9px; }
.ligne.routine .ligne-h { color: #39466C; }
.ligne.routine .tag { opacity: .7; }
.ligne.routine .ligne-msg {
  color: var(--texte-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ligne.routine .ligne-point { box-shadow: none; opacity: .6; }

/* décisions : texte plein */
.ligne.decision .ligne-msg { color: var(--texte); }
.ligne.decision .ligne-h { color: var(--texte-3); }

/* ALERTE, VETO, DANGER : barre gauche de 2 px, teinte, balayage à l'arrivée */
.ligne:is([data-tag="ALERTE"], [data-tag="VETO"], [data-tag="DANGER"], [data-tag="ERREUR"])::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--acc);
  box-shadow: 0 0 10px var(--acc);
}
.ligne[data-tag="ALERTE"] { background-image: linear-gradient(90deg, rgba(255, 209, 102, .09), transparent 58%); }
.ligne[data-tag="VETO"]   { background-image: linear-gradient(90deg, rgba(255, 59, 92, .1), transparent 58%); }
.ligne[data-tag="DANGER"] { background-image: linear-gradient(90deg, rgba(255, 90, 54, .1), transparent 58%); }
.ligne[data-tag="ERREUR"] { background-image: linear-gradient(90deg, rgba(255, 59, 92, .12), transparent 58%); }
.ligne:is([data-tag="ALERTE"], [data-tag="VETO"], [data-tag="DANGER"])::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, var(--tf), transparent);
  transform: translateX(-100%);
  opacity: 0;
  pointer-events: none;
}
.ligne.neuve:is([data-tag="ALERTE"], [data-tag="VETO"], [data-tag="DANGER"])::after {
  animation: balayage 900ms 120ms var(--sortie);
}
.ligne:is([data-tag="ALERTE"], [data-tag="VETO"], [data-tag="DANGER"]) .ligne-msg { color: var(--texte); }
/* DANGER tremble 3 fois de 2 px */
.ligne.neuve[data-tag="DANGER"] {
  animation:
    ligne-ouvre 220ms var(--sortie) both,
    tremble 380ms 220ms ease-in-out;
}
/* mise à jour sur place d'une ligne de routine (« ×5 ») */
.ligne.flash::after,
.ligne.maj::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--tf, rgba(127, 156, 217, .14));
  opacity: 0;
  pointer-events: none;
  animation: flash-ligne 900ms ease-out;
}

/* --------------------------------------------------------------------------
   10. La scène et son HUD (§3, §6, §10)
   -------------------------------------------------------------------------- */
#scene {
  position: relative;
  z-index: 2;
  isolation: isolate;
  padding: 0;
  border-radius: var(--r-scene);
  background: var(--scene);
  touch-action: pan-y;
  min-height: 0;
}
#scene-canvas {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: calc(var(--r-scene) - 1px);
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
  transition: opacity 600ms ease;
}
#scene-canvas:active { cursor: grabbing; }
#scene-canvas canvas {
  display: block;
  width: 100%;
  height: 100%;
  outline: none;
  touch-action: pan-y;
}
.calque { position: absolute; inset: 0; pointer-events: none; }
#scene-fils {
  z-index: 1;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: calc(var(--r-scene) - 1px);
  transition: opacity 240ms ease;
}
#scene-fils line { vector-effect: non-scaling-stroke; }
#scene-fils line:not([stroke]) { stroke: rgba(234, 240, 255, .42); }
#scene-fils line:not([stroke-width]) { stroke-width: 1; }
#scene-etiquettes {
  z-index: 2;
  overflow: hidden;
  border-radius: calc(var(--r-scene) - 1px);
  font: 600 10.5px/1 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--texte);
  transition: opacity 240ms ease;
}
body.etiquettes-off #scene-etiquettes,
body.etiquettes-off #scene-fils { opacity: 0; }

/* étiquettes des scènes : noyau3d.js (.n3-et, .n3-agent, .n3-num, .n3-tok, .n3-tampon,
   .n3-nais, .n3-hype, .n3-vignette) et noyau2d.js (.n2-et, .n2-ag, .n2-num, .n2-tok)
   posent elles-mêmes transform et opacity en ligne et injectent leur habillage
   (§5 du plan). Ici : le socle commun, sans rien imposer à leur dessin. */
#scene-etiquettes > :not(style) {
  position: absolute;
  left: 0;
  top: 0;
  white-space: nowrap;
  pointer-events: none;
}
/* tokens, gagnants manqués, naissance, tampon du Bilan, hypes : casse d'origine
   (« PUMP ×20 · quota »), comme dans la vue 2D ; seuls les agents sont en capitales */
#scene-etiquettes :is(.n3-tok, .n3-nais, .n3-tampon, .n3-hype) {
  text-transform: none;
  letter-spacing: .02em;
}
#scene-etiquettes .n3-num { letter-spacing: 0; }

/* HUD */
#scene-hud {
  z-index: 3;
  overflow: hidden;
  border-radius: calc(var(--r-scene) - 1px);
  /* vignette douce pour détacher le noyau et lire le HUD */
  background: radial-gradient(ellipse 75% 70% at 50% 46%, transparent 58%, rgba(6, 10, 24, .5) 100%);
}
#scene-hud > * { pointer-events: none; }

.hud-gauche {
  position: absolute;
  left: 16px;
  top: 14px;
  max-width: min(46%, 340px);
  display: flex;
  flex-direction: column;
  gap: 7px;
}
#hud-titre {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  font: 700 11px/1.25 var(--f-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--texte-3);
  text-shadow: 0 1px 8px rgba(6, 10, 24, .9);
}
#hud-titre .n { color: var(--a1); }
#hud-debit {
  font: 700 13px/1 var(--f-mono);
  letter-spacing: .01em;
  text-transform: none;
  color: var(--or-matiere);
  text-shadow: 0 0 14px rgba(255, 194, 75, .35);
  white-space: nowrap;
}
#hud-titre .direct {
  position: relative;
  padding-left: 11px;
  font-weight: 400;
  letter-spacing: .04em;
  text-transform: none;
  color: var(--texte-3);
  white-space: nowrap;
}
#hud-titre .direct::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--a3);
  box-shadow: 0 0 8px var(--a3);
  animation: veille 2s ease-in-out infinite;
}
#hud-regle {
  margin: 0;
  max-width: 310px;
  font: 400 11px/1.45 var(--f-mono);
  color: var(--texte-2);
  text-shadow: 0 1px 8px rgba(6, 10, 24, .95);
  pointer-events: auto;
}
/* repliée après 3 visites : une ligne, dépliée au survol */
#hud-regle.replie {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  overflow: hidden;
  opacity: .6;
  transition: opacity 150ms ease;
}
@media (hover: hover) {
  #hud-regle.replie:hover { -webkit-line-clamp: unset; opacity: 1; }
}

.hud-droite {
  position: absolute;
  right: 14px;
  top: 14px;
  max-width: 52%;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}
#hud-boutons {
  display: flex;
  gap: 6px;
  pointer-events: auto;
}
#hud-boutons button {
  position: relative;
  height: 32px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 12px;
  border-radius: 8px;
  border: 1px solid var(--ligne-2);
  background: rgba(6, 10, 24, .68);
  color: var(--texte-2);
  font: 700 10.5px/1 var(--f-mono);
  letter-spacing: .07em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: transform 160ms var(--sortie);
}
@media (hover: hover) {
  #hud-boutons button:hover { color: var(--texte); border-color: rgba(63, 224, 255, .45); }
}
#hud-boutons button:active { transform: scale(.96); }
#hud-boutons .ico { font-size: 8.5px; line-height: 1; }
#hud-boutons #btn-visite {
  color: var(--a3);
  border-color: rgba(63, 224, 255, .55);
  background: rgba(63, 224, 255, .07);
  box-shadow: 0 0 18px rgba(63, 224, 255, .08);
}
#hud-boutons button[aria-pressed="true"] {
  color: var(--texte);
  background: rgba(91, 140, 255, .16);
  border-color: rgba(91, 140, 255, .5);
}
#hud-boutons #btn-pause[aria-pressed="true"] {
  color: var(--attention);
  background: rgba(255, 178, 63, .1);
  border-color: rgba(255, 178, 63, .55);
}
#hud-boutons #btn-visite[aria-pressed="true"] {
  color: var(--scene);
  background: var(--a3);
  border-color: var(--a3);
}

#hud-hypes {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px;
  pointer-events: auto;
}

/* puces des hypes (HUD et panneau 07) */
.hype-puce {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 10px 0 9px;
  border-radius: 999px;
  border: 1px solid rgba(255, 107, 213, .38);
  background: rgba(255, 107, 213, .1);
  color: var(--hype);
  font: 700 11px/1 var(--f-mono);
  letter-spacing: .02em;
  white-space: nowrap;
}
.hype-puce.neuve { animation: fondu 300ms ease-out; }
.hype-puce::before {
  content: "";
  flex: none;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--hype);
  box-shadow: 0 0 7px var(--hype);
}
.hype-puce small, .hype-puce span { font-weight: 400; color: rgba(255, 107, 213, .72); }
.hype-puce.vide,
#hud-hypes .vide {
  height: 24px;
  display: inline-flex;
  align-items: center;
  padding: 0 10px;
  border-radius: 999px;
  border: 1px dashed rgba(110, 125, 168, .42);
  background: rgba(6, 10, 24, .6);
  color: var(--texte-3);
  font: 400 10.5px/1 var(--f-mono);
}
.hype-puce.vide::before { display: none; }

.hud-centre {
  position: absolute;
  left: 50%;
  top: 14px;
  z-index: 2;
  width: min(360px, calc(100% - 32px));
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
#toast-zone {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
#toast-zone > * { pointer-events: auto; }

.toast {
  position: relative;
  overflow: hidden;
  display: grid;
  align-content: center;
  gap: 3px;
  min-height: 56px;
  padding: 9px 14px 11px 16px;
  border-radius: 10px;
  background: rgba(8, 13, 30, .95);
  border: 1px solid rgba(63, 224, 255, .38);
  box-shadow: 0 14px 36px rgba(0, 0, 0, .5);
  animation: toast-entre 320ms var(--sortie) both;
}
.toast::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--a3);
}
.toast.alerte {
  border-color: var(--a4);
  background: linear-gradient(180deg, rgba(40, 32, 12, .55), rgba(8, 13, 30, .96) 70%), rgba(8, 13, 30, .96);
  box-shadow: 0 14px 36px rgba(0, 0, 0, .55), 0 0 30px rgba(255, 209, 102, .28);
}
.toast.alerte::before { background: var(--a4); box-shadow: 0 0 12px var(--a4); }
.toast.sort { animation: toast-sort 240ms ease-in forwards; }
.toast-titre {
  font: 700 10.5px/1.2 var(--f-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--a3);
}
.toast.alerte .toast-titre { color: var(--a4); }
.toast-texte {
  font: 500 13px/1.35 var(--f-titre);
  color: var(--texte);
}
.toast-barre {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--a3);
  transform-origin: left center;
  animation: toast-barre 6s linear forwards;
}
.toast.alerte .toast-barre { background: var(--a4); box-shadow: 0 0 8px var(--a4); }
.toast-suite { display: block; margin-top: 4px; font: 400 10.5px/1.2 var(--f-mono); color: var(--texte-3); }

#depuis-carte {
  pointer-events: auto;
  position: relative;
  padding: 10px 14px 10px 17px;
  border-radius: 10px;
  background: rgba(8, 13, 30, .93);
  border: 1px solid rgba(230, 238, 255, .16);
  box-shadow: 0 12px 30px rgba(0, 0, 0, .45);
  font: 500 12.5px/1.45 var(--f-titre);
  color: var(--texte-2);
  animation: toast-entre 420ms var(--sortie) both;
}
#depuis-carte::before {
  content: "";
  position: absolute;
  left: 0;
  top: 10px;
  bottom: 10px;
  width: 3px;
  border-radius: 0 2px 2px 0;
  background: var(--a1);
  box-shadow: 0 0 10px rgba(230, 238, 255, .5);
}
#depuis-carte b, #depuis-carte strong { color: var(--texte); }

.hud-bas {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  padding-top: 22px;
  background: linear-gradient(180deg, transparent, rgba(6, 10, 24, .55) 38%, rgba(6, 10, 24, .9));
}
#narration {
  position: relative;
  height: 28px;
  margin: 0 16px;
  overflow: hidden;
  font: 400 13px/28px var(--f-titre);
  color: var(--texte);
  white-space: nowrap;
  text-overflow: ellipsis;
}
.narr {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 100%;
  min-width: 0;
  animation: fondu 300ms ease-out;
}
.narr.sort { position: absolute; inset: 0; animation: fondu-sortie 300ms ease-in forwards; }
.narr-point {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--c, var(--texte-2));
  box-shadow: 0 0 8px var(--c, transparent);
}
.narr-nom {
  flex: none;
  font: 700 11px/1 var(--f-mono);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--c, var(--texte-2));
}
.narr-texte {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 400 13px/1.2 var(--f-titre);
  color: var(--texte);
}
.narr-age {
  flex: none;
  font: 400 11px/1 var(--f-mono);
  color: var(--texte-3);
}

/* légende des étiquettes de la scène (sur téléphone : sous la scène) */
.legende {
  margin: -2px 16px 6px;
  font: 400 10.5px/1.3 var(--f-mono);
  color: var(--texte-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.legende .losange { color: var(--gain); }
/* vue statique de secours : pas d'étiquettes, donc pas de légende */
.app:has(#scene-secours:not([hidden])) .legende { display: none; }

/* barre d'étapes : ① Naissance 3 004 → ② Suivi 130 → … */
#etapes {
  list-style: none;
  margin: 0;
  height: 48px;
  padding: 0 12px;
  display: flex;
  align-items: center;
  gap: 18px;
  overflow: hidden;
  border-top: 1px solid rgba(42, 60, 115, .45);
  background: linear-gradient(180deg, rgba(6, 10, 24, 0), rgba(6, 10, 24, .9));
  pointer-events: auto;
}
.etape {
  --c: var(--texte-2);
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
  padding: 6px 4px;
  white-space: nowrap;
  cursor: default;
}
.etape[data-anneau="0"] { --c: var(--a1); }
.etape[data-anneau="1"] { --c: var(--a2); }
.etape[data-anneau="2"] { --c: var(--a3); }
.etape[data-anneau="3"] { --c: var(--a4); }
.etape[data-anneau="4"] { --c: var(--a5); }
.etape + .etape::before {
  content: "→";
  position: absolute;
  left: -14px;
  top: 50%;
  margin-top: -.55em;
  font: 400 12px/1.1 var(--f-mono);
  color: var(--eteint);
}
.etape::after {
  content: "";
  position: absolute;
  left: 4px;
  right: 4px;
  bottom: 0;
  height: 2px;
  border-radius: 1px;
  background: var(--c);
  box-shadow: 0 0 10px var(--c);
  transform: scaleX(0);
  transform-origin: left center;
  opacity: 0;
  transition: transform 250ms var(--sortie), opacity 250ms ease;
}
.etape.allumee::after { transform: none; opacity: 1; }
@media (hover: hover) {
  .etape:hover::after { transform: none; opacity: 1; }
  .etape:hover .etape-nom { color: var(--texte); }
}
.etape-num { font: 700 13px/1 var(--f-mono); color: var(--c); }
.etape-nom { font: 500 12px/1 var(--f-titre); color: var(--texte-2); }
.etape.allumee .etape-nom { color: var(--texte); }
.etape b { font: 700 12.5px/1 var(--f-mono); color: var(--texte); }

/* infobulle d'un token (coordonnées client : position fixe, app.js pose left/top) */
#infobulle {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 60;
  width: 260px;
  padding: 10px 12px 11px;
  border-radius: 10px;
  background: rgba(8, 13, 30, .97);
  border: 1px solid rgba(63, 224, 255, .32);
  box-shadow: 0 16px 40px rgba(0, 0, 0, .55), 0 0 22px rgba(63, 224, 255, .08);
  font: 400 11.5px/1.45 var(--f-mono);
  color: var(--texte-2);
  pointer-events: none;
  animation: fondu 160ms ease-out;
}
.ib-titre {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin: 0 0 6px;
  font: 600 15px/1.2 var(--f-titre);
  color: var(--texte);
}
.ib-titre :is(small, span) { font: 400 11px/1.2 var(--f-mono); color: var(--texte-3); }
.ib-ligne { display: flex; justify-content: space-between; gap: 10px; }
.ib-ligne b, .ib-ligne strong { font-weight: 500; color: var(--texte); }
ol.ariane {
  list-style: none;
  margin: 8px 0 0;
  padding: 8px 0 0;
  border-top: 1px solid var(--ligne);
  display: flex;
  flex-wrap: wrap;
  gap: 3px 0;
  font: 700 10.5px/1.35 var(--f-mono);
}
ol.ariane li { color: var(--texte-3); }
ol.ariane li.ok { color: var(--gain); }
ol.ariane li.ko { color: var(--danger); }
ol.ariane li.att { color: var(--texte-3); font-weight: 400; }
ol.ariane li + li::before { content: "›"; margin: 0 6px; color: var(--eteint); font-weight: 400; }

/* repli SVG statique si ni WebGL ni Canvas ne démarrent */
#scene-secours {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  padding: 56px 16px 92px;
  border-radius: calc(var(--r-scene) - 1px);
  overflow: hidden;
  background: radial-gradient(ellipse at 50% 46%, #0B1230, var(--scene) 70%);
}
#scene-secours svg { width: min(92%, 620px); height: auto; max-height: 92%; display: block; }
#scene-secours .secours-coeur { transform-origin: 260px 230px; animation: respire 3.6s ease-in-out infinite; }

/* données figées */
body.fige #scene-canvas { opacity: .45; }
body.fige :is(.kpi-valeur, .agent-age, #journal-liste) { opacity: .55; }
body.fige #scene-hud::after {
  content: "Données figées · le radar ne répond plus, nouvel essai automatique";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  width: max-content;
  max-width: calc(100% - 48px);
  margin-inline: auto;
  padding: 8px 14px;
  transform: translateY(-50%);
  border-radius: 999px;
  border: 1px solid rgba(255, 178, 63, .5);
  background: rgba(6, 10, 24, .88);
  color: var(--attention);
  font: 700 10.5px/1.35 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  text-align: center;
  animation: fondu 400ms ease-out;
}

/* lignes de rappel carte → satellite (bureau) */
#rappels {
  position: fixed;
  inset: 0;
  z-index: 30;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}
#rappels path.rappel { fill: none; transition: opacity 500ms ease; }
#rappels path.rappel:not([stroke]) { stroke: var(--c, var(--a3)); }
#rappels path.rappel:not([stroke-width]) { stroke-width: 1; }
#rappels path.rappel[pathLength="1"] {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: trace-rappel 300ms var(--sortie) forwards;
}
#rappels path.rappel:is(.efface, .sort) { opacity: 0; }
#rappels circle.paquet { filter: drop-shadow(0 0 3px rgba(234, 240, 255, .7)); transition: opacity 300ms ease; }
#rappels circle.paquet:not([fill]) { fill: var(--texte); }

/* --------------------------------------------------------------------------
   11. 04 · Résultats des alertes (§7)
   -------------------------------------------------------------------------- */
#reussite {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto auto auto minmax(0, 1fr);
  column-gap: 14px;
  align-items: center;
}
#reussite > h2 { grid-column: 1 / -1; grid-row: 1; }
#reussite > #verdict { grid-column: 1 / -1; grid-row: 2; margin: 0 0 10px; }
#reussite-anneau, #reussite-stats { grid-row: 3; }
#manques { grid-row: 4; }

/* verdict : ce qui marche, ce qui rate (aujourd'hui, puis 7 jours) */
.verdict {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 7px 10px 7px 12px;
  border-radius: 6px;
  background: rgba(15, 24, 52, .5);
  border-left: 2px solid var(--v, var(--texte-3));
  font: 400 11.5px/1.4 var(--f-titre);
  color: var(--texte-2);
}
.verdict:empty { display: none; }
.verdict[data-ton="danger"] { --v: var(--danger); }
.verdict[data-ton="gain"] { --v: var(--gain); }
.verdict b { color: var(--texte); font-weight: 600; }
.verdict b.danger { color: var(--danger); }
.verdict b.gain { color: var(--gain); }
#sous-scene { display: none; }                 /* téléphone seulement */
#reussite-anneau {
  display: block;
  width: 132px;
  height: 132px;
  overflow: visible;
  animation: fondu 600ms ease-out;
}
#reussite-anneau circle:not([fill]), #reussite-anneau path:not([fill]) { fill: none; }
#reussite-anneau text:not([fill]) { fill: var(--texte); }
#reussite-anneau text { font-family: var(--f-titre); font-variant-numeric: tabular-nums; }
#reussite-stats {
  margin: 0;
  min-width: 0;
  display: grid;
  gap: 3px;
  font: 400 11.5px/1.4 var(--f-mono);
  color: var(--texte-2);
}
#reussite-stats dt {
  margin-top: 5px;
  font: 700 9.5px/1.2 var(--f-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texte-3);
}
#reussite-stats dt:first-child { margin-top: 0; }
#reussite-stats dd { margin: 0; color: var(--texte); overflow-wrap: anywhere; }
#reussite-stats dd :is(.gain, .attention, .danger, .inconnu) { font-weight: 700; }
#manques {
  grid-column: 1 / -1;
  align-self: stretch;
  list-style: none;
  margin: 12px 0 0;
  padding: 10px 0 0;
  min-height: 0;
  overflow-y: auto;
  border-top: 1px solid var(--ligne);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
#manques > :not(.manque):not(.voir-tout):not(:has(.voir-tout)) {
  font: 700 10px/1.2 var(--f-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--texte-3);
}
li.manque {
  position: relative;
  padding-left: 18px;
  font: 400 11.5px/1.4 var(--f-mono);
  color: var(--texte-2);
}
body.ouverture li.manque, li.manque.neuve { animation: fondu 400ms ease-out backwards; }
/* losange vert creux : gagnant manqué */
li.manque::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 4px;
  width: 7px;
  height: 7px;
  border: 1.5px solid var(--gain);
  transform: rotate(45deg);
  box-shadow: 0 0 6px rgba(43, 255, 163, .45);
}
li.manque :is(b, strong) { font: 600 12px/1.4 var(--f-titre); color: var(--texte); }
li.manque :is(small, em, span) { font-style: normal; color: var(--texte-3); }
button.voir-tout {
  align-self: flex-start;
  padding: 4px 0;
  font: 700 10.5px/1.2 var(--f-mono);
  letter-spacing: .05em;
  color: var(--a3);
  border-bottom: 1px dotted rgba(63, 224, 255, .5);
}
@media (hover: hover) {
  button.voir-tout:hover { color: var(--texte); }
}

/* --------------------------------------------------------------------------
   12. 05 · Dernières alertes (tableau bureau, cartes téléphone)
   -------------------------------------------------------------------------- */
#alertes {
  display: flex;
  flex-direction: column;
  padding-bottom: 6px;
  container-type: inline-size;
  container-name: alertes;
}
.table-defile {
  flex: 1 1 auto;
  min-height: 0;
  margin: 0 -8px;
  overflow: auto;
  overscroll-behavior: contain;
}
#alertes-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font: 400 13px/1.25 var(--f-titre);
  color: var(--texte);
}
#alertes-table th {
  position: sticky;
  top: 0;
  z-index: 2;
  height: 30px;
  padding: 0 6px;
  text-align: left;
  white-space: nowrap;
  background: var(--panneau-plein);
  border-bottom: 1px solid var(--ligne);
  font: 700 9.5px/1 var(--f-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texte-3);
}
#alertes-table td {
  position: relative;
  height: 36px;
  padding: 0 6px;
  vertical-align: middle;
  white-space: nowrap;
  overflow: hidden;
  border-bottom: 1px solid rgba(26, 39, 80, .55);
}
#alertes-table tbody tr { cursor: default; }
@media (hover: hover) {
  #alertes-table tbody tr:hover td { background: rgba(22, 34, 74, .55); }
}
#alertes-table :is(th, td):first-child { padding-left: 8px; }
#alertes-table :is(th, td):last-child { padding-right: 8px; }

/* colonnes (§7) */
#alertes-table .c-heure { width: 56px; }
#alertes-table .c-token { min-width: 140px; max-width: 220px; }
#alertes-table .c-score { width: 70px; }
#alertes-table .c-mc { width: 72px; }
#alertes-table .c-pic { width: 90px; }
#alertes-table .c-now { width: 64px; }
#alertes-table .c-etat { width: 120px; }
#alertes-table .c-avert { width: 28px; text-align: center; }
#alertes-table .c-lien { width: 28px; text-align: center; }

.c-heure { font: 400 11.5px/1.2 var(--f-mono); color: var(--texte-2); }
.c-token { overflow: hidden; text-overflow: ellipsis; line-height: 1.15; }
.c-token :is(b, strong) { font: 600 14px/1.1 var(--f-titre); color: var(--texte); margin-right: 5px; }
.c-token small { font: 400 11px/1.1 var(--f-titre); color: var(--texte-3); }
.c-token :is(span, em, .meta) { font: 400 10px/1.2 var(--f-mono); font-style: normal; color: var(--texte-3); }
.c-token :is(.meta, div) { display: block; overflow: hidden; text-overflow: ellipsis; }
.c-token button {
  margin-left: 4px;
  width: 20px;
  height: 20px;
  border-radius: 5px;
  vertical-align: middle;
  color: var(--texte-3);
  font: 400 12px/20px var(--f-mono);
  text-align: center;
  transition: opacity 150ms ease;
}
@media (hover: hover) {
  #alertes-table .c-token button { opacity: 0; }
  #alertes-table tr:hover .c-token button { opacity: 1; }
  .c-token button:hover { color: var(--a3); background: rgba(63, 224, 255, .1); }
}
.c-score, .c-pic, .c-mc, .c-now, .c-avert { font: 500 12px/1 var(--f-mono); }
.c-mc { color: var(--texte-2); }
.c-now { font-weight: 700; font-size: 13px; }
.c-avert { color: var(--attention); }
.c-lien a {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  border: 1px solid var(--ligne-2);
  color: var(--texte-3);
  font: 400 12px/1 var(--f-mono);
}
@media (hover: hover) {
  .c-lien a:hover { color: var(--a3); border-color: rgba(63, 224, 255, .5); }
}
.c-etat .badge + .badge { margin-left: 4px; }

/* barres (score, pic) */
.barre {
  position: relative;
  display: inline-block;
  vertical-align: middle;
  width: 40px;
  height: 4px;
  margin-right: 6px;
  border-radius: 2px;
  background: rgba(42, 60, 115, .55);
  overflow: hidden;
}
.barre > i {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 100%;
  border-radius: inherit;
  transform-origin: left center;
  background: linear-gradient(90deg, rgba(255, 209, 102, .45), var(--a4));
}
body.ouverture .barre > i,
.neuve .barre > i { animation: barre-entre 800ms var(--sortie) backwards; }
.c-pic .barre > i { background: rgba(234, 240, 255, .55); }
.barre > i + i { background: var(--c, var(--texte)); opacity: .9; }

/* badges d'état */
.badge {
  display: inline-block;
  padding: 3px 6px 2px;
  border-radius: 4px;
  font: 700 9.5px/1 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--texte-2);
  background: rgba(169, 182, 217, .1);
  box-shadow: inset 0 0 0 1px rgba(169, 182, 217, .28);
}
.badge.chute {
  color: var(--danger);
  background: rgba(255, 77, 106, .13);
  box-shadow: inset 0 0 0 1px rgba(255, 77, 106, .4);
}
.badge.chute.neuve,
.neuve .badge.chute { animation: pulse-chute 700ms ease-in-out 2; }
.badge.dev {
  color: #FFFFFF;
  background: rgba(255, 77, 106, .82);
  box-shadow: 0 0 10px rgba(255, 77, 106, .35);
}
.badge.migre {
  color: var(--migre);
  background: rgba(79, 240, 210, .12);
  box-shadow: inset 0 0 0 1px rgba(79, 240, 210, .4);
}
.badge.fin {
  color: var(--texte-3);
  background: transparent;
  box-shadow: inset 0 0 0 1px rgba(110, 125, 168, .35);
}

/* nouvelle alerte : arrive par le haut, balayage doré de 1,5 s colonne par colonne */
#alertes-table tr.neuve td { animation: entre-haut 420ms var(--sortie) backwards; }
#alertes-table tr.neuve td:first-child { box-shadow: inset 2px 0 0 var(--a4); }
#alertes-table td::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 209, 102, .24), transparent);
  transform: translateX(-100%);
  opacity: 0;
  pointer-events: none;
}
#alertes-table tr.neuve td::after {
  animation: balayage 640ms var(--sortie);
  animation-delay: calc(var(--col, 0) * 95ms);
}
.c-heure { --col: 0; }
.c-token { --col: 1; }
.c-score { --col: 2; }
.c-mc { --col: 3; }
.c-pic { --col: 4; }
.c-now { --col: 5; }
.c-etat { --col: 6; }
.c-avert { --col: 7; }
.c-lien { --col: 8; }

/* colonne centrale étroite : on retire les colonnes secondaires, MC d'abord (≈ 1440 px), puis ⚠ ;
   le lien DexScreener (↗) reste toujours visible */
@container alertes (max-width: 780px) {
  #alertes-table .c-mc { display: none; }
}
@container alertes (max-width: 660px) {
  #alertes-table .c-avert { display: none; }
}
@container alertes (max-width: 560px) {
  #alertes-table .c-etat { width: 96px; }
  #alertes-table .c-pic { width: 76px; }
  #alertes-table .c-score .barre { width: 30px; }
}

/* cartes (téléphone) */
#alertes-cartes { display: none; }
/* si app.js n'a rempli que les cartes (pointeur tactile en paysage…), on les montre */
#alertes:has(#alertes-table tbody:empty) #alertes-cartes:not(:empty) { display: flex; flex-direction: column; gap: 8px; }
#alertes:has(#alertes-table tbody:empty):has(#alertes-cartes:not(:empty)) .table-defile { display: none; }
.carte-alerte {
  --c: var(--a4);
  position: relative;
  isolation: isolate;
  min-height: 72px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px 10px;
  padding: 10px 12px 10px 15px;
  border-radius: 10px;
  background: rgba(15, 24, 52, .55);
  border: 1px solid rgba(76, 125, 255, .14);
  overflow: hidden;
  font: 400 12px/1.3 var(--f-mono);
  color: var(--texte-2);
}
.carte-alerte::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--c);
  opacity: .8;
}
.carte-alerte.neuve::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(90deg, transparent, rgba(255, 209, 102, .2), transparent);
  transform: translateX(-100%);
  animation: balayage 1.5s var(--sortie);
}
.carte-alerte.neuve { animation: entre-haut 420ms var(--sortie) backwards; }
.carte-alerte :is(b, strong) { font: 600 15px/1.15 var(--f-titre); color: var(--texte); }
.carte-alerte > * { order: 6; }
.carte-alerte .c-heure { order: 0; font-size: 11px; color: var(--texte-3); }
.carte-alerte .c-token { order: 1; flex: 1 1 52%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.carte-alerte .c-token :is(.meta, div) { margin-top: 2px; }
.carte-alerte .c-now { order: 2; margin-left: auto; font: 700 15px/1 var(--f-mono); white-space: nowrap; }
.carte-alerte .c-pic { order: 3; flex: 1 1 40%; min-width: 120px; display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--texte-2); }
.carte-alerte .c-pic .barre { flex: 1; width: auto; height: 5px; margin: 0; }
.carte-alerte .c-etat { order: 4; display: flex; flex-wrap: wrap; gap: 4px; }
.carte-alerte .c-etat .badge + .badge { margin-left: 0; }
.carte-alerte .c-lien { order: 5; }
.carte-alerte .c-lien a { width: 28px; height: 28px; }

/* --------------------------------------------------------------------------
   13. 06 · Entonnoir
   -------------------------------------------------------------------------- */
#entonnoir {
  display: flex;
  flex-direction: column;
}
#entonnoir-etapes {
  list-style: none;
  position: relative;
  margin: 0;
  padding: 0 0 0 16px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  flex: none;
}
/* rail du flux et 3 points qui circulent (un trajet ≈ 60 / débit s, --trajet) */
#entonnoir-etapes:not(:empty)::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 10px;
  bottom: 10px;
  width: 1px;
  background: linear-gradient(180deg, var(--a1), var(--a3) 62%, var(--a4));
  opacity: .32;
}
#entonnoir-etapes:not(:empty)::after {
  content: "";
  position: absolute;
  left: 3.5px;
  top: 0;
  width: 4px;
  height: 133.333%;
  background: radial-gradient(circle at 50% 50%, var(--a3) 0 1.5px, rgba(63, 224, 255, .35) 1.6px 2px, transparent 2.2px) 0 0 / 4px 25% repeat-y;
  animation: flux-points calc(var(--trajet, 2.9s) / 3) linear infinite;
  pointer-events: none;
}
.etage {
  --c: var(--a2);
  position: relative;
  display: grid;
  grid-template-columns: minmax(84px, 40%) minmax(0, 1fr) 54px;
  align-items: center;
  gap: 10px;
  height: 34px;
}
.etage:nth-child(1) { --c: var(--a1); }
.etage:nth-child(4) { --c: var(--a3); }
.etage:nth-child(5) { --c: var(--a2); }
.etage:nth-child(6) { --c: var(--a4); }
.etage + .etage { border-top: 1px solid rgba(26, 39, 80, .45); }
.etage-nom {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 500 12px/1.2 var(--f-titre);
  color: var(--texte-2);
}
.etage-barre {
  position: relative;
  height: 10px;
  border-radius: 3px;
  background: rgba(42, 60, 115, .3);
  overflow: hidden;
}
.etage-barre > i {
  display: block;
  height: 100%;
  width: 100%;
  border-radius: inherit;
  transform-origin: left center;
  background: var(--c);
  opacity: .9;
}
body.ouverture .etage-barre > i,
.etage.neuve .etage-barre > i { animation: barre-entre 800ms var(--sortie) backwards; }
.etage-n {
  font: 700 12.5px/1 var(--f-mono);
  color: var(--texte);
  text-align: right;
  white-space: nowrap;
}
/* part des nés : les barres sont compressées, le pourcentage donne l'ordre de grandeur */
.etage-n small { display: block; margin-top: 2px; font: 500 10.5px/1 var(--f-mono); color: var(--texte-3); }
/* sorties (sous-ensembles des nés) : grises, en pointillés, renvoi au disque de poussière */
.etage.sortie .etage-nom { padding-left: 14px; position: relative; color: var(--texte-3); }
.etage.sortie .etage-nom::before {
  content: "↳";
  position: absolute;
  left: 0;
  color: var(--eteint);
  font-family: var(--f-mono);
}
.etage.sortie .etage-nom::after {
  content: " ∴";
  color: var(--poussiere);
  font-family: var(--f-mono);
}
.etage.sortie .etage-barre {
  background: transparent;
  box-shadow: inset 0 0 0 1px rgba(110, 125, 168, .38);
}
.etage.sortie .etage-barre > i {
  background: repeating-linear-gradient(90deg, rgba(110, 125, 168, .6) 0 4px, transparent 4px 7px);
  opacity: 1;
}
.etage.sortie .etage-n { color: var(--texte-3); font-weight: 500; }

#rejets {
  list-style: none;
  margin: 8px 0 0;
  padding: 8px 0 0;
  border-top: 1px solid var(--ligne);
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-height: 0;
  overflow: hidden;
}
#rejets li {
  padding: 3px 7px;
  border-radius: 6px;
  background: rgba(74, 88, 120, .16);
  box-shadow: inset 0 0 0 1px rgba(74, 88, 120, .45);
  font: 500 11px/1.2 var(--f-mono);
  color: var(--texte-2);
}
body.ouverture #rejets li, #rejets li.neuve { animation: fondu 500ms ease-out backwards; }
#rejets li b { color: var(--texte); font-weight: 700; }

/* --------------------------------------------------------------------------
   14. 07 · Hypes · 08 · Frise · pied de page
   -------------------------------------------------------------------------- */
#hypes { display: flex; flex-direction: column; }
#hypes-liste {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 6px;
  min-height: 0;
  overflow-y: auto;
}
#hypes-liste .vide code { color: var(--hype); background: rgba(255, 107, 213, .1); }

#frise { display: flex; flex-direction: column; padding-bottom: 10px; }
#frise > h2 { margin-bottom: 6px; }
#frise-canvas {
  display: block;
  flex: 1 1 auto;
  width: 100%;
  height: 100%;
  min-height: 0;
}

#pied {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 6px 18px;
  padding: 12px 4px 0;
  border-top: 1px solid rgba(26, 39, 80, .7);
  font: 400 11px/1.5 var(--f-mono);
  color: var(--texte-3);
}
#pied::after {
  content: "Analyse seulement · le radar n'achète et ne vend jamais rien";
  color: var(--eteint);
}

#ancres { display: none; }
#toast-fixe { display: none; }                 /* téléphone seulement */

/* --------------------------------------------------------------------------
   15. Fiche du bas (#feuille) : fiche d'agent ou de token
   -------------------------------------------------------------------------- */
#feuille {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 80;
  max-height: 78vh;
  max-height: 78dvh;
  display: flex;
  flex-direction: column;
  padding-bottom: var(--inset-bas);
  border-radius: 16px 16px 0 0;
  background: var(--panneau-plein);
  border: 1px solid var(--ligne-2);
  border-bottom: 0;
  box-shadow: 0 -18px 50px rgba(0, 0, 0, .55);
  transform: translateY(104%);
  visibility: hidden;
  transition: transform 300ms var(--sortie), visibility 0s linear 300ms;
}
#feuille.ouverte {
  transform: none;
  visibility: visible;
  transition: transform 380ms var(--sortie);
  animation: feuille-entre 380ms var(--sortie);
  box-shadow: 0 -18px 50px rgba(0, 0, 0, .55), 0 0 0 100vmax rgba(2, 4, 10, .55);
}
.feuille-poignee {
  flex: none;
  display: grid;
  place-items: center;
  height: 26px;
  cursor: grab;
  touch-action: none;
}
.feuille-poignee::before {
  content: "";
  width: 40px;
  height: 4px;
  border-radius: 2px;
  background: var(--ligne-2);
}
.feuille-contenu {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 2px var(--g-d) 18px var(--g-g);
  font: 400 13px/1.45 var(--f-titre);
  color: var(--texte-2);
}
.feuille-contenu h3 {
  margin: 0 0 4px;
  display: flex;
  align-items: center;
  gap: 8px;
  font: 600 17px/1.2 var(--f-titre);
  color: var(--texte);
}
.feuille-contenu h4 {
  margin: 16px 0 6px;
  font: 700 10px/1.2 var(--f-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--texte-3);
}
.feuille-contenu p { margin: 0 0 10px; }
.feuille-contenu :is(ol, ul) { list-style: none; margin: 0; padding: 0; }
.feuille-contenu canvas { display: block; width: 100%; height: 12px; margin: 6px 0 12px; }
.feuille-contenu dl { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; margin: 0 0 10px; }
.feuille-contenu dt { font: 400 11px/1.4 var(--f-mono); color: var(--texte-3); }
.feuille-contenu dd { margin: 0; font: 500 12px/1.4 var(--f-mono); color: var(--texte); }
.feuille-contenu .ligne { padding-inline: 0; }
.feuille-contenu button:not(.voir-tout) {
  min-height: 40px;
  padding: 0 16px;
  border-radius: 10px;
  border: 1px solid var(--ligne-2);
  background: rgba(15, 24, 52, .7);
  color: var(--texte);
  font: 700 11px/1 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   16. Ouverture (3,6 s) : panneaux qui montent un à un (60 ms d'écart)
   -------------------------------------------------------------------------- */
#tete { --rang: 0; }
#kpis { --rang: 1; }
#scene { --rang: 2; }
#equipage { --rang: 3; }
#journal { --rang: 3; }
#reussite { --rang: 4; }
#alertes { --rang: 5; }
#entonnoir { --rang: 6; }
#hypes { --rang: 7; }
#frise { --rang: 8; }
#pied { --rang: 9; }
body.ouverture :is(#tete, .panneau, #pied) {
  animation: monte 480ms var(--sortie) backwards;
  animation-delay: calc(var(--rang, 0) * 60ms);
}
body.ouverture .kpi {
  animation: monte 480ms var(--sortie) backwards;
  animation-delay: calc(60ms + var(--k, 0) * 45ms);
}
.kpi:nth-child(2) { --k: 1; }
.kpi:nth-child(3) { --k: 2; }
.kpi:nth-child(4) { --k: 3; }
.kpi:nth-child(5) { --k: 4; }
.kpi:nth-child(6) { --k: 5; }
body.ouverture .hud-gauche { animation: fondu 600ms 500ms ease-out backwards; }
body.ouverture .hud-droite { animation: fondu 600ms 700ms ease-out backwards; }
body.ouverture .hud-bas { animation: fondu 500ms 800ms ease-out backwards; }
body.ouverture #scene-etiquettes,
body.ouverture #scene-fils { animation: fondu 800ms 1.5s ease-out backwards; }

/* --------------------------------------------------------------------------
   17. Ajustements bureau / tablette
   -------------------------------------------------------------------------- */
@media (min-width: 1680px) {
  .kpi {
    padding: 7px 16px 6px;
    grid-template-areas:
      "num label label"
      "val val spark"
      "sous sous spark";
  }
  .kpi-valeur { font-size: 44px; line-height: 1; }
}

/* scène plus étroite que 680 px : HUD compact */
@media (min-width: 768px) and (max-width: 1399.98px) {
  #hud-boutons .long { display: none; }
  #hud-regle { max-width: 250px; }
}
/* colonne du journal trop étroite pour « Journal en direct » + les 3 filtres */
@media (min-width: 768px) and (max-width: 1679.98px) {
  #journal > h2 .long { display: none; }
}
@media (min-width: 768px) and (max-width: 1359.98px) {
  .etape-nom { display: none; }
  #etapes { gap: 16px; }
}
@media (min-width: 768px) and (max-width: 1179.98px) {
  #marque p { display: none; }
}
/* tuiles KPI plus étroites : sparkline et crans réduits pour ne pas toucher la valeur */
@media (min-width: 1200px) and (max-width: 1599.98px) {
  .kpi-spark { width: 88px; }
}
@media (min-width: 1200px) and (max-width: 1399.98px) {
  .kpi-spark { width: 60px; }
  .crans { gap: 3px; }
  .crans i { width: 5px; height: 14px; }
  .kpi-valeur { font-size: 31px; }
}
@media (min-width: 768px) and (max-width: 1199.98px) {
  #kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .kpi-spark { width: 96px; }
}
@media (min-width: 768px) and (max-width: 1023.98px) {
  #p-maj { display: none; }
  #hud-regle, #hud-regle.replie { display: none; }
  #hud-titre .direct { display: none; }
  .pastille { padding-right: 9px; letter-spacing: .05em; }
}

/* --------------------------------------------------------------------------
   18. Téléphone (≤ 767 px, Mini App Telegram en portrait, référence 390 px)
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  .app {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 0 var(--g-d) calc(24px + var(--inset-bas)) var(--g-g);
  }
  #tete { order: 1; }
  #kpis { order: 2; }
  #scene { order: 3; }
  #equipage { order: 4; }
  #ancres { order: 5; }
  #reussite { order: 6; }
  #alertes { order: 7; }
  #journal { order: 8; }
  #entonnoir { order: 9; }
  #hypes { order: 10; }
  #frise { display: none; }
  #pied { order: 11; }
  #rappels { display: none; }
  #infobulle { display: none !important; }

  :is(#equipage, #alertes, #journal, #entonnoir, #reussite) {
    scroll-margin-top: calc(48px + 48px + 12px + var(--inset-haut));
  }

  .panneau { padding: 12px; }
  .panneau::after { inset: -1px; }

  /* lisibilité sur iPhone : plus de gris « éteint », plus de texte sous 11 px */
  :root { --eteint: var(--texte-3); }
  .ligne.routine .ligne-h { color: var(--texte-3); }
  :is(.kpi-num, .kpi-label, .agent-tete > .tag, .agent-tete > .agent-age, .ligne > .tag, .badge, #reussite-stats dt, .narr-nom, .narr-age) { font-size: 11px; }
  :is(.ligne-h, .c-token :is(span, em, .meta), .panneau > h2 small, #pied) { font-size: 11.5px; }
  #scene-etiquettes :is(.n3-tok, .n3-nais, .n3-hype) { font-size: 11px; }
  #scene-etiquettes .n3-agent { font-size: 11.5px; }

  /* titres trop longs pour 390 px : le complément part (« échelle » de l'entonnoir gardée : elle sert à lire les barres) */
  :is(#reussite, #alertes) > h2 small { display: none; }
  #journal > h2 .long { display: none; }

  /* 1. barre collante de 48 px */
  #tete {
    position: sticky;
    top: 0;
    z-index: 40;
    height: calc(48px + var(--inset-haut));
    margin: 0 calc(-1 * var(--g-d)) 0 calc(-1 * var(--g-g));
    padding: var(--inset-haut) var(--g-d) 0 var(--g-g);
    gap: 10px;
    background: #050813;                       /* opaque : le contenu ne défile pas en transparence sous le logo */
    border-bottom: 1px solid var(--ligne);
    overflow: visible;
  }
  #tete::before, #tete::after { display: none; }
  #marque { gap: 8px; }
  #logo-noyau { width: 22px; height: 22px; }
  #titre { font-size: 15px; letter-spacing: .06em; }
  #marque p { display: none; }
  /* une seule pastille : trois points d'état dans une même capsule */
  #etats {
    position: relative;
    gap: 0;
    height: 26px;
    padding: 0 3px;
    border-radius: 999px;
    border: 1px solid var(--ligne-2);
    background: rgba(10, 16, 36, .62);
  }
  #etats::after { content: ""; position: absolute; inset: -9px -6px; }   /* cible tactile de 44 px */
  #etats .pastille {
    width: 18px;
    height: 24px;
    padding: 0;
    border: 0;
    background: transparent;
    font-size: 0;
    letter-spacing: 0;
    animation: none;
  }
  #etats .pastille::before,
  #etats .pastille::after { left: 50%; margin-left: -3px; }
  #p-maj { display: none; }
  #horloge-bloc { padding-left: 0; border-left: 0; }
  #horloge { font-size: 13px; }
  #date { display: none; }

  /* 2. KPI en grille 3 × 2 */
  #kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
  #kpis:empty::before { height: 164px; }
  .kpi {
    height: 78px;
    padding: 9px 9px 7px;
    border-radius: 10px;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "num label"
      "val val"
      "sous sous";
    column-gap: 5px;
  }
  .kpi::before { height: 2px; }
  .kpi-label { letter-spacing: .03em; }
  .kpi-valeur { font-size: 22px; line-height: 1.1; align-self: end; }
  /* une ligne d'explication courte (« depuis minuit », « médiane ×0,21 »…), le détail au toucher */
  .kpi-sous { display: block; font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .kpi-spark, .crans { display: none; }
  .kpi-badge { right: 8px; top: auto; bottom: 24px; }

  /* 3. scène bord à bord */
  #scene {
    height: clamp(340px, 92vw, 400px);
    margin: 0 calc(-1 * var(--g-d)) 0 calc(-1 * var(--g-g));
    border-radius: 0;
    border-left: 0;
    border-right: 0;
    border-color: var(--ligne);
  }
  #scene::before, #scene::after { display: none; }
  #scene-canvas, #scene-fils, #scene-etiquettes, #scene-hud, #scene-secours { border-radius: 0; }
  #scene-secours { padding: 44px 8px 56px; }
  .hud-gauche { left: 12px; top: 11px; max-width: 60%; }
  #hud-titre { font-size: 0; gap: 0; }
  #hud-debit { font-size: 11px; }
  #hud-titre .direct, #hud-regle, #hud-regle.replie { display: none; }
  .hud-droite { right: 10px; top: 8px; max-width: 40%; }
  #hud-hypes { display: none; }
  #hud-boutons #btn-etiquettes { display: none; }
  #hud-boutons { gap: 12px; }
  #hud-boutons :is(#btn-visite, #btn-pause)::after { content: ""; position: absolute; inset: -6px; }   /* 44 px au doigt */
  #hud-boutons :is(#btn-visite, #btn-pause) {
    width: 32px;
    padding: 0;
    gap: 0;
    justify-content: center;
    border-radius: 50%;
    font-size: 0;
    letter-spacing: 0;
  }
  #hud-boutons #btn-visite .ico { display: none; }
  #hud-boutons #btn-visite::before { content: "?"; font: 700 14px/1 var(--f-titre); }
  /* pictogramme pause (deux barres) / lecture (triangle) dessiné en CSS */
  #hud-boutons #btn-pause::before {
    content: "";
    width: 3px;
    height: 11px;
    border-radius: 1px;
    background: currentColor;
    box-shadow: 6px 0 0 currentColor;
    transform: translateX(-3px);
  }
  #hud-boutons #btn-pause[aria-pressed="true"]::before {
    width: 0;
    height: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    transform: translateX(1.5px);
    border-left: 9px solid currentColor;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
  }
  .hud-centre { top: 50px; width: calc(100% - 24px); }
  .toast { min-height: 52px; }
  .hud-bas { padding-top: 18px; }
  #narration {
    height: 40px;
    margin: 0 12px 9px;
    font-size: 12px;
    line-height: 1.38;
    white-space: normal;
  }
  .narr {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    height: auto;
    max-height: 40px;
  }
  .narr > * { display: inline; vertical-align: baseline; }
  .narr-point { display: inline-block; margin-right: 6px; vertical-align: 1px; }
  .narr-nom { margin-right: 6px; }
  .narr-texte { white-space: normal; font-size: 12px; line-height: 1.38; }
  .narr-age { margin-left: 6px; }
  #etapes { display: none; }
  .hud-bas .legende { display: none; }       /* sous la scène, dans #sous-scene */

  /* sous la scène : légende des étiquettes, puis le verdict (ce qui marche, ce qui rate) */
  #sous-scene { order: 3; display: flex; flex-direction: column; gap: 8px; margin-top: -4px; }
  #sous-scene .legende { margin: 0; font: 400 11px/1.4 var(--f-mono); color: var(--texte-3); white-space: normal; }
  #reussite > #verdict { display: none; }

  /* 4. bande ÉQUIPAGE : défilement horizontal aimanté, puces de 132 × 56 */
  #equipage {
    padding: 0;
    background: none;
    border: 0;
    box-shadow: none;
  }
  #equipage::before, #equipage::after { display: none; }
  #equipage > h2 { margin: 0 0 8px; }
  #agents-liste {
    flex-direction: row;
    gap: 8px;
    margin: 0 calc(-1 * var(--g-d)) 0 calc(-1 * var(--g-g));
    padding: 2px var(--g-d) 6px var(--g-g);
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--g-g) var(--g-d);
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  #agents-liste::-webkit-scrollbar { display: none; }
  #agents-liste:empty::before {
    height: 56px;
    background: repeating-linear-gradient(90deg, rgba(15, 24, 52, .6) 0 132px, transparent 132px 140px);
  }
  #agents-liste > .agent {
    flex: 0 0 132px;
    height: 56px;
    min-height: 0;
    padding: 8px 9px 8px 12px;
    border-radius: 10px;
    gap: 0;
    scroll-snap-align: start;
    background: rgba(15, 24, 52, .62);
    border-color: rgba(76, 125, 255, .14);
  }
  .agent-msg, .agent-role, .agent-frise, .agent-extra, .agent-badge { display: none; }
  .agent-tete {
    height: auto;
    display: grid;
    grid-template-columns: 8px minmax(0, 1fr) auto;
    grid-template-rows: 18px 18px;
    column-gap: 6px;
    row-gap: 3px;
    align-items: center;
  }
  .agent-point { grid-area: 1 / 1; }
  .agent-nom { grid-area: 1 / 2 / 2 / 4; font-size: 12px; }
  .agent-tete > .tag {
    display: inline-block;
    grid-area: 2 / 1 / 3 / 3;
    justify-self: start;
    margin: 0;
    max-width: 100%;
    padding: 2px 4px;
    letter-spacing: .02em;
  }
  .agent-tete > .agent-age,
  .agent-tete > :not(.tag) + .agent-age { grid-area: 2 / 3; margin: 0; }
  .agent[data-etat="travail"] { border-color: rgba(43, 255, 163, .3); }
  /* retour visuel au toucher (iOS : écouteur touchstart posé par app.js) */
  :is(.agent, .carte-alerte, li.manque, .ligne):active { background-color: var(--tuile); }

  /* 5. barre d'ancres collante (top 48, hauteur 40) */
  #ancres {
    position: sticky;
    top: calc(48px + var(--inset-haut));
    z-index: 39;
    display: flex;
    align-items: center;
    gap: 6px;
    height: 48px;
    margin: -4px calc(-1 * var(--g-d)) 0 calc(-1 * var(--g-g));
    padding: 0 var(--g-d) 0 var(--g-g);
    background: #050813;                       /* opaque, comme la barre du haut */
    border-bottom: 1px solid var(--ligne);
    animation: descend 280ms var(--sortie);
  }
  #ancres a::after { content: ""; position: absolute; inset: -5px -3px; }   /* 44 px au doigt */
  #ancres a {
    position: relative;
    flex: 1 1 0;
    height: 34px;
    display: grid;
    place-items: center;
    border-radius: 8px;
    border: 1px solid var(--ligne);
    background: rgba(15, 24, 52, .6);
    font: 700 10.5px/1 var(--f-mono);
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--texte-2);
  }
  #ancres a:is([aria-current], .actif) {
    color: var(--a3);
    border-color: rgba(63, 224, 255, .45);
    background: rgba(63, 224, 255, .08);
  }

  /* 6. résultats : anneau de 112 px */
  #reussite { grid-template-columns: 112px minmax(0, 1fr); }
  #reussite-anneau { width: 112px; height: 112px; }
  #reussite-stats { font-size: 11px; }
  button.voir-tout { position: relative; padding: 10px 0; }

  /* 7. alertes : cartes de 72 px au lieu du tableau */
  .table-defile { display: none; }
  #alertes-cartes { display: flex; flex-direction: column; gap: 8px; }
  /* et l'inverse : seulement le tableau rempli → on garde le tableau */
  #alertes:has(#alertes-cartes:empty):has(#alertes-table tbody:not(:empty)) .table-defile { display: block; }
  #alertes:has(#alertes-cartes:empty):has(#alertes-table tbody:not(:empty)) #alertes-cartes { display: none; }
  #alertes-cartes > button { align-self: stretch; min-height: 40px; }
  .carte-alerte .c-lien a { position: relative; width: 36px; height: 36px; }
  .carte-alerte .c-lien a::after { content: ""; position: absolute; inset: -4px; }

  /* 8. journal : une colonne, page qui défile, message sur 2 lignes */
  #journal { grid-template-rows: 44px auto; }
  #journal > h2 {
    display: block;
    min-width: 0;
    padding-left: 12px;
    overflow: hidden;
    text-overflow: ellipsis;
    letter-spacing: .07em;
  }
  #journal-filtre { margin-right: 8px; }
  #journal-filtre button { position: relative; padding: 0 6px; height: 32px; line-height: 32px; font-size: 11px; letter-spacing: .03em; }
  #journal-filtre button::after { content: ""; position: absolute; inset: -6px -1px; }
  #journal-liste { overflow: visible; max-height: none; padding-bottom: 4px; }
  #journal-liste > button,
  #journal > button:not(#journal-nouveaux) {
    display: block;
    width: calc(100% - 24px);
    min-height: 40px;
    margin: 8px 12px 12px;
    border-radius: 10px;
    border: 1px solid var(--ligne-2);
    background: rgba(15, 24, 52, .6);
    font: 700 11px/1 var(--f-mono);
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--texte-2);
  }
  #journal-nouveaux { top: 50px; }
  .ligne {
    grid-template-columns: 56px auto minmax(0, 1fr);
    padding: 6px 12px;
    column-gap: 6px;
  }
  .ligne-point { display: none; }
  .ligne > .tag { padding: 1px 5px; max-width: 72px; }
  .ligne-msg {
    font-size: 12px;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
  }
  .ligne-rep { grid-column: 3; justify-self: start; margin-top: 2px; }

  /* 9. entonnoir : barres horizontales serrées */
  .etage { height: 30px; grid-template-columns: minmax(80px, 42%) minmax(0, 1fr) 48px; gap: 8px; }
  .etage-barre { height: 8px; }
  .etage-nom { font-size: 12px; }

  /* 11. pied */
  #pied { flex-direction: column; gap: 2px; padding-top: 10px; }
  #pied::after { color: var(--texte-3); }

  /* toasts quand la scène est hors écran : sous les barres collantes (48 + 48 px) */
  #toast-fixe {
    display: flex;
    flex-direction: column;
    gap: 8px;
    position: fixed;
    z-index: 85;
    top: calc(48px + 48px + 8px + var(--inset-haut));
    left: var(--g-g);
    right: var(--g-d);
    pointer-events: none;
  }
  #toast-fixe > * { pointer-events: auto; }

  /* fiche du bas */
  #feuille { max-height: 82vh; max-height: 82dvh; }
}

/* téléphone en paysage étroit : on garde la scène lisible */
@media (max-width: 767.98px) and (orientation: landscape) {
  #scene { height: clamp(300px, 70vh, 400px); }
}

/* bureau : la fiche devient une carte centrée */
@media (min-width: 768px) {
  #feuille {
    left: 50%;
    right: auto;
    bottom: 16px;
    width: min(560px, calc(100vw - 48px));
    margin-left: calc(min(560px, calc(100vw - 48px)) / -2);
    border-radius: 16px;
    border-bottom: 1px solid var(--ligne-2);
    padding-bottom: 0;
    transform: translateY(calc(100% + 24px));
  }
  #feuille.ouverte { transform: none; }
  #ancres { display: none !important; }
}

/* Mini App Telegram : pas de sélection accidentelle sur les commandes */
body.telegram :is(#tete, #kpis, #hud-boutons, #journal-filtre, #ancres, .agent, .pastille) {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* --------------------------------------------------------------------------
   19. Mouvement réduit : fondus de 120 ms seulement, aucune boucle
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-property: opacity !important;
    transition-duration: 120ms !important;
    transition-delay: 0s !important;
  }
}
html:has(body.reduit) { scroll-behavior: auto; }
/* Mini App Telegram réduite (body.inactif) : boucles CSS figées */
body.inactif *, body.inactif *::before, body.inactif *::after { animation-play-state: paused !important; }
body.reduit *, body.reduit *::before, body.reduit *::after,
body.reduit::before, body.reduit::after {
  animation-duration: 1ms !important;
  animation-delay: 0s !important;
  animation-iteration-count: 1 !important;
  transition-property: opacity !important;
  transition-duration: 120ms !important;
  transition-delay: 0s !important;
}

/* --------------------------------------------------------------------------
   20. Animations (transform et opacity uniquement, sauf mention)
   -------------------------------------------------------------------------- */
@keyframes monte { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes fondu { from { opacity: 0; } to { opacity: 1; } }
@keyframes fondu-sortie { from { opacity: 1; } to { opacity: 0; } }
@keyframes attente { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }
@keyframes descend { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@keyframes entre-haut { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@keyframes reflet { from { transform: translateX(-14%); } to { transform: translateX(100%); } }
@keyframes tourne { to { transform: rotate(360deg); } }
@keyframes respire { 0%, 100% { opacity: .75; transform: scale(1); } 50% { opacity: 1; transform: scale(1.06); } }
@keyframes onde { 0% { opacity: .6; transform: scale(1); } 100% { opacity: 0; transform: scale(2.4); } }
@keyframes ping { 0% { opacity: .6; transform: scale(1); } 100% { opacity: 0; transform: scale(2.4); } }
@keyframes veille { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
@keyframes secousse {
  0%, 100% { transform: none; }
  20% { transform: translateX(-3px); }
  45% { transform: translateX(3px); }
  70% { transform: translateX(-2px); }
  88% { transform: translateX(1px); }
}
@keyframes deux-points { 0% { opacity: 1; } 50% { opacity: .22; } }
/* exception assumée : petit anneau SVG de 14 px */
@keyframes car-vide { from { stroke-dashoffset: 0; } to { stroke-dashoffset: 100; } }
/* exception du plan (§9.5) : tracé des lignes de rappel */
@keyframes trace-rappel { to { stroke-dashoffset: 0; } }
@keyframes kpi-brille { 0% { opacity: 1; } 100% { opacity: .6; } }
@keyframes kpi-lueur { 0% { opacity: .28; } 100% { opacity: .055; } }
@keyframes rebond { 0% { transform: none; } 32% { transform: scale(1.08); } 62% { transform: scale(.985); } 100% { transform: none; } }
@keyframes badge-monte { 0% { opacity: 1; transform: translateY(0); } 70% { opacity: 1; } 100% { opacity: 0; transform: translateY(-14px); } }
@keyframes point-spark { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .55; transform: scale(1.8); } }
@keyframes balaye-carte { 0% { opacity: .12; transform: translateX(-35%); } 100% { opacity: 0; transform: translateX(0); } }
/* exception du plan (§9.3) : ouverture de la ligne du journal */
@keyframes ligne-ouvre { from { grid-template-rows: 0fr; opacity: .25; } to { grid-template-rows: 1fr; opacity: 1; } }
@keyframes ligne-glisse { from { transform: translateX(-6px); } to { transform: none; } }
@keyframes tag-flash { 0% { opacity: .36; } 100% { opacity: 0; } }
@keyframes balayage { 0% { opacity: 1; transform: translateX(-100%); } 100% { opacity: 1; transform: translateX(100%); } }
@keyframes tremble {
  0%, 100% { transform: none; }
  15% { transform: translateX(-2px); }
  32% { transform: translateX(2px); }
  49% { transform: translateX(-2px); }
  66% { transform: translateX(2px); }
  83% { transform: translateX(-2px); }
}
@keyframes flash-ligne { 0% { opacity: 1; } 100% { opacity: 0; } }
@keyframes pop { 0% { opacity: 0; transform: scale(.6); } 60% { opacity: 1; transform: scale(1.12); } 100% { transform: none; } }
@keyframes toast-entre { from { opacity: 0; transform: translateY(-14px); } to { opacity: 1; transform: none; } }
@keyframes toast-sort { to { opacity: 0; transform: translateY(-10px); } }
@keyframes toast-barre { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@keyframes flash-page { 0% { opacity: 0; } 18% { opacity: 1; } 44% { opacity: .12; } 68% { opacity: 1; } 100% { opacity: 0; } }
@keyframes barre-entre { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes flux-points { from { transform: translateY(-25%); } to { transform: translateY(0); } }
@keyframes pulse-chute { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@keyframes feuille-entre { from { transform: translateY(100%); } to { transform: none; } }
