/* ENGENDRÉ par outils/jetons.py depuis brand/themes/ — NE PAS ÉDITER. */

/* Fanar Clair */
:root {
  --fond: #F5F4F2;
  --surface: #FFFFFF;
  --surfaceEntete: #FAF9F9;
  --surfaceEnfoncee: #F8F7F6;
  --texte: #221F1C;
  --texteSecondaire: #514942;
  --texteFaible: #776D62;
  --texteDesactive: #A3978A;
  --texteSurAction: #FFFFFF;
  --bordure: #EEECEA;
  --bordureForte: #C4BCB4;
  --bordureFocus: #C8102E;
  --accent: #C8102E;
  --accentFilet: #F7D9DF;
  --accentFond: #FDF2F4;
  --accentTexte: #A50D26;
  --action: #C8102E;
  --actionSurvol: #A50D26;
  --actionEnfonce: #7E0A1D;
  --diffusion: #0B6E63;
  --diffusionFond: #E6F4F0;
  --diffusionTexte: #0B6E63;
  --attente: #6F4F0C;
  --attenteFond: #FBF1DE;
  --attenteTexte: #6F4F0C;
  --alerte: #A50D26;
  --alerteFond: #FDF2F4;
  --alerteTexte: #A50D26;
  --plancherDiffusion: #12131A;
  --plancherBadge: #C8102E;
  --fondRail: #EEECEA;
  --fondRailSurvol: #FFFFFF;
  --railTexteFaible: #73695F;
  --railFilet: #E3DFDA;
  --evenement1: #2B5FD9;
  --evenement1Fond: #E8EEFC;
  --evenement2: #7445C9;
  --evenement2Fond: #F0EAFA;
  --evenement3: #C2367E;
  --evenement3Fond: #FBE9F2;
  --evenement4: #0B7A8F;
  --evenement4Fond: #E3F3F6;
  --evenement5: #4549A8;
  --evenement5Fond: #EAEBF7;
  --evenement6: #5F6614;
  --evenement6Fond: #F0F2E1;
  --evenement7: #9A5B2E;
  --evenement7Fond: #F6ECE4;
  --evenement8: #556270;
  --evenement8Fond: #ECEFF2;
  --textePlancher: #FFFFFF;
  --textePlancherFaible: #B4B7C4;
  --plancherCommande: #2A2C38;
  --plancherCommandeSurvol: #3A3D4C;
}

/* Fanar Sombre */
:root[data-theme="fanar-sombre"] {
  --fond: #121110;
  --surface: #1F1D1C;
  --surfaceEntete: #272523;
  --surfaceEnfoncee: #171614;
  --texte: #F6F5F3;
  --texteSecondaire: #C1BBB4;
  --texteFaible: #988D83;
  --texteDesactive: #6E665E;
  --texteSurAction: #FFFFFF;
  --bordure: #363330;
  --bordureForte: #504A45;
  --bordureFocus: #EB5E6E;
  --accent: #EB5E6E;
  --accentFilet: #5A2B31;
  --accentFond: #241416;
  --accentTexte: #EB5E6E;
  --action: #D21026;
  --actionSurvol: #8B0E1C;
  --actionEnfonce: #760C18;
  --diffusion: #2FA18A;
  --diffusionFond: #142421;
  --diffusionTexte: #2FA18A;
  --attente: #B88520;
  --attenteFond: #241F14;
  --attenteTexte: #B88520;
  --alerte: #EB5E6E;
  --alerteFond: #241416;
  --alerteTexte: #EB5E6E;
  --plancherDiffusion: #12131A;
  --plancherBadge: #C8102E;
  --fondRail: #1B1A18;
  --fondRailSurvol: #272522;
  --railTexteFaible: #988D83;
  --railFilet: #2E2C29;
  --evenement1: #6F9BF2;
  --evenement1Fond: #172036;
  --evenement2: #A98AE6;
  --evenement2Fond: #221C30;
  --evenement3: #E57FB2;
  --evenement3Fond: #2C1824;
  --evenement4: #4FB8CC;
  --evenement4Fond: #13272B;
  --evenement5: #8C90E0;
  --evenement5Fond: #1C1D33;
  --evenement6: #A9B356;
  --evenement6Fond: #22251A;
  --evenement7: #D49A6A;
  --evenement7Fond: #2A2019;
  --evenement8: #9AA8B8;
  --evenement8Fond: #1D2228;
  --textePlancher: #FFFFFF;
  --textePlancherFaible: #B4B7C4;
  --plancherCommande: #2A2C38;
  --plancherCommandeSurvol: #3A3D4C;
}
/* Servi PRÉCÉDÉ de jetons.css (la charte, qui porte les valeurs de tous les
   tokens) : le serveur concatène les deux (dashboard/mod.rs, FANAR_CSS). */

/* Fanar — le design system du dashboard (F3.5, le contrat que F4 hérite :
   docs/FRONT-DESIGN-SYSTEM.md). Écrit main sur les tokens BRAND — AUCUNE
   valeur de couleur hors de :root. Propriétés LOGIQUES partout : le RTL est
   prêt depuis le premier composant (dir sur <html>, BRAND §7).
   Doctrine tenue : zéro ombre portée, zéro animation d'ambiance, dégradé
   sur les seules surfaces de marque (connexion, tête de sidebar) — un outil
   de supervision se juge à la vitesse de lecture (BRAND §5). L'audace est
   ailleurs : la ligne de cadence, et une coque qui assume navy + champagne. */

/* ===================================================================== */
/* 1. TOKENS — la seule source de vérité                                  */
/* ===================================================================== */
:root {
  /* CHARTE BLANC ET ROUGE (30/09/2026, ADR-0071) — les valeurs vivent dans
     jetons.css, ENGENDRÉ par outils/jetons.py depuis brand/themes/. Les noms
     historiques de ce fichier (F3.5) restent, pour que chaque composant garde
     son vocabulaire : ils POINTENT sur la charte, ils ne portent plus de
     valeur. Un hex ici serait une seconde source de vérité. */
  --ink: var(--texte);
  --depth: var(--actionSurvol);
  --gold: var(--accent);             /* l'identité : le rouge Fanar */
  --porcelain: var(--fond);
  --mist: var(--texteDesactive);
  --live: var(--diffusion);          /* EN DIFFUSION — un seul sens */
  --alert: var(--alerte);
  --pending: var(--attente);

  --surface-head: var(--surfaceEntete);
  --line: var(--bordure);
  --line-strong: var(--bordureForte);
  --gold-hairline: var(--accentFilet);
  --gold-deep: var(--accentTexte);
  --mist-deep: var(--texteSecondaire);
  --mist-soft: var(--texteFaible);
  --alert-strong: var(--action);

  --live-bg: var(--diffusionFond);   --live-ink: var(--diffusionTexte);
  --alert-bg: var(--alerteFond);     --alert-ink: var(--alerteTexte);
  --pending-bg: var(--attenteFond);  --pending-ink: var(--attenteTexte);

  /* F5.3 — palette CATÉGORIELLE de la grille du planificateur : une teinte
   * par layout, l'ordre des slots est le mécanisme de sûreté daltonienne
   * (validé au script dataviz, surface blanche : adjacents CVD ΔE ≥ 6,1
   * avec encodage secondaire — légende nominative + liste des règles —,
   * vision normale ΔE ≥ 28). Les sosies des couleurs d'ÉTAT sont relégués
   * en fin (7 ≈ teal --live, 8 ≈ rouge --alert) : une composition réelle a
   * 2-3 layouts. JAMAIS la couleur seule : le nom accompagne toujours. */
  --plan-1: #2A78D6; --plan-2: #EB6834; --plan-3: #4A3AA7; --plan-4: #EDA100;
  --plan-5: #008300; --plan-6: #E87BA4; --plan-7: #1BAF7A; --plan-8: #E34948;

  --font-ui: "Manrope", system-ui, sans-serif;
  --font-data: "IBM Plex Mono", ui-monospace, monospace;

  /* Échelle 4/8 et rayons */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; --sp-10: 40px;
  --r-s: 4px; --r-m: 8px; --r-l: 12px; --r-pill: 999px;

  --side-w: 232px;
  --side-w-rail: 64px;
}

