/* ============================================================================
   TECHNO-BAT — moteur commercial. Système visuel « Atelier », révision 2.
   ---------------------------------------------------------------------------
   La révision 1 posait un noir chaud (#0c0b0a) et un orange vif (#ff7a18).
   C'est le réflexe par défaut, et il ne venait de rien : ni du métier, ni de
   la matière. Il est remplacé par ce que Boris a réellement sous les yeux.

   FOND      anthracite froid, la couleur des charpentes et des armoires
             techniques (RAL 7016 assombri). Biais bleu-vert assumé : ce n'est
             pas un noir neutre, c'est de l'acier à l'ombre.
   ACCENT    minium — la peinture antirouille orange terreuse posée sur acier
             brut avant finition. Désaturée, pas néon. Un seul accent, partout.
   ALERTE    rouge incendie, réservé à UNE chose : ce qui bloque. Jamais décor.
   TEXTE     craie sur acier, légèrement chaude pour tenir sur un fond froid.

   LE TRAIT PORTE LE SENS, PAS LA COULEUR.
   Vocabulaire du plan d'exécution : l'existant se dessine en trait plein,
   le projeté en tirets. Ici, un fait confirmé porte un trait plein, un signal
   un trait tireté, un inconnu aucun trait. Une couleur de moins, une règle
   de plus — et la doctrine fait/signal/inconnu devient lisible sans légende.

   Un seul monde : l'atelier est sombre, c'est un choix, pas un oubli.
   ========================================================================= */

:root {
  color-scheme: dark;

  --acier:      #191d20;
  --acier-haut: #212629;
  --acier-bas:  #14181a;
  --trait:      #333a3e;
  --trait-bas:  #262c2f;

  --craie:      #e8e6e0;
  --craie-2:    #9ba1a1;
  --craie-3:    #878f92;   /* 4,64:1 sur --acier-haut — mesuré, pas estimé */

  /* --minium remplit (filets, boutons, jauges) ; il ne porte JAMAIS de texte :
     3,77:1 sur fond posé, sous le seuil. Le texte accentué prend --minium-vif. */
  --minium:     #d4571f;
  --minium-vif: #e87a45;
  --minium-nu:  rgba(212, 87, 31, .13);
  --incendie:   #e85f52;   /* 4,51:1 sur --acier-haut */
  --incendie-nu:rgba(232, 95, 82, .12);

  /* Un seul système de formes, et sa règle : les conteneurs prennent --r-gd,
     les commandes --r, les pastilles --r-pt, les indicateurs restent des
     barres. Six rayons sans règle, c'est six accidents. */
  --r-pt:   8px;
  --r:      10px;
  --r-gd:   14px;
  --colonne: 1180px;

  --lettrage: Archivo, 'Archivo Fallback', system-ui, sans-serif;
  --donnee:  'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0 }
html { -webkit-text-size-adjust: 100% }

body {
  min-height: 100dvh;
  background: var(--acier);
  color: var(--craie);
  font: 400 15px/1.6 var(--lettrage);
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--minium); color: #180a03 }

:focus-visible {
  outline: 2px solid var(--minium-vif);
  outline-offset: 2px;
  border-radius: 4px;
}

.n { font-family: var(--donnee); font-variant-numeric: tabular-nums; font-feature-settings: 'zero' 1 }

/* ── Le cartouche ───────────────────────────────────────────────────────────
   Pas une barre d'application : le cartouche d'un plan d'exécution. Il porte
   l'affaire, le registre, la date et la provenance des données — les quatre
   choses qu'on lit en bas à droite d'un plan avant de faire quoi que ce soit. */
.cartouche {
  position: sticky; top: 0; z-index: 40;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: stretch;
  gap: 0;
  background: var(--acier-bas);
  border-bottom: 1px solid var(--trait);
}

.cart-marque {
  display: flex; flex-direction: column; justify-content: center;
  gap: 3px;
  padding: 13px 22px;
  border-right: 1px solid var(--trait);
}
.cart-marque b {
  font: 800 14px/1 var(--lettrage);
  font-stretch: 118%;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.cart-marque span {
  font: 400 12px/1 var(--donnee);
  color: var(--craie-3);
  letter-spacing: .04em;
}

.cart-champs {
  display: flex; align-items: stretch;
  overflow-x: auto;
  scrollbar-width: none;
}
.cart-champs::-webkit-scrollbar { display: none }
.cart-champs > div {
  display: flex; flex-direction: column; justify-content: center; gap: 4px;
  padding: 11px 20px;
  white-space: nowrap;
}
/* Un filet ne se tire qu'ENTRE deux cases. Le cartouche allégé n'en ayant
   plus qu'une, le filet de droite tombait dans le vide. */
.cart-champs > div + div { border-left: 1px solid var(--trait-bas) }
.cart-champs dt {
  font: 600 12px/1 var(--lettrage);
  font-stretch: 118%;
  letter-spacing: .17em; text-transform: uppercase;
  color: var(--craie-3);
}
.cart-champs dd { font: 400 13px/1 var(--donnee); color: var(--craie-2) }

/* Le registre : deux finalités, une seule machine. */
.registre { display: flex; gap: 0; border: 1px solid var(--trait); border-radius: var(--r-pt); overflow: hidden }
.registre button {
  display: flex; align-items: center;
  min-height: 44px; padding: 0 15px;
  font: 600 13px/1 var(--lettrage);
  letter-spacing: .09em; text-transform: uppercase;
  border: 0; cursor: pointer;
  background: transparent; color: var(--craie-3);
  transition: color .15s, background .15s;
}
.registre button:hover { color: var(--craie) }
.registre button[aria-pressed="true"] { background: var(--craie); color: var(--acier-bas) }

/* Les trois espaces. Onglets à filet, pas à pastille : on est sur un plan. */
.espaces { display: flex; align-items: stretch }
.espaces button {
  position: relative;
  font: 600 13px/1 var(--lettrage);
  letter-spacing: .02em;
  padding: 0 22px; border: 0; border-left: 1px solid var(--trait-bas);
  background: transparent; color: var(--craie-3); cursor: pointer;
  transition: color .15s, background .15s;
}
.espaces button:hover { color: var(--craie); background: var(--acier-haut) }
.espaces button[aria-current="page"] { color: var(--craie) }
.espaces button[aria-current="page"]::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px; background: var(--minium);
}

/* ── Corps ───────────────────────────────────────────────────────────────── */
.corps {
  max-width: var(--colonne);
  margin: 0 auto;
  padding: 40px 28px 96px;
  display: flex; flex-direction: column; gap: 40px;
}

.tete { display: flex; flex-direction: column; gap: 12px }
.oeil {
  font: 700 12px/1 var(--lettrage);
  font-stretch: 118%;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--minium-vif);
}
.tete h1 {
  font: 800 clamp(30px, 3.6vw, 44px)/1.06 var(--lettrage);
  letter-spacing: -.035em;
  max-width: 22ch; text-wrap: balance;
}
.chapo { color: var(--craie-2); font-size: 17px; max-width: 62ch }
.chapo b { color: var(--craie); font-weight: 600 }

