/* =========================================================================
   gtm-tools — feuille de style
   =========================================================================
   Registre éditorial sombre et chaud : fond brun profond, texte crème, titres
   en capitales appuyées, accents ambre.

   Une contrainte gouverne le reste : l'écran de vérification est le moment où
   l'utilisateur engage une écriture dans les comptes d'un client. Les pastilles
   d'état y sont les éléments les plus contrastés de la page, et rien de ce qui
   porte une décision n'est posé sur un fond variable.
   ========================================================================= */

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

/* L'attribut `hidden` doit l'emporter sur toute règle d'affichage : le
   navigateur ne lui applique qu'un `display: none` de sa feuille par défaut, que
   la moindre déclaration d'auteur écrase. Tout l'affichage conditionnel de
   l'outil repose dessus. */
[hidden] { display: none !important; }

:root {
  color-scheme: dark;

  --r-xl: 18px;
  --r-l: 12px;
  --r-m: 8px;
  --r-pastille: 999px;
  --largeur: min(1560px, 92vw);

  /* Le fond n'est pas noir mais brun : c'est ce qui donne sa chaleur à
     l'ensemble et empêche le crème du texte de paraître cru. */
  --fond: #100b06;
  --surface: #1a1209;
  --surface-2: #22180d;
  --surface-3: #2c2012;
  --trait: #33261599;
  --trait-fort: #4a3720;

  --texte: #f5e4c7;
  --texte-2: #bda98a;
  --texte-3: #8b7a5f;

  --accent: #e8952f;
  --accent-vif: #ffb257;
  --accent-doux: #2a1c0b;
  --accent-trait: #6a4818;
  --accent-texte: #180f04;

  --ombre-l: 0 2px 8px rgba(0, 0, 0, .55), 0 40px 70px -30px rgba(0, 0, 0, .95);

  --ok-f: #14301c;   --ok-t: #8fdda6;   --ok-b: #2c6b40;   --ok-p: #52c77a;
  --neuf-f: #3a2409; --neuf-t: #ffc37a; --neuf-b: #7a5417; --neuf-p: #e8952f;
  --corr-f: #3a3009; --corr-t: #ffe08a; --corr-b: #756219; --corr-p: #e0bc2c;
  --alr-f: #3d1610;  --alr-t: #ffa79b;  --alr-b: #7c3226;  --alr-p: #e0402b;
  --neu-f: #241a0f;  --neu-t: #bda98a;  --neu-b: #4a3720;  --neu-p: #8b7a5f;

  --t: 180ms cubic-bezier(.3, .8, .3, 1);

  /* Climate Crisis pour les titres : une grotesque d'affichage très appuyée,
     qui ne fonctionne qu'en grand et en capitales — d'où son emploi limité aux
     intitulés d'écran et au logotype. Le repli reste une grasse condensée du
     système, le temps que la police arrive ou si elle n'arrive pas. */
  --titre: 400 1em/.98 "Climate Crisis", "Arial Black", "Helvetica Neue", sans-serif;
}

/* ---------------------------------------------------------------- Fond --- */
body {
  margin: 0;
  padding: 0 0 9rem;
  min-height: 100vh;
  font: 16px/1.65 "Inter Tight", ui-sans-serif, -apple-system, BlinkMacSystemFont,
        "Segoe UI", system-ui, sans-serif;
  color: var(--texte);
  background: var(--fond);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ------------------------------------------------------------ Ossature --- */
/* La barre collante doit toucher les bords de l'écran : l'enveloppe ne borne
   donc plus la largeur, chaque bande s'en charge. */
.enveloppe { width: 100%; }
.barre-etapes, .carte { max-width: var(--largeur); margin-inline: auto; }

/* En-tête collant, sur toute la largeur : le repère ne quitte jamais l'écran,
   et la barre se teinte dès qu'on descend. */
.entete {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;
  max-width: var(--largeur); margin: 0 auto;
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--trait-fort);
  background: var(--fond);
}
.entete h1 {
  margin: 0;
  font: var(--titre); font-size: 1.25rem;
  text-transform: uppercase; letter-spacing: 0; padding-right: 1.5rem;
  color: var(--texte);
}