/* --- Fontes auto-hébergées (OFL — VENDOR.md, sha consignés) --- */
@font-face {
  font-family: "Manrope";
  src: url("fonts/manrope-latin.woff2") format("woff2");
  font-weight: 200 800; /* variable */
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("fonts/ibm-plex-mono-400-latin.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

/* ===================================================================== */
/* 2. BASE                                                                */
/* ===================================================================== */
* { box-sizing: border-box; }
html { height: 100%; }
body {
  margin: 0;
  min-height: 100%;
  background: var(--porcelain);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 15px;            /* body 15/24 (BRAND §4) */
  line-height: 1.6;
  font-variant-numeric: tabular-nums; /* les colonnes ne tremblent pas */
}
a { color: inherit; }
:focus-visible { outline: 2px solid var(--depth); outline-offset: 2px; border-radius: var(--r-s); }

h1 { font-size: 28px; line-height: 34px; letter-spacing: -0.015em; font-weight: 700; margin: 0; }
/* h2 = titre de carte : micro caps + tick or — le filet premium (BRAND §3),
   l'identité structure, elle ne signale jamais un état */
h2 {
  font-size: 11px; line-height: 16px; letter-spacing: 0.045em;
  text-transform: uppercase; font-weight: 500; color: var(--mist-deep);
  margin: 0 0 var(--sp-3);
  padding-block-end: var(--sp-2);
  border-block-end: 1px solid var(--line);
  position: relative;
}
h2::after {
  content: "";
  position: absolute;
  inset-block-end: -1px;
  inset-inline-start: 0;
  inline-size: 24px;
  border-block-end: 2px solid var(--gold);
}
.data { font-family: var(--font-data); font-size: 13px; line-height: 20px; }
.num { text-align: end; }

/* --- LA COUCHE DE BASE DES CONTRÔLES ----------------------------------- */
/*
 * Elle manquait, et son absence se voyait : un `<button>` sans classe
 * gardait l'apparence du système — Arial, bordure `outset`, gris 239. Sept
 * boutons du tableau de bord étaient dans ce cas, et le motif du bouton
 * secondaire était recopié à la main six fois ailleurs.
 *
 * On pose donc le DÉFAUT, pas un correctif par bouton : tout contrôle est
 * habillé par construction, et les composants nommés le surchargent
 * naturellement (un sélecteur de classe bat un sélecteur d'élément).
 *
 * `font: inherit` d'abord, parce que c'est l'oubli le plus courant — même
 * un bouton entièrement peint reste en Arial sans lui.
 */
button,
input,
select,
textarea,
::file-selector-button {
  font: inherit;
  color: inherit;
}

/* Le bouton SECONDAIRE, qui est le défaut : surface, filet, encre. Le
   bouton primaire (`--ink` plein) reste un choix explicite — il n'y a
   qu'une action principale par écran. */
button {
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-m);
  background: var(--surface);
  color: var(--ink);
  font-weight: 600;
  cursor: pointer;
}
button:hover { background: var(--surface-head); }
button:disabled { opacity: 0.5; cursor: default; }

/* UN LIEN QUI AGIT COMME UN BOUTON. Il manquait, et son absence s'est vue
   sur le site public : « Télécharger l'image » y était un lien souligné là
   où c'est L'ACTION de la page.
   
   Pourquoi une classe et pas un `<button>` : ces gestes NAVIGUENT. Un bouton
   qui navigue casse le clic du milieu, le « ouvrir dans un onglet » et la
   copie d'adresse — trois choses qu'un visiteur fait sans y penser. On garde
   donc un `<a>`, et on lui donne l'apparence.
   
   Les valeurs sont celles du bouton ci-dessus, pas des cousines : deux
   apparences qui divergent d'un pixel se remarquent quand elles sont côte à
   côte, et elles le sont souvent. */
.btn {
  display: inline-block;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-m);
  background: var(--surface);
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { background: var(--surface-head); }
.btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }

/* Le PRIMAIRE — encre pleine. Un seul par écran : c'est ce qui lui donne son
   sens. `button.btn-primaire` existe aussi, pour les formulaires. */
.btn-primaire,
button.btn-primaire {
  background: var(--action);
  border-color: var(--action);
  color: var(--texteSurAction);
}
.btn-primaire:hover,
button.btn-primaire:hover { background: var(--actionSurvol); border-color: var(--actionSurvol); }

/* Les champs de saisie : le même filet que partout, jamais le `inset` gris
   du navigateur. */
input[type="text"],
input[type="number"],
input[type="search"],
input[type="time"],
input[type="date"],
input[type="email"],
input[type="password"],
input[type="url"],
textarea {
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-m);
  background: var(--surface);
  color: var(--ink);
}
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
}

/* Les cases à cocher : `accent-color` habille la coche NATIVE — pas de
   fausse case en CSS, donc pas de clavier ni de lecteur d'écran à réécrire. */
input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--gold-deep);
  inline-size: 16px;
  block-size: 16px;
}

/* Le bouton du sélecteur de fichier : natif, mais habillé. Le remplacer par
   un faux bouton coûterait l'accessibilité que le navigateur donne. */
::file-selector-button {
  margin-inline-end: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-m);
  background: var(--surface);
  color: var(--ink);
  font-weight: 600;
  cursor: pointer;
}
::file-selector-button:hover { background: var(--surface-head); }

/* ===================================================================== */
/* 3. LA COQUE — sidebar navy, filet champagne                            */
/* ===================================================================== */
body.app {
  display: grid;
  grid-template-areas: "banner banner" "side main";
  grid-template-columns: var(--side-w) 1fr;
  grid-template-rows: auto 1fr;
  min-block-size: 100vh;
}
html.side-folded body.app { grid-template-columns: var(--side-w-rail) 1fr; }

/* --- Bandeau d'auth de dev : CRIANT, permanent (ADR-0037) --- */
.dev-banner {
  grid-area: banner;
  background: repeating-linear-gradient(135deg,
    var(--pending), var(--pending) 14px, var(--ink) 14px, var(--ink) 28px);
  color: var(--porcelain);
  text-align: center;
  padding-block: 6px;
  padding-inline: var(--sp-3);
  font-weight: 700;
  font-size: 13px;
  text-shadow: 0 1px 2px var(--ink);
}

.side {
  grid-area: side;
  background: var(--fondRail);
  color: var(--texteSecondaire);
  border-inline-end: 1px solid var(--railFilet);
}
.side-inner {
  position: sticky;
  inset-block-start: 0;
  block-size: 100%;
  max-block-size: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
/* Le rail clair du CMS de référence (docs/etude-cms/01-coque.md) : logo en
   tête, `‹` pour replier, les entrées dans l'ordre du CMS, l'active sur fond
   de surface en rouge de texte (maquette validée le 30/09). */
.side-head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding-block: var(--sp-4);
  padding-inline: var(--sp-4);
}
.brand { display: flex; align-items: center; gap: var(--sp-3); text-decoration: none; min-inline-size: 0; }
.brand img { flex: none; }
.brand-name {
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--texte);
  font-size: 17px;
}
.side-toggle {
  margin-inline-start: auto;
  background: none;
  border: none;
  color: var(--railTexteFaible);
  cursor: pointer;
  padding: var(--sp-1);
  border-radius: var(--r-s);
  line-height: 0;
}
.side-toggle:hover { color: var(--texte); background: var(--fondRailSurvol); }
.side-toggle svg { transition: transform 120ms; }
html.side-folded .side-toggle svg { transform: scaleX(-1); }
html[dir="rtl"] .side-toggle svg { transform: scaleX(-1); }
html[dir="rtl"].side-folded .side-toggle svg { transform: none; }

.side-nav { flex: 1; padding-block: var(--sp-2); padding-inline: var(--sp-3); overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.side-group {
  font-size: 11px; line-height: 16px; letter-spacing: 0.045em;
  text-transform: uppercase; font-weight: 600;
  color: var(--railTexteFaible);
  margin: 0;
  padding-block: var(--sp-4) var(--sp-1);
  padding-inline: var(--sp-3);
}
.side-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding-block: 8px;
  padding-inline: var(--sp-3);
  border-radius: var(--r-m);
  color: var(--texteSecondaire);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
}
.side-item svg { flex: none; }
a.side-item:hover { background: var(--fondRailSurvol); color: var(--texte); }
.side-item.active {
  background: var(--surface);
  color: var(--accentTexte);
  font-weight: 700;
}
/* Les sous-entrées (Médias › Images…) : retrait sous le parent. */
.side-sub { display: flex; flex-direction: column; padding-inline-start: 28px; }
.side-sub .side-item { font-size: 13px; padding-block: 5px; font-weight: 400; }
/* Ce qui n'est pas encore construit se voit, et le DIT (le motif « Premium »
   du CMS de référence, retourné en honnêteté : « bientôt », jamais un leurre). */