/* ── LE RAIL — pièce de signature ────────────────────────────────────────────
   Six crans, six preuves. Un cran plein est atteint, un cran tireté ne l'est
   pas, un cran cerclé de rouge est celui où la population est arrêtée.
   Le même dispositif sert dans les trois espaces, à trois densités. */
.rail { display: flex; flex-direction: column; gap: 14px }

.rail-piste {
  display: grid;
  grid-template-columns: repeat(var(--n, 6), minmax(0, 1fr));
  gap: 1px;
  border-radius: var(--r);
  overflow: hidden;
}

.cran {
  display: flex; flex-direction: column; gap: 7px;
  padding: 13px 14px 15px;
  background: var(--acier-haut);
  border-top: 2px solid var(--trait);
  min-width: 0;
}

/* Le filet du cran se trace une fois, de gauche à droite. C'est le seul
   moment orchestré de la page : il dit dans quel ordre la machine avance. */
.cran::before {
  content: ""; display: block;
  height: 2px; margin: -15px -14px 0;
  background: var(--trait);
  transform-origin: left;
}
@keyframes trace { from { transform: scaleX(0) } to { transform: scaleX(1) } }

.cran.atteint { border-top-color: transparent }
.cran.atteint::before { background: var(--minium) }
.cran.vide { border-top-style: dashed }
.cran.vide::before { background: none }
.cran.goulot::before { background: var(--incendie) }
.cran.goulot { background: linear-gradient(180deg, var(--incendie-nu), transparent 70%), var(--acier-haut) }

.cran-n {
  font: 600 27px/1 var(--donnee);
  font-variant-numeric: tabular-nums;
  color: var(--craie);
  letter-spacing: -.02em;
}
.cran.vide .cran-n { color: var(--craie-3) }
.cran.goulot .cran-n { color: var(--incendie) }
.cran-l {
  font: 600 13px/1.3 var(--lettrage);
  letter-spacing: .04em;
  color: var(--craie-2);
  overflow-wrap: anywhere;
}
.cran-p { font: 400 12px/1.4 var(--donnee); color: var(--craie-3) }

.rail-dit { font-size: 15px; color: var(--craie-2); max-width: 72ch }
.rail-dit b { color: var(--craie); font-weight: 600 }
.rail-dit .bloque { color: var(--incendie); font-weight: 600 }

/* Rail compact : la position d'un seul compte, dans une ligne de liste. */
.rail-mini { display: flex; gap: 3px; align-items: center }
.rail-mini i { display: block; width: 15px; height: 3px; border-radius: 2px; background: var(--trait) }
.rail-mini i.on { background: var(--minium) }
.rail-mini i.ici { background: var(--minium-vif); box-shadow: 0 0 0 2px var(--minium-nu) }
.rail-mini b {
  font: 500 13px/1 var(--lettrage); color: var(--craie-3);
  margin-left: 6px; letter-spacing: .03em; white-space: nowrap;
}

/* ── Faits : le trait dit le statut ─────────────────────────────────────────
   plein = confirmé · tireté = signal · nu = inconnu. */