.carte {
  padding: clamp(1.5rem, 4vw, 3.5rem) 0 0;
  background: transparent;
  border: none;
  box-shadow: none;
}

/* Entrée uniforme. Une seule définition pour tout ce qui apparaît : les étapes
   de l'assistant, les onglets, et les blocs du relevé qui se remplissent au fil
   du balayage. Deux durées différentes suffiraient à faire paraître l'interface
   mal réglée. */
section[data-ecran]:not([hidden]),
div[data-onglet]:not([hidden]),
#np-resultat > details {
  animation: entrer 340ms cubic-bezier(.2, .8, .2, 1) both;
}

/* L'onglet et l'étape qu'il contient changent parfois ensemble — au premier
   affichage, notamment. Sans cela, les deux animations s'additionneraient et le
   déplacement serait deux fois plus ample que partout ailleurs. */
div[data-onglet]:not([hidden]) section[data-ecran]:not([hidden]) { animation: none; }

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

/* --------------------------------------------------------------- Onglets ---
   Capsule flottante en bas d'écran. Elle reste sous la main quel que soit le
   défilement, ne dispute pas la vedette au titre, et libère l'en-tête. */
.onglets {
  position: fixed; z-index: 50;
  left: 50%; bottom: 1.6rem; transform: translateX(-50%);
  display: flex; gap: .25rem;
  padding: .35rem;
  border-radius: var(--r-pastille);
  background: color-mix(in srgb, var(--surface-2) 82%, transparent);
  border: 1px solid var(--trait-fort);
  box-shadow: 0 10px 40px -10px rgba(0, 0, 0, .9);
  backdrop-filter: blur(18px) saturate(1.4);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
}
.onglets button {
  padding: .6rem 1.5rem; font-size: .72rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .1em;
  color: var(--texte-3); background: transparent;
  border: none; border-radius: var(--r-pastille);
  box-shadow: none;
  cursor: pointer;
  transition: color var(--t), background var(--t), transform var(--t);
}
.onglets button:active { transform: none; }
.onglets button:hover:not(.actif) { color: var(--texte); background: var(--surface-3);
                                    transform: none; box-shadow: none; }
.onglets button.actif { background: var(--accent); color: var(--accent-texte);
                        box-shadow: none; transform: none; }

/* --------------------------------------------------------- Progression --- */
.barre-etapes { padding: 1.6rem 0 0; }
body[data-onglet="non-publie"] .barre-etapes { display: none; }

.etapes {
  display: flex; align-items: center; gap: .45rem;
  margin: 0; padding: 0; list-style: none; flex-wrap: wrap;
  counter-reset: etape;
}
.etapes li { display: flex; align-items: center; gap: .45rem; }
.etapes li::after { content: ""; width: 24px; height: 1px; background: var(--trait-fort); }
.etapes li:last-child::after { display: none; }

.etapes span {
  display: inline-flex; align-items: center; gap: .5rem;
  font-size: .72rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em;
  color: var(--texte-3); transition: color var(--t);
}
.etapes span::before {
  counter-increment: etape; content: counter(etape);
  width: 1.45rem; height: 1.45rem; display: grid; place-items: center;
  border-radius: 50%; font-size: .7rem; font-weight: 800;
  background: transparent; color: var(--texte-3);
  border: 1px solid var(--trait-fort);
  transition: all var(--t);
}

body[data-ecran="saisie"]     .etapes [data-etape="saisie"],
body[data-ecran="analytics"]  .etapes [data-etape="analytics"],
body[data-ecran="tagmanager"] .etapes [data-etape="tagmanager"],
body[data-ecran="plan"]       .etapes [data-etape="plan"],
body[data-ecran="resultat"]   .etapes [data-etape="resultat"] { color: var(--texte); }