.side-soon { color: var(--texteDesactive); cursor: default; }
.soon {
  font-style: normal;
  font-size: 10px;
  letter-spacing: 0.045em;
  text-transform: uppercase;
  color: var(--attenteTexte);
  background: var(--attenteFond);
  border-radius: var(--r-pill);
  padding-block: 0;
  padding-inline: var(--sp-2);
  margin-inline-start: auto;
}
.side-foot {
  padding-block: var(--sp-4);
  padding-inline: var(--sp-5);
  border-block-start: 1px solid var(--railFilet);
  display: flex; flex-direction: column; gap: 2px;
}
.side-user {
  display: block;
  color: var(--railTexteFaible);
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Plié : le rail — badge et pictos seuls, libellés retirés du flux */
html.side-folded .brand-name,
html.side-folded .side-item span,
html.side-folded .soon,
html.side-folded .side-group,
html.side-folded .side-sub,
html.side-folded .side-user { display: none; }
html.side-folded .side-head { padding-inline: var(--sp-3); justify-content: center; flex-wrap: wrap; gap: var(--sp-2); }
html.side-folded .side-toggle { margin-inline-start: 0; }
html.side-folded .side-item { justify-content: center; padding-inline: 0; }
html.side-folded .side-foot { display: none; }

/* La BARRE DU HAUT (01-coque.md) : le titre de la page à gauche, le compte
   et le bouton d'envoi à droite. */
.barre {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding-block: var(--sp-3);
  padding-inline: var(--sp-8);
  border-block-end: 1px solid var(--bordure);
  background: var(--surface);
}
.barre-titre { font-size: 20px; line-height: 28px; font-weight: 700; margin: 0; margin-inline-end: auto; color: var(--texte); }
.barre-compte { color: var(--texteSecondaire); font-size: 13px; }

.main { grid-area: main; min-inline-size: 0; }

/* ===================================================================== */
/* 4. PAGE                                                                */
/* ===================================================================== */
.page {
  max-inline-size: 1280px;
  margin-inline: auto;
  padding-block: var(--sp-8) var(--sp-10);
  padding-inline: var(--sp-8);
}
.page-head {
  display: flex;
  align-items: baseline;
  gap: var(--sp-4);
  flex-wrap: wrap;
  margin-block-end: var(--sp-5);
}
.page-sub { color: var(--mist-deep); font-size: 13px; line-height: 18px; margin: 0; max-inline-size: 72ch; }
.footnote { color: var(--mist-deep); font-size: 12px; line-height: 18px; }
.backlink { color: var(--mist-deep); text-decoration: none; font-size: 13px; }
.backlink:hover { color: var(--ink); }
.tenant-chip {
  border: 1px solid var(--line-strong);
  background: var(--surface);
  border-radius: var(--r-pill);
  padding-block: 1px;
  padding-inline: var(--sp-3);
  font-size: 13px;
  color: var(--mist-deep);
}

/* ===================================================================== */
/* 5. LE VERDICT + LA SYNTHÈSE — la bonne nouvelle avant la table         */
/* ===================================================================== */
.pulse {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-l);
  padding-block: var(--sp-4);
  padding-inline: var(--sp-6);
  margin-block-end: var(--sp-4);
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  flex-wrap: wrap;
}
.verdict {
  font-size: 20px;
  line-height: 28px;
  font-weight: 700;
  margin: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.verdict::before {
  content: "";
  inline-size: 10px;
  block-size: 10px;
  border-radius: var(--r-pill);
  flex: none;
}
.verdict-ok { color: var(--live-ink); }
.verdict-ok::before { background: var(--live); }
.verdict-alert { color: var(--alert-ink); }
.verdict-alert::before { background: var(--alert); }
.verdict-pending { color: var(--pending-ink); }
.verdict-pending::before { background: var(--pending); }
.verdict-neutral { color: var(--ink); }
.verdict-neutral::before { background: var(--mist); }

.pulse-stats { display: flex; gap: var(--sp-8); margin-inline-start: auto; flex-wrap: wrap; }
.stat { text-align: center; min-inline-size: 56px; }
.stat b { display: block; font-size: 28px; line-height: 34px; letter-spacing: -0.015em; font-weight: 700; }
.stat span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px; line-height: 16px; letter-spacing: 0.045em;
  text-transform: uppercase; font-weight: 500;
  color: var(--mist-deep);
}
.stat .dot { inline-size: 7px; block-size: 7px; border-radius: var(--r-pill); flex: none; }
.dot-live { background: var(--live); }
.dot-alert { background: var(--alert); }
.dot-pending { background: var(--pending); }
.stat-dim b { color: var(--mist-deep); }

/* ===================================================================== */
/* 6. FILTRES — GET sans JS, selects habillés (chevron CSS pur : la CSP    */
/*    'self' interdit les data:)                                          */
/* ===================================================================== */
.filters { display: flex; gap: var(--sp-3); align-items: end; margin-inline-start: auto; font-size: 13px; }
.filters label { display: flex; flex-direction: column; gap: 2px; color: var(--mist-deep); font-weight: 500; }
.select { position: relative; display: inline-flex; }
.select select {
  appearance: none;
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-m);
  padding-block: 6px;
  padding-inline: var(--sp-3) var(--sp-8);
  min-inline-size: 132px;
  cursor: pointer;
}
.select::after {
  content: "";
  position: absolute;
  inset-inline-end: 12px;
  inset-block-start: 50%;
  inline-size: 7px;
  block-size: 7px;
  border-inline-end: 1.5px solid var(--mist-deep);
  border-block-end: 1.5px solid var(--mist-deep);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}
.select select:hover { border-color: var(--mist-deep); }
.filters button {
  font: inherit;
  font-weight: 700;
  color: var(--texteSurAction);
  background: var(--action);
  border: 1px solid var(--action);
  border-radius: var(--r-m);
  padding-block: 6px;
  padding-inline: var(--sp-4);
  cursor: pointer;
}
.filters button:hover { background: var(--depth); border-color: var(--depth); }

/* ===================================================================== */
/* 7. LA TABLE — le composant central de la supervision                   */
/* ===================================================================== */
.table-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-l);
  overflow-x: auto; /* une table large défile DANS sa carte, jamais la page */
}
table { border-collapse: collapse; inline-size: 100%; }
th {
  text-align: start;
  font-size: 11px;
  line-height: 16px;
  letter-spacing: 0.045em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--mist-deep);
  background: var(--surface-head);
  padding-block: 10px;
  padding-inline: var(--sp-3);
  border-block-end: 1px solid var(--line);
  white-space: nowrap;
}
td {
  padding-block: var(--sp-3);
  padding-inline: var(--sp-3);
  border-block-end: 1px solid var(--line);
  vertical-align: middle;
  font-size: 13px;
  line-height: 20px;
}
tbody tr:last-child td { border-block-end: none; }
tbody tr:hover td { background: var(--surface-head); }
th.num { text-align: end; }
/* L'en-tête long des générations respire sur deux lignes — la table tient
   dans sa carte à 1600px sans défiler */
th.th-gen { white-space: normal; max-inline-size: 130px; }

.device-link {
  font-weight: 400;
  text-decoration: none;
  border-block-end: 1px dotted var(--line-strong);
  /* Un identifiant d'écran ne se coupe JAMAIS : il se lit d'un bloc ou la
     table défile dans sa carte. */
  white-space: nowrap;
}
.device-link:hover { border-block-end: 1px solid var(--ink); }

/* La ligne muette : LA chose la plus contrastée de la page — le jugement
   visuel. Rien de décoratif ne crie plus fort qu'un muet. */
.row-silent td { background: var(--alert-bg); }
.row-silent td:first-child { box-shadow: inset 3px 0 0 var(--alert); }
[dir="rtl"] .row-silent td:first-child { box-shadow: inset -3px 0 0 var(--alert); }
.row-silent:hover td { background: var(--alert-bg); }

/* ===================================================================== */
/* 8. BADGES ET TAGS — couleur + LIBELLÉ, jamais la couleur seule         */
/* ===================================================================== */
.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 11px;
  line-height: 16px;
  letter-spacing: 0.045em;
  font-weight: 700;
  border-radius: var(--r-pill);
  padding-block: 3px;
  padding-inline: 10px;
  min-inline-size: 84px;
  white-space: nowrap;
}
.badge::before {
  content: "";
  inline-size: 7px;
  block-size: 7px;
  border-radius: var(--r-pill);
  flex: none;
}
.badge-online { background: var(--live-bg); color: var(--live-ink); }
.badge-online::before { background: var(--live); } /* LE teal comptable */
.badge-silent { background: var(--alert-bg); color: var(--alert-ink); }
.badge-silent::before { background: var(--alert); }
.row-silent .badge-silent { background: var(--surface); }
.badge-never_seen { background: var(--pending-bg); color: var(--pending-ink); }
.badge-never_seen::before { background: var(--pending); }