.faits { display: flex; flex-wrap: wrap; gap: 7px }
.fait {
  font: 500 13px/1 var(--lettrage);
  color: var(--craie-2);
  border: 1px solid var(--trait);
  padding: 7px 11px; border-radius: var(--r-pt);
  white-space: nowrap;
}
.fait b { color: var(--craie); font-weight: 600; font-family: var(--donnee); font-size: 13px }
.fait.signal { border-style: dashed; color: var(--craie-3) }
.fait.inconnu { border-color: transparent; color: var(--craie-3); padding-left: 0 }
/* La règle était contredite ici : un fait confirmé et un fait ordinaire
   portaient le MÊME trait plein, seule la couleur les séparait. C'est
   l'épaisseur du trait qui distingue maintenant, la couleur n'appuie que. */
.fait.fort { border-width: 2px; border-color: var(--minium); color: var(--craie) }

/* Une action à mener n'est pas un fait : elle sort de la famille des traits.
   Le chevron dit « la suite est là », pas « ceci est constaté ». */
.prochain {
  display: inline-flex; align-items: center; gap: 8px;
  font: 600 13px/1.3 var(--lettrage); color: var(--minium-vif);
}
.prochain::before {
  content: ""; width: 7px; height: 7px; flex: none;
  border-right: 2px solid currentColor; border-top: 2px solid currentColor;
  transform: rotate(45deg);
}
.prochain.ecart { color: var(--incendie) }
.fait.manque { border-style: dashed; border-color: var(--incendie); color: var(--incendie) }
a.fait { text-decoration: none }
a.fait:hover { border-color: var(--minium); color: var(--craie) }



@keyframes pose { from { opacity: 0; transform: translateY(10px) } to { opacity: 1; transform: none } }

.etiq {
  display: inline-flex; align-items: center; gap: 8px; align-self: flex-start;
  font: 700 12px/1 var(--lettrage);
  font-stretch: 118%;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--minium-vif);
}
.etiq.retard { color: var(--incendie) }


@media (min-width: 1100px) {

}
.pourquoi { color: var(--craie-2); max-width: 66ch }
.pourquoi b { color: var(--craie); font-weight: 600 }

.duo { display: flex; gap: 10px; flex-wrap: wrap; padding-top: 4px }
.principal, .secondaire {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 46px; padding: 8px 22px; min-width: 0;
  text-align: center; overflow-wrap: anywhere;
  font: 700 15px/1 var(--lettrage);
  border-radius: var(--r); cursor: pointer;
  white-space: nowrap; transition: background .15s, border-color .15s, color .15s;
  border: 1px solid transparent;
}
.principal { background: var(--minium); color: #180a03; border-color: var(--minium) }
.principal:hover { background: var(--minium-vif); border-color: var(--minium-vif) }
.principal:active { transform: translateY(1px) }
.secondaire { background: transparent; color: var(--craie-2); border-color: var(--trait) }
.secondaire:hover { color: var(--craie); border-color: var(--craie-3) }
.secondaire:active { transform: translateY(1px) }

/* ── Listes : lignes à filet, pas cartes empilées ────────────────────────── */
.pile { display: flex; flex-direction: column }
.titre-bloc {
  display: flex; align-items: baseline; justify-content: space-between; gap: 6px 18px; flex-wrap: wrap;
  font: 700 12px/1.5 var(--lettrage);
  font-stretch: 118%;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--craie-3);
  padding-bottom: 12px; border-bottom: 1px solid var(--trait);
}

.ligne {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center; gap: 10px 22px;
  padding: 17px 0;
  border-bottom: 1px solid var(--trait-bas);
}
.ligne-corps { display: flex; flex-direction: column; gap: 8px; min-width: 0 }
.ligne h3 { font: 600 20px/1.3 var(--lettrage); letter-spacing: -.018em }
.ligne p { color: var(--craie-2); font-size: 14px; max-width: 76ch }
.ligne-haut { display: flex; align-items: center; gap: 12px; flex-wrap: wrap }
.ligne .etiq { color: var(--craie-3) }
.ligne .etiq.retard { color: var(--incendie) }
.agir {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 18px;
  font: 600 13px/1 var(--lettrage);
  border-radius: var(--r-pt); cursor: pointer; text-decoration: none;
  background: transparent; color: var(--craie-2); border: 1px solid var(--trait);
  white-space: nowrap; transition: .15s;
}
.agir:hover { color: var(--craie); border-color: var(--minium) }
.ligne .agir { min-width: 195px }

/* ── Le compte ───────────────────────────────────────────────────────────── */
.compte {
  display: flex; flex-direction: column; gap: 18px;
  background: var(--acier-haut);
  border: 1px solid var(--trait);
  border-radius: var(--r-gd);
  padding: 20px 24px;
}
.compte-tete { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px }
/* Le résumé tient sur une ligne : la position sur le rail, le volume, le
   territoire, et surtout ce qui bloque. Le dossier complet se déplie. */