body[data-ecran="saisie"]     .etapes [data-etape="saisie"]::before,
body[data-ecran="analytics"]  .etapes [data-etape="analytics"]::before,
body[data-ecran="tagmanager"] .etapes [data-etape="tagmanager"]::before,
body[data-ecran="plan"]       .etapes [data-etape="plan"]::before,
body[data-ecran="resultat"]   .etapes [data-etape="resultat"]::before {
  background: var(--accent); color: var(--accent-texte); border-color: var(--accent);
}

/* --------------------------------------------------------- Typographie --- */
h2 {
  font: var(--titre);
  font-size: clamp(2.2rem, 6.5vw, 5rem);
  text-transform: uppercase; letter-spacing: -.01em;
  margin: 0 0 2.8rem;
}
h3 {
  font-size: .7rem; font-weight: 800; text-transform: uppercase; letter-spacing: .14em;
  color: var(--accent); margin: 3rem 0 1.2rem;
  display: flex; align-items: center; gap: .8rem; flex-wrap: wrap;
}
h3::after { content: ""; flex: 1 1 2rem; height: 1px; background: var(--trait-fort); }
.discret { color: var(--texte-2); font-size: 1.1rem; margin: 0 0 2.8rem; max-width: 52rem; }
a { color: var(--accent-vif); text-underline-offset: .2em; }
code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .9em; }
strong { color: var(--texte); }

/* ------------------------------------------------------------ Contrôles --- */
input[type=text], input[type=date], select {
  font: inherit; color: var(--texte);
  padding: .7rem .85rem;
  border: 1px solid var(--trait-fort);
  border-radius: var(--r-m);
  background: var(--surface-2);
  transition: border-color var(--t), box-shadow var(--t);
  max-width: 100%;
}
select { max-width: min(28rem, 100%); }
select option { background: #22180d; color: #f5e4c7; }
input::placeholder { color: var(--texte-3); }
input[type=text]:hover, select:hover { border-color: var(--accent-trait); }
input:focus-visible, select:focus-visible {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-doux);
}
button:focus-visible, a:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px;
}
input[type=checkbox] { accent-color: var(--accent); width: 1.05rem; height: 1.05rem; }

/* Boutons à ombre portée franche — un bloc décalé, sans dégradé ni flou. Le
   registre est celui de la typographie d'affichage retenue : net, épais,
   assumé. Au survol le bouton avance vers son ombre, au clic il l'écrase :
   le geste est physique, on sent qu'on appuie. */
button {
  font: inherit; font-size: .74rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .1em;
  color: var(--texte);
  padding: .85rem 1.6rem;
  border: 2px solid var(--texte);
  border-radius: 10px;
  background: transparent;
  box-shadow: 4px 4px 0 var(--accent);
  cursor: pointer;
  transition: transform 120ms ease-out, box-shadow 120ms ease-out,
              background var(--t), color var(--t);
}
/* Le bouton ne bouge pas au survol : seule la couleur change. Le déplacement
   est réservé au clic, où il traduit l'appui. */
button:hover:not([disabled]) { background: var(--texte); color: var(--fond); }
button:active:not([disabled]) { transform: translate(4px, 4px); box-shadow: 0 0 0 var(--accent); }
button[disabled] { opacity: .3; box-shadow: 4px 4px 0 var(--trait-fort); cursor: not-allowed; }

/* L'action principale porte l'ambre plein, son ombre est plus sombre : elle
   avance d'un cran sur le reste sans changer de langage. */