.tag {
  display: inline-block;
  font-size: 11px;
  line-height: 16px;
  border-radius: var(--r-s);
  padding-block: 1px;
  padding-inline: 6px;
  margin-inline-start: 6px;
  font-family: var(--font-ui);
  font-weight: 500;
  white-space: nowrap;
}
.tag-pending { background: var(--pending-bg); color: var(--pending-ink); }
.tag-warn { background: var(--alert-bg); color: var(--alert-ink); }
.action { color: var(--ink); font-weight: 700; margin-inline-start: 6px; white-space: nowrap; }
.alert-count {
  display: inline-block;
  background: var(--alert-strong);
  color: var(--surface);
  font-weight: 700;
  font-size: 12px;
  border-radius: var(--r-pill);
  min-inline-size: 22px;
  padding-inline: 6px;
  text-align: center;
}
.alert-zero { color: var(--mist-deep); }

/* ===================================================================== */
/* 9. LA LIGNE DE CADENCE — la signature (BRAND §5)                       */
/* ===================================================================== */
.th-cadence, .cadence-cell { inline-size: 210px; }
/* La cellule empile en HAUTEUR : la barre, puis les mots avec la signature
   à côté. En largeur, les trois poussaient la table hors de sa carte — et
   c'est la dernière colonne, donc celle qu'on ne voit jamais défiler. */
.cad { display: grid; gap: 2px; justify-items: start; }
.cad-ligne { display: flex; align-items: baseline; gap: var(--sp-2); }
.cad svg.cadence { inline-size: 120px; block-size: 10px; flex: none; }
.cad-wide svg.cadence { inline-size: 420px; block-size: 14px; }
.cad-wide { margin-block: var(--sp-3); }
.cad-live .seg { fill: var(--live); }
.cad-mute .seg { fill: var(--mist); opacity: 0.55; }
/* La boucle en MOTS d'abord, la signature de cadence en second registre
   (constat n°6 du 10/08 : une signature se reconnaît, elle ne répond pas à
   « qu'est-ce qui passe à l'écran ? »). */
.cad-lue { white-space: nowrap; }
.cad-notation { color: var(--mist-deep); white-space: nowrap; font-size: .82em; }
.cad-absent { color: var(--mist-deep); font-size: 12px; font-style: italic; }

/* ===================================================================== */
/* 10. FICHE DEVICE                                                       */
/* ===================================================================== */
.device-head { display: flex; align-items: center; gap: var(--sp-3); margin-block: var(--sp-3); }
.routed {
  border-inline-start: 3px solid var(--alert);
  background: var(--surface);
  border-block: 1px solid var(--line);
  border-inline-end: 1px solid var(--line);
  padding-block: var(--sp-3);
  padding-inline: var(--sp-4);
  border-start-end-radius: var(--r-m);
  border-end-end-radius: var(--r-m);
  max-inline-size: 78ch;
  font-weight: 500;
}
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  align-items: start; /* chaque carte à SA hauteur : pas de vide étiré */
  gap: var(--sp-4);
  margin-block: var(--sp-4);
}
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-l);
  padding-block: var(--sp-4);
  padding-inline: var(--sp-5);
  margin-block-end: var(--sp-4);
}
.cards .card { margin-block-end: 0; }
.card-forte { border-inline-start: 4px solid var(--alert); }
dl { margin: 0; }
.kpi {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-block: 5px;
  border-block-end: 1px solid var(--line);
}
.kpi:last-child { border-block-end: none; }
.kpi dt { color: var(--mist-deep); font-size: 13px; }
.kpi dd { margin: 0; text-align: end; }
.kpi.warn dd { color: var(--pending-ink); font-weight: 700; }
.kpi.bad dd { color: var(--alert-ink); font-weight: 700; }

/* --- Timeline 48 h --- */
svg.timeline { inline-size: 100%; block-size: 36px; }
.tl-track { fill: var(--porcelain); }
.tl-beat { fill: var(--live); }
.tl-throttled { fill: var(--pending); }
.tl-drop { fill: var(--alert); }

/* ===================================================================== */
/* 11. ALERTES — la tournée par métier                                    */
/* ===================================================================== */
/* Les colonnes de tête ont la MÊME largeur d'une carte-groupe à l'autre :
   la tournée du technicien se lit d'un bloc, l'œil suit une colonne unique
   même quand les tables sont des éléments distincts. Réservé à l'écran
   Alertes : sur la fiche device, une seule table — elle reste fluide. */
.alerts-tournee td:nth-child(1) { inline-size: 88px; }
.alerts-tournee td:nth-child(2) { inline-size: 132px; }
.alerts-tournee td:nth-child(3) { inline-size: 196px; }
.alerts-tournee td:nth-child(4) { inline-size: 132px; }
.alerts .detail { overflow-wrap: anywhere; }
.alerts .sev {
  display: inline-block;
  font-size: 11px;
  line-height: 16px;
  font-weight: 700;
  letter-spacing: 0.045em;
  border-radius: var(--r-pill);
  padding-block: 2px;
  padding-inline: 10px;
  text-align: center;
}
/* forte = la SEULE pilule pleine : intégrité/sécurité au-dessus de tout */
.sev-forte .sev { background: var(--alert-strong); color: var(--surface); }
.sev-haute .sev { background: var(--alert-bg); color: var(--alert-ink); }
.sev-moyenne .sev { background: var(--pending-bg); color: var(--pending-ink); }
.alerts .detail { color: var(--mist-deep); }
.group-card { padding-block-start: var(--sp-4); }
.group-card table { margin-inline: calc(-1 * var(--sp-5)); inline-size: calc(100% + 2 * var(--sp-5)); }
.group-card td:first-child,
/* F4 : les tables de carte à EN-TÊTE existent désormais (historique des
   générations, diff). Sans cette règle, la marge négative de la table
   rognait la première lettre du premier `th` — défaut F3.5 invisible tant
   qu'aucune table de carte n'avait de thead. */
.group-card th:first-child { padding-inline-start: var(--sp-5); }
.group-card td:last-child,
.group-card th:last-child { padding-inline-end: var(--sp-5); }
.scroll-x { overflow-x: auto; }

/* ===================================================================== */
/* 12. LES ÉTATS VIDES — le produit se vend dans ses vides                */
/* ===================================================================== */
.empty {
  text-align: center;
  color: var(--mist-deep);
  padding-block: var(--sp-10);
  padding-inline: var(--sp-6);
  font-size: 15px;
}
.all-clear {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-l);
  text-align: center;
  padding-block: var(--sp-10);
  padding-inline: var(--sp-6);
}
.all-clear-title {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  font-size: 20px;
  line-height: 28px;
  font-weight: 700;
  color: var(--live-ink);
  margin: 0 0 var(--sp-2);
}
.all-clear-title::before {
  content: "";
  inline-size: 10px;
  block-size: 10px;
  border-radius: var(--r-pill);
  background: var(--live);
}
.all-clear p { margin: 0; color: var(--mist-deep); max-inline-size: 56ch; margin-inline: auto; }

/* La carte d'appairage : le premier écran se raconte (ADR-0021) */
.onboard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-l);
  max-inline-size: 640px;
  margin-inline: auto;
  margin-block: var(--sp-8);
  padding-block: var(--sp-10);
  padding-inline: var(--sp-10);
  text-align: center;
}
.onboard img { display: block; margin-inline: auto; margin-block-end: var(--sp-4); }
.onboard h3 { font-size: 20px; line-height: 28px; font-weight: 700; margin: 0 0 var(--sp-2); }
.onboard-sub { color: var(--mist-deep); margin: 0 0 var(--sp-8); }
.onboard ol { list-style: none; margin: 0; padding: 0; text-align: start; display: grid; gap: var(--sp-5); }
.onboard li { display: flex; gap: var(--sp-4); align-items: baseline; }
.step-n {
  flex: none;
  inline-size: 28px;
  block-size: 28px;
  border-radius: var(--r-pill);
  background: var(--gold-hairline); /* l'or GUIDE : identité, pas un état */
  color: var(--gold-deep);
  font-weight: 700;
  font-size: 13px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transform: translateY(6px);
}
.onboard li b { display: block; }
.onboard li p { margin: 2px 0 0; color: var(--mist-deep); font-size: 13px; line-height: 20px; }

/* ===================================================================== */
/* 13. DOCUMENT BRUT (diagnostic opérateur, replié)                       */
/* ===================================================================== */
.raw-doc { margin-block: var(--sp-4); }
.raw-doc summary { cursor: pointer; color: var(--mist-deep); font-size: 13px; }
.raw-doc pre {
  background: var(--ink);
  color: var(--porcelain);
  padding-block: var(--sp-3);
  padding-inline: var(--sp-4);
  border-radius: var(--r-m);
  overflow-x: auto;
}