.compte-resume { display: flex; align-items: center; flex-wrap: wrap; gap: 9px }
.compte-resume .agir { margin-left: auto }
.compte { gap: 16px }
.compte.ouvert { border-color: var(--craie-3) }
.compte-tete h3 { font: 800 23px/1.2 var(--lettrage); letter-spacing: -.028em }
.sousligne { font: 400 13px/1.5 var(--donnee); color: var(--craie-3); margin-top: 5px }
.interet {
  font: 600 27px/1 var(--donnee); font-variant-numeric: tabular-nums;
  color: var(--minium-vif); letter-spacing: -.02em;
  display: flex; flex-direction: column; align-items: flex-end; gap: 5px;
}
.interet span {
  font: 600 12px/1 var(--lettrage); font-stretch: 118%;
  letter-spacing: .15em; text-transform: uppercase; color: var(--craie-3);
}
.bloc { display: flex; flex-direction: column; gap: 8px; padding-top: 16px; border-top: 1px solid var(--trait-bas) }
.bloc h4 {
  font: 700 12px/1 var(--lettrage); font-stretch: 118%;
  letter-spacing: .18em; text-transform: uppercase; color: var(--craie-3);
}
.bloc p { color: var(--craie-2); font-size: 14px }
.bloc p b { color: var(--craie); font-weight: 600 }
.marches { list-style: none; display: flex; flex-direction: column; gap: 9px }
.marches li { display: grid; grid-template-columns: 92px 1fr; gap: 4px 14px; font-size: 14px }
.m-date { font: 400 13px/1.5 var(--donnee); color: var(--craie-3) }
.m-obj { color: var(--craie-2) }
.m-meta { grid-column: 2; font: 400 13px/1.4 var(--donnee); color: var(--craie-3) }

.filtres { display: flex; gap: 8px; flex-wrap: wrap }
.filtre {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 0 16px;
  font: 600 13px/1 var(--lettrage);
  border-radius: var(--r-pt); cursor: pointer;
  background: transparent; color: var(--craie-3); border: 1px solid var(--trait);
  transition: .15s;
}
.filtre:hover { color: var(--craie) }
.filtre[aria-pressed="true"] { background: var(--craie); color: var(--acier-bas); border-color: var(--craie) }

/* ── Machine : réglages et lecture ───────────────────────────────────────── */
.reglage {
  display: flex; flex-direction: column; gap: 12px;
  background: var(--acier-haut); border: 1px solid var(--trait);
  border-radius: var(--r-gd); padding: 24px 26px;
}
.reglage h3 { font: 700 17px/1.25 var(--lettrage); letter-spacing: -.02em }
.reglage > p { color: var(--craie-2); font-size: 14px; max-width: 62ch }
.paire {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px 20px;
  align-items: baseline; padding: 9px 0; border-bottom: 1px solid var(--trait-bas);
}
.paire:last-child { border-bottom: 0 }
.paire .k { color: var(--craie-3); font-size: 14px; overflow-wrap: anywhere; min-width: 0 }
.paire .v { color: var(--craie); font: 400 13px/1.4 var(--donnee); text-align: right; overflow-wrap: anywhere }
.val { font: 600 40px/1 var(--donnee); font-variant-numeric: tabular-nums; letter-spacing: -.03em }
input[type="range"] {
  width: 100%; height: 44px; accent-color: var(--minium);
  -webkit-appearance: none; appearance: none; background: transparent;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 6px; border-radius: 2px; background: var(--trait);
}
input[type="range"]::-moz-range-track { height: 6px; border-radius: 2px; background: var(--trait) }
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; margin-top: -7px;
  width: 20px; height: 20px; border-radius: 50%; background: var(--minium); border: 0; cursor: pointer;
}
input[type="range"]::-moz-range-thumb {
  width: 20px; height: 20px; border-radius: 50%; background: var(--minium); border: 0; cursor: pointer;
}
input[type="range"]::-moz-range-progress { height: 6px; border-radius: 2px; background: var(--minium) }

.attente { list-style: none; display: flex; flex-direction: column; gap: 11px }
.attente li {
  color: var(--craie-2); font-size: 14px;
  padding-left: 16px; border-left: 1px solid var(--trait);
}
.attente li b { color: var(--craie); font-weight: 600 }










 }

.vide-etat {
  display: flex; flex-direction: column; gap: 10px;
  border: 1px dashed var(--trait); border-radius: var(--r-gd); padding: 30px 28px;
}
.vide-etat b { font: 700 20px/1.3 var(--lettrage) }
.vide-etat span { color: var(--craie-2); font-size: 15px; max-width: 56ch }

.replie {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  border: 1px dashed var(--trait); border-radius: var(--r); padding: 16px 20px;
  color: var(--craie-2); font-size: 14px;
}
.replie b { color: var(--craie); font-weight: 600 }
.replie.alerte { border-style: solid; border-color: var(--incendie); background: var(--incendie-nu) }