.principal {
  color: var(--accent-texte); background: var(--accent); border-color: var(--accent);
  box-shadow: 4px 4px 0 #7a4a10;
}
.principal:hover:not([disabled]) {
  background: var(--accent-vif); color: var(--accent-texte); border-color: var(--accent-vif);
}
.principal:active:not([disabled]) { box-shadow: 0 0 0 #7a4a10; }

.champ { display: flex; gap: .8rem; align-items: center; flex-wrap: wrap; margin: .9rem 0; }
label {
  display: inline-flex; align-items: center; gap: .6rem;
  color: var(--texte-3); font-size: .72rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .08em;
}
label > input, label > select {
  color: var(--texte); font-size: 1rem; font-weight: 400;
  text-transform: none; letter-spacing: normal;
}

/* Le champ et son bouton forment une paire, pas une liste : l'écart doit se
   voir, sans quoi le bouton paraît collé au champ. */
.saisie-domaine { margin: 0 0 .6rem; gap: 1.5rem; }
.saisie-domaine input[type=text] {
  flex: 1 1 22rem; font-size: 1.3rem; font-weight: 500;
  padding: 1.05rem 1.2rem; border-radius: var(--r-l);
}
.saisie-domaine .principal { padding: 1.05rem 2.2rem; font-size: .8rem; }

/* -------------------------------------------------------------- Tables --- */
.tableau {
  overflow-x: auto; margin: 1.5rem 0;
  border: 1px solid var(--trait-fort); border-radius: var(--r-l);
}
table { border-collapse: collapse; width: 100%; background: var(--surface); }
th, td { text-align: left; padding: .9rem 1.05rem; border-bottom: 1px solid var(--trait); }
th {
  font-size: .66rem; font-weight: 800; text-transform: uppercase; letter-spacing: .13em;
  color: var(--texte-3); background: var(--surface-2);
}
tbody tr { transition: background var(--t); }
tbody tr:hover td { background: var(--surface-2); }
tbody tr:last-child td { border-bottom: none; }
td:first-child { font-weight: 600; }

/* ------------------------------------------------------------ Pastilles --- */
.badge {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .28rem .75rem .28rem .6rem;
  border-radius: var(--r-pastille);
  font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .07em;
  white-space: nowrap; border: 1px solid;
}
.badge::before { content: ""; width: .45rem; height: .45rem; border-radius: 50%; background: currentColor; }
.reuse    { background: var(--ok-f);   color: var(--ok-t);   border-color: var(--ok-b); }
.create   { background: var(--neuf-f); color: var(--neuf-t); border-color: var(--neuf-b); }
.update   { background: var(--corr-f); color: var(--corr-t); border-color: var(--corr-b); }
.conflict { background: var(--alr-f);  color: var(--alr-t);  border-color: var(--alr-b); }
.skip     { background: var(--neu-f);  color: var(--neu-t);  border-color: var(--neu-b); }

/* Repointer une balise existante vers une propriété tout juste créée est bien
   plus lourd de conséquences qu'une correction de déclencheur, bien que les
   deux partagent l'action "update". */
.badge.repointage { background: var(--alr-p); color: #fff; border-color: transparent; }
tr.repointage td { background: color-mix(in srgb, var(--alr-p) 14%, transparent);
                   box-shadow: inset 3px 0 0 var(--alr-p); }
tr.visee td { background: color-mix(in srgb, var(--corr-p) 12%, transparent); }

/* ------------------------------------------------------------- Alertes --- */
.alerte {
  padding: .95rem 1.1rem; border-radius: var(--r-m); margin: .9rem 0;
  font-size: .94rem; border: 1px solid; border-left-width: 3px;
}
.alerte.reuse    { background: var(--ok-f);   color: var(--ok-t);   border-color: var(--ok-b);   border-left-color: var(--ok-p); }
.alerte.create   { background: var(--neuf-f); color: var(--neuf-t); border-color: var(--neuf-b); border-left-color: var(--neuf-p); }
.alerte.update   { background: var(--corr-f); color: var(--corr-t); border-color: var(--corr-b); border-left-color: var(--corr-p); }
.alerte.conflict { background: var(--alr-f);  color: var(--alr-t);  border-color: var(--alr-b);  border-left-color: var(--alr-p); }
.alerte a, .alerte strong { color: inherit; }

#erreur {
  background: var(--alr-f); color: var(--alr-t);
  border: 1px solid var(--alr-b); border-left: 3px solid var(--alr-p);
  padding: .95rem 1.1rem; border-radius: var(--r-m); margin: 0 0 .6rem; font-weight: 600;
}
#erreur-journal {
  background: var(--corr-f); color: var(--corr-t);
  border: 1px solid var(--corr-b); border-left: 3px solid var(--corr-p);
  padding: .4rem 1.1rem; border-radius: var(--r-m); margin: 0 0 1.4rem; font-size: .92rem;
}
#erreur-journal ul { margin: .3rem 0 .7rem; padding-left: 1.2rem; }