/* ===================================================================== */
/* 14. CONNEXION — la surface de marque (le seul dégradé plein écran)     */
/* ===================================================================== */
.login-body {
  background: linear-gradient(160deg, var(--depth), var(--ink));
  min-height: 100vh;
  display: grid;
  place-items: center;
  color: var(--porcelain);
}
.login-surface { text-align: center; padding: var(--sp-8); max-inline-size: 440px; }
.login-badge {
  display: block;
  margin-inline: auto;
  margin-block-end: var(--sp-4);
  border-radius: var(--r-pill);
  outline: 1px solid var(--gold-hairline);
  outline-offset: 6px;
}
.login-title { color: var(--gold); letter-spacing: 0.22em; font-size: 20px; line-height: 28px; margin: 0; }
.login-sub { color: var(--mist); margin-block: var(--sp-1) var(--sp-8); }
.login-none { color: var(--porcelain); }
.login-dev { border-radius: var(--r-m); margin-block-end: var(--sp-5); }
.login-btn {
  display: inline-block;
  background: var(--gold);
  color: var(--ink);
  font-weight: 700;
  text-decoration: none;
  border-radius: var(--r-m);
  padding-block: var(--sp-3);
  padding-inline: var(--sp-8);
  margin-block-start: var(--sp-2);
}
.login-btn:hover { background: var(--gold-hairline); }
.login-btn-disabled { background: var(--depth); color: var(--mist); cursor: not-allowed; }
.login-body .footnote { color: var(--mist); }

/* ===================================================================== */
/* 15. F4 — CONTENU ET PREUVE (bibliothèque, publications, facturable,     */
/*     encodages). Trois composants NOUVEAUX seulement, inscrits au        */
/*     design system avant emploi : .badge-neutral, .thumb, .money.        */
/* ===================================================================== */

/* --- Le badge NEUTRE : un état terminal qui n'est ni un incident ni une
   diffusion. `done` n'est PAS teal — le teal veut dire « ça diffuse en ce
   moment » et l'opérateur les compte. */
.badge-neutral { background: var(--surface-head); color: var(--mist-deep); }
.badge-neutral::before { background: var(--line-strong); }
.badge-ok { background: var(--live-bg); color: var(--live-ink); }
.badge-ok::before { background: var(--live); }
.badge-pending, .badge-queued, .badge-running {
  background: var(--pending-bg);
  color: var(--pending-ink);
}
.badge-pending::before, .badge-queued::before, .badge-running::before {
  background: var(--pending);
}
.badge-alert, .badge-refused { background: var(--alert-bg); color: var(--alert-ink); }
.badge-alert::before, .badge-refused::before { background: var(--alert); }
/* L'ÉCHEC infra est LE NÔTRE : le seul aplat plein de cet écran. */
.badge-failed { background: var(--alert-strong); color: var(--surface); }
.badge-failed::before { background: var(--surface); }
.row-silent .badge-alert { background: var(--surface); }
.tag-gold { background: var(--gold-hairline); color: var(--gold-deep); }

/* --- L'aperçu : l'image réelle sous plafond, ou une tuile TYPÉE. Zéro
   illustration, zéro ombre — une vraie vignette vidéo exigerait un
   encodage, c'est un acte, il n'est pas simulé ici. */
.thumb {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 48px;
  block-size: 27px;
  border-radius: var(--r-s);
  background: var(--surface-head);
  border: 1px solid var(--line);
  object-fit: contain;
  font-family: var(--font-ui);
  font-size: 9px;
  line-height: 12px;
  letter-spacing: 0.045em;
  font-weight: 700;
  color: var(--mist-deep);
  flex: none;
}
.thumb img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  background: var(--surface-head);
}

/* --- Le chiffre facturable : mono, tabulaire, à la fin — et JAMAIS
   arrondi (BRAND §7 : c'est une facture). */
.money {
  font-family: var(--font-data);
  text-align: end;
  white-space: nowrap;
}
tfoot th, tfoot td {
  background: var(--surface-head);
  border-block-start: 1px solid var(--line-strong);
  border-block-end: none;
  font-weight: 700;
  font-size: 13px;
  line-height: 20px;
  padding-block: var(--sp-3);
  padding-inline: var(--sp-3);
}
tfoot th { text-transform: none; letter-spacing: 0; color: var(--ink); }

/* --- Le second registre d'une cellule : la précision qui suit le chiffre
   (unité humaine, codec, source, bail) — jamais un état, jamais une
   couleur d'état. */
.meta {
  display: block;
  font-family: var(--font-data);
  font-size: 11px;
  line-height: 16px;
  color: var(--mist-deep);
}
.num .meta { text-align: end; }
.empty-cell { color: var(--mist-deep); }
.live-count {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--live-ink);
  font-weight: 500;
  white-space: nowrap;
}

/* --- Les dates de saisie du facturable : le même habillage que les selects */
input.date {
  font-family: var(--font-data);
  font-size: 13px;
  line-height: 20px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-m);
  padding-block: 6px;
  padding-inline: var(--sp-3);
}
.btn-export {
  display: inline-block;
  background: var(--action);
  color: var(--texteSurAction);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  border-radius: var(--r-m);
  padding-block: 7px;
  padding-inline: var(--sp-5);
  margin-inline-end: var(--sp-4);
}
.btn-export:hover { background: var(--depth); }
.export { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; margin-block: var(--sp-5) 0; }
.export .footnote { margin: 0; max-inline-size: 78ch; }

/* --- Le diff PAR CONTENU : ce qui entre, ce qui sort, ce qui reste. Le
   signe porte le sens AVEC la couleur (jamais la couleur seule). */
.diff-sign {
  font-family: var(--font-data);
  font-weight: 700;
  inline-size: 24px;
  text-align: center;
}
.diff-add td { background: var(--live-bg); }
.diff-add .diff-sign { color: var(--live-ink); }
.diff-del td { background: var(--alert-bg); }
.diff-del .diff-sign { color: var(--alert-ink); }
.diff-same td { color: var(--mist-deep); }
.diff-add:hover td { background: var(--live-bg); }
.diff-del:hover td { background: var(--alert-bg); }

/* --- Un travail refusé ou écarté : la VRAIE raison, en pleine largeur.
   Elle est longue par nature (la ligne fautive de l'outil) — elle se lit,
   elle ne se tronque pas. */
.job-forte { border-block-start: 1px solid var(--line); padding-block: var(--sp-4); }
.job-forte:first-of-type { border-block-start: none; padding-block-start: var(--sp-2); }
.job-head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin: 0 0 var(--sp-2);
  font-size: 13px;
  line-height: 20px;
}
.job-reason {
  margin: 0;
  background: var(--surface-head);
  border-inline-start: 3px solid var(--alert);
  border-radius: var(--r-s);
  padding-block: var(--sp-2);
  padding-inline: var(--sp-3);
  font-size: 12px;
  line-height: 18px;
  color: var(--ink);
  overflow-wrap: anywhere;
}

/* --- Indicateur de requête htmx ------------------------------------------
   htmx injecte ces règles en <style> INLINE par défaut ; notre CSP
   (style-src 'self', sans unsafe-inline) les bloque — une violation par
   navigation, ET l'indicateur resterait VISIBLE en permanence, l'inverse
   de son intention (mesuré au banc F3.5). L'injection est donc désactivée
   par le meta htmx-config de base.html, et les règles vivent ICI, dans une
   feuille 'self'. Même effet, zéro violation, CSP inchangée. */
.htmx-indicator { opacity: 0; visibility: hidden; }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
  opacity: 1;
  visibility: visible;
  transition: opacity 200ms ease-in;
}

/* --- F5.4 : le dépôt de la Bibliothèque (ADR-0040) ------------------------
   Le formulaire est la vérité (il POSTe sans JS) ; l'îlot upload.js n'est
   que le confort. Composants inscrits à FRONT-DESIGN-SYSTEM §5.4 : la zone
   de dépôt, la liste des fichiers choisis, la barre de progression. Aucun
   token nouveau — tout est composé des tokens du §2. */

/* la ligne d'attente d'un média en devenir : le filet est AMBRE (en cours),
   jamais rouge — le rouge reste au refus et à l'échec. */
.job-reason.job-attente { border-inline-start-color: var(--pending); }