/* ── Session d'appels ───────────────────────────────────────────────────── */
.fiche { display: flex; flex-direction: column; gap: 18px }
.fiche .nom { font: 800 30px/1.1 var(--lettrage); letter-spacing: -.035em }
.fiche .role { color: var(--craie-2); font-size: 15px }
.fiche .role b { color: var(--craie); font-weight: 600 }
.champ { display: flex; flex-direction: column; gap: 6px; padding-top: 14px; border-top: 1px solid var(--trait-bas) }
.champ dt {
  font: 700 12px/1 var(--lettrage); font-stretch: 118%;
  letter-spacing: .18em; text-transform: uppercase; color: var(--craie-3);
}
.champ dd { color: var(--craie); font-size: 15px }
.champ dd.attenue { color: var(--craie-2) }
.ouverture { border-left: 2px solid var(--minium); padding-left: 14px; color: var(--craie-2) }
.numero { font: 600 23px/1 var(--donnee); letter-spacing: -.01em }
.appeler {
  display: inline-flex; align-items: center; gap: 10px; text-decoration: none;
  font: 700 15px/1 var(--lettrage); padding: 14px 22px; border-radius: var(--r);
  background: var(--minium); color: #180a03;
}
.appeler:hover { background: var(--minium-vif) }
textarea {
  width: 100%; min-height: 130px; resize: vertical;
  background: var(--acier-bas); color: var(--craie);
  border: 1px solid var(--trait); border-radius: var(--r);
  padding: 14px 16px; font: 400 15px/1.6 var(--lettrage);
}
textarea::placeholder { color: var(--craie-3) }
.aide { color: var(--craie-3); font-size: 13px; max-width: 62ch }
.extrait { border: 1px dashed var(--trait); border-radius: var(--r); padding: 16px 18px }
.extrait .l { display: grid; grid-template-columns: minmax(0, 150px) 1fr; gap: 6px 16px; padding: 6px 0 }
.extrait dt { color: var(--craie-3); font-size: 13px }
.extrait dd { color: var(--craie); font-size: 14px }

/* ── Responsive : le cartouche se replie, il ne déborde jamais ──────────── */
@media (max-width: 900px) {
  .cartouche { grid-template-columns: 1fr auto }
  .espaces { grid-column: 1 / -1; border-top: 1px solid var(--trait-bas) }
  .espaces button { flex: 1; min-height: 48px; border-left: 0; border-right: 1px solid var(--trait-bas); padding: 0 8px }
  .espaces button:last-child { border-right: 0 }
  .cart-champs > div:nth-child(n+3) { display: none }
}
@media (max-width: 620px) {
  .corps { padding: 26px 16px 90px; gap: 30px }
  .cart-marque { padding: 11px 14px }
  .cart-marque b { font-size: 13px; letter-spacing: .05em }
  /* Au téléphone le cartouche ne garde que le registre : la date est déjà en
     tête de page, le verrou est déjà sur le rail. Une case de moins vaut
     mieux qu'une case coupée au milieu d'un mot. */
  .cart-champs > div:nth-child(n+2) { display: none }
  .cart-champs > div { padding: 8px 14px; border-right: 0 }
  .rail-piste { grid-template-columns: repeat(2, minmax(0, 1fr)) }
  .titre-bloc { letter-spacing: .12em }
  .ligne .agir { min-width: 0; width: 100% }

  .ligne { grid-template-columns: 1fr }
  .agir { justify-self: start }


  .compte-tete { flex-direction: column; gap: 12px }
  .interet { flex-direction: row; align-items: baseline; gap: 10px }
  .marches li { grid-template-columns: 1fr }
  .m-meta { grid-column: 1 }
}

@media (prefers-reduced-motion: reduce) {
  /* On retire le DÉPLACEMENT, on garde le RETOUR. Un survol, un appui, un
     changement d'état continuent de se voir : ce sont eux qui disent que la
     commande a été reçue. */

  .cran.avance { animation: none; border-top-color: var(--minium-vif) }
  .cran.avance .cran-n { color: var(--minium-vif) }
  .principal:active, .secondaire:active, .agir:active { transform: none }
}


/* ══ MOUVEMENT ══════════════════════════════════════════════════════════════
   Deux moments, et deux seulement.

   1. L'ENTRÉE, à la première peinture de chaque espace uniquement. Elle dit
      dans quel ordre la machine avance. Rejouée à chaque clic, elle ne disait
      plus rien : le filet de signature se retraçait quand on changeait un
      filtre. Elle est donc portée par .corps.entree, posée une seule fois.

   2. LA FRAPPE, quand un cran a réellement gagné des comptes depuis la
      dernière visite. C'est le seul mouvement qui n'est pas décoratif : il ne
      se déclenche que si le business a avancé pour de vrai. Le reste du
      temps, rien ne bouge — et c'est ce silence qui rend la frappe lisible.
   ═════════════════════════════════════════════════════════════════════════ */

.entree .cran::before {
  animation: trace .5s cubic-bezier(.22, 1, .36, 1) backwards;
  animation-delay: calc(var(--i, 0) * .07s);
}

.entree .ligne {
  animation: pose .4s cubic-bezier(.22, 1, .36, 1) backwards;
  animation-delay: calc(var(--i, 0) * .035s);
}
.entree .compte {
  animation: pose .4s cubic-bezier(.22, 1, .36, 1) backwards;
  animation-delay: calc(var(--i, 0) * .04s);
}