#compte-connecte {
  display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
  margin: 0 0 1.6rem; font-size: .82rem; color: var(--texte-2);
  padding: .55rem .85rem; background: var(--surface-2);
  border: 1px solid var(--trait); border-radius: var(--r-m);
}
#compte-connecte button { padding: .3rem .8rem; font-size: .64rem; }

#plan-raison-blocage { color: var(--texte-2); font-size: .9rem; margin: 0; }
#plan-raison-blocage:empty { display: none; }

.encadre {
  margin: 1.1rem 0; padding: 1.15rem 1.3rem;
  border: 1px solid var(--accent-trait); border-radius: var(--r-l);
  background: var(--accent-doux);
}
.encadre > p:first-child { margin-top: 0; }
.encadre > p:last-child { margin-bottom: 0; }
.encadre .discret { margin-bottom: .9rem; color: var(--texte-2); }

a.principal {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .85rem 1.6rem; border-radius: 10px;
  font-size: .74rem; font-weight: 800; text-transform: uppercase; letter-spacing: .1em;
  text-decoration: none; background: var(--accent); color: var(--accent-texte);
  border: 2px solid var(--accent); box-shadow: 4px 4px 0 #7a4a10;
  transition: transform 120ms ease-out, box-shadow 120ms ease-out, background var(--t);
}
a.principal:hover { background: var(--accent-vif); border-color: var(--accent-vif); }
a.principal:active { transform: translate(4px, 4px); box-shadow: 0 0 0 #7a4a10; }

/* --------------------------------------------------------- Chargement ---- */
.chargement { display: flex; align-items: center; gap: 1rem; padding: 3rem 0; }
.rotor {
  width: 1.35rem; height: 1.35rem; flex: none;
  border: 2px solid var(--trait-fort); border-top-color: var(--accent);
  border-radius: 50%; animation: tourner 700ms linear infinite;
}
#avancement { font-size: 1.05rem; color: var(--texte-2); margin: 0; }
@keyframes tourner { to { transform: rotate(360deg); } }

/* ------------------------------------------------------------ Résultat --- */
pre {
  background: var(--fond); border: 1px solid var(--trait-fort); color: var(--texte-2);
  padding: 1.1rem 1.2rem; border-radius: var(--r-m);
  overflow-x: auto; font-size: .8rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; line-height: 1.7;
}
#res-journal { color: var(--texte-2); font-size: .93rem; }
.chiffres { display: flex; gap: .9rem; flex-wrap: wrap; margin: 1.4rem 0 1.8rem; }
.chiffre {
  flex: 1 1 15rem; padding: 1.3rem 1.4rem; border-radius: var(--r-l);
  background: var(--accent-doux); border: 1px solid var(--accent-trait);
}
.chiffre b {
  display: block; font-size: 1.7rem; font-weight: 800; letter-spacing: -.02em;
  color: var(--accent-vif);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.chiffre span {
  font-size: .64rem; text-transform: uppercase; letter-spacing: .14em;
  font-weight: 800; color: var(--texte-3);
}

.actions {
  display: flex; gap: .8rem; align-items: center; flex-wrap: wrap;
  margin-top: 2.4rem; padding-top: 1.6rem; border-top: 1px solid var(--trait-fort);
}

/* --------------------------------------------- Relevé des non publiées --- */
#np-resultat .exp-compte {
  border: 1px solid var(--trait-fort); border-radius: var(--r-l);
  background: var(--surface-2); margin: .7rem 0;
}
#np-resultat summary {
  cursor: pointer; padding: .85rem 1rem; font-weight: 700;
  list-style: none; display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
}
#np-resultat summary::-webkit-details-marker { display: none; }
#np-resultat code { color: var(--accent); font-weight: 600; }
#np-resultat .exp-compte-nb {
  margin-left: auto; font-weight: 800; font-size: .66rem; color: var(--texte-3);
  text-transform: uppercase; letter-spacing: .09em;
}
#np-resultat .tableau { margin: 0 1rem 1rem; }