.up-card h2 { margin-block: 0 var(--sp-3); font-size: 16px; line-height: 24px; }
.up-rangee {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--sp-4);
  margin-block-end: var(--sp-3);
}
.up-rangee label { font-size: 12px; color: var(--mist-deep); display: inline-grid; gap: var(--sp-1); }
.up-borne { margin: 0; color: var(--mist-deep); font-size: 12px; line-height: 18px; max-inline-size: 62ch; }

.up-zone {
  border: 2px dashed var(--line-strong);
  border-radius: var(--r-m);
  background: var(--surface-head);
  padding: var(--sp-5);
  text-align: center;
}
/* le retour visuel du survol de glisser-déposer — une classe togglée par
   l'îlot, JAMAIS un style inline (CSP 'self', la leçon --zc-ratio F5.2) */
.up-zone.up-survol { border-color: var(--ink); background: var(--surface); }
.up-invite { margin: 0; font-size: 15px; }
.up-ou { margin-block: var(--sp-1); color: var(--mist-deep); font-size: 12px; }
.up-parcourir { display: inline-block; font-size: 13px; }
.up-parcourir input[type="file"] { display: block; margin-inline: auto; margin-block-start: var(--sp-2); font-size: 12px; }

.up-liste { list-style: none; margin: var(--sp-3) 0 0; padding: 0; }
.up-item {
  display: grid;
  grid-template-columns: 48px minmax(140px, 1fr) minmax(160px, 2fr);
  gap: var(--sp-3);
  align-items: center;
  padding-block: var(--sp-2);
  border-block-start: 1px solid var(--line);
}
.up-item:first-child { border-block-start: none; }
/* l'identité dès la sélection : la vignette d'une IMAGE se dessine au
   canvas (createImageBitmap — une URL blob: violerait img-src 'self') */
.thumb canvas {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  background: var(--surface-head);
}
.up-nom { font-weight: 600; font-size: 13px; overflow-wrap: anywhere; }
.up-meta { color: var(--mist-deep); font-size: 12px; font-family: var(--mono, monospace); }
.up-suivi { display: grid; gap: var(--sp-1); }
.up-bar {
  block-size: 6px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface-head);
  overflow: hidden;
}
/* la barre avance par transform (scaleX posé par l'îlot en unité, pas un
   style de peinture) — l'ambre dit « en cours », comme partout */
.up-bar-fill {
  display: block;
  block-size: 100%;
  inline-size: 100%;
  background: var(--pending);
  transform-origin: 0 50%;
  transform: scaleX(0);
}
.up-msg { margin: 0; font-size: 12px; line-height: 18px; color: var(--mist-deep); overflow-wrap: anywhere; }
.up-item.up-refuse .up-msg { color: var(--alert-ink); }
.up-actions { margin-block: var(--sp-3) 0; }
.up-submit {
  padding: var(--sp-2) var(--sp-5);
  border: 1px solid var(--action);
  border-radius: var(--r-m);
  background: var(--action);
  color: var(--texteSurAction);
  font-weight: 700;
  cursor: pointer;
}
.up-submit:hover { background: var(--depth); border-color: var(--depth); }
.up-submit:disabled { opacity: 0.5; cursor: default; }
/* l'îlot actif remplace le bouton : chaque fichier part avec SA barre dès
   la sélection ; sans JS le bouton reste et le <form> POSTe — la vérité */
.up-js .up-submit { display: none; }
.up-js .up-actions { margin: 0; }

/* Le geste de chaque ligne de dépôt : annuler pendant l'envoi, réessayer
   quand le TRANSFERT a lâché, retirer tant que ça attend. Jamais
   « réessayer » sur un refus : le verdict vient du contenu, le rejouer
   donnerait le même, et proposer le geste serait mentir. */
.up-acte { margin-block-start: var(--sp-2); padding: 2px var(--sp-3); font-size: 12px; font-weight: 600; }
.up-bilan:not([hidden]) { display: block; margin: var(--sp-3) 0 0; }

/* ═══ SITE PUBLIC ═══════════════════════════════════════════════════════════
   La première surface que voit quelqu'un qui ne nous connaît pas encore, et
   la SEULE sans barre latérale : pas de navigation d'outil, pas d'état, pas
   de donnée. Un visiteur n'a rien à piloter — il a une décision à prendre.

   Elle emprunte les mêmes JETONS que le reste (couleurs, espacements,
   rayons) : c'est ce qui fait qu'on reconnaît le même produit en passant du
   site au tableau de bord. Ce qui change, c'est le rythme — plus d'air, des
   titres plus grands, une seule colonne. */

.site { background: var(--porcelain); color: var(--ink); }

.site-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-6);
  padding: var(--sp-5) var(--sp-8);
  background: var(--ink);
  /* LE filet identité, le même qu'ailleurs : l'or borne, il ne remplit pas. */
  border-block-end: 1px solid var(--gold);
}
.site-head .brand { color: var(--porcelain); }
.site-nav { display: flex; align-items: center; gap: var(--sp-6); }
.site-nav a { color: var(--porcelain); text-decoration: none; font-weight: 600; }
.site-nav a:hover { text-decoration: underline; }
/* SUR FOND SOMBRE, le primaire s'inverse : `--ink` sur `--ink` ne se voyait
   pas — le bouton d'entrée du site était devenu un lien fantôme. L'or porte
   l'action ici, et l'encre revient en texte : c'est le seul endroit où
   `--gold` sert de FOND, et il le fait sur un geste unique, jamais sur un
   état (BRAND §3). */
.site-nav .btn { text-decoration: none; }
.site-head .btn-primaire {
  background: var(--gold); border-color: var(--gold); color: var(--ink);
}
.site-head .btn-primaire:hover { background: var(--gold-hairline); border-color: var(--gold-hairline); }

.site-main { max-width: 900px; margin: 0 auto; padding: var(--sp-10) var(--sp-6); }
.site-main > section { margin-block-end: var(--sp-10); }
.site-main h2 { font-size: 24px; margin-block-end: var(--sp-5); }
.site-main h3 { font-size: 17px; margin-block-end: var(--sp-2); }
.site-main ol, .site-main ul { padding-inline-start: var(--sp-6); line-height: 1.7; }
.site-main li { margin-block-end: var(--sp-2); }

/* L'accroche. Une seule idée, en grand — jamais deux. */
.hero { text-align: center; padding-block: var(--sp-8) var(--sp-6); }
.hero h1 { font-size: clamp(28px, 5vw, 44px); line-height: 1.2; margin-block-end: var(--sp-5); }
.hero-sub {
  font-size: 18px; line-height: 1.6; color: var(--mist-deep);
  max-width: 620px; margin: 0 auto var(--sp-8);
}
.hero-actions { display: flex; gap: var(--sp-4); justify-content: center; flex-wrap: wrap; }

.btn-lg { padding: var(--sp-3) var(--sp-6); font-size: 16px; }

.etapes-liste { counter-reset: etape; list-style: none; padding: 0; }
.etapes-liste li {
  counter-increment: etape; position: relative;
  padding-inline-start: var(--sp-10); margin-block-end: var(--sp-4);
  font-size: 17px; line-height: 1.6;
}
.etapes-liste li::before {
  content: counter(etape);
  position: absolute; inset-inline-start: 0; inset-block-start: 0;
  width: 28px; height: 28px; border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--ink); color: var(--gold);
  font-variant-numeric: tabular-nums; font-weight: 700; font-size: 14px;
}

.atouts-grille {
  display: grid; gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.atouts-grille article {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-l); padding: var(--sp-5);
}
.atouts-grille p { color: var(--mist-deep); line-height: 1.6; margin: 0; }

.mono {
  font-family: var(--font-data); font-size: 13px;
  background: var(--surface-head); border: 1px solid var(--line);
  border-radius: var(--r-m); padding: var(--sp-3);
  /* Une empreinte se recopie en entier : elle défile, elle ne se tronque
     pas — un sha256 coupé ne protège de rien. */
  overflow-x: auto; white-space: pre;
}

/* `.page-head` est en COLONNES au tableau de bord (titre + actions sur une
   ligne). Sur le site, un titre et sa phrase se lisent l'un sous l'autre. */
.site-main .page-head { display: block; margin-block-end: var(--sp-8); }
.site-main .page-head h1 { font-size: 32px; margin-block-end: var(--sp-3); }
.site-main .page-head .page-sub { font-size: 17px; line-height: 1.6; max-width: 640px; }

/* Le formulaire des portes client (ADR-0054) : sur la surface de connexion,
   les champs s'empilent — une étiquette au-dessus de chaque champ, pleine
   largeur, et un seul bouton primaire. */