/* Le cran franchi. 700 ms, une seule fois, jamais en boucle. */
.cran.avance { animation: frappe .7s cubic-bezier(.22, 1, .36, 1) }
.cran.avance::before { background: var(--minium-vif) }
@keyframes frappe {
  0%   { background: var(--minium-nu) }
  18%  { background: rgba(232, 122, 69, .22) }
  100% { background: var(--acier-haut) }
}

/* Ce que la machine a fait pendant qu'on ne regardait pas. */
/* Une phrase se compose en flux inline. En flex, chaque suite de texte
   devient un élément de flex et gagne l'écart : les mots se détachent. */
.avancee { font-size: 15px; color: var(--craie); max-width: 72ch }
.avancee b { font-family: var(--donnee); color: var(--minium-vif); font-weight: 600 }
.avancee .pastille {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--minium); margin-right: 9px;
}
.avancee.rien { color: var(--craie-3) }

/* L'accusé de réception. Le seul instant d'accomplissement de la matinée ne
   peut pas être une disparition silencieuse. */
.replie.accompli { border-style: solid; border-color: var(--minium); background: var(--minium-nu) }
.replie.accompli b { color: var(--craie) }

/* Mesuré : la ligne la plus longue rendue faisait 138 caractères. */
.attente li { max-width: 78ch }


/* ══ AUJOURD'HUI — LES TROIS ZONES ══════════════════════════════════════════
   Zone 1 : ce qui exige mon temps. Zone 2 : ce qui a changé. Zone 3 : ce que
   la machine fait. Elles ne se ressemblent pas, parce qu'elles ne demandent
   pas la même chose : agir, comprendre, faire confiance.
   ═════════════════════════════════════════════════════════════════════════ */

.zone { display: flex; flex-direction: column; gap: 16px }

/* ── ZONE 1 : une intervention est un acte, pas une carte de plus ────────── */
.inter {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 14px 28px; align-items: start;
  padding: 18px 0; border-bottom: 1px solid var(--trait-bas);
}
.inter-corps { display: flex; flex-direction: column; gap: 8px; min-width: 0 }
.inter-corps h3 { font: 600 20px/1.25 var(--lettrage); letter-spacing: -.02em }
.inter-corps p { color: var(--craie-2); font-size: 14px; max-width: 72ch }
.inter-actes { display: flex; flex-direction: column; gap: 8px; align-items: stretch }
.inter-actes .principal, .inter-actes .secondaire { min-width: 190px }

/* La première porte le filet de tête : c'est celle qui passe devant. */
.majeure-inter {
  position: relative; background: var(--acier-haut);
  border: 1px solid var(--trait); border-radius: var(--r-gd);
  padding: 24px 26px; border-bottom: 1px solid var(--trait); overflow: hidden;
}
.majeure-inter::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 2px; background: var(--minium);
}
.majeure-inter .inter-corps h3 { font-size: 23px; font-weight: 800; letter-spacing: -.028em }

/* ── INTERVENTION BORIS : un bon de travaux, pas une notification ────────────
      Ces lignes ne se décident pas, elles se FONT. La forme le dit : le geste
      est une définition, pas une phrase persuasive ; le filet de gauche est
      épais parce que c'est un fait déterminant (la machine est arrêtée là) ;
      le rouge ne marque QUE l'échéance qui serre. Rouge partout = rouge nulle
      part. */
.z-main .aide { max-width: 72ch }
.main {
  border-left: 3px solid var(--trait);
  border-top: 1px solid var(--trait-bas);
  padding: 18px 0 20px 20px;
  display: flex; flex-direction: column; gap: 12px;
}
.main.serre { border-left-color: var(--incendie) }
.main h3 { font: 700 19px/1.25 var(--lettrage); letter-spacing: -.022em }
.m-pourquoi { color: var(--craie-3); font-size: 14px; max-width: 72ch }
.m-geste {
  display: grid; grid-template-columns: 148px minmax(0, 1fr);
  gap: 7px 20px; align-items: baseline;
}
.m-geste dt {
  font: 600 12px/1.3 var(--lettrage); letter-spacing: .07em; text-transform: uppercase;
  color: var(--craie-3);
}
.m-geste dd { color: var(--craie); font-size: 15px; min-width: 0; overflow-wrap: anywhere }
.m-geste dd a { color: var(--minium-vif); text-underline-offset: 3px }
.m-geste dd code { font: 400 14px/1.4 var(--donnee); color: var(--craie-2) }
.m-geste .m-impact { color: var(--craie-2); font-size: 14px }
.m-j {
  font: 600 13px/1 var(--donnee); font-variant-numeric: tabular-nums;
  color: var(--craie-3); margin-left: 8px;
}
.main.serre .m-j { color: var(--incendie) }
.m-actes { display: flex; gap: 10px; flex-wrap: wrap; align-items: center }
.m-actes .secondaire { display: inline-flex; align-items: center; text-decoration: none }

@media (max-width: 720px) {
  .m-geste { grid-template-columns: minmax(0, 1fr); gap: 3px 0 }
  .m-geste dd { margin-bottom: 9px }
}