/* ------------------------------------------------- Confort et accessibilité --- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

@media (max-width: 40rem) {
  .carte { padding: 1.2rem; }
  th, td { padding: .65rem .7rem; font-size: .91rem; }
  .etapes span { font-size: .64rem; }
  .etapes li::after { width: 12px; }
  .onglets { margin-left: 0; }
  .saisie-domaine input[type=text] { font-size: 1.1rem; }
}

/* ====================================================================
   Réactions
   ==================================================================== */

/* Les lignes du tableau se décalent au survol et leur filet gauche s'allume :
   on suit une ligne des yeux sans la perdre. */
tbody tr {
  transition: background var(--t), transform var(--t), box-shadow var(--t);
}
tbody tr:hover td {
  background: var(--surface-2);
  box-shadow: inset 3px 0 0 var(--accent);
}
tbody tr:hover { transform: translateX(5px); }
tr.repointage:hover { transform: translateX(5px); }

/* Apparition décalée des lignes : le tableau se compose au lieu de surgir. */
tbody tr { animation: monter 420ms cubic-bezier(.2, .8, .2, 1) both; }
tbody tr:nth-child(1) { animation-delay: 30ms; }
tbody tr:nth-child(2) { animation-delay: 70ms; }
tbody tr:nth-child(3) { animation-delay: 110ms; }
tbody tr:nth-child(4) { animation-delay: 150ms; }
tbody tr:nth-child(5) { animation-delay: 190ms; }
tbody tr:nth-child(6) { animation-delay: 230ms; }
tbody tr:nth-child(n+7) { animation-delay: 270ms; }
@keyframes monter {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

/* Les pastilles gonflent légèrement au survol de leur ligne, et leur puce
   pulse : l'état se signale de lui-même. */
tbody tr:hover .badge { transform: scale(1.06); }
.badge { transition: transform var(--t); transform-origin: left center; }
tbody tr:hover .badge::before { animation: battre 1.1s ease-in-out infinite; }
@keyframes battre {
  0%, 100% { transform: scale(1); opacity: 1; }
  50%      { transform: scale(1.5); opacity: .6; }
}

/* Boutons : léger soulèvement, puis enfoncement franc au clic. */
/* Aucun soulèvement au survol : voir la règle des boutons plus haut. */

/* Le champ de saisie s'élargit quand on s'en saisit. */
.saisie-domaine input[type=text] {
  transition: border-color var(--t), box-shadow var(--t), transform 220ms cubic-bezier(.2,.8,.2,1);
}
.saisie-domaine input[type=text]:focus-visible { transform: scale(1.012); }

/* Les blocs du relevé arrivent en cascade, comme les lignes. */
#np-resultat > details:hover { border-color: var(--accent-trait); }
#np-resultat > details { transition: border-color var(--t); }

/* L'étape courante respire : un halo lent qui ne distrait pas. */
body[data-ecran="saisie"]     .etapes [data-etape="saisie"]::before,
body[data-ecran="analytics"]  .etapes [data-etape="analytics"]::before,
body[data-ecran="tagmanager"] .etapes [data-etape="tagmanager"]::before,
body[data-ecran="plan"]       .etapes [data-etape="plan"]::before,
body[data-ecran="resultat"]   .etapes [data-etape="resultat"]::before {
  animation: halo 2.6s ease-in-out infinite;
}
@keyframes halo {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  60%      { box-shadow: 0 0 0 7px transparent; }
}

/* Les intertitres tirent leur filet à l'entrée. */
h3::after { transform-origin: left; animation: tirer 620ms cubic-bezier(.2,.8,.2,1) both; }
@keyframes tirer { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* ====================================================================
   Scène flottante
   ====================================================================
   La référence tient d'abord à sa mise en scène : un centre habité, un vide
   large, et des objets qui dérivent autour à des vitesses différentes. Le
   décor est posé par deco.js, purement ornemental et absent sous
   prefers-reduced-motion. */

#scene {
  position: fixed; inset: 0; z-index: -1;
  pointer-events: none; overflow: hidden;
}

/* Enveloppe : la dérive horizontale. */
.flot {
  position: absolute;
  animation: deriveX var(--dx, 20s) ease-in-out var(--retard, 0s) infinite alternate;
  will-change: transform;
}
@keyframes deriveX {
  from { transform: translate3d(calc(var(--ax) * -1), 0, 0); }
  to   { transform: translate3d(var(--ax), 0, 0); }
}

/* Contenu : la dérive verticale, de période différente. La composition des deux
   donne une trajectoire qui ne se referme pas. */
.halo, .jeton {
  animation: deriveY var(--dy, 26s) ease-in-out var(--retard, 0s) infinite alternate;
  will-change: transform;
}
@keyframes deriveY {
  from { transform: translate3d(0, calc(var(--ay) * -1), 0); }
  to   { transform: translate3d(0, var(--ay), 0); }
}

/* Disques diffus : la profondeur sans détail qui accroche l'œil. */
.halo {
  width: 26vmax; height: 26vmax; margin: -13vmax;
  border-radius: 50%;
  background: radial-gradient(circle, var(--accent) 0%, transparent 68%);
  opacity: .13;
}

/* Jetons de vocabulaire : ce que l'outil manipule, en suspension. */
.jeton {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .78rem; letter-spacing: .05em;
  color: var(--accent);
  opacity: .42;
  padding: .35rem .8rem;
  border: 1px solid currentColor;
  border-radius: var(--r-pastille);
  white-space: nowrap;
}

/* L'écran d'entrée devient une scène : le contenu occupe le centre, le vide
   fait le reste. */
section[data-ecran="saisie"] {
  min-height: 58vh;
  display: flex; flex-direction: column; justify-content: center;
}
section[data-ecran="saisie"] h2 { font-size: clamp(2.6rem, 9vw, 7rem); }
section[data-ecran="saisie"] .discret { font-size: 1.15rem; }

/* ---------------------------------------------------------- Progression --- */
.prog {
  display: flex; align-items: center; gap: 1rem; flex-wrap: nowrap;
  margin: 1rem 0;
}
.prog-texte {
  flex: 0 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--texte-2); font-size: .92rem;
}
.prog-piste {
  flex: 1 1 8rem; height: 6px;
  background: var(--surface-3);
  border-radius: var(--r-pastille);
  overflow: hidden;
}
.prog-jauge {
  display: block; height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-vif));
  border-radius: var(--r-pastille);
  /* La jauge glisse au lieu de sauter : sur un balayage long, c'est ce
     mouvement continu qui dit que l'outil travaille encore. */
  transition: width 260ms cubic-bezier(.3, .8, .3, 1);
}
.prog-chiffre {
  flex: none;
  font-variant-numeric: tabular-nums;
  font-size: .72rem; font-weight: 800; letter-spacing: .06em;
  color: var(--accent);
}