.login-form { display: grid; gap: var(--sp-4); text-align: start; margin-block: var(--sp-6); }
.login-form label { display: grid; gap: var(--sp-1); font-weight: 600; font-size: 14px; }
.login-form input { inline-size: 100%; font-weight: 400; }
.login-form .aide { font-weight: 400; font-size: 13px; color: var(--mist-deep); }
.login-form .login-btn { margin-block-start: var(--sp-2); }

.site-foot {
  border-block-start: 1px solid var(--line);
  padding: var(--sp-8) var(--sp-6);
  text-align: center; color: var(--mist-deep); font-size: 14px;
}

/* ---------- Le programme d'un écran (ADR-0055) ------------------------------
   Le pli « Quand » de « Diffuser sur… », la page Programme, et la ligne du
   parc qui dit le programme en mots. Tout sur les tokens existants. */
.card-h { margin: 0 0 var(--sp-3); font-size: 15px; font-weight: 600; letter-spacing: .01em; }
.bo-quand { display: grid; gap: var(--sp-2); }
.bo-choix { display: flex; gap: var(--sp-3); align-items: flex-start; padding: var(--sp-3) var(--sp-4); border: 1px solid var(--line); border-radius: var(--r-s); background: var(--surface); cursor: pointer; }
.bo-choix:hover { background: var(--surface-head); }
.bo-choix:has(input:checked) { border-color: var(--gold); box-shadow: inset 3px 0 0 var(--gold); }
.bo-choix input { margin-block-start: 4px; flex: none; }
.bo-choix b { font-size: 15px; }
.bo-detail { display: grid; gap: var(--sp-3); margin: 0 0 var(--sp-2) var(--sp-5); padding: var(--sp-3) var(--sp-4); border-inline-start: 2px solid var(--gold-hairline); }
.bo-jours { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.bo-heures { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: center; }
.bo-heures label { display: inline-flex; gap: var(--sp-2); align-items: center; }
.bo-reste label { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }
.bo-programme { margin: 2px 0 0 26px; }
.routed-ok { border-inline-start-color: var(--live); }
.routed-warn { border-inline-start-color: var(--pending); }
.prog-liste { list-style: none; margin: 0; padding: 0; }
.prog-entree { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); padding: var(--sp-3) 0; border-block-end: 1px solid var(--line); }
.prog-entree:last-child { border-block-end: 0; }
.prog-boucle { font-weight: 600; }
.prog-boucle a { color: inherit; }
.prog-quand { color: var(--mist-deep); }
.prog-retirer { margin-inline-start: auto; font: inherit; font-size: 13px; padding: var(--sp-1) var(--sp-3); border: 1px solid var(--line); border-radius: var(--r-s); background: var(--surface); cursor: pointer; }
.prog-retirer:hover { border-color: var(--alert); color: var(--alert); }
.fleet-programme { margin: 3px 0 0; font-weight: 400; }
.fleet-programme a { color: var(--gold-deep); }
/* Le dépôt : le bouton natif du navigateur (« Choose Files », en anglais)
   disparaît derrière un libellé à nous ; le champ reste focusable. */
.up-parcourir input[type="file"] { position: absolute; inline-size: 1px; block-size: 1px; opacity: 0; overflow: hidden; margin: 0; }
.up-parcourir { position: relative; }
.up-parcourir:focus-within .btn { outline: 2px solid var(--gold); outline-offset: 1px; }

/* ===================================================================== */
/* L5. TABLEAU DE BORD (docs/etude-cms/02-tableau-de-bord.md)             */
/* ===================================================================== */
.tdb { display: flex; flex-direction: column; gap: var(--sp-5); max-inline-size: 980px; margin-inline: 0; }
.tdb-accueil {
  background: var(--accent);
  color: var(--texteSurAction);
  border-radius: var(--r-l);
  padding-block: var(--sp-6);
  padding-inline: var(--sp-6);
}
.tdb-bonjour { margin: 0; font-size: 18px; font-weight: 700; }
.tdb-accroche { margin: var(--sp-1) 0 0; font-size: 14px; }
.tdb-carte {
  background: var(--surface);
  border: 1px solid var(--bordure);
  border-radius: var(--r-l);
  padding-block: var(--sp-5);
  padding-inline: var(--sp-6);
}
.tdb-carte-titre { margin: 0 0 var(--sp-4); font-size: 16px; font-weight: 700; color: var(--texte); }
.tdb-vide-titre { margin: 0; font-weight: 700; color: var(--texte); }
.tdb-vide-texte { margin: var(--sp-1) 0 var(--sp-4); color: var(--texteSecondaire); font-size: 14px; line-height: 20px; max-inline-size: 60ch; }
.tdb-tuiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--sp-3); }
.tdb-tuile {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-1);
  padding-block: var(--sp-4);
  background: var(--surfaceEnfoncee);
  border: 1px solid var(--bordure);
  border-radius: var(--r-m);
  text-decoration: none;
  color: var(--texteSecondaire);
}
.tdb-tuile:hover { border-color: var(--bordureForte); color: var(--texte); }
.tdb-tuile-nom { font-size: 13px; }
.tdb-tuile-n { font-size: 26px; line-height: 32px; font-weight: 700; color: var(--texte); font-variant-numeric: tabular-nums; }
.tdb-tuile-alerte .tdb-tuile-n { color: var(--alerteTexte); }
.tdb-pied { margin: var(--sp-4) 0 0; font-size: 13px; }
.tdb-pied a { color: var(--accentTexte); }
.bientot { max-inline-size: 640px; }
.bientot-marque { margin: 0 0 var(--sp-2); }

/* ADR-0077 — un réglage de la fiche écran (le fuseau). */
.reglage { margin-block-start: var(--sp-5); max-inline-size: 720px; }
.reglage-form { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
.reglage-label { color: var(--texteSecondaire); font-size: 14px; }
.reglage-ok { margin: 0 0 var(--sp-3); color: var(--diffusionTexte); background: var(--diffusionFond); border-radius: var(--r-m); padding: var(--sp-2) var(--sp-3); font-size: 13px; }
.reglage-note { margin: var(--sp-3) 0 0; color: var(--attenteTexte); font-size: 13px; }

/* L4 — le bouton d'envoi de la barre du haut (01-coque.md) et sa page. */
.envoi {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  border-radius: var(--r-m);
  padding-block: 7px; padding-inline: var(--sp-4);
  font-size: 13px; font-weight: 700; text-decoration: none;
  border: 1px solid transparent;
}
.envoi-attente { background: var(--action); color: var(--texteSurAction); }
.envoi-attente:hover { background: var(--actionSurvol); }
.envoi-ajour { background: var(--texte); color: var(--texteSurAction); }
.envoi-compte { background: var(--texteSurAction); color: var(--accentTexte); border-radius: var(--r-pill); min-inline-size: 22px; padding-inline: 6px; font-size: 12px; line-height: 20px; text-align: center; }
.envoi-page { display: flex; flex-direction: column; gap: var(--sp-4); max-inline-size: 880px; }
.envoi-liste { margin: 0 0 var(--sp-4); padding-inline-start: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-1); font-size: 14px; color: var(--texteSecondaire); }
.reglage-envoi { margin-block-start: var(--sp-4); padding-block-start: var(--sp-4); border-block-start: 1px solid var(--bordure); }