/* ── ZONE 2 : ce qui a changé. Du langage commercial, jamais informatique. ─ */
.faits-liste { list-style: none; display: flex; flex-direction: column; gap: 2px }
.faits-liste li {
  display: grid; grid-template-columns: 54px minmax(0, 1fr) auto;
  gap: 6px 16px; align-items: baseline;
  padding: 11px 0; border-bottom: 1px solid var(--trait-bas);
}
.faits-liste .fn {
  font: 600 23px/1 var(--donnee); font-variant-numeric: tabular-nums;
  color: var(--craie-3); letter-spacing: -.02em;
}
.faits-liste .fd { color: var(--craie-2); font-size: 15px }
.faits-liste .fq { font: 400 13px/1.4 var(--donnee); color: var(--craie-3); text-align: right }
.faits-liste li.gain .fn { color: var(--minium-vif) }
.faits-liste li.gain .fd { color: var(--craie) }

/* ── ZONE 3 : la maturité des séquences. Le même geste que le rail, un autre
      sujet : le rail dit la maturité d'un COMPTE, ceci dit celle d'un ENVOI. */
.maturite { display: flex; align-items: stretch; gap: 1px; border-radius: var(--r); overflow: hidden }
.etape {
  flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px;
  padding: 13px 14px 15px; background: var(--acier-haut);
  border-top: 2px dashed var(--trait);
}
.etape.occupee { border-top: 2px solid var(--minium) }
.etape.sortie { border-top: 2px solid var(--trait); background: var(--acier-bas) }
.e-n {
  font: 600 23px/1 var(--donnee); font-variant-numeric: tabular-nums; color: var(--craie-3);
}
.etape.occupee .e-n { color: var(--craie) }
.e-l { font: 600 13px/1.2 var(--lettrage); color: var(--craie-3); letter-spacing: .04em }

.prochaine-auto { font-size: 15px; color: var(--craie-2); max-width: 72ch }
.prochaine-auto b { color: var(--craie); font-weight: 600 }
.prochaine-auto .pastille {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--minium); margin-right: 9px;
}

/* Le stock derrière le verrou. Même forme que le verrou — c'est la même
   nature d'information : un compte de choses arrêtées — mais le trait est
   plein, parce que ces approches sont des faits construits, pas un manque. */
.stock-pret {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: 8px 18px; align-items: center;
  border: 1px solid var(--trait); border-radius: var(--r); padding: 16px 20px;
}
.sp-n {
  font: 600 30px/1 var(--donnee); font-variant-numeric: tabular-nums;
  color: var(--minium-vif); letter-spacing: -.03em;
}
.sp-t { color: var(--craie-2); font-size: 14px; max-width: 72ch }
.sp-t b { color: var(--craie); font-weight: 600 }

.verrou {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 8px 18px; align-items: center;
  border: 1px dashed var(--trait); border-radius: var(--r); padding: 16px 20px;
}
.v-n {
  font: 600 30px/1 var(--donnee); font-variant-numeric: tabular-nums;
  color: var(--incendie); letter-spacing: -.03em;
}
.v-t { color: var(--craie-2); font-size: 14px }
.v-t b { color: var(--craie); font-weight: 600 }

/* ══ MOUVEMENT ÉVÉNEMENTIEL ═════════════════════════════════════════════════
   Le produit ne bouge pas au chargement pour faire joli. Il bouge quand un
   ÉVÉNEMENT RÉEL s'est produit, et le geste dit lequel.

     un cran franchi           → le cran frappe          (frappe)
     quelque chose a changé    → les gains surgissent    (surgit)
     une intervention traitée  → la ligne se retire      (retire)

   Un événement, un geste. Jamais deux à la fois, jamais en boucle. Quand
   rien ne s'est produit, rien ne bouge — et c'est ce silence qui rend le
   geste lisible quand il arrive.
   ═════════════════════════════════════════════════════════════════════════ */

.z-change.bouge .faits-liste li.gain {
  animation: surgit .55s cubic-bezier(.22, 1, .36, 1) backwards;
  animation-delay: calc(var(--i, 0) * .08s);
}
@keyframes surgit {
  0%   { opacity: 0; transform: translateY(6px) }
  100% { opacity: 1; transform: none }
}
.z-change.bouge .faits-liste li.gain .fn {
  animation: chiffre .7s cubic-bezier(.22, 1, .36, 1) backwards;
  animation-delay: calc(var(--i, 0) * .08s + .1s);
}
@keyframes chiffre {
  0%   { color: var(--craie); transform: scale(1.18) }
  100% { color: var(--minium-vif); transform: none }
}

.replie.accompli { animation: surgit .4s cubic-bezier(.22, 1, .36, 1) }

@media (max-width: 620px) {
  /* La colonne « auto » de la valeur écrasait l'étiquette à 3 px de large :
     « Fenêtre » débordait de sa propre boîte. Au téléphone, la paire
     s'empile. */
  .paire { grid-template-columns: 1fr; gap: 3px }
  .paire .v { text-align: left }
  .inter { grid-template-columns: 1fr }
  .inter-actes { flex-direction: row; flex-wrap: wrap }
  .inter-actes .principal, .inter-actes .secondaire { min-width: 0; flex: 1 }
  .maturite { flex-wrap: wrap }
  .etape { flex: 1 1 30%; }
  .verrou { grid-template-columns: auto minmax(0, 1fr) }
  .verrou .agir { grid-column: 1 / -1; justify-self: start }
  .faits-liste li { grid-template-columns: 44px minmax(0, 1fr) }
  .faits-liste .fq { grid-column: 2; text-align: left }
}