@media (max-width: 40rem) {
  .prog { flex-wrap: wrap; gap: .5rem; }
  .prog-texte { flex: 1 1 100%; }
}

/* ------------------------------------------------------------- Barrage ---
   Sous cette largeur, le tableau du plan ne tient plus : ses trois colonnes se
   replient et l'on ne voit plus l'état d'une ressource en même temps que son
   nom. Or c'est exactement ce qu'il faut lire avant de confirmer une écriture
   chez un client. On ferme donc la porte plutôt que de laisser valider à
   l'aveugle. */
#barrage { display: none; }

@media (max-width: 56rem) {
  .enveloppe, .onglets, #scene { display: none !important; }

  #barrage {
    display: flex; flex-direction: column; justify-content: center;
    min-height: 100vh; padding: 2rem 1.6rem;
    max-width: 34rem; margin: 0 auto;
  }
  #barrage p { color: var(--texte-2); font-size: 1.05rem; margin: 0 0 1.4rem; }
  /* Sélecteur porté au niveau de l'identifiant : `#barrage p` l'emporterait
     sinon sur une simple classe, et le titre resterait au corps du texte. */
  #barrage .barrage-titre {
    font: var(--titre); font-size: clamp(2.8rem, 16vw, 4.5rem);
    text-transform: uppercase; color: var(--texte) !important;
    margin: 0 0 1.6rem !important; line-height: .95;
  }
  #barrage .barrage-chute {
    color: var(--accent) !important;
    font-weight: 700; font-size: 1.15rem !important; margin-bottom: 0 !important;
  }
}