/* L5 — la liste Écrans (docs/etude-cms/08-ecrans.md). */
.ecrans { display: flex; flex-direction: column; gap: var(--sp-3); }
.ecrans-outils { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
.ecrans-outils input[type="search"] { min-inline-size: 260px; }
.ecrans-ajouter { margin-inline-start: auto; }
.ecrans-compte { margin: 0; color: var(--texteFaible); font-size: 13px; }
.ecrans-table { inline-size: 100%; }
.ecrans-nom a { color: var(--texte); font-weight: 600; text-decoration: none; }
.ecrans-nom a:hover { color: var(--accentTexte); }
.ecrans-actions { text-align: end; white-space: nowrap; }
.ecrans-actions a { color: var(--accentTexte); }
.envoi-etat { margin-inline-start: var(--sp-2); font-size: 12px; font-weight: 600; }
.envoi-etat-ok { color: var(--diffusionTexte); }
.envoi-etat-attente { color: var(--attenteTexte); }
/* Les trois états du CMS (ADR-0079) : une pastille, un mot. */
.statut { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; border-radius: var(--r-pill); padding-block: 2px; padding-inline: var(--sp-2); }
.statut::before { content: ""; inline-size: 7px; block-size: 7px; border-radius: 50%; background: currentColor; }
.statut-online { color: var(--diffusionTexte); background: var(--diffusionFond); }
.statut-offline { color: var(--alerteTexte); background: var(--alerteFond); }
.statut-non_inscrit { color: var(--texteSecondaire); background: var(--surfaceEnfoncee); }

/* L5c — la fiche d'un écran et « Ajouter un écran » (ADR-0079). */
.fiche { display: flex; flex-direction: column; gap: var(--sp-4); max-inline-size: 1040px; }
.fiche-grille { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: var(--sp-4); align-items: start; }
@media (max-width: 800px) { .fiche-grille { grid-template-columns: 1fr; } }
.fiche-colonne { display: flex; flex-direction: column; gap: var(--sp-4); }
.fiche-etat { display: flex; flex-direction: column; gap: var(--sp-3); }
.fiche-etat p { margin: 0; }
.fiche-id { color: var(--texteFaible); font-size: 13px; }
.fiche-form { display: flex; flex-direction: column; gap: var(--sp-3); }
.fiche-champ { display: flex; flex-direction: column; gap: var(--sp-1); font-size: 13px; color: var(--texteSecondaire); }
.fiche-champ b { color: var(--accentTexte); }
.fiche-champ input[type="text"] { max-inline-size: 420px; }
.fiche-aide { margin: 0; color: var(--texteFaible); font-size: 12px; line-height: 18px; }
.fiche-aide a { color: var(--accentTexte); }
.fiche-actions { display: flex; gap: var(--sp-2); justify-content: flex-end; margin: 0; }
.fiche-code { flex-direction: row; flex-wrap: wrap; align-items: center; }
.fiche-erreur { margin: 0 0 var(--sp-3); color: var(--alerteTexte); background: var(--alerteFond); border-radius: var(--r-m); padding: var(--sp-2) var(--sp-3); font-size: 13px; }
.fiche-lecteurs { display: flex; gap: var(--sp-3); }
.fiche-lecteur { display: flex; flex-direction: column; gap: 2px; border: 1px solid var(--bordure); border-radius: var(--r-m); padding: var(--sp-3) var(--sp-4); font-weight: 700; color: var(--texte); }
.fiche-lecteur small { font-weight: 400; color: var(--texteFaible); }
.fiche-lecteur-choisi { border-color: var(--accent); background: var(--accentFond); }

/* L5d — les Médias (docs/etude-cms/03-medias.md). */
.medias { display: flex; flex-direction: column; gap: var(--sp-3); }
.medias-titre { margin: var(--sp-2) 0 0; font-size: 15px; color: var(--texte); }
.medias-titre span { color: var(--texteFaible); font-size: 13px; margin-inline-start: var(--sp-2); }
.medias-table { inline-size: 100%; }
.medias-nom { display: flex; align-items: center; gap: var(--sp-3); }
.medias-nom-texte { display: flex; flex-direction: column; gap: 2px; min-inline-size: 0; }
.medias-details { color: var(--texteFaible); font-size: 12px; }
.medias-refs { color: var(--texteSecondaire); font-size: 13px; }
/* L5e — « Ajouter une Playlist » (type Classique). */
.liste-ajout summary { cursor: pointer; margin: 0; }
.liste-ajout[open] summary { margin-block-end: var(--sp-3); }
.liste-ajout .fiche-lecteurs { margin-block-end: var(--sp-3); }
.ecrans-nom .medias-details { display: block; }

/* Le menu ⋮ d'une ligne de bibliothèque (Dupliquer, Supprimer — L5f,
   ADR-0081) : un pli natif, dont l'ouverture tient lieu de confirmation. */
.co-menu { display: inline-block; position: relative; margin-inline-start: var(--sp-2); }
.co-menu summary { list-style: none; cursor: pointer; padding-inline: var(--sp-2); font-weight: 700; }
.co-menu summary::-webkit-details-marker { display: none; }
.co-menu[open] > form { display: block; }
.co-menu > form { display: none; margin: 0; }
.co-menu[open] {
  position: absolute;
  inset-inline-end: 0;
  z-index: 5;
  display: grid;
  gap: var(--sp-1);
  padding: var(--sp-2);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-m);
}
.co-menu button { inline-size: 100%; text-align: start; }
.co-suppr { color: var(--alert); }

/* L5d (2/3) — la Bibliothèque en miroir : outils, dossiers, fiche (ADR-0083). */
.me-outils { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: start; margin-block: var(--sp-2) var(--sp-4); }
.me-outils summary { cursor: pointer; font-weight: 600; font-size: 14px; }
.me-mots-liste a { margin-inline-end: var(--sp-2); }
.me-mots-liste a[aria-current="true"] { font-weight: 700; }
.me-dossier-form { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: end; margin-block-start: var(--sp-2); }
.me-dossier-ligne .thumb-dossier { display: inline-grid; place-items: center; inline-size: 2.5rem; block-size: 1.6rem; }
.me-deplacer { display: flex; gap: var(--sp-1); align-items: center; }
.me-colonnes { display: grid; grid-template-columns: minmax(16rem, 24rem) 1fr; gap: var(--sp-6); align-items: start; }
@media (max-width: 900px) { .me-colonnes { grid-template-columns: 1fr; } }
.me-details, .me-reglages { display: grid; gap: var(--sp-3); }
.me-apercu { display: grid; place-items: center; inline-size: 100%; aspect-ratio: 16 / 9; overflow: hidden; }
.me-apercu img { inline-size: 100%; block-size: 100%; object-fit: contain; }
.me-dl { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-1) var(--sp-3); margin: 0; font-size: 13px; }
.me-dl dt { color: var(--mist-deep); }
.me-dl dd { margin: 0; }
.me-utilise summary { cursor: pointer; }
.me-reglages .bo-champ input { max-inline-size: 32rem; }

/* L5d (3/3) — la disponibilité : l'icône, la fenêtre close, le filtre. */
.me-dispo-icone { margin-inline-start: var(--sp-1); font-size: 12px; color: var(--mist-deep); }
.me-dispo-icone.me-expire { color: var(--alert); font-weight: 600; }
.me-filtre-dispo { display: inline-flex; gap: var(--sp-2); font-size: 13px; }
.me-dispo-dates { display: grid; gap: var(--sp-2); padding-inline-start: var(--sp-4); }
.me-dispo-dates[hidden] { display: none; }

/* L5-compte — le menu du compte, Mon profil, Mes paramètres (ADR-0084). */
.compte-menu { position: relative; margin-inline-start: var(--sp-3); }
.compte-menu summary { list-style: none; cursor: pointer; font-size: 20px; line-height: 1; padding: var(--sp-1) var(--sp-2); }
.compte-menu summary::-webkit-details-marker { display: none; }
.compte-liste { position: absolute; inset-inline-end: 0; z-index: 10; display: grid; gap: var(--sp-1); min-inline-size: 14rem; padding: var(--sp-3); background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-m); }
.compte-liste a, .compte-liste button { text-align: start; padding: var(--sp-1) 0; }
.compte-liste form { margin: 0; }
.cpt-onglets { display: flex; flex-wrap: wrap; gap: var(--sp-6); margin-block-end: var(--sp-4); border-block-end: 1px solid var(--line); }
.cpt-onglets a { padding-block: var(--sp-2); color: var(--mist-deep); text-decoration: none; font-weight: 600; font-size: 14px; }
.cpt-onglets a[aria-current="page"] { color: var(--ink); border-block-end: 2px solid var(--gold); }
.cpt-carte { display: grid; gap: var(--sp-3); max-inline-size: 40rem; }
.cpt-rubrique { margin: var(--sp-4) 0 var(--sp-2); font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--mist-deep); }
.cpt-themes, .cpt-roles { display: grid; gap: var(--sp-2); border: 0; padding: 0; margin: 0; }
.cpt-theme { display: grid; gap: 2px; padding: var(--sp-3); border: 1px solid var(--line-strong); border-radius: var(--r-m); cursor: pointer; }
.cpt-theme:has(input:checked) { border-color: var(--gold); }
.cpt-sommaire { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; max-inline-size: 48rem; }
.cpt-sommaire li { display: flex; justify-content: space-between; align-items: center; gap: var(--sp-3); padding: var(--sp-3); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-m); }
.cpt-sommaire li > a, .cpt-sommaire li > span:first-child { display: grid; gap: 2px; text-decoration: none; color: var(--ink); }
.cpt-compteur { color: var(--mist-deep); font-size: 13px; white-space: nowrap; }

/* Les cases à cocher des réglages — communes (déplacées de compose.css pour
   les pages du compte, ADR-0084). */
.bo-case { display: flex; align-items: baseline; gap: var(--sp-2); padding-block: var(--sp-1); cursor: pointer; font-size: 14px; }
.bo-case .cp-meta { display: inline; }
.bo-case-off { color: var(--mist-deep); cursor: not-allowed; }