@media (prefers-reduced-motion: reduce) {
  .z-change.bouge .faits-liste li.gain,
  .z-change.bouge .faits-liste li.gain .fn,
  .replie.accompli { animation: none }
}

/* La bannière d'essai doit être impossible à confondre avec un état réel. */
.replie.essai {
  border-style: solid; border-width: 2px; border-color: var(--incendie);
  background: var(--incendie-nu);
}
.replie.essai b { color: var(--incendie); letter-spacing: .06em }

/* ══ VOIE B — LA CARTE DE DÉCISION ══════════════════════════════════════════
   Elle ne ressemble pas à une intervention de la voie A, parce qu'elle ne
   demande pas la même chose : pas « fais ce geste », mais « tranche ». Le
   verdict de la machine est posé, visible, et séparé de la décision. */
.decision {
  grid-column: 1 / -1;
  background: var(--acier-haut); border: 1px solid var(--trait);
  border-radius: var(--r-gd); padding: 24px 26px; position: relative; overflow: hidden;
}
.decision::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 2px; background: var(--trait);
}
.decision.presse::before { background: var(--incendie) }

/* Le verdict de la machine. Il s'affiche, il ne décide pas. */
.verdict {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  padding: 12px 0; border-top: 1px solid var(--trait-bas); border-bottom: 1px solid var(--trait-bas);
}
.v-mot {
  font: 800 20px/1 var(--lettrage); font-stretch: 118%;
  letter-spacing: .1em; flex: none;
}
.v-go .v-mot { color: var(--minium-vif) }
.v-voir .v-mot { color: var(--craie-2) }
.v-dit { color: var(--craie-2); font-size: 14px; max-width: 66ch }

/* Le dossier : des faits alignés, lisibles d'un coup. */
.dossier { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px 24px }
.dossier > div { display: flex; flex-direction: column; gap: 4px; min-width: 0 }
.dossier dt {
  font: 700 12px/1 var(--lettrage); font-stretch: 118%;
  letter-spacing: .16em; text-transform: uppercase; color: var(--craie-3);
}
.dossier dd { font: 400 13px/1.4 var(--donnee); color: var(--craie); overflow-wrap: anywhere }

/* Ce qui plaide, ce qui pèse contre. Le trait porte le sens, comme partout. */
.peser { list-style: none; display: flex; flex-direction: column; gap: 6px }
.peser li { font-size: 14px; padding-left: 16px; position: relative; color: var(--craie-2) }
.peser li::before { content: ""; position: absolute; left: 0; top: .62em; width: 8px; height: 1px }
.peser.pour li::before { background: var(--minium); height: 2px }
.peser.contre li::before { background: var(--craie-3); border-top: 1px dashed var(--craie-3) }

@media (max-width: 620px) {
  .decision { padding: 20px 18px }
  .dossier { grid-template-columns: 1fr }
}

/* Les décisions non ouvertes : une ligne qui dit le verdict, l'objet et
   l'échéance. On les ouvre une par une, on ne les fait pas défiler. */
.decision-repliee {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto;
  gap: 10px 18px; align-items: center;
  padding: 14px 0; border-bottom: 1px solid var(--trait-bas);
}
.v-mot.petit { font-size: 13px; letter-spacing: .12em; min-width: 108px }
.d-objet { color: var(--craie-2); font-size: 14px; overflow-wrap: anywhere }
.d-echeance { font: 400 13px/1 var(--donnee); color: var(--craie-3); white-space: nowrap }
.d-echeance.presse { color: var(--incendie) }
.decision-repliee.presse .v-mot { color: var(--incendie) }

@media (max-width: 620px) {
  .decision-repliee { grid-template-columns: auto minmax(0, 1fr) }
  .decision-repliee .agir { grid-column: 1 / -1; justify-self: start }
}

/* Le niveau de profondeur du verdict. Une recommandation tirée du seul avis
   ne se présente pas comme une conclusion tirée des pièces du marché. */
.v-niveau {
  font: 500 12px/1 var(--donnee); color: var(--craie-3);
  border: 1px dashed var(--trait); border-radius: var(--r-pt); padding: 5px 9px;
}
.v-prequalifie .v-mot { color: var(--minium-vif) }

/* Le geste exact attendu de Boris. Court, précis, et le seul de la carte. */
.geste {
  font-size: 14px; color: var(--craie); max-width: 72ch;
  padding-left: 16px; border-left: 2px solid var(--minium);
}
.decision.acces::before { background: var(--craie-3) }
.decision.acces.presse::before { background: var(--incendie) }

/* Au téléphone, un libellé d'action long ne doit pas pousser sa boîte hors du
   cadre : il se met sur deux lignes plutôt que de déborder. */
@media (max-width: 620px) {
  .inter-actes .principal, .inter-actes .secondaire, .inter-actes .agir { width: 100% }
}