/* ------------------------------------------- Onglet « Non publié » ---
   Le titre y est un intitulé de page, pas une accroche : il n'a pas à occuper
   la moitié de l'écran comme sur les étapes de l'assistant. */
div[data-onglet="non-publie"] h2 { font-size: clamp(1.8rem, 3.4vw, 2.8rem); margin-bottom: 1.6rem; }

/* Le balayage dure : sa jauge devient l'élément principal de la page tant
   qu'il tourne. */
#np-avancement.prog {
  margin: 1.6rem 0 2rem;
  padding: 1.1rem 1.3rem;
  background: var(--surface-2);
  border: 1px solid var(--trait-fort);
  border-radius: var(--r-l);
}
#np-avancement.prog .prog-piste { height: 10px; }
#np-avancement.prog .prog-texte { font-size: .95rem; color: var(--texte); }
#np-avancement.prog .prog-chiffre { font-size: .9rem; }

.np-attente {
  color: var(--texte-3); font-size: .95rem;
  padding: 2.5rem 0; text-align: center;
  border: 1px dashed var(--trait-fort); border-radius: var(--r-l);
}

/* --------------------------------------------------------------- Porte ---
   Écran de connexion. Deux colonnes sur large : l'identité à gauche, le jeu à
   droite, chacune dans son plein. Rien de l'outil n'y transparaît. */
body.porte {
  display: grid; place-items: center;
  min-height: 100vh; padding: clamp(1.5rem, 4vw, 3rem);
}
body.porte main {
  width: min(1400px, 100%);
  display: grid; gap: clamp(2rem, 5vw, 5rem);
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
}
@media (min-width: 62rem) {
  body.porte main { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
}

body.porte h1 {
  font: var(--titre); font-size: clamp(3rem, 8vw, 6.5rem);
  text-transform: uppercase; margin: 0 0 1.6rem; color: var(--texte);
}
body.porte p { color: var(--texte-2); font-size: 1.12rem; margin: 0 0 2.6rem; }
.porte-identite { max-width: 34rem; }

/* Le panneau de jeu est une surface à part : on comprend d'un regard qu'il ne
   fait pas partie de la connexion. */
.porte-jeu {
  padding: clamp(1.2rem, 2.5vw, 2rem);
  background: var(--surface); border: 1px solid var(--trait-fort);
  border-radius: var(--r-xl);
}

/* ------------------------------------------------------------- Le jeu ---
   Course sans fin, dans l'esprit du dinosaure de Chrome. Décoratif : il ne
   conditionne ni ne retarde la connexion. */
#jeu {
  display: block; width: 100%; height: clamp(160px, 24vh, 240px);
  cursor: pointer; touch-action: manipulation;
}

.jeu-barre {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap;
  margin-top: .6rem; padding-top: 1.2rem;
  border-top: 1px solid var(--trait);
}
.jeu-tableau { display: flex; gap: 2.6rem; margin: 0 !important; }
.jeu-tableau span {
  font-size: .64rem; font-weight: 800; text-transform: uppercase; letter-spacing: .14em;
  color: var(--texte-3);
}
.jeu-tableau b {
  display: block; font-size: 2rem; font-weight: 800;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--accent); letter-spacing: -.02em;
}
.jeu-regle {
  font-size: .86rem !important; color: var(--texte-3) !important;
  margin: 1.4rem 0 0 !important;
}
.jeu-message {
  margin: .8rem 0 0 !important; font-size: .9rem !important;
  color: var(--alr-t) !important; font-weight: 600;
}
