/* ═══════════════════════════════════════════════════════════════════
   central/dashboard.css — feuille de style du dashboard central.

   Sortie VERBATIM du <style> du <head> de central/dashboard.html le
   2026-08-09 (règle de découpe des god-modules, décision 2026-07-09) :
   2 680 lignes, soit 22 % du fichier, qui butait sur son plafond de
   ratchet (12 072 / 12 077) — un simple correctif CSS n'y tenait plus.

   ⚠ La CASCADE dépend de la POSITION : ce fichier est chargé par un
   <link> posé exactement là où était le <style>, donc AVANT les 4 blocs
   <style> qui suivent dans le <body>. Déplacer le <link> changerait
   silencieusement quelles règles gagnent.

   ⚠ Servi par /dashboard.css (central/server.js) → ce n'est PAS un
   require() : il doit rester listé dans package.json > build.files et
   copié par les DEUX Dockerfiles, sinon 404 silencieux dans l'EXE ou
   dans le conteneur — dashboard SANS AUCUN STYLE (gotchas #81, #155).
   La passe (d) de check-prebuild le vérifie automatiquement.
   ═══════════════════════════════════════════════════════════════════ */
/* ─── Tokens (light + dark) ─────────────────────────────────────── */
:root,
[data-theme="light"] {
  --brand:        #c45200;
  --brand-soft:   #d97706;
  --brand-bg:     #fff4eb;
  --bg:           #f5f7fa;
  --bg-deep:      #ebeff5;
  --panel:        #ffffff;
  --panel-2:      #f9fafc;
  --border:       #e2e8f0;
  --border-soft:  #eef2f7;
  --text:         #1e293b;
  --text-2:       #475569;
  --text-3:       #94a3b8;
  --ok:           #16a34a;
  --info:         #0284c7;
  --warn:         #d97706;
  --bad:          #dc2626;
  --shadow:       0 1px 2px rgba(15,23,42,.04), 0 4px 16px rgba(15,23,42,.06);
  --shadow-pop:   0 8px 28px rgba(15,23,42,.12);
  /* Voile de bord d'une zone qui défile horizontalement : le SEUL indice qu'il
     reste du contenu hors écran. Sur tablette la barre de défilement est un
     survol qui n'apparaît qu'au geste (mesuré le 2026-08-09 : 0 px réservé),
     donc sans ce voile, rien ne dit à l'opérateur que ça continue. */
  --scroll-edge:  rgba(15,23,42,.18);
  color-scheme: light;
}
[data-theme="dark"] {
  --brand:        #f97316;
  --brand-soft:   #fb923c;
  --brand-bg:     rgba(251,146,60,.08);
  /* Palette « bleu nuit industriel » alignée sur le mockup central v2.
     Plus froide et plus identitaire (cohérente avec l'écran de pesée GEI). */
  --bg:           #0A0F15;
  --bg-deep:      #070B11;
  --panel:        #131C25;
  --panel-2:      #1B2733;
  --border:       #1E293B;
  --border-soft:  #334155;
  --text:         #e2e8f0;
  --text-2:       #94a3b8;
  --text-3:       #64748b;
  --ok:           #22c55e;
  --info:         #38bdf8;
  --warn:         #fbbf24;
  --bad:          #ef4444;
  --shadow:       0 1px 2px rgba(0,0,0,.3), 0 4px 16px rgba(0,0,0,.35);
  --shadow-pop:   0 12px 36px rgba(0,0,0,.5);
  --scroll-edge:  rgba(0,0,0,.6);
  color-scheme: dark;
}

/* ─── Base ─────────────────────────────────────────────────────── */
* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0; min-height: 100%;
  background: var(--bg); color: var(--text);
  font-family: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  font-size: 13px; line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overflow-x: hidden;     /* empêche tout débordement horizontal du viewport (mobile) */
}
.mono {
  font-family: ui-monospace, "SF Mono", "Menlo", "Consolas", "Roboto Mono", monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}
button { font: inherit; cursor: pointer; }
a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ─── App shell ────────────────────────────────────────────────── */
.app { display: flex; flex-direction: column; min-height: 100vh; }
.app[hidden] { display: none; }

/* ─── Header ───────────────────────────────────────────────────── */
.hdr {
  display: flex; align-items: center; gap: 14px;
  height: 56px;
  padding: 0 20px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 30;
}
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 14px; color: var(--text); }
.logo-mark {
  width: 28px; height: 28px; border-radius: 6px;
  background: linear-gradient(135deg, var(--brand), var(--brand-soft));
  color: #fff; font-weight: 800; font-size: 13px;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 1px rgba(0,0,0,.08) inset;
}
.logo b { color: var(--brand); }
.logo .sub { color: var(--text-2); font-size: 11px; font-weight: 500; margin-left: 2px; }

/* ─── Nom du central dans le header (avec marquee si trop long) ─── */
.hdr-central-name {
  display: flex; align-items: center; gap: 10px;
  max-width: 320px;
  overflow: hidden;
}
.hdr-central-name .sep { color: var(--border); font-weight: 400; font-size: 18px; opacity: 0.5; }
.hdr-central-name .marq {
  position: relative;
  overflow: hidden;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
  /* fade des bords pour l'effet "ça sort proprement" */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 12px, #000 calc(100% - 12px), transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 12px, #000 calc(100% - 12px), transparent 100%);
}
.hdr-central-name .marq-track {
  display: inline-block;
  font-size: 13px;
  font-weight: 700;
  color: var(--brand);
  letter-spacing: 0.2px;
  padding-left: 100%;             /* part de la droite */
  animation: marqMove 16s linear infinite;
}
.hdr-central-name .marq-track b { color: var(--text); font-weight: 600; margin: 0 6px; opacity: 0.8; }
.hdr-central-name .marq-track .icn { margin: 0 8px; opacity: 0.6; }
.hdr-central-name:hover .marq-track { animation-play-state: paused; }
/* Si le texte tient sans déborder, on désactive l'animation (classe .static
   posée par JS quand scrollWidth <= clientWidth) */
.hdr-central-name.static .marq-track {
  padding-left: 0;
  animation: none;
}
.hdr-central-name.static .marq {
  -webkit-mask-image: none;
          mask-image: none;
}
@keyframes marqMove {
  0%   { transform: translateX(0%); }
  100% { transform: translateX(-100%); }
}

/* ─── Animation Skeleton (chargement initial des pages) ─────────── */
.skel {
  display: inline-block;
  position: relative;
  overflow: hidden;
  background: var(--panel-2, #1F2733);
  border-radius: 4px;
  color: transparent !important;
  user-select: none;
  pointer-events: none;
  min-height: 12px;
}
.skel::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255,255,255,0.12) 50%,
    transparent 100%
  );
  animation: skelShimmer 1.4s ease-in-out infinite;
  transform: translateX(-100%);
}
[data-theme="light"] .skel { background: #E5E7EB; }
[data-theme="light"] .skel::after {
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(0,0,0,0.08) 50%,
    transparent 100%
  );
}
@keyframes skelShimmer {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* ─── Animation scroll reveal (fade + slide-up) ────────────────── */
/* Pose la classe .reveal sur tout élément qu'on veut animer.
   Au boot et au scroll, un IntersectionObserver ajoute .in dès que
   l'élément est visible — animation 400ms cubic-bezier. Une seule fois
   par élément (pas re-animer au scroll arrière). */
.reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.45s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.reveal.in {
  opacity: 1;
  transform: translateY(0);
}
/* Stagger : si plusieurs .reveal sont enfants directs d'un même conteneur,
   le 2e, 3e... démarrent légèrement plus tard. Effet "cascade" naturel. */
.reveal:nth-child(2) { transition-delay: 0.05s; }
.reveal:nth-child(3) { transition-delay: 0.10s; }
.reveal:nth-child(4) { transition-delay: 0.15s; }
.reveal:nth-child(5) { transition-delay: 0.20s; }
.reveal:nth-child(6) { transition-delay: 0.25s; }
/* Respecte la préférence système "réduire les animations" — accessibilité */
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}
/* Variantes utilitaires */
.skel-line  { display: block; height: 12px; border-radius: 3px; margin: 4px 0; }
.skel-line.lg { height: 18px; }
.skel-line.xl { height: 28px; }
.skel-line.w-80 { width: 80%; }
.skel-line.w-60 { width: 60%; }
.skel-line.w-40 { width: 40%; }
.skel-line.w-25 { width: 25%; }
.skel-card { display: block; width: 100%; height: 100%; min-height: 80px; border-radius: 8px; }
.skel-row { display: flex; gap: 10px; align-items: center; padding: 8px 0; }
.skel-row .skel { flex: 1; height: 14px; }
.skel-row .skel.fix { flex: 0 0 auto; width: 80px; }
.skel-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

.hdr .spacer { flex: 1; }

.poste-select {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 10px 6px 12px;
  background: var(--bg-deep);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 12px; color: var(--text);
  cursor: pointer;
  max-width: 260px;
}
.poste-select:hover { border-color: var(--brand); }
.poste-select .lbl { color: var(--text-2); font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; }
.poste-select .val { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.poste-select .car { color: var(--text-3); margin-left: auto; }

.health {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--text-2);
  padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--border);
}
.health .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 3px rgba(34,197,94,.18);
}
.health.bad .dot { background: var(--bad); box-shadow: 0 0 0 3px rgba(239,68,68,.18); }

.iconbtn {
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px; border: 1px solid var(--border);
  background: var(--bg-deep); color: var(--text-2);
}
.iconbtn:hover { color: var(--text); border-color: var(--brand); }

.user-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 4px 10px 4px 4px;
  border-radius: 999px; border: 1px solid var(--border);
  color: var(--text-2); font-size: 12px;
  background: transparent;
}
.avatar {
  width: 24px; height: 24px; border-radius: 50%;
  background: linear-gradient(135deg, var(--brand), var(--brand-soft));
  color: #fff; font-weight: 700; font-size: 10px;
  display: inline-flex; align-items: center; justify-content: center;
}

/* ─── Tabs nav (desktop) ────────────────────────────────────────── */
.tabs {
  display: flex; align-items: stretch;
  height: 44px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  padding: 0 16px; gap: 2px;
  position: sticky; top: 56px; z-index: 25;
}
.tab {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 0 14px;
  font-size: 13px; color: var(--text-2);
  background: transparent; border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.tab.active { color: var(--text); border-bottom-color: var(--brand); font-weight: 600; }
.tab:hover:not(.active) { color: var(--text); }
.tab .badge {
  font-size: 10px; padding: 1px 6px; border-radius: 999px;
  background: var(--bg-deep); color: var(--text-2);
}

/* ─── Bottom nav (mobile) ───────────────────────────────────────── */
.bnav {
  display: none;
  position: fixed; bottom: 0; left: 0; right: 0;
  height: 64px;
  background: var(--panel);
  border-top: 1px solid var(--border);
  z-index: 40;
  padding-bottom: env(safe-area-inset-bottom);
}
/* 5 colonnes : Vue · Pesées · [FAB Refresh] · Sites · Menu */
.bnav .row { display: grid; grid-template-columns: repeat(5, 1fr); height: 64px; }
.bnav button {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  background: transparent; border: 0;
  font-size: 10px; color: var(--text-2);
  min-height: 44px;
  cursor: pointer;
}
.bnav button.active { color: var(--brand); }
.bnav button.active svg { stroke-width: 2.4; }

/* FAB central — bouton actualiser surélevé */
.bnav .fab-wrap {
  display: flex; align-items: flex-start; justify-content: center;
  position: relative;
}
.bnav .fab {
  width: 56px; height: 56px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--brand), var(--brand-soft));
  border: 3px solid var(--panel);
  color: white;
  display: flex; align-items: center; justify-content: center;
  position: absolute; top: -22px;
  box-shadow: 0 4px 14px rgba(196,82,0,0.35);
  cursor: pointer;
  transition: transform .15s, box-shadow .15s;
}
.bnav .fab:hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(196,82,0,0.45); }
.bnav .fab:active { transform: scale(0.94); }
.bnav .fab.spinning svg { animation: bnav-spin 0.8s linear infinite; }
@keyframes bnav-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.bnav .fab-wrap .fab-lbl {
  position: absolute; bottom: 6px;
  font-size: 10px; color: var(--text-2); font-weight: 600;
}

/* ─── Sheet bottom (menu mobile : variante B — list-rows iOS-like) ─── */
/* Taille forcee des SVG dans la sheet (sinon ils heritent de regles
   globales et deviennent geants — vu sur tel : chevrons 60x60px qui
   ecrasent les sous-titres). */
.bnav-sheet svg { width: 16px; height: 16px; flex-shrink: 0; }
.bnav-sheet .sr-ic svg { width: 18px; height: 18px; }
.bnav-sheet .sr-arrow { width: 16px; height: 16px; }
.bnav-sheet .sc-where svg { width: 11px; height: 11px; }
.bnav-sheet .sc-logo img { width: 100%; height: 100%; }
.bnav-sheet-bg {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  z-index: 60;
  display: none;
  opacity: 0;
  transition: opacity .2s;
  /* un drag sur le fond sombre ne doit PAS scroller la page derrière */
  touch-action: none;
  overscroll-behavior: contain;
}
.bnav-sheet-bg.show { display: block; opacity: 1; }
/* Verrou de défilement : tant que la sheet est ouverte, la page derrière est
   figée (sinon un scroll dans le menu entraîne le fond — bug terrain 2026-07-23). */
html.sheet-open, body.sheet-open { overflow: hidden !important; }
.bnav-sheet {
  position: fixed; bottom: 0; left: 0; right: 0;
  background: var(--bg);
  border-radius: 24px 24px 0 0;
  z-index: 61;
  max-height: 88vh;
  display: flex; flex-direction: column;
  overflow: hidden;
  transform: translateY(100%);
  transition: transform .25s ease-out;
}
/* ⚠ L'ombre est portée par l'état OUVERT, jamais par le tiroir lui-même
   (2026-08-09, défaut signalé par l'utilisateur puis mesuré).
   Fermé, ce tiroir n'est pas masqué : il est seulement DÉPLACÉ sous l'écran
   par `translateY(100%)`. Il reste donc rendu (`visibility: visible`,
   `opacity: 1`), et une `box-shadow` déborde par définition HORS de la boîte
   qui la porte — ici 32 px vers le HAUT (décalage négatif), à 40 % d'opacité,
   en `z-index: 61`. Résultat : une bande sombre peinte en permanence sur le
   bas de la page, au-dessus de tout le reste, et qui ne bouge pas au
   défilement puisque l'élément est `fixed`.
   Le voile de fond `.bnav-sheet-bg` ne souffrait pas du problème : lui est
   éteint par `display: none`.
   ⚠ Ne PAS « corriger » en déplaçant davantage le tiroir : une ombre de 32 px
   de flou déborde toujours de quelque chose qu'on croit hors champ. Ce qui ne
   doit pas se voir ne doit pas être PEINT.
   Mesuré à 1183 px de large : ce n'était donc pas un défaut de tablette, la
   bande était là sur tous les écrans. */
.bnav-sheet.show { transform: translateY(0); box-shadow: 0 -8px 32px rgba(0,0,0,0.4); }
.bnav-sheet .grabber {
  width: 42px; height: 4px;
  background: var(--border-strong, var(--border-soft));
  border-radius: 99px;
  margin: 10px auto 0;
  flex-shrink: 0;
  cursor: pointer;
}
/* Header de la sheet avec bouton fermer (visible toujours) */
.bnav-sheet .sheet-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 16px 4px;
  flex-shrink: 0;
}
.bnav-sheet .sheet-head .sh-title {
  font-size: 16px; font-weight: 700; color: var(--text);
}
.bnav-sheet .sheet-head .sh-close {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--panel); border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-1); cursor: pointer;
  flex-shrink: 0;
}
.bnav-sheet .sheet-head .sh-close:active { background: var(--panel-2); }

/* Carte identité central */
.bnav-sheet .sheet-central {
  margin: 16px 14px 0;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 14px; padding: 12px 14px;
  display: flex; align-items: center; gap: 12px;
  flex-shrink: 0;
}
.bnav-sheet .sheet-central .sc-logo {
  width: 44px; height: 44px; border-radius: 11px;
  background: linear-gradient(135deg, var(--brand), var(--brand-soft, var(--brand)));
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; font-weight: 800; color: #fff;
  box-shadow: 0 4px 10px rgba(196,82,0,0.3);
  flex-shrink: 0;
  overflow: hidden;
}
.bnav-sheet .sheet-central .sc-logo img {
  width: 100%; height: 100%; object-fit: contain; padding: 4px;
}
.bnav-sheet .sheet-central .sc-info { flex: 1; min-width: 0; }
.bnav-sheet .sheet-central .sc-nm {
  font-size: 14px; font-weight: 700; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bnav-sheet .sheet-central .sc-where {
  font-size: 11.5px; color: var(--text-2); margin-top: 2px;
  display: flex; align-items: center; gap: 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bnav-sheet .sheet-central .sc-where svg { width: 11px; height: 11px; color: var(--brand); flex-shrink: 0; }
.bnav-sheet .sheet-central .sc-pill {
  background: rgba(16,185,129,0.15); color: #10B981;
  padding: 3px 8px; border-radius: 99px;
  font-size: 9.5px; font-weight: 700; font-family: var(--mono);
  display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0;
}
.bnav-sheet .sheet-central .sc-pill::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%; background: #10B981;
}
.bnav-sheet .sheet-central .sc-pill.warn { background: rgba(245,158,11,0.15); color: #F59E0B; }
.bnav-sheet .sheet-central .sc-pill.warn::before { background: #F59E0B; }
.bnav-sheet .sheet-central .sc-pill.bad { background: rgba(239,68,68,0.15); color: #EF4444; }
.bnav-sheet .sheet-central .sc-pill.bad::before { background: #EF4444; }

/* Section title */
.bnav-sheet .sheet-section-title {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 1.2px;
  color: var(--text-3); font-weight: 700;
  padding: 18px 18px 6px;
  flex-shrink: 0;
}

/* Zone scrollable (sections) */
.bnav-sheet .sheet-scroll {
  flex: 1; overflow-y: auto;
  padding-bottom: calc(14px + env(safe-area-inset-bottom));
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;   /* le scroll interne ne se propage pas au fond */
}

/* List card avec rows pleine largeur */
.bnav-sheet .sheet-list {
  margin: 0 14px 6px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 14px; overflow: hidden;
}
.bnav-sheet .sheet-row {
  padding: 13px 14px;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 12px; cursor: pointer;
  background: transparent; border-left: 0; border-right: 0; border-top: 0;
  width: 100%; text-align: left;
  color: var(--text);
  font-family: inherit;
  transition: background .15s;
}
.bnav-sheet .sheet-row:last-child { border-bottom: 0; }
.bnav-sheet .sheet-row:active,
.bnav-sheet .sheet-row:hover { background: var(--panel-2); }
.bnav-sheet .sheet-row .sr-ic {
  width: 36px; height: 36px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.bnav-sheet .sheet-row .sr-body { flex: 1; min-width: 0; }
.bnav-sheet .sheet-row .sr-lbl {
  font-size: 14px; font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bnav-sheet .sheet-row .sr-sub {
  font-size: 11.5px; color: var(--text-3); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bnav-sheet .sheet-row .sr-stat {
  font-family: var(--mono); font-size: 12px; color: var(--text-2);
  text-align: right; flex-shrink: 0;
}
.bnav-sheet .sheet-row .sr-stat b { color: var(--text); font-weight: 700; }
.bnav-sheet .sheet-row .sr-badge {
  background: #EF4444; color: #fff; font-size: 9.5px;
  padding: 2px 7px; border-radius: 99px; font-family: var(--mono); font-weight: 700;
  flex-shrink: 0;
}
.bnav-sheet .sheet-row .sr-arrow { color: var(--text-3); flex-shrink: 0; }
/* Couleurs par catégorie */
.bnav-sheet .sheet-row.cat-green  .sr-ic { background: rgba(16,185,129,0.15); color: #10B981; }
.bnav-sheet .sheet-row.cat-purple .sr-ic { background: rgba(167,139,250,0.18); color: #A78BFA; }
.bnav-sheet .sheet-row.cat-amber  .sr-ic { background: rgba(245,158,11,0.15); color: #F59E0B; }
.bnav-sheet .sheet-row.cat-blue   .sr-ic { background: rgba(59,130,246,0.15); color: #3B82F6; }
.bnav-sheet .sheet-row.cat-gray   .sr-ic { background: var(--panel-2); color: var(--text-2); }
.bnav-sheet .sheet-row.cat-brand  .sr-ic { background: rgba(196,82,0,0.15); color: var(--brand); }
.bnav-sheet .sheet-row.cat-danger .sr-ic { background: rgba(239,68,68,0.15); color: #EF4444; }
.bnav-sheet .sheet-row.cat-danger .sr-lbl { color: #EF4444; }

/* Toggle iOS-style (utilisé pour le switch thème) */
.bnav-sheet .sheet-toggle {
  width: 42px; height: 24px; border-radius: 99px;
  background: var(--panel-2); border: 1px solid var(--border);
  position: relative; cursor: pointer; transition: .2s;
  flex-shrink: 0;
}
.bnav-sheet .sheet-toggle::after {
  content: ''; position: absolute; top: 1px; left: 1px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--text-2); transition: .2s;
}
.bnav-sheet .sheet-toggle.on { background: var(--brand); border-color: var(--brand); }
.bnav-sheet .sheet-toggle.on::after { left: 19px; background: #fff; }

/* ─── Main ─────────────────────────────────────────────────────── */
main { flex: 1; padding: 18px 20px 28px; max-width: 1600px; width: 100%; margin: 0 auto; }
.page { display: none; flex-direction: column; gap: 14px; }
.page.active { display: flex; }

/* ─── Filter bar ───────────────────────────────────────────────── */
.filterbar {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; flex-wrap: wrap;
}
.filterbar .lead { color: var(--text-2); margin-right: 4px; display: inline-flex; align-items: center; gap: 4px; }
.filterbar .spacer { flex: 1; }
.filterbar .summary { font-size: 11px; color: var(--text-2); }
.filterbar .summary b.mono { font-weight: 700; color: var(--text); }
.filterbar .summary b.brand { color: var(--brand); }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 10px;
  border-radius: 7px;
  background: var(--panel); border: 1px solid var(--border);
  font-size: 12px; color: var(--text-2);
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
  user-select: none;
}
.chip:hover { background: var(--panel-2); border-color: var(--text-3); color: var(--text); }
.chip b { color: var(--text); font-weight: 500; }
.chip.active,
.chip.on { border-color: var(--brand); color: var(--brand); background: var(--brand-bg); font-weight: 600; }
.chip.on b, .chip.active b { color: var(--brand); }
/* Inputs date du journal : le picker natif suit le thème de la page */
#journal-chip-dates { cursor: default; }
#journal-chip-dates input[type="date"] { color-scheme: dark; }
[data-theme="light"] #journal-chip-dates input[type="date"] { color-scheme: light; }

.period {
  display: inline-flex;
  background: var(--bg-deep);
  border: 1px solid var(--border);
  border-radius: 8px; padding: 2px;
  font-size: 11px;
}
.period button {
  background: transparent; border: 0; color: var(--text-2);
  padding: 4px 10px; border-radius: 6px; font-size: 11px;
}
.period button.active {
  background: var(--panel); color: var(--text);
  box-shadow: 0 0 0 1px var(--border);
}

.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 7px;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border);
  font-size: 12px;
}
.btn:hover { border-color: var(--brand); }
.btn.primary { background: var(--brand); color: #fff; border-color: var(--brand); }
.btn.primary:hover { background: var(--brand-soft); border-color: var(--brand-soft); }
.btn.ghost { background: transparent; }

/* ─── KPI grid ─────────────────────────────────────────────────── */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 10px;
}
.kpi {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow);
}
.kpi .label {
  font-size: 10px; color: var(--text-2);
  text-transform: uppercase; letter-spacing: .06em;
  display: flex; align-items: center; gap: 5px;
}
.kpi .label svg { color: var(--brand); }
.kpi .value {
  font-family: ui-monospace, "SF Mono", monospace;
  font-variant-numeric: tabular-nums;
  font-size: 22px; font-weight: 700; margin-top: 4px;
  letter-spacing: -.02em;
}
.kpi .value .unit { font-size: 11px; color: var(--text-2); font-weight: 500; margin-left: 3px; }
.kpi .delta {
  font-size: 10px; margin-top: 2px;
  display: flex; align-items: center; gap: 3px;
}
.kpi .delta.up { color: var(--ok); }
.kpi .delta.down { color: var(--bad); }
.kpi .delta.flat { color: var(--text-3); }
.kpi .spark {
  position: absolute; right: 10px; top: 10px; opacity: .7;
}

/* ─── Panel ────────────────────────────────────────────────────── */
.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: var(--shadow);
  display: flex; flex-direction: column;
}
.panel-hd {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border-soft);
  gap: 8px;
}
.panel-hd h3 { margin: 0; font-size: 13px; font-weight: 600; }
.panel-hd .sub { font-size: 11px; color: var(--text-2); }
.panel-bd { padding: 12px 16px; }
.panel-bd.flush { padding: 0; }

/* ─── Pills ────────────────────────────────────────────────────── */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 500;
  border: 1px solid transparent;
  white-space: nowrap;
}
.pill .dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.pill.ok   { background: rgba(22,163,74,.10);  color: var(--ok);   border-color: rgba(22,163,74,.25); }
.pill.ok   .dot { background: var(--ok); box-shadow: 0 0 0 2px rgba(22,163,74,.2); }
.pill.warn { background: rgba(217,119,6,.10); color: var(--warn); border-color: rgba(217,119,6,.25); }
.pill.warn .dot { background: var(--warn); }
.pill.bad  { background: rgba(220,38,38,.10);  color: var(--bad);  border-color: rgba(220,38,38,.25); }
.pill.bad  .dot { background: var(--bad); box-shadow: 0 0 0 2px rgba(220,38,38,.25); animation: dotPulse 2s ease-in-out infinite; }
.pill.idle { background: var(--bg-deep); color: var(--text-2); border-color: var(--border); }
.pill.idle .dot { background: var(--text-3); }

.sens {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; padding: 1px 6px; border-radius: 4px;
  font-weight: 600; font-family: inherit;
}
.sens.in  { background: rgba(2,132,199,.10);  color: var(--info); }
.sens.out { background: rgba(217,119,6,.10); color: var(--brand-soft); }

/* ─── Table ────────────────────────────────────────────────────── */
.tbl-wrap { overflow: auto; }
/* Indicateur de scroll (« molette ») : chevron ▾ au bas d'une zone scrollable —
   visible seulement s'il reste du contenu dessous, disparaît une fois en bas. */
.scroll-hint-wrap { position: relative; }
.scroll-hint {
  position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%);
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand, #F97316); color: #fff;
  box-shadow: 0 3px 10px rgba(0,0,0,.42);
  opacity: 0; pointer-events: none; z-index: 6;
  transition: opacity .25s ease;
}
.scroll-hint.show { opacity: .92; animation: scrollHintBounce 1.5s ease-in-out infinite; }
.scroll-hint svg { width: 16px; height: 16px; display: block; }
@keyframes scrollHintBounce {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50%      { transform: translateX(-50%) translateY(4px); }
}
/* Scrollbar visible/stylée pour ces zones (renforce l'affordance « molette »). */
.scroll-hint-wrap .tbl-wrap { scrollbar-width: thin; }
.scroll-hint-wrap .tbl-wrap::-webkit-scrollbar { width: 11px; height: 11px; }
.scroll-hint-wrap .tbl-wrap::-webkit-scrollbar-thumb { background: var(--border, #1E293B); border-radius: 6px; border: 2px solid transparent; background-clip: padding-box; }
.scroll-hint-wrap .tbl-wrap::-webkit-scrollbar-thumb:hover { background: var(--brand, #F97316); background-clip: padding-box; }
.tbl { width: 100%; border-collapse: collapse; font-size: 12px; }
.tbl th {
  text-align: left; font-weight: 600; font-size: 10.5px;
  color: var(--brand); text-transform: uppercase; letter-spacing: .06em;
  padding: 8px 12px; border-bottom: 2px solid var(--brand);
  background: var(--panel-2); position: sticky; top: 0;
}
.tbl td {
  padding: 8px 12px; border-bottom: 1px solid var(--border-soft);
  vertical-align: middle;
}
.tbl tr:last-child td { border-bottom: 0; }
.tbl tr:hover td { background: var(--panel-2); }
.tbl .num { text-align: right; font-family: ui-monospace, "SF Mono", monospace; font-variant-numeric: tabular-nums; }
.tbl .net { font-weight: 700; color: var(--brand); }

/* ─── Bar row (top produits) ───────────────────────────────────── */
.bar-row {
  display: grid; grid-template-columns: 18px 1fr auto;
  gap: 6px; align-items: center; padding: 7px 0;
}
.bar-row .rank { font-size: 11px; color: var(--text-3); font-family: ui-monospace, monospace; }
.bar-row .nm { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-row .vl { font-size: 12px; font-weight: 600; font-family: ui-monospace, monospace; }
.bar-row .vl .u { color: var(--text-2); font-weight: 400; }
.bar-track { grid-column: 1 / -1; height: 6px; border-radius: 3px; background: var(--border-soft); overflow: hidden; }
.bar-fill { height: 100%; background: linear-gradient(90deg, var(--brand), var(--brand-soft)); border-radius: 3px; }

/* ─── Mobile cards (pesées) ────────────────────────────────────── */
.mcard {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  display: grid; grid-template-columns: 1fr auto;
  gap: 6px 12px; align-items: baseline;
  box-shadow: var(--shadow);
  position: relative;
}
.mcard .plaque { font-weight: 700; font-size: 14px; font-family: ui-monospace, "SF Mono", monospace; }
.mcard .net { font-family: ui-monospace, "SF Mono", monospace; font-weight: 700; font-size: 15px; color: var(--brand); }
.mcard .meta { grid-column: 1 / -1; font-size: 11px; color: var(--text-2); display: flex; gap: 10px; flex-wrap: wrap; }
.mcard .meta b { color: var(--text); font-weight: 500; }
/* Mode suppression : carte avec checkbox visible + état sélectionné */
.mcard.delmode { padding-left: 42px; cursor: pointer; -webkit-tap-highlight-color: rgba(220,38,38,0.15); }
.mcard.delmode::before {
  content: '';
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px;
  border: 2px solid var(--border); border-radius: 5px;
  background: var(--bg);
  transition: all 0.12s ease;
}
.mcard.delmode.sel {
  background: rgba(220,38,38,0.08);
  border-color: rgba(220,38,38,0.45);
}
.mcard.delmode.sel::before {
  background: #DC2626;
  border-color: #DC2626;
}
.mcard.delmode.sel::after {
  content: '';
  position: absolute; left: 17px; top: 50%; transform: translateY(-60%) rotate(45deg);
  width: 6px; height: 12px;
  border: solid #fff;
  border-width: 0 2.5px 2.5px 0;
  pointer-events: none;
}

/* ─── Charts ───────────────────────────────────────────────────── */
.spark, .barchart { display: block; width: 100%; }

/* ─── Layout helpers ───────────────────────────────────────────── */
.row { display: grid; gap: 12px; }
.row.r2-3 { grid-template-columns: 1.4fr 1fr; }
.row.r3   { grid-template-columns: 1.4fr 1fr 1fr; }
.row.r2   { grid-template-columns: 1fr 1fr; }
.row.r3eq { grid-template-columns: repeat(3, 1fr); }

/* ─── Login ────────────────────────────────────────────────────── */
.login-bg {
  position: fixed; inset: 0;
  /* Split-screen : panneau Flux (gauche) + formulaire (droite), même arrière-plan. */
  display: grid; grid-template-columns: minmax(0, 1fr) clamp(400px, 33vw, 600px); align-items: stretch;
  background: var(--bg);   /* fond plat (validé) — le dégradé était retiré au mockup */
  z-index: 100;
}
.login-right {
  display: flex; align-items: center; justify-content: center;
  padding: 24px; overflow: auto;
}
@media (max-width: 880px) {
  .login-bg { grid-template-columns: 1fr; }
  .login-left { display: none; }      /* sous 880px : juste le formulaire centré (comportement actuel) */
}
.login-card {
  width: 100%; max-width: 380px;
}
.login-card .brand {
  text-align: center; margin-bottom: 28px;
}
.login-card .brand .mark {
  width: 56px; height: 56px; border-radius: 14px;
  background: linear-gradient(135deg, var(--brand), var(--brand-soft));
  color: #fff; font-weight: 800; font-size: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 4px var(--brand-bg), 0 8px 24px rgba(196,82,0,.2);
  margin-bottom: 14px;
}
.login-card .brand h1 { margin: 0; font-size: 20px; }
.login-card .brand h1 b { color: var(--brand); }
.login-card .brand .sub { font-size: 12px; color: var(--text-2); margin-top: 4px; }
.login-card .box {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; padding: 24px;
  box-shadow: var(--shadow-pop);
}
.login-card label.fld {
  display: block; font-size: 11px; color: var(--text-2);
  text-transform: uppercase; letter-spacing: .06em; margin-bottom: 6px;
}
.login-card .srv {
  padding: 10px 12px; background: var(--bg-deep);
  border: 1px solid var(--border); border-radius: 7px;
  display: flex; justify-content: space-between; align-items: center;
  font-family: ui-monospace, monospace; font-size: 12px; color: var(--text-2);
}
.login-card .keyfld {
  width: 100%; padding: 11px 12px;
  background: var(--bg-deep); border: 1px solid var(--border);
  border-radius: 7px; color: var(--text);
  font-family: ui-monospace, monospace; font-size: 13px;
  outline: none;
}
.login-card .keyfld:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-bg);
}
.login-card .err {
  margin-top: 10px; font-size: 12px; color: var(--bad);
  display: none;
}
.login-card .err.show { display: block; }

/* ─── Login : panneau gauche « Constellation » (split-screen, classes scopées .lgc-*) ── */
.login-left {
  --lgc-accent: var(--brand);
  --lgc-vis-1:#0d1924; --lgc-vis-2:#080d13;
  --lgc-ink:#dde7ef; --lgc-ink-2:#93a4b3;
  --lgc-line:rgba(255,255,255,.12);
  --lgc-node:#14202c; --lgc-node-line:rgba(255,255,255,.18);
  --lgc-grid:rgba(120,165,200,.085); --lgc-glow:rgba(249,115,22,.16);
  --lgc-card:rgba(11,18,26,.66); --lgc-card-line:rgba(255,255,255,.1);
  position: relative; overflow: hidden;
  background: radial-gradient(125% 100% at 32% 22%, var(--lgc-vis-1), var(--lgc-vis-2) 72%);
  container-type: size;
}
html[data-theme="light"] .login-left {
  --lgc-vis-1:#dde8ef; --lgc-vis-2:#eaf1f6;
  --lgc-ink:#15242f; --lgc-ink-2:#566875;
  --lgc-line:rgba(20,48,68,.18);
  --lgc-node:#ffffff; --lgc-node-line:rgba(20,48,68,.2);
  --lgc-grid:rgba(40,85,115,.1); --lgc-glow:rgba(249,115,22,.14);
  --lgc-card:rgba(255,255,255,.72); --lgc-card-line:rgba(20,48,68,.12);
}
.login-left::before { /* grille de fond */
  content:""; position:absolute; inset:-2px;
  background-image:
    linear-gradient(var(--lgc-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--lgc-grid) 1px, transparent 1px);
  background-size:2.6cqmin 2.6cqmin;
  -webkit-mask:radial-gradient(120% 95% at 50% 45%, #000 50%, transparent 92%);
          mask:radial-gradient(120% 95% at 50% 45%, #000 50%, transparent 92%);
  opacity:.7; pointer-events:none;
}
.lgc-scan {
  position:absolute; inset:0; pointer-events:none; z-index:6;
  background:radial-gradient(130% 120% at 50% 40%, transparent 55%, rgba(0,0,0,.28) 100%);
}
html[data-theme="light"] .lgc-scan { background:radial-gradient(130% 120% at 50% 40%, transparent 60%, rgba(30,55,80,.12) 100%); }
.lgc-stage { position:absolute; inset:0; font-size:clamp(13px, 3.35cqmin, 42px); }
.lgc-svg { width:100%; height:100%; }

/* badges + légende */
.lgc-status, .lgc-rt {
  position:absolute; z-index:7; top:1.15em;
  display:flex; align-items:center; gap:.5em;
  font-size:.56em; font-weight:500; letter-spacing:.4px; color:var(--lgc-ink-2);
  background:var(--lgc-card); border:1px solid var(--lgc-card-line);
  padding:.5em .85em; border-radius:999px;
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
}
.lgc-status { left:1.15em; } .lgc-rt { right:1.15em; }
.lgc-status b { color:var(--lgc-ink); font-family:ui-monospace, monospace; font-weight:600; }
.lgc-live { width:.6em; height:.6em; border-radius:50%; background:var(--lgc-accent); position:relative; }
.lgc-live::after { content:""; position:absolute; inset:0; border-radius:50%; background:var(--lgc-accent); animation:lgc-ping 2.4s ease-out infinite; }
@keyframes lgc-ping { 0%{transform:scale(1);opacity:.7} 80%,100%{transform:scale(3.2);opacity:0} }

/* constellation (réseau hub-and-spoke) */
.lgc-net { position:absolute; inset:0; }
.lgc-net .radar { transform-box:view-box; transform-origin:50px 50px; animation:lgc-spin 16s linear infinite; }
@keyframes lgc-spin { to { transform:rotate(360deg); } }
.lgc-net .flow { stroke:var(--lgc-accent); stroke-width:.5; fill:none; stroke-linecap:round; stroke-dasharray:.4 4.6; animation:lgc-march 1.6s linear infinite; }
@keyframes lgc-march { to { stroke-dashoffset:-5; } }
.lgc-net .link { stroke:var(--lgc-line); stroke-width:.35; fill:none; }
.lgc-net .ring { fill:none; stroke:var(--lgc-accent); stroke-width:.4; transform-box:view-box; transform-origin:center; animation:lgc-pulse 3.4s ease-out infinite; }
@keyframes lgc-pulse { 0%{transform:scale(.4);opacity:.65} 75%,100%{transform:scale(1.9);opacity:0} }
.lgc-net .node { transform-box:view-box; transform-origin:center; }
.lgc-net .node circle.body { fill:var(--lgc-node); stroke:var(--lgc-node-line); stroke-width:.4; }
.lgc-net .node circle.glow { fill:var(--lgc-accent); animation:lgc-twinkle 3s ease-in-out infinite; }
@keyframes lgc-twinkle { 0%,100%{opacity:.55;transform:scale(1)} 50%{opacity:1;transform:scale(1.25)} }
.lgc-net .hub-core { fill:var(--lgc-accent); }
.lgc-net .hub-halo { fill:var(--lgc-glow); }
.lgc-net text { font-family:ui-monospace, monospace; font-weight:500; fill:var(--lgc-ink-2); font-size:2.05px; letter-spacing:.2px; }
.lgc-net .hub-label { fill:var(--lgc-ink); font-weight:600; font-size:2.4px; letter-spacing:.6px; }

/* ─── Login : bouton « Se connecter » (style Claude design) ─────── */
.lgc-submit {
  position:relative; overflow:hidden;
  width:100%; border:0; cursor:pointer; color:#fff;
  font-family:inherit; font-size:15.5px; font-weight:600; letter-spacing:.3px;
  background:linear-gradient(180deg, var(--brand-soft), var(--brand));
  border-radius:11px; padding:15px 16px;
  display:flex; align-items:center; justify-content:center; gap:9px;
  box-shadow:0 12px 26px -12px rgba(196,82,0,.6), inset 0 1px 0 rgba(255,255,255,.25);
  transition:transform .15s, box-shadow .25s, filter .2s;
}
.lgc-submit:hover { filter:brightness(1.05); box-shadow:0 16px 30px -12px rgba(196,82,0,.7), inset 0 1px 0 rgba(255,255,255,.3); }
.lgc-submit:active { transform:translateY(1px) scale(.995); }
.lgc-submit .lgc-arr { width:18px; height:18px; }
.lgc-submit .lgc-spin { display:none; width:18px; height:18px; border:2px solid rgba(255,255,255,.4); border-top-color:#fff; border-radius:50%; animation:lgc-spin .7s linear infinite; }
.lgc-submit.loading .lgc-lbl, .lgc-submit.loading .lgc-arr { display:none; }
.lgc-submit.loading .lgc-spin { display:block; }
.lgc-submit::after { content:""; position:absolute; top:0; left:-60%; width:40%; height:100%; background:linear-gradient(100deg, transparent, rgba(255,255,255,.35), transparent); transform:skewX(-18deg); animation:lgc-shine 5s ease-in-out infinite; }
@keyframes lgc-shine { 0%,100%{left:-60%} 55%,75%{left:130%} }

/* ─── Login : formulaire droit conforme au design (scopé .lgcf-*) ─── */
.login-right form:not(#login-change) { font-size: 16px; }
.login-right { position:relative; background:var(--panel); border-left:1px solid var(--border); }
.login-right::before { content:""; position:absolute; top:0; left:0; right:0; height:30%; background:linear-gradient(180deg, var(--brand-bg), transparent); opacity:.6; pointer-events:none; }
.login-right > form { position:relative; z-index:1; }

.lgcf-brand { display:flex; align-items:center; gap:.8em; margin-bottom:.5em; }
.lgcf-brand .nm { line-height:1.1; }
.lgcf-brand .nm h1 { margin:0; font-size:1.32em; font-weight:700; letter-spacing:.2px; color:var(--text); }
.lgcf-brand .nm h1 em { font-style:normal; color:var(--brand); }
.lgcf-brand .nm .tag { font-size:.74em; color:var(--text-3); font-family:ui-monospace, monospace; letter-spacing:.3px; display:flex; align-items:center; gap:.4em; margin-top:.2em; }
.lgcf-subtitle { margin:.9em 0 1.05em; font-size:.92em; color:var(--text-2); line-height:1.5; }

.lgcf-server { display:flex; align-items:center; gap:.7em; background:var(--bg-deep); border:1px solid var(--border); border-radius:10px; padding:.7em .8em; margin-bottom:1.05em; }
.lgcf-server .sicon { width:2em; height:2em; border-radius:8px; background:var(--panel-2); display:grid; place-items:center; color:var(--text-2); flex:0 0 auto; }
.lgcf-server .sicon svg { width:1.05em; height:1.05em; }
.lgcf-server .sbody { flex:1; min-width:0; }
.lgcf-server .slabel { font-size:.64em; letter-spacing:1px; text-transform:uppercase; color:var(--text-3); font-family:ui-monospace, monospace; }
.lgcf-server .surl { display:block; color:var(--text); font-family:ui-monospace, monospace; font-size:.82em; font-weight:500; margin-top:.1em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.lgcf-health { flex:0 0 auto; display:flex; align-items:center; gap:.4em; background:rgba(54,211,153,.12); border:1px solid rgba(54,211,153,.4); color:var(--ok); font-family:ui-monospace, monospace; font-size:.66em; font-weight:600; letter-spacing:.4px; padding:.35em .55em; border-radius:999px; white-space:nowrap; }
.lgcf-health .hd { width:.5em; height:.5em; border-radius:50%; background:var(--ok); }
/* Le badge n'est vert que lorsqu'on a VU le serveur répondre (2026-08-09).
   « wait » tant que la réponse n'est pas là, « ko » s'il ne répond pas —
   avant, le vert était écrit en dur dans le HTML et tenait bon même serveur
   éteint, ce qui envoyait chercher la panne du mauvais côté. */
.lgcf-health.wait { background:rgba(148,163,184,.12); border-color:rgba(148,163,184,.4); color:var(--text-3); }
.lgcf-health.wait .hd { background:var(--text-3); }
.lgcf-health.ko { background:rgba(220,38,38,.12); border-color:rgba(220,38,38,.45); color:var(--bad); }
.lgcf-health.ko .hd { background:var(--bad); }

.lgcf-field { margin-bottom:1em; }
.lgcf-field label { display:block; font-size:.76em; font-weight:500; color:var(--text-2); margin-bottom:.4em; letter-spacing:.2px; }
.lgcf-input { position:relative; display:flex; align-items:center; }
.lgcf-input .ic { position:absolute; left:.85em; color:var(--text-3); pointer-events:none; display:flex; }
.lgcf-input .ic svg { width:1.1em; height:1.1em; }
.lgcf-input input { width:100%; font-family:inherit; font-size:.95em; color:var(--text); background:var(--bg-deep); border:1px solid var(--border); border-radius:10px; padding:.85em .9em .85em 2.8em; outline:none; transition:border-color .2s, box-shadow .2s; }
.lgcf-input input::placeholder { color:var(--text-3); }
.lgcf-input input:focus { border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-bg); }
.lgcf-input .eye { position:absolute; right:.55em; width:2em; height:2em; border:0; cursor:pointer; background:transparent; color:var(--text-3); border-radius:8px; display:grid; place-items:center; transition:color .2s, background .2s; }
.lgcf-input .eye:hover { color:var(--text); background:var(--panel-2); }

.lgcf-rowmid { display:flex; align-items:center; justify-content:space-between; margin:.15em 0 1.05em; }
.lgcf-check { display:flex; align-items:center; gap:.55em; cursor:pointer; user-select:none; font-size:.84em; color:var(--text-2); }
.lgcf-check input { position:absolute; opacity:0; width:0; height:0; }
.lgcf-check .cbox { width:1.15em; height:1.15em; border-radius:6px; border:1.5px solid var(--border); background:var(--bg-deep); display:grid; place-items:center; transition:.2s; flex:0 0 auto; }
.lgcf-check .cbox svg { width:.85em; height:.85em; color:#fff; opacity:0; transform:scale(.5); transition:.18s; }
.lgcf-check input:checked + .cbox { background:var(--brand); border-color:var(--brand); }
.lgcf-check input:checked + .cbox svg { opacity:1; transform:scale(1); }

.lgcf-api { margin-top:.85em; display:flex; align-items:center; justify-content:center; gap:.5em; font-size:.82em; color:var(--text-3); text-decoration:none; padding:.7em; border-radius:8px; border:1px dashed var(--border); transition:color .2s, border-color .2s, background .2s; cursor:pointer; }
.lgcf-api:hover { color:var(--text-2); border-color:var(--brand); background:var(--brand-bg); }
.lgcf-api svg { width:1em; height:1em; opacity:.8; flex:0 0 auto; }
.lgcf-api .saTag { font-family:ui-monospace, monospace; font-size:.78em; color:var(--brand); letter-spacing:.5px; }

.lgcf-foot { margin-top:1.15em; display:flex; align-items:center; justify-content:space-between; gap:1em; font-size:.72em; color:var(--text-3); font-family:ui-monospace, monospace; }
.lgcf-foot .env { display:inline-flex; align-items:center; gap:.4em; border:1px solid var(--border); border-radius:999px; padding:.25em .6em; }
.lgcf-foot .env i { width:.45em; height:.45em; border-radius:50%; background:var(--ok); }

/* taille du formulaire alignée sur le mockup (fluide 340→440px) */
.login-right .login-card { max-width: clamp(340px, 26vw, 440px); }

/* ─── Settings ─────────────────────────────────────────────────── */
.settings-grid { display: grid; grid-template-columns: 220px 1fr; gap: 20px; }
.settings-nav { display: flex; flex-direction: column; gap: 2px; font-size: 13px; }
.settings-nav .it {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; border-radius: 6px; cursor: pointer;
  color: var(--text-2); border: 1px solid transparent;
}
.settings-nav .it.active {
  background: var(--panel); color: var(--text); font-weight: 600;
  border-color: var(--border);
}
/* ─── Comptes & rôles : cartes avatar (grille responsive, remplit la largeur) ─── */
.users-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 10px; padding: 12px; }
.user-card { display: flex; gap: 11px; align-items: flex-start; border: 1px solid var(--border); border-radius: 10px; padding: 11px 13px; background: var(--panel-2); }
.user-av { flex: 0 0 auto; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 16px; color: #fff; background: linear-gradient(135deg, var(--brand), #b8430a); }
.user-av.gei { background: linear-gradient(135deg, #8b5cf6, #4f46e5); }
.user-body { min-width: 0; flex: 1; }
.user-login { font-weight: 700; font-size: 14.5px; line-height: 1.2; }
.user-you { font-size: 10px; color: var(--text-3); font-weight: 500; }
.user-name { font-size: 12.5px; color: var(--text-2); margin-top: 1px; }
.user-role { display: inline-block; font-size: 11px; color: var(--text-2); background: var(--bg-deep); border: 1px solid var(--border); border-radius: 20px; padding: 1px 9px; margin-top: 6px; }
.user-state { font-size: 12px; margin-top: 6px; }
.user-acts { flex: 0 0 auto; display: flex; flex-direction: column; gap: 6px; align-self: stretch; }
.user-acts .btn { width: 100%; text-align: center; }
.row.set-fld { grid-template-columns: 200px 1fr; gap: 14px 18px; }
.inp {
  padding: 8px 12px; background: var(--bg-deep);
  border: 1px solid var(--border); border-radius: 6px;
  color: var(--text); font-size: 13px; outline: none;
  font-family: inherit; width: 100%;
}
.inp:focus { border-color: var(--brand); }
.theme-card {
  flex: 1; padding: 14px; border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--bg-deep); cursor: pointer;
}
.theme-card.sel {
  border-color: var(--brand); background: var(--brand-bg);
}

/* ─── Site card (page sites) ──────────────────────────────────── */
.sitecard { display: flex; flex-direction: column; }
.sitecard .topgrid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 10px 16px; padding: 14px 16px;
}
.sitecard .kv .k { font-size: 10px; color: var(--text-3); text-transform: uppercase; letter-spacing: .06em; }
.sitecard .kv .v { font-family: ui-monospace, monospace; font-size: 20px; font-weight: 700; margin-top: 2px; }
.sitecard .kv .v.brand { color: var(--brand); }
.sitecard .kv .v.bad   { color: var(--bad); }
.sitecard .kv .v.small { font-size: 13px; font-weight: 500; }
.sitecard .actions { padding: 10px 16px; border-top: 1px solid var(--border-soft); display: flex; gap: 6px; }
.sitecard .actions .btn { flex: 1; justify-content: center; }
.sitecard .actions .site-del-btn { color: #DC2626; border-color: rgba(220,38,38,0.3); flex: 0 0 auto; padding: 0 10px; }
.sitecard .actions .site-del-btn:hover { background: rgba(220,38,38,0.08); border-color: #DC2626; }
.sitecard.add {
  align-items: center; justify-content: center;
  min-height: 280px;
  border-style: dashed; background: transparent;
  color: var(--text-2); cursor: pointer;
  text-align: center;
}
.sitecard.add .circ {
  width: 48px; height: 48px; border-radius: 50%;
  border: 2px dashed var(--border);
  display: inline-flex; align-items: center; justify-content: center;
  margin-bottom: 8px;
}

/* ─── Toast ────────────────────────────────────────────────────── */
.toast {
  position: fixed; bottom: 20px; right: 20px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 8px; padding: 12px 16px; font-size: 12px;
  box-shadow: var(--shadow-pop);
  display: flex; align-items: center; gap: 10px;
  z-index: 200; max-width: 320px;
  transform: translateY(20px); opacity: 0;
  transition: transform .25s, opacity .2s;
  pointer-events: none;
}
.toast.show { transform: translateY(0); opacity: 1; }

/* Badge "à venir v2.1" */
.badge-soon {
  display: inline-flex; align-items: center;
  font-size: 9px; font-weight: 600;
  padding: 1px 6px; border-radius: 999px;
  background: rgba(217,119,6,.12);
  color: var(--warn);
  border: 1px solid rgba(217,119,6,.3);
  text-transform: uppercase; letter-spacing: .04em;
  margin-left: 6px; vertical-align: 1px;
  white-space: nowrap;
}
.is-soon { opacity: .55; }
.is-soon:hover { border-color: var(--border); }

/* ═══ RESPONSIVE ════════════════════════════════════════════════ */
/* Tablette */
@media (max-width: 1100px) {
  .kpi-grid { grid-template-columns: repeat(3, 1fr); }
  .row.r2-3, .row.r3 { grid-template-columns: 1fr; }
  .row.r3eq { grid-template-columns: 1fr 1fr; }
  .panel-hd .period button { padding: 4px 8px; }
}

/* ─── Sites strip (page Bons : cards de sites cliquables) ─────── */
.bons-sites-strip {
  display: flex; gap: 8px;
  overflow-x: auto; padding-bottom: 4px;
  scrollbar-width: thin;
}
.bons-sites-strip::-webkit-scrollbar { height: 4px; }
.bons-sites-strip::-webkit-scrollbar-thumb { background: var(--border-soft); border-radius: 4px; }
.bons-sites-strip .site-card {
  flex: 0 0 auto;
  min-width: 150px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 14px;
  cursor: pointer;
  transition: all .15s;
  display: flex; flex-direction: column; gap: 4px;
}
.bons-sites-strip .site-card:hover {
  background: var(--panel-2);
  border-color: var(--text-3);
  transform: translateY(-1px);
}
.bons-sites-strip .site-card.on {
  background: var(--brand-bg);
  border-color: var(--brand);
  box-shadow: 0 0 0 1px var(--brand);
}
.bons-sites-strip .site-card.all { min-width: 100px; }
.bons-sites-strip .site-card .head {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 700;
  color: var(--text);
}
.bons-sites-strip .site-card .dot {
  width: 7px; height: 7px; border-radius: 50%;
  flex: 0 0 auto;
}
.bons-sites-strip .site-card .dot.live { background: #10B981; box-shadow: 0 0 0 2px rgba(16,185,129,0.2); }
.bons-sites-strip .site-card .dot.warn { background: #F59E0B; box-shadow: 0 0 0 2px rgba(245,158,11,0.25); }
.bons-sites-strip .site-card .dot.bad  { background: #DC2626; box-shadow: 0 0 0 2px rgba(220,38,38,0.25); animation: dotPulse 2s ease-in-out infinite; }
.bons-sites-strip .site-card .dot.off  { background: var(--text-3); }
@keyframes dotPulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}
.bons-sites-strip .site-card .stats {
  display: flex; gap: 10px;
  font-size: 10.5px; color: var(--text-2);
  font-family: 'Consolas', monospace;
}
.bons-sites-strip .site-card .stats b { color: var(--text); font-weight: 700; }
.bons-sites-strip .site-card .stats .alert { color: #F59E0B; }
.bons-sites-strip .site-card .stats .crit  { color: #DC2626; }
.bons-sites-strip .site-card.all .stats { color: var(--text-2); }
.bons-sites-strip .site-card.on .head { color: var(--brand); }

/* ─── KPI cliquables (page Bons) ─────────────────────────────── */
.kpi.kpi-clickable {
  position: relative;
}
.kpi.kpi-clickable:hover {
  background: var(--panel-2) !important;
  transform: translateY(-1px);
}
.kpi.kpi-clickable:active { transform: translateY(0); }

/* ─── Bons actifs : grille de cards ──────────────────────────── */
.bons-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
}
.bons-grid .bon-card {
  background: var(--bg-deep);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  cursor: pointer;
  transition: border-color .15s, transform .15s;
  display: flex; flex-direction: column; gap: 8px;
}
.bons-grid .bon-card:hover {
  border-color: var(--brand);
  transform: translateY(-1px);
}

/* ══ Stock, vue SIMPLE : grille de cartes par produit ══════════════════
   Portage de .stock-card de l'app DESKTOP (js/stock.js + css/app.css) dans
   la palette du dashboard — demande user 2026-09-09 : « sur le web, tout est
   large ». La vue restaurée le matin empilait des bandeaux pleine largeur ;
   le poste range ses produits en GRILLE, plusieurs par ligne, chacun avec un
   chiffre lisible de loin. Correspondance des tokens (poste et dashboard ne
   les nomment pas pareil) : --surface→--panel · --bg2→--panel-2 ·
   --red→--bad · --green→--ok · --amber→--warn · --text3→--text-3.
   ⚠ Pas d'accordéon ici, comme au poste : la carte se CLIQUE et ouvre la
   modale de détail. En grille, une carte qui se déplie pousse toute sa ligne. */
.stk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; }
.stk-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  cursor: pointer;
  transition: box-shadow .15s, transform .15s, border-color .15s;
}
.stk-card:hover { box-shadow: 0 4px 12px rgba(0,0,0,.06); transform: translateY(-1px); border-color: var(--brand); }
[data-theme="dark"] .stk-card:hover { box-shadow: 0 4px 14px rgba(0,0,0,.4); }
/* La bande d'en-tête doit SE VOIR (retour user 2026-09-09, mesuré) :
   --panel-2 sur --panel ne faisait que 1,04 de contraste en clair, soit 4 %
   d'écart — invisible. --bg-deep donne 1,15, et la bordure passe d'un
   --border à 1,07 (rien) à un gris franc à 1,74, tout près du 1,79 du poste.
   ⚠ La bordure est un rgba FIXE, pas un color-mix : la feuille l'interdit
   (l.~3209, Chrome 111+ n'est pas une hypothèse tenable sur les tablettes de
   terrain). Un slate à 45 % tient sur les deux thèmes (1,74 clair / 1,72 sombre). */
.stk-card-hd {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 11px 13px;
  border-bottom: 1px solid rgba(100,116,139,.45);
  background: var(--bg-deep);
}
.stk-card-nom {
  font-size: 13.5px; font-weight: 700; color: var(--text);
  line-height: 1.25; word-break: break-word;
}
/* --text-3 sur cette bande donnait 2,46 : sous le 4,5 exigé par WCAG pour du
   petit texte. Du gris sur du gris, exactement ce que l'utilisateur a signalé.
   --text-2 monte à 6,57. */
.stk-card-sub { font-size: 10.5px; color: var(--text-2); margin-top: 2px; }
.stk-card-pill {
  flex: 0 0 auto; font-size: 10.5px; font-weight: 700;
  padding: 2px 8px; border-radius: 99px; white-space: nowrap;
}
/* Même recette que .pv-badge : le TEXTE porte le token (donc suit le thème),
   le FOND est un rgba fixe à faible alpha, lisible sur clair comme sur sombre.
   Le premier jet utilisait color-mix() en style inline — la pastille aurait
   perdu tout son fond sur un navigateur < Chrome 111. */
.stk-card-pill.st-crit { color: var(--bad);    background: rgba(220,38,38,.13); }
.stk-card-pill.st-bas  { color: var(--warn);   background: rgba(217,119,6,.16); }
.stk-card-pill.st-ok   { color: var(--ok);     background: rgba(22,163,74,.13); }
.stk-card-pill.st-none { color: var(--text-2); background: rgba(148,163,184,.16); }
.stk-card-bd { padding: 13px; }
/* Le chiffre du stock : c'est CE nombre qu'on vient lire, il domine la carte. */
.stk-card-big { font-family: var(--mono); font-size: 30px; font-weight: 800; line-height: 1; }
.stk-card-big small { font-size: 13px; opacity: .6; }
/* Pastilles d'engagement — affichées seulement quand elles valent quelque
   chose (le poste fait pareil : zéro engagé n'est pas une information). */
.stk-card-bons { display: flex; gap: 6px; margin: 9px 0 4px; flex-wrap: wrap; font-size: 10.5px; }
.stk-card-bons span { padding: 2px 8px; border-radius: 99px; font-weight: 600; }
.stk-card-stats { display: flex; gap: 12px; margin: 10px 0 0; font-size: 11.5px; flex-wrap: wrap; }
.stk-card-seuil { margin-top: 10px; }
.stk-card-seuil-hd { display: flex; justify-content: space-between; font-size: 10px; color: var(--text-3); margin-bottom: 3px; }
.stk-card-jauge { height: 6px; background: var(--bg-deep); border-radius: 3px; overflow: hidden; }
.stk-card-jauge > div { height: 100%; border-radius: 3px; transition: width .3s; }
/* L'écran Stock a DEUX dispositions (cartes sans stockage tiers · maître-détail
   avec) et n'en montre qu'une. Le masquage se fait par le SEUL attribut `hidden`
   (#198 : deux masquages concurrents se démasquent mal) — mais `hidden` vaut
   display:none à spécificité 0 : sans ce !important, le display:grid de
   .stk-grid et celui de .stk-md le battraient et les DEUX vues s'afficheraient.
   Porté par #page-stock pour ne rien changer ailleurs. */
#page-stock [hidden] { display: none !important; }
/* ── Produits ARCHIVÉS : rangés, pas effacés ─────────────────────────────
   Un produit archivé au poste porte encore du stock et de l'historique (les
   deux cas mesurés en production le 2026-09-10 en portaient 6 et 1 mouvements).
   Le dashboard les listait comme ACTIFS — il recevait le drapeau sans jamais
   le lire (#226). Ils sont maintenant repliés ici plutôt que masqués : une
   disparition muette se lit comme une perte de données (#231).
   Le repli est un <details> natif — aucun JS d'ouverture à maintenir. */
.stk-arch { margin-top: 16px; border-top: 1px dashed rgba(100,116,139,.45); padding-top: 12px; }
.stk-arch > summary {
  cursor: pointer; list-style: none; user-select: none;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 12px; font-weight: 700; color: var(--text-2);
  padding: 6px 0;
}
.stk-arch > summary::-webkit-details-marker { display: none; }
.stk-arch > summary::before {
  content: '▸'; font-size: 11px; color: var(--text-3);
  transition: transform .15s; display: inline-block;
}
.stk-arch[open] > summary::before { transform: rotate(90deg); }
.stk-arch > summary:hover { color: var(--text); }
.stk-arch-aide { font-weight: 500; font-size: 10.5px; color: var(--text-3); }
.stk-arch .stk-grid { margin-top: 10px; }
/* La carte archivée reste LISIBLE : pas d'opacity, qui écraserait le contraste
   du texte (le même piège que le --text-3 corrigé plus haut sur .stk-card-sub).
   C'est le trait tireté et le fond creusé qui disent « rangé ». */
.stk-card-arch { border-style: dashed; background: var(--bg-deep); }
/* Même recette que les autres pastilles : le texte porte le token, le fond est
   un rgba fixe — jamais color-mix() (Chrome 111+ non tenable sur tablette). */
.stk-card-pill.st-arch { color: var(--text-2); background: rgba(100,116,139,.22); }
/* Bouton « ranger / remettre » de la carte produit (③, 2026-09-10). Discret au
   repos : ce n'est pas le geste courant de l'écran, et une carte couverte de
   boutons se lit moins vite. Il se révèle au survol de la carte. */
.stk-card-actes { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.stk-card-arch-btn {
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text-2);
  border-radius: 7px; cursor: pointer; font-size: 12px; line-height: 1;
  padding: 4px 7px; opacity: .45; transition: opacity .15s, border-color .15s, color .15s;
}
.stk-card:hover .stk-card-arch-btn { opacity: 1; }
.stk-card-arch-btn:hover { border-color: var(--brand); color: var(--text); }
/* Le même geste que sur la carte, dans la disposition maître-détail (tiers).
   Il est ici PLEINEMENT visible, pas au survol : le panneau de détail est un
   écran de travail sur UN produit, pas une grille à balayer du regard. */
.stk-dt-actes { display: flex; align-items: flex-end; gap: 10px; flex: 0 0 auto; }
.stk-dt-arch {
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text-2);
  border-radius: 8px; cursor: pointer; font-size: 11.5px; font-weight: 600;
  padding: 6px 11px; white-space: nowrap; transition: border-color .15s, color .15s;
}
.stk-dt-arch:hover { border-color: var(--brand); color: var(--text); }
/* Sur un écran TACTILE il n'y a pas de survol : le bouton resterait à 45 %
   d'opacité, donc illisible là où on tape avec le doigt (les tablettes de
   terrain sont un vrai cas ici, cf. la refonte tablette du 09/08). */
@media (hover: none) {
  .stk-card-arch-btn { opacity: 1; padding: 6px 10px; }
}
/* Sous-cartes propriétaire — calquées sur .prop-card du desktop */
.stk-props {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 11px;
  margin-top: 11px; padding-top: 12px;
  border-top: 1px solid var(--border);
}
.stk-prop {
  background: var(--panel-2);
  border: 1.5px solid var(--border);
  border-radius: 10px;
  padding: 12px 13px;
  position: relative;
  cursor: pointer;
  transition: border-color .14s, transform .14s;
}
.stk-prop:hover { border-color: var(--brand); transform: translateY(-2px); }
.stk-prop.muta {
  background: linear-gradient(135deg, var(--brand-bg), var(--panel-2));
  border-left: 3px solid var(--brand);
}
.stk-prop:not(.muta) { border-left: 3px solid #7C3AED; }
.stk-prop.muta::before {
  content: 'GEI';
  position: absolute; top: 9px; right: 11px;
  font-size: 9px; color: var(--text-3); letter-spacing: 1.5px; font-weight: 800;
}
.stk-prop-hd { display: flex; align-items: center; justify-content: space-between; gap: 6px; margin-bottom: 7px; }
.stk-prop-nm { font-size: 13px; font-weight: 800; color: var(--text); letter-spacing: -.2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stk-prop-ic { width: 21px; height: 21px; border-radius: 6px; display: flex; align-items: center; justify-content: center; font-size: 10.5px; font-weight: 800; flex-shrink: 0; }
.stk-prop-ic.client { background: rgba(124,58,237,.14); color: #7C3AED; border: 1px solid #7C3AED; }
.stk-prop-ic.muta   { background: var(--brand-bg); color: var(--brand); border: 1px solid var(--brand); }
.stk-prop-stock { font-family: var(--mono); font-size: 21px; font-weight: 800; letter-spacing: -.5px; color: var(--text); margin: 3px 0 5px; }
.stk-prop-stock small { font-size: 11px; color: var(--text-3); font-weight: 600; }
.stk-prop-stock.low { color: var(--warn); }
.stk-prop-stock.critical { color: var(--bad); }
.stk-prop-st {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 9.5px; font-weight: 800; padding: 2px 8px; border-radius: 99px;
  text-transform: uppercase; letter-spacing: .6px;
}
.stk-prop-st::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.stk-prop-st.ok       { background: rgba(22,163,74,.13);  color: var(--ok); }
.stk-prop-st.bas      { background: rgba(217,119,6,.15);  color: var(--warn); }
.stk-prop-st.critique { background: rgba(220,38,38,.13);  color: var(--bad); }
.stk-prop-ft { margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 3px; }
.stk-prop-fr { display: flex; justify-content: space-between; font-size: 10.5px; color: var(--text-3); }
.stk-prop-fr b { color: var(--text); font-family: var(--mono); font-weight: 700; }
.stk-prop-fr.engage b   { color: var(--warn); }
.stk-prop-fr.recevoir b { color: var(--info); }
.stk-prop-fr.dispo b    { color: var(--ok); }
.bon-card .bon-card-head {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 10px;
}
.bon-card .bon-num {
  font-family: 'Consolas', monospace;
  font-size: 14px; font-weight: 700;
  color: var(--text);
}
.bon-card .bon-client {
  font-size: 12px; color: var(--text-2);
  margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 180px;
}
.bon-card .bon-statut {
  font-size: 10.5px; font-weight: 700;
  padding: 3px 10px; border-radius: 99px;
  flex: 0 0 auto; white-space: nowrap;
}
.bon-card .bon-prod {
  display: flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--brand); font-weight: 700;
}
.bon-card .bon-prod .bon-site {
  margin-left: auto;
  font-size: 10px; color: var(--text-3); font-weight: 600;
  background: var(--bg-2); padding: 1px 6px; border-radius: 99px;
}
.bon-card .bon-tonnage {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
}
.bon-card .bon-tonnage .bon-charge {
  font-family: 'Consolas', monospace;
  font-size: 22px; font-weight: 800;
}
.bon-card .bon-tonnage .bon-commande {
  font-size: 12px; color: var(--text-2);
}
.bon-card .bon-tonnage .bon-reste {
  margin-left: auto;
  font-size: 10.5px; color: var(--text-3); white-space: nowrap;
}
.bon-card .bon-bar {
  height: 7px; background: var(--bg-2);
  border-radius: 4px; overflow: hidden;
}
.bon-card .bon-bar-fill {
  height: 100%; border-radius: 4px;
  transition: width .5s;
}
.bon-card .bon-meta {
  display: flex; justify-content: space-between;
  font-size: 10.5px; color: var(--text-3);
  font-family: 'Consolas', monospace;
}
.bons-grid .bon-empty {
  grid-column: 1 / -1;
  text-align: center; padding: 40px 20px;
  color: var(--text-3); font-size: 13px; font-style: italic;
}

/* Mobile (< 700px) — englobe smartphones (~360px) + petites tablettes
   portrait. Breakpoint à 700px pour matcher les règles hero définies
   plus bas (et éviter le piège des règles qui ne s'appliqueraient
   qu'entre 601-700px). */
@media (max-width: 700px) {
  /* Padding bas = hauteur bnav (64px) + safe-area inset (barre geste
     Android récente) + 24px d'air pour ne pas que le dernier item
     touche le FAB orange (qui déborde de 22px au-dessus de la bnav). */
  body { padding-bottom: calc(64px + env(safe-area-inset-bottom) + 24px); }
  main { padding: 12px 12px 18px; }
  /* Les toasts (bottom:20px par défaut) chevauchaient la bnav. On les
     repousse au-dessus. */
  .toast { bottom: calc(64px + env(safe-area-inset-bottom) + 16px); }

  /* Header compact */
  .hdr { height: 52px; padding: 0 12px; gap: 8px; position: relative; }
  .hdr .health,
  .hdr .user-pill,
  .hdr .logo .sub { display: none; }
  .hdr .iconbtn[data-action="logout"] { display: none; } /* dans menu */
  .logo { font-size: 13px; }
  /* Nom du central : ticker pleine largeur sous le header sur mobile
     (sinon le header est trop chargé pour avoir un espace de défilement utile) */
  .hdr-central-name {
    position: absolute;
    top: 100%; left: 0; right: 0;
    max-width: none;
    padding: 6px 12px;
    background: linear-gradient(180deg, var(--panel) 0%, var(--bg) 100%);
    border-bottom: 1px solid var(--border);
    box-shadow: 0 2px 6px rgba(0,0,0,0.15);
    z-index: 5;
  }
  .hdr-central-name .sep { display: none; }
  .hdr-central-name .marq-track { font-size: 12px; }
  /* Le marquee du nom de site (.hdr-central-name) est positionné en absolute
     top:100% sous le header. Il fait ~32px de haut (padding 6+6 +
     font-size 12 + line-height + border). Sans assez de padding-top
     sur le main, le marquee CHEVAUCHE la première section (filterbar,
     boutons, etc.) — l'utilisateur voit alors une bande qui défile à
     l'endroit où il y avait du contenu. Fix : padding suffisant pour
     que le contenu commence APRÈS le marquee. */
  body.has-central-name main { padding-top: 38px; }

  /* Tabs top → cachés, bnav prend le relais */
  .tabs { display: none; }
  .bnav { display: block; }

  /* KPIs en 2 colonnes, plus compacts */
  .kpi-grid { grid-template-columns: 1fr 1fr; gap: 6px; }
  .kpi { padding: 8px 10px; }
  .kpi .value { font-size: 18px; line-height: 1.1; }
  .kpi .label { font-size: 10px; letter-spacing: 0.4pt; }
  .kpi .spark { display: none; }

  /* Layouts → empilés + gap réduit */
  main { padding: 10px 10px 18px; }
  .row.r2-3, .row.r3, .row.r2, .row.r3eq { grid-template-columns: 1fr; gap: 8px; }
  .row { gap: 8px; }
  .panel { margin-bottom: 0; }
  /* Réduit l'espace entre les blocs principaux (hero, KPIs, panneaux) */
  .panel + .panel { margin-top: 8px; }

  /* Filter bar scrollable horizontal — scrollbar masquée sinon elle
     rogne du contenu visible (cf. retour utilisateur). Le scroll reste
     possible via swipe / drag. */
  .filterbar {
    flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0;
    scrollbar-width: none; -ms-overflow-style: none;
  }
  .filterbar::-webkit-scrollbar { display: none; }
  .filterbar > * { flex-shrink: 0; }
  .filterbar .summary, .filterbar .spacer { display: none; }
  .filterbar .btn[data-action="export"] { display: none; }

  /* Tableau → cards.
     ⚠ La page Pesées est sortie d'ici le 2026-08-09 : elle bascule en cartes
     dès 900 px (et non 700), parce que sa table fait 14 colonnes et déborde
     déjà en tablette portrait. Sa règle vit avec les correctifs tablette, en
     bas de ce fichier. « Activité récente » de la Vue d'ensemble garde le
     seuil 700 : l'audit du 08/08 l'a trouvée correcte en tablette. */
  #activity-table-wrap { display: none; }
  #activity-cards { display: flex; flex-direction: column; gap: 8px; }

  /* Sites grid simple */
  .row.sites-grid { grid-template-columns: 1fr !important; }

  /* Settings: nav en haut */
  .settings-grid { grid-template-columns: 1fr; }
  .settings-nav {
    flex-direction: row; overflow-x: auto; gap: 4px; padding-bottom: 4px;
    scrollbar-width: none; -ms-overflow-style: none;
  }
  .settings-nav::-webkit-scrollbar { display: none; }
  .settings-nav .it { white-space: nowrap; }
  .row.set-fld { grid-template-columns: 1fr; gap: 6px 0; }
  .row.set-fld label { font-weight: 600; }
  /* Comptes & rôles : le tableau 5 colonnes déborde/coupe sur mobile →
     on l'empile en cartes labellisées (même parti-pris que bons/stock/sites). */
  /* Comptes & rôles = cartes avatar (.users-grid/.user-card) responsives dès
     le desktop → rien de spécifique à faire en mobile ici. */

  /* Login */
  .login-card { max-width: 100%; }

  /* ── Listes de cartes en 2 colonnes (réduit le scroll mobile) ──
     minmax(0,1fr) : sans le min 0, une carte au contenu large pousse la colonne
     au-delà du 1fr → la grille déborde à droite de l'écran (cartes coupées). */
  .bons-grid { grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 8px; }
  .stk-props { grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 8px; }
  .clients-grid { grid-template-columns: minmax(0,1fr) minmax(0,1fr) !important; gap: 8px !important; }
  .bons-grid .bon-card, .clients-grid .panel, .stk-props .stk-prop { min-width: 0; overflow: hidden; }
  /* Vue « Par produit » : cartes accordéon en 2 colonnes. Le header passe en wrap
     (titre + total/badge/alerte sur 2 lignes) pour rester lisible à demi-largeur ; la
     carte DÉPLIÉE repasse en pleine largeur → ses sous-stocks gardent la place. */
  /* (.stk-grid est en auto-fill : il se replie seul. L'ancienne règle 2
     colonnes visait l'accordéon, supprimé le 2026-09-09.) */
  /* Touch targets ≥ 44 */
  .iconbtn, .chip, .btn { min-height: 36px; }
  .tab, .bnav button { min-height: 44px; }
}

/* Desktop only (≥ 701px, complément du bloc mobile ci-dessus).
   #pesees-cards n'y est plus : son seuil à lui est 900 px (bas de fichier). */
@media (min-width: 701px) {
  #activity-cards { display: none; }
}

/* Print (export PDF) */
@media print {
  .hdr, .tabs, .bnav, .filterbar { display: none; }
  .panel { box-shadow: none; border-color: #ccc; }
}

/* ═══════════════════════════════════════════════════════════════════
   ─── Dashboard central v2 (refonte) — page-overview uniquement ───
   ════════════════════════════════════════════════════════════════════ */

/* Layout 2 colonnes (page-overview uniquement) */
/* Largeur max alignée sur le mockup (1320px). On l'applique à TOUTE
   la page-overview pour que filterbar, hero et les panneaux soient
   visuellement alignés au même bord gauche / centrés dans le main. */
#page-overview.active { max-width: 1320px; margin: 0 auto; width: 100%; }
.ov2-wrap { display: grid; grid-template-columns: minmax(0,1fr) 320px; gap: 16px; align-items: start; }
/* ⚠ minmax(0,1fr) et NON `1fr` nu : `1fr` = minmax(auto,1fr) → la colonne ne
   peut pas rétrécir sous la largeur de son plus large enfant (gros nombre mono,
   strip, heatmap…) → elle gonfle au-delà du viewport et le contenu est coupé à
   droite sur mobile. min-width:0 sur les enfants (items de grille = min-width:auto
   par défaut) pour qu'ils rétrécissent aussi. */
@media (max-width: 1100px) {
  .ov2-wrap { grid-template-columns: minmax(0, 1fr); }
  .ov2-wrap > * { min-width: 0; }
}

/* Couleurs accent réutilisées */
:root, [data-theme="light"] { --green: #16a34a; --amber: #d97706; --red: #dc2626; --blue: #0284c7; --purple: #7c3aed; }
[data-theme="dark"]         { --green: #22c55e; --amber: #fbbf24; --red:  #ef4444; --blue: #38bdf8; --purple: #a78bfa; }

/* ─── HERO orange ─── */
.hero {
  background: linear-gradient(135deg, #C45200 0%, #E8731F 100%);
  color: #fff;
  border-radius: 14px;
  padding: 16px 26px 12px;
  margin-bottom: 14px;
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow);
}
.hero::before { content: ''; position: absolute; top: -30px; right: -20px; font-size: 180px; opacity: 0.08; line-height: 1; pointer-events: none; }
.hero-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; gap: 10px; flex-wrap: wrap; }
.hero-title { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 1.5px; opacity: 0.85; display: flex; align-items: center; gap: 8px; }
.seg { display: flex; background: rgba(0,0,0,0.22); border-radius: 99px; padding: 2px; font-size: 11px; }
.seg button { border: 0; background: transparent; color: rgba(255,255,255,0.85); padding: 5px 14px; border-radius: 99px; font-weight: 700; font-size: 11.5px; cursor: pointer; white-space: nowrap; transition: all .15s; display: inline-flex; align-items: center; gap: 4px; }
.seg button:hover { color: #fff; }
.seg button.on { background: #fff; color: #c45200; }
.hero-val {
  font-family: ui-monospace, "SF Mono", Consolas, monospace;
  font-size: 72px; font-weight: 800; line-height: 0.88; letter-spacing: -.015em;
  /* margin-top calibré pour équilibrer avec l'espace sous le chiffre :
     hero-head a margin-bottom: 6 → on ajoute 4 pour totaliser ~10 px en haut.
     Le bas du chiffre a aussi ~10 px (hero-chart margin-top 2 + padding-top 6 + border 1). */
  margin-top: 4px;
}
.hero-val small { font-size: 22px; font-weight: 500; opacity: 0.7; margin-left: 10px; }
@media (max-width: 700px) {
  /* Hero mobile : compact, alignement gauche cohérent avec desktop */
  .hero { padding: 10px 14px 8px; margin-bottom: 10px; }
  .hero-head { gap: 6px; margin-bottom: 0; }
  .hero-title { font-size: 10px; letter-spacing: 0.8pt; line-height: 1.2; }
  /* Chiffre principal : aligné à gauche, taille réduite, line-height
     compact pour éliminer l'air optique au-dessus et en-dessous du glyphe.
     margin-top plus généreux pour décoller le chiffre du header
     (les switches étant à droite, on a de la place visuelle). */
  .hero-val {
    font-size: 46px;
    margin-top: 12px;
    line-height: 0.88;
  }
  .hero-val small { font-size: 14px; margin-left: 6px; }
  /* Segments plus petits */
  .seg { font-size: 10px; padding: 1.5px; }
  .seg button { padding: 4px 10px; font-size: 10.5px; }
  /* Bouton 👁 — coin haut-droite du hero */
  .hero-hide-btn {
    position: absolute;
    top: 12px; right: 12px;
    margin-left: 0;
    z-index: 2;
    width: 26px; height: 26px;
  }
  .hero-sub { font-size: 11px; gap: 10px; margin-top: 3px; }
  /* Graphe : collé au chiffre (zéro marge), pas de border-top.
     padding-top: 3 pour équilibrer avec margin-top: 3 du hero-val. */
  .hero-chart {
    margin-top: 0;
    padding-top: 3px;
    border-top: 0;
  }
  .hero-chart-head { margin-bottom: 4px; }
  .hero-chart-title { font-size: 10px; letter-spacing: 0.6pt; }
  .hero-chart-bars { height: 50px; gap: 2px; }
}
/* Bouton 👁 pour masquer/afficher le montant (confidentialité) */
.hero-hide-btn {
  background: rgba(255,255,255,0.12);
  border: 1px solid rgba(255,255,255,0.2);
  color: #fff;
  border-radius: 99px;
  width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  margin-left: 6px;
  transition: all 0.15s;
  padding: 0;
}
.hero-hide-btn:hover { background: rgba(255,255,255,0.22); transform: scale(1.05); }
.hero-hide-btn.on { background: rgba(255,255,255,0.28); }
/* Mode masqué : le contenu est remplacé par des bullets par le JS.
   On ajoute juste une opacité légèrement réduite + cursor pour signaler
   que c'est cliquable, sans flou (qui peut être contourné en zoomant). */
.hero-val.masked {
  user-select: none;
  cursor: pointer;
  opacity: 0.92;
  letter-spacing: 0.06em;
}
.hero-sub { display: flex; gap: 20px; margin-top: 4px; font-size: 12.5px; opacity: 0.95; flex-wrap: wrap; }
.hero-sub:empty { display: none; }
.hero-sub b { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-weight: 800; font-size: 14px; }

.hero-chart { margin-top: 2px; padding-top: 6px; border-top: 1px solid rgba(255,255,255,0.15); }
.hero-chart-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; gap: 10px; flex-wrap: wrap; }
.hero-chart-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; opacity: 0.75; display: flex; align-items: center; gap: 6px; }
.hero-chart-bars { display: flex; align-items: stretch; gap: 4px; height: 80px; }
.hero-chart-bars > div { flex: 1; display: flex; flex-direction: column; align-items: stretch; min-width: 0; }
.hero-chart-bars .track { flex: 1; background: rgba(255,255,255,0.10); border-radius: 4px; display: flex; flex-direction: column; justify-content: flex-end; overflow: hidden; }
.hero-chart-bars .fill { width: 100%; background: linear-gradient(180deg, rgba(255,255,255,0.95), rgba(255,255,255,0.6)); border-radius: 4px 4px 0 0; transition: height .3s; }
.hero-chart-bars .fill.cur { background: linear-gradient(180deg, #FBBF24, #F59E0B); box-shadow: 0 0 0 2px rgba(255,255,255,0.55), 0 0 12px rgba(251,191,36,0.4); }
.hero-chart-bars .lbl { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 9px; color: rgba(255,255,255,0.55); margin-top: 4px; text-align: center; }

/* ─── KPI cards v2 (refonte page-overview) ─── */
.kpi-grid.v2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; margin-bottom: 14px; }
.kpi.v2 {
  background: var(--panel); border: 1px solid var(--border); border-left: 3px solid var(--brand);
  border-radius: 10px; padding: 11px 14px; cursor: pointer; transition: all .15s;
}
.kpi.v2:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,0.18); border-left-color: var(--brand-soft); }
.kpi.v2 .kpi-lbl { display: flex; align-items: center; gap: 5px; font-size: 10.5px; color: var(--text-3); text-transform: uppercase; letter-spacing: .5px; font-weight: 600; margin-bottom: 3px; }
.kpi.v2 .kpi-lbl svg { color: var(--brand); }
.kpi.v2 .kpi-val { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-variant-numeric: tabular-nums; font-size: 20px; font-weight: 800; line-height: 1.1; letter-spacing: -.01em; color: var(--text); }
.kpi.v2 .kpi-val small { font-size: 12px; font-weight: 500; opacity: .55; margin-left: 3px; }
.kpi.v2 .kpi-sub { font-size: 10.5px; color: var(--text-2); margin-top: 3px; }
.kpi.v2.blue   { border-left-color: var(--blue);   } .kpi.v2.blue   .kpi-lbl svg { color: var(--blue);   }
.kpi.v2.amber  { border-left-color: var(--amber);  } .kpi.v2.amber  .kpi-lbl svg { color: var(--amber);  }
.kpi.v2.green  { border-left-color: var(--green);  } .kpi.v2.green  .kpi-lbl svg { color: var(--green);  }
.kpi.v2.purple { border-left-color: var(--purple); } .kpi.v2.purple .kpi-lbl svg { color: var(--purple); }
.kpi.v2.red    { border-left-color: var(--red);    } .kpi.v2.red    .kpi-lbl svg { color: var(--red);    }

/* ─── Panel v2 (refonte) ─── */
.panel.v2 { padding: 16px 18px; margin-bottom: 14px; display: block; }
.panel.v2 .panel-hd { display: flex; justify-content: space-between; align-items: center; padding: 0; border: 0; margin-bottom: 12px; }
.panel.v2 .panel-title { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: var(--text-2); display: flex; align-items: center; gap: 8px; }
.panel.v2 .panel-title .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--brand); }
.panel.v2 .panel-action { font-size: 11px; color: var(--brand-soft); cursor: pointer; font-weight: 600; background: transparent; border: 0; }
.panel.v2 .panel-action:hover { text-decoration: underline; }

/* ─── Sites strip ─── */
.sites-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; }
.site-card {
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px; cursor: pointer; transition: all .15s; position: relative; overflow: hidden;
}
.site-card:hover { border-color: var(--brand); transform: translateY(-2px); box-shadow: 0 8px 20px rgba(15,23,42,0.10); }
.site-card.offline { opacity: 0.6; }
.site-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.site-status { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; display: inline-block; vertical-align: middle; }
.site-status.live { background: var(--green); box-shadow: 0 0 0 3px rgba(34,197,94,0.18); animation: ovpulse 2s infinite; }
@keyframes ovpulse { 0%,100% { box-shadow: 0 0 0 3px rgba(34,197,94,0.18); } 50% { box-shadow: 0 0 0 5px rgba(34,197,94,0.04); } }
.site-status.warn { background: var(--amber); }
.site-status.offline { background: var(--text-3); }
.site-name { font-weight: 700; font-size: 13.5px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.site-since { font-size: 10.5px; color: var(--text-3); flex-shrink: 0; }
.site-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 8px; }
.site-stat .v { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 15px; font-weight: 700; color: var(--text); }
.site-stat .v.brand { color: var(--brand); }
.site-stat .l { font-size: 9.5px; color: var(--text-3); text-transform: uppercase; letter-spacing: .5px; }
.spark-mini { height: 28px; display: flex; align-items: flex-end; gap: 2px; }
/* Pas de min-height : un jour à 0 doit rester invisible (sinon barre dorée
   fantôme du jour courant quand aucune activité ce jour) */
.spark-mini > div { flex: 1; background: linear-gradient(180deg, var(--brand-soft), var(--brand)); border-radius: 2px 2px 0 0; opacity: 0.65; }
.spark-mini > div.cur { opacity: 1; background: linear-gradient(180deg, #FBBF24, #F59E0B); }

/* ─── Rank rows (top X) ─── */
.rank-row { display: flex; align-items: center; gap: 10px; padding: 7px 6px; margin: 0 -6px; cursor: pointer; border-radius: 6px; transition: background .12s; }
.rank-row:hover { background: var(--panel-2); }
.rank-pos { width: 22px; height: 22px; border-radius: 50%; background: var(--panel-2); color: var(--text-2); font-size: 11px; font-weight: 700; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.rank-row:first-child .rank-pos { background: var(--brand); color: #fff; }
.rank-row:nth-child(2) .rank-pos { background: var(--brand-soft); color: #fff; }
.rank-info { flex: 1; min-width: 0; }
.rank-name { font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.rank-bar { height: 5px; background: var(--panel-2); border-radius: 3px; overflow: hidden; margin-top: 4px; }
.rank-bar > div { height: 100%; background: linear-gradient(90deg, var(--brand), var(--brand-soft)); border-radius: 3px; }
.rank-bar > div.green { background: linear-gradient(90deg, var(--green), #34D399); }
.rank-val { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 12px; font-weight: 700; color: var(--brand); white-space: nowrap; }
.rank-val.green { color: var(--green); }
.rank-site { font-size: 9.5px; padding: 1px 6px; border-radius: 99px; background: var(--panel-2); color: var(--text-3); margin-left: 6px; }

/* ─── Activity v2 ─── */
.act { padding: 9px 8px; border-bottom: 1px solid var(--border); cursor: pointer; transition: background .12s; display: flex; align-items: center; gap: 10px; }
.act:hover { background: var(--panel-2); }
.act:last-child { border-bottom: 0; }
.act-time { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 10.5px; color: var(--text-3); width: 70px; flex-shrink: 0; }
.act-info { flex: 1; min-width: 0; }
.act-info b { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 12px; }
.act-meta { font-size: 10.5px; color: var(--text-3); margin-top: 1px; }
.act-val { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 12px; font-weight: 700; color: var(--brand); white-space: nowrap; }
.act-site { font-size: 9.5px; padding: 1px 7px; border-radius: 99px; background: rgba(124,58,237,0.18); color: var(--purple); font-weight: 600; flex-shrink: 0; }
[data-theme="dark"] .act-site { background: rgba(167,139,250,0.18); color: #c4b5fd; }

/* ─── Heatmap ─── */
.hm { display: grid; grid-template-columns: 38px repeat(24, 1fr); gap: 3px; margin-top: 8px; }
.hm-lbl { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 9.5px; color: var(--text-3); text-align: right; padding-right: 4px; line-height: 18px; }
.hm-cell { height: 18px; border-radius: 3px; cursor: pointer; transition: transform .12s; }
.hm-cell:hover { transform: scale(1.4); z-index: 2; }
.hm-axis { display: grid; grid-template-columns: 38px repeat(24, 1fr); gap: 3px; margin-top: 3px; }
.hm-axis > div { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 8.5px; color: var(--text-3); text-align: center; }

/* ─── Comparaison sites (tableau v2) ─── */
.tbl-compare { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.tbl-compare th { padding: 6px 8px; text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: .5px; color: var(--text-3); font-weight: 700; border-bottom: 1px solid var(--border-soft); }
.tbl-compare th.num { text-align: right; }
.tbl-compare td { padding: 8px; border-bottom: 1px solid var(--border); color: var(--text); }
.tbl-compare td.num { text-align: right; font-family: ui-monospace, "SF Mono", Consolas, monospace; font-variant-numeric: tabular-nums; }
.tbl-compare tbody tr { cursor: pointer; transition: background .12s; }
.tbl-compare tbody tr:hover { background: var(--panel-2); }
.tbl-compare tbody tr.total { background: var(--brand-bg); cursor: default; }
.tbl-compare tbody tr.total:hover { background: var(--brand-bg); }
.tbl-compare tr:last-child td { border-bottom: 0; }
.tbl-compare .ca { color: var(--brand); font-weight: 700; }

/* ─── Alertes ─── */
.alert-line { display: flex; gap: 10px; padding: 10px 12px; border-radius: 8px; border-left: 3px solid var(--amber); background: rgba(217,119,6,0.06); margin-bottom: 6px; cursor: pointer; transition: background .12s; }
.alert-line:hover { background: rgba(217,119,6,0.12); }
.alert-line.crit { border-left-color: var(--red); background: rgba(220,38,38,0.06); }
.alert-line.crit:hover { background: rgba(220,38,38,0.12); }
.alert-line.info { border-left-color: var(--blue); background: rgba(2,132,199,0.06); }
.alert-line.info:hover { background: rgba(2,132,199,0.12); }
.alert-line .alert-ic { font-size: 15px; flex-shrink: 0; }
.alert-line .alert-title { font-size: 12px; font-weight: 700; color: var(--text); }
.alert-line .alert-msg { font-size: 10.5px; color: var(--text-2); margin-top: 1px; }
.alert-count { font-size: 11px; color: var(--amber); background: rgba(217,119,6,0.15); padding: 2px 8px; border-radius: 99px; font-weight: 700; }

/* ─── Sidebar lignes KPI compactes ─── */
.kpi-line { display: flex; justify-content: space-between; align-items: center; padding: 7px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
.kpi-line:last-child { border-bottom: 0; }
.kpi-line .lbl { color: var(--text-2); display: inline-flex; align-items: center; gap: 7px; }
.kpi-line .lbl svg { color: var(--brand); }
.kpi-line .val { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 15px; font-weight: 700; color: var(--text); }
.kpi-line .val.brand { color: var(--brand); }
.kpi-line .val.green { color: var(--green); }
.kpi-line .val.amber { color: var(--amber); }

/* ─── Two-col interne aux panels ─── */
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
/* U-2 audit : aligné à 700px (cohérent avec le bloc mobile principal) */
@media (max-width: 700px) { .two-col { grid-template-columns: 1fr; } }

/* ─── Comparaison sites : bascule tableau ↔ cards selon largeur ─── */
.sites-compare-cards { display: none; flex-direction: column; gap: 10px; }
.scc-card { background: var(--bg-deep); border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; cursor: pointer; transition: all .15s; }
.scc-card:hover { border-color: var(--brand); transform: translateY(-1px); }
.scc-card.scc-total { background: var(--brand-bg); border-color: var(--brand-soft); cursor: default; }
.scc-card.scc-total:hover { border-color: var(--brand-soft); transform: none; }
.scc-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.scc-head b { flex: 1; font-size: 13.5px; color: var(--text); }
.scc-since { font-size: 11px; color: var(--text-3); }
.scc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; }
.scc-cell-wide { grid-column: 1 / -1; }
.scc-l { font-size: 10px; color: var(--text-3); text-transform: uppercase; letter-spacing: .5px; font-weight: 600; margin-bottom: 2px; }
.scc-v { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-variant-numeric: tabular-nums; font-size: 14px; font-weight: 700; color: var(--text); }
.scc-v small { font-size: 11px; font-weight: 500; opacity: .55; }
.scc-v.ca { color: var(--brand); }
/* Mobile : on cache le tableau et on montre les cards */
@media (max-width: 700px) {
  .tbl-compare-wrap { display: none; }
  .sites-compare-cards { display: flex; }
}

/* ═══════════════════════════════════════════════════════════════════
   PAGE RAPPORTS (#page-reports) — tout scopé pour éviter collisions
   ═══════════════════════════════════════════════════════════════════ */
#page-reports {
  /* Vars locales — défaut = mode clair (texte actif lisible) */
  --rpt-brand-light: var(--brand);    /* texte sur cards actives */
  --rpt-brand2: #E8731F;
  --rpt-night: #1B2733;
  --rpt-green: #10B981;
  --rpt-amber: #F59E0B;
  --rpt-red: #DC2626;
  --rpt-purple: #7C3AED;
  max-width: 1440px;
  margin: 0 auto;
  width: 100%;
}
/* Mode sombre : on revient à l'orange clair pour bien contraster sur les fonds bleu nuit */
:root[data-theme="dark"] #page-reports {
  --rpt-brand-light: #FDBA74;
}
#page-reports.active {
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}
/* Évite que les grid items débordent à cause de leur contenu (tableau large) */
#page-reports.active > aside,
#page-reports.active > section { min-width: 0; }

/* Wrapper "Filtres avancés" — invisible en desktop (juste un container) */
#page-reports .rpt-adv-panel {
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0 0 12px 0;
}
#page-reports .rpt-adv-panel > .rpt-panel-title { display: none; }
/* En desktop, le bandeau garde son propre style (background/border/round) */

/* ─── Tablette (≤1100px) : layout 1 colonne, sidebar empilée au-dessus ─── */
@media (max-width: 1100px) and (min-width: 901px) {
  #page-reports.active { grid-template-columns: 1fr; }
  #page-reports .rpt-sidebar { position: static; }
}

/* ─── Mobile (≤900px) : sidebar empilée + panels en accordéon ─── */
@media (max-width: 900px) {
  #page-reports.active { display: block; }
  #page-reports .rpt-sidebar {
    position: static;
    width: 100%; max-width: none;
    padding: 0;
    margin-bottom: 8px;
  }

  /* ── Accordéon mobile : on cache tout ce qui suit le titre quand fermé ── */
  #page-reports .rpt-panel {
    padding: 0 !important;
    margin-bottom: 6px !important;
    border-radius: 10px;
  }
  #page-reports .rpt-panel-title {
    padding: 7px 12px !important;
    cursor: pointer;
    margin-bottom: 0 !important;
    font-size: 10.5px;
    gap: 6px;
  }
  #page-reports .rpt-panel-title .rpt-acc-summary {
    margin-left: auto;
    font-size: 11px; font-weight: 600;
    color: var(--text-3);
    text-transform: none; letter-spacing: 0;
    max-width: 55%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  #page-reports .rpt-panel-title .rpt-acc-summary b {
    color: var(--rpt-brand-light); font-weight: 700;
  }
  #page-reports .rpt-panel-title .rpt-acc-caret {
    font-size: 14px; color: var(--text-3);
    transition: transform .15s;
    margin-left: 6px;
  }
  #page-reports .rpt-panel.rpt-acc.open .rpt-panel-title .rpt-acc-caret {
    transform: rotate(180deg);
    color: var(--rpt-brand-light);
  }
  /* Le body du panel = tout ce qui suit le titre — caché par défaut */
  #page-reports .rpt-panel.rpt-acc:not(.open) > *:not(.rpt-panel-title) { display: none; }
  /* Quand ouvert : padding sur le 1er enfant après titre */
  #page-reports .rpt-panel.rpt-acc.open > .rpt-panel-title { border-bottom: 1px solid var(--border); }
  #page-reports .rpt-panel.rpt-acc.open > *:not(.rpt-panel-title) {
    padding-left: 12px !important; padding-right: 12px !important;
    padding-bottom: 8px !important; padding-top: 6px !important;
  }

  /* ── Type de rapport : chips horizontaux scrollables (au lieu de cards 2×2) ── */
  #page-reports .rpt-mode-grid {
    display: flex !important;
    grid-template-columns: none;
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: 6px;
    padding-bottom: 1px;
    scrollbar-width: thin;
  }
  #page-reports .rpt-mode-grid::-webkit-scrollbar { height: 3px; }
  #page-reports .rpt-mode-grid::-webkit-scrollbar-thumb { background: var(--border-soft); border-radius: 4px; }
  #page-reports .rpt-mode-card {
    flex: 0 0 auto;
    grid-column: auto !important;
    padding: 5px 10px;
    border-radius: 99px;
    border-width: 1.5px;
    text-align: left;
    display: inline-flex; align-items: center; gap: 6px;
    white-space: nowrap;
  }
  #page-reports .rpt-mode-card .ico { font-size: 12.5px; margin: 0; }
  #page-reports .rpt-mode-card .sub { display: none; }
  #page-reports .rpt-mode-card .ttl { font-size: 11.5px; }

  /* ── Niveau de détail : 3 boutons plus compacts ── */
  #page-reports .rpt-niv-btn { padding: 5px 4px; }
  #page-reports .rpt-niv-btn .ttl { font-size: 11px; }
  #page-reports .rpt-niv-btn .sub { font-size: 9px; }

  /* ── Bouton "Réinitialiser" : taille réduite en mobile ── */
  #page-reports #rpt-reset { padding: 7px 10px; font-size: 11.5px; }
  #page-reports .rpt-panel:has(#rpt-reset) { padding: 6px !important; }

  /* ── Hero compact + export en colonne ── */
  #page-reports .rpt-preview-head { flex-direction: column; gap: 8px; }
  #page-reports .rpt-summary-card {
    min-width: 0;
    padding: 10px 14px 12px;
    gap: 7px;
  }
  #page-reports .rpt-summary-card .ttl { font-size: 10px; }
  #page-reports .rpt-summary-card .watermark { width: 80px; height: 80px; right: -5px; opacity: 0.08; }
  /* Chips période réduites : seulement les 3 raccourcis essentiels */
  #page-reports .rpt-hero-presets .chip[data-preset="yesterday"],
  #page-reports .rpt-hero-presets .chip[data-preset="30d"],
  #page-reports .rpt-hero-presets .chip[data-preset="lastmonth"],
  #page-reports .rpt-hero-presets .chip[data-preset="year"] {
    display: none;
  }
  #page-reports .rpt-hero-presets { gap: 5px; }
  #page-reports .rpt-hero-presets .chip { padding: 3px 9px; font-size: 10.5px; }
  /* Stats : 2 par ligne (grid 2×2) compactes */
  #page-reports .rpt-summary-stats {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px 14px;
  }
  #page-reports .rpt-summary-stat .val { font-size: 18px; }
  #page-reports .rpt-summary-stat .val small { font-size: 10.5px; margin-left: 3px; }
  #page-reports .rpt-summary-stat .lbl { font-size: 10px; }
  #page-reports .rpt-summary-meta { font-size: 10.5px; }
  #page-reports .rpt-export-actions { width: 100%; min-width: 0; }

  /* ── Filtres avancés : accordéon en mobile ── */
  #page-reports .rpt-adv-panel {
    background: var(--panel) !important;
    border: 1px solid var(--border) !important;
    border-radius: 10px !important;
    margin: 0 0 6px !important;
    padding: 0 !important;
  }
  #page-reports .rpt-adv-panel > .rpt-panel-title { display: flex !important; }
  /* Le bandeau à l'intérieur n'a plus son propre style — le panel le porte */
  #page-reports .rpt-adv-panel > .rpt-adv-bar {
    background: transparent !important;
    border: 0 !important;
    border-radius: 0 !important;
    margin: 0 !important;
    padding: 8px 12px 10px !important;
    flex-wrap: wrap;
    gap: 8px;
  }
  /* Bandeau caché si pas open */
  #page-reports .rpt-adv-panel.rpt-acc:not(.open) > .rpt-adv-bar { display: none; }
  #page-reports .rpt-adv-panel .rpt-adv-bar .lbl { display: none; }
  #page-reports .rpt-adv-bar .ff label { display: none; }
  #page-reports .rpt-adv-bar select { min-width: 0; flex: 1; font-size: 11.5px; padding: 5px 6px; }
  #page-reports .rpt-adv-bar .ff { flex: 1 1 calc(50% - 5px); }
  #page-reports .rpt-adv-bar .clear { margin-left: auto; }

  /* ── Synthèse cards : 1 colonne ── */
  #page-reports .rpt-synth-grid { grid-template-columns: 1fr; gap: 10px; padding: 10px; }

  /* Cacher les éléments inutilisés (héritage de la version drawer) */
  #page-reports .rpt-mobile-toolbar,
  #page-reports .rpt-drawer-bg,
  #page-reports .rpt-drawer-close { display: none !important; }
}
/* En desktop, les éléments mobile-only restent cachés */
@media (min-width: 901px) {
  #page-reports .rpt-mobile-toolbar,
  #page-reports .rpt-drawer-bg,
  #page-reports .rpt-drawer-close { display: none !important; }
  #page-reports .rpt-panel-title .rpt-acc-summary,
  #page-reports .rpt-panel-title .rpt-acc-caret { display: none; }
}

#page-reports .rpt-panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 14px;
}
#page-reports .rpt-panel-title {
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 1.2px;
  color: var(--text-3);
  margin-bottom: 12px;
  display: flex; align-items: center; gap: 8px;
}
#page-reports .rpt-panel-title svg { color: var(--rpt-brand-light); }

#page-reports .rpt-sidebar { position: sticky; top: 70px; align-self: start; }

/* Modes */
#page-reports .rpt-mode-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
#page-reports .rpt-mode-card {
  padding: 10px 8px;
  border: 2px solid var(--border-soft);
  background: var(--bg-deep);
  border-radius: 10px;
  cursor: pointer;
  text-align: center;
  transition: all .15s;
  color: var(--text-2);
}
#page-reports .rpt-mode-card:hover { border-color: var(--rpt-brand-light); color: var(--text); }
#page-reports .rpt-mode-card.on {
  border-color: var(--brand);
  background: var(--brand-bg);
  color: var(--rpt-brand-light);
}
#page-reports .rpt-mode-card .ico { font-size: 18px; margin-bottom: 3px; }
#page-reports .rpt-mode-card .ttl { font-size: 12px; font-weight: 700; }
#page-reports .rpt-mode-card .sub { font-size: 10px; color: var(--text-3); margin-top: 2px; }
#page-reports .rpt-mode-card.on .sub { color: var(--rpt-brand-light); opacity: 0.75; }

/* Niveaux */
#page-reports .rpt-niv-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
#page-reports .rpt-niv-btn {
  padding: 7px 4px;
  border: 1.5px solid var(--border-soft);
  background: var(--bg-deep);
  border-radius: 8px;
  cursor: pointer;
  text-align: center;
  color: var(--text-2);
  transition: all .15s;
}
#page-reports .rpt-niv-btn:hover { color: var(--text); border-color: var(--text-3); }
#page-reports .rpt-niv-btn.on { background: var(--brand-bg); border-color: var(--brand); color: var(--rpt-brand-light); }
#page-reports .rpt-niv-btn .ttl { font-size: 11.5px; font-weight: 700; }
#page-reports .rpt-niv-btn .sub { font-size: 9.5px; color: var(--text-3); margin-top: 1px; }
#page-reports .rpt-niv-btn.on .sub { color: var(--rpt-brand-light); opacity: 0.75; }

/* Custom cols */
#page-reports .rpt-custom-cols {
  margin-top: 10px;
  padding: 10px 12px;
  background: var(--bg-deep);
  border: 1px dashed var(--border-soft);
  border-radius: 8px;
  font-size: 11px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px 8px;
}
#page-reports .rpt-custom-cols .ch {
  display: flex; align-items: center; gap: 5px;
  padding: 3px 0;
  color: var(--text-2);
  cursor: pointer;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#page-reports .rpt-custom-cols .ch:hover { color: var(--text); }
#page-reports .rpt-custom-cols input[type="checkbox"] { accent-color: var(--brand); flex: 0 0 auto; }

/* Fields */
#page-reports .rpt-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
#page-reports .rpt-field { margin-bottom: 10px; }
#page-reports .rpt-field label {
  display: block;
  font-size: 11px; font-weight: 700; color: var(--text-3);
  margin-bottom: 4px;
  text-transform: uppercase; letter-spacing: 0.5px;
}
#page-reports .rpt-field input,
#page-reports .rpt-field select {
  width: 100%;
  background: var(--bg-deep);
  border: 1px solid var(--border-soft);
  color: var(--text);
  padding: 7px 10px;
  border-radius: 7px;
  font-size: 12.5px;
  font-family: inherit;
}
#page-reports .rpt-field input:focus,
#page-reports .rpt-field select:focus {
  outline: none; border-color: var(--brand);
}

/* Chips presets */
#page-reports .rpt-preset-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
#page-reports .rpt-preset-row .chip {
  padding: 4px 10px;
  border: 1px solid var(--border-soft);
  background: var(--bg-deep);
  border-radius: 99px;
  font-size: 11px;
  color: var(--text-2);
  cursor: pointer;
}
#page-reports .rpt-preset-row .chip:hover { color: var(--text); border-color: var(--text-3); }
#page-reports .rpt-preset-row .chip.on { background: var(--brand-bg); color: var(--rpt-brand-light); border-color: var(--brand); }

/* Sites chips */
#page-reports .rpt-sites-chips { display: flex; flex-wrap: wrap; gap: 6px; }
#page-reports .rpt-site-chip {
  padding: 5px 10px 5px 8px;
  border: 1.5px solid var(--border-soft);
  background: var(--bg-deep);
  border-radius: 99px;
  font-size: 11.5px;
  color: var(--text-2);
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  transition: all .15s;
}
#page-reports .rpt-site-chip .dot { width: 6px; height: 6px; border-radius: 50%; }
#page-reports .rpt-site-chip .dot.live { background: var(--rpt-green); box-shadow: 0 0 0 2px rgba(16,185,129,0.2); }
#page-reports .rpt-site-chip .dot.warn { background: var(--rpt-amber); box-shadow: 0 0 0 2px rgba(245,158,11,0.25); }
#page-reports .rpt-site-chip .dot.bad  { background: #DC2626; box-shadow: 0 0 0 2px rgba(220,38,38,0.25); animation: dotPulse 2s ease-in-out infinite; }
#page-reports .rpt-site-chip .dot.off { background: var(--text-3); }
#page-reports .rpt-site-chip:hover { color: var(--text); border-color: var(--text-3); }
#page-reports .rpt-site-chip.on { background: var(--brand-bg); color: var(--rpt-brand-light); border-color: var(--brand); }
#page-reports .rpt-site-chip.all { font-weight: 700; }

/* Adv bar (filtres horizontaux dans la colonne main) */
#page-reports .rpt-adv-bar {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px 14px;
  margin-bottom: 12px;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
#page-reports .rpt-adv-bar .lbl {
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 1px;
  color: var(--text-3); display: inline-flex; align-items: center; gap: 6px;
  margin-right: 4px;
}
#page-reports .rpt-adv-bar .lbl svg { color: var(--rpt-brand-light); }
#page-reports .rpt-adv-bar .ff { display: inline-flex; align-items: center; gap: 6px; }
#page-reports .rpt-adv-bar .ff label { font-size: 11px; color: var(--text-3); font-weight: 600; }
#page-reports .rpt-adv-bar select {
  background: var(--bg-deep);
  border: 1px solid var(--border-soft);
  color: var(--text);
  padding: 5px 8px;
  border-radius: 7px;
  font-size: 12px;
  font-family: inherit;
  min-width: 110px;
}
#page-reports .rpt-adv-bar select:focus { outline: none; border-color: var(--brand); }
#page-reports .rpt-adv-bar select.has-val {
  border-color: var(--brand);
  background: var(--brand-bg);
  color: var(--rpt-brand-light);
  font-weight: 700;
}
#page-reports .rpt-adv-bar .clear {
  background: transparent; border: 0; color: var(--text-3);
  font-size: 11.5px; cursor: pointer; margin-left: auto;
  padding: 4px 8px; border-radius: 6px;
}
#page-reports .rpt-adv-bar .clear:hover { color: var(--text); background: var(--bg-deep); }

/* Preview head (summary + actions) */
#page-reports .rpt-preview-head {
  display: flex; flex-wrap: wrap; gap: 14px;
  align-items: stretch; margin-bottom: 14px;
}
#page-reports .rpt-summary-card {
  flex: 1 1 auto;
  background: linear-gradient(135deg, var(--brand) 0%, var(--rpt-brand2) 100%);
  color: white;
  border-radius: 12px;
  padding: 14px 20px;
  min-width: 0;
  display: flex; flex-direction: column; gap: 8px;
  overflow: hidden;
  position: relative;
}
#page-reports .rpt-summary-card .watermark {
  position: absolute; top: 50%; right: -10px;
  transform: translateY(-50%);
  width: 140px; height: 140px;
  opacity: 0.10;
  pointer-events: none;
  color: white;
}
#page-reports .rpt-summary-card .ttl {
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 1.2px; opacity: 0.85;
  display: inline-flex; align-items: center; gap: 6px;
}
#page-reports .rpt-summary-card .ttl svg { opacity: 0.85; }
/* Force le contenu au-dessus du watermark */
#page-reports .rpt-summary-card > *:not(.watermark) { position: relative; z-index: 1; }

/* Tête du hero : titre à gauche, chips presets à droite */
#page-reports .rpt-hero-head {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; flex-wrap: wrap;
}
#page-reports .rpt-hero-presets {
  display: flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end;
}
#page-reports .rpt-hero-presets .chip {
  padding: 4px 10px;
  border: 1px solid rgba(255,255,255,0.25);
  background: rgba(255,255,255,0.10);
  border-radius: 99px;
  font-size: 11px;
  color: rgba(255,255,255,0.92);
  cursor: pointer;
  font-weight: 600;
  transition: all .15s;
}
#page-reports .rpt-hero-presets .chip:hover {
  background: rgba(255,255,255,0.20);
  border-color: rgba(255,255,255,0.45);
}
#page-reports .rpt-hero-presets .chip.on {
  background: white;
  color: var(--brand);
  border-color: white;
  font-weight: 700;
}
#page-reports .rpt-summary-stats { display: flex; flex-wrap: wrap; gap: 22px; }
#page-reports .rpt-summary-stat { line-height: 1.15; }
#page-reports .rpt-summary-stat .val { font-family: 'Consolas', monospace; font-size: 26px; font-weight: 800; }
#page-reports .rpt-summary-stat .val small { font-size: 13px; font-weight: 500; opacity: 0.7; margin-left: 4px; }
#page-reports .rpt-summary-stat .lbl { font-size: 11px; opacity: 0.85; font-weight: 600; }
#page-reports .rpt-summary-meta { font-size: 11.5px; opacity: 0.92; }

/* Export actions */
#page-reports .rpt-export-actions {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 6px;
  min-width: 240px;
}
#page-reports .rpt-export-actions .ttl {
  font-size: 11px; font-weight: 800; color: var(--text-3); text-transform: uppercase; letter-spacing: 1px;
  margin-bottom: 2px;
}
#page-reports .rpt-export-actions .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
#page-reports .rpt-btn {
  padding: 7px 10px;
  border-radius: 8px;
  border: 1px solid var(--border-soft);
  background: var(--bg-deep);
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  justify-content: center;
  transition: all .15s;
  font-family: inherit;
}
#page-reports .rpt-btn:hover { background: var(--panel-2); border-color: var(--text-3); }
#page-reports .rpt-btn.primary {
  background: linear-gradient(135deg, var(--brand), var(--rpt-brand2));
  border-color: var(--brand);
  color: white;
  font-weight: 700;
}
#page-reports .rpt-btn.primary:hover { filter: brightness(1.08); }
#page-reports .rpt-btn.ghost { background: transparent; }

/* Vue tabs */
#page-reports .rpt-view-tabs {
  display: flex; gap: 2px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 3px;
  margin-bottom: 12px;
  width: fit-content;
}
#page-reports .rpt-view-tab {
  padding: 7px 14px;
  font-size: 12px; font-weight: 700;
  color: var(--text-2);
  background: transparent;
  border: 0; border-radius: 7px;
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  font-family: inherit;
}
#page-reports .rpt-view-tab:hover { color: var(--text); }
#page-reports .rpt-view-tab.on { background: var(--brand); color: white; }

/* Preview panel + table */
#page-reports .rpt-preview-panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}
#page-reports .rpt-preview-toolbar {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-deep);
  font-size: 12px; color: var(--text-2);
}
#page-reports .rpt-preview-toolbar b { color: var(--text); font-weight: 700; }
#page-reports .rpt-preview-toolbar .spacer { flex: 1; }
/* Le tableau scrolle DANS sa zone (molette verticale) au lieu d'allonger toute la
   page quand il y a beaucoup de lignes. overflow-x conservé pour les tableaux larges. */
#page-reports .rpt-tbl-wrap { overflow: auto; max-height: calc(100vh - 220px); }
#page-reports table.rpt-table { width: 100%; border-collapse: collapse; font-size: 12px; }
#page-reports table.rpt-table th {
  text-align: left;
  padding: 9px 10px;
  background: var(--bg-deep);
  color: var(--text-3);
  font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.5px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  position: sticky; top: 0; z-index: 1;   /* en-tête figé pendant le scroll */
}
#page-reports table.rpt-table td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  white-space: nowrap;
}
#page-reports table.rpt-table tr:hover td { background: var(--bg-deep); }
#page-reports table.rpt-table td.n,
#page-reports table.rpt-table th.n { text-align: right; font-family: 'Consolas', monospace; }
#page-reports table.rpt-table tr.group-head td {
  background: linear-gradient(90deg, var(--brand-bg), transparent 60%);
  color: var(--rpt-brand-light);
  font-weight: 800;
  text-transform: uppercase;
  font-size: 11.5px;
  letter-spacing: 0.5px;
  padding-top: 10px; padding-bottom: 10px;
  border-top: 2px solid var(--brand);
}
#page-reports table.rpt-table tr.group-subtot td {
  background: var(--bg-deep);
  font-weight: 800;
  color: var(--text);
  border-bottom: 2px solid var(--border-soft);
}
#page-reports table.rpt-table tr.grand-tot td {
  background: var(--rpt-night);
  color: #FDBA74;                   /* orange clair fixe (fond toujours sombre) */
  font-weight: 800;
  font-size: 13px;
  border-top: 2px solid var(--brand);
}
#page-reports .rpt-badge-site {
  font-size: 10px; padding: 1px 7px; border-radius: 99px;
  background: rgba(124, 58, 237, 0.18);
  color: #c4b5fd;
  font-weight: 700;
}
#page-reports .rpt-sens-e { color: var(--rpt-green); font-weight: 700; font-size: 11px; }
#page-reports .rpt-sens-s { color: var(--rpt-amber); font-weight: 700; font-size: 11px; }
#page-reports .rpt-empty {
  padding: 40px 20px;
  text-align: center;
  color: var(--text-3);
  font-size: 13px;
}
#page-reports .rpt-empty svg { width: 32px; height: 32px; opacity: 0.5; margin-bottom: 8px; }
#page-reports .rpt-loading {
  opacity: 0.6;
  pointer-events: none;
}

/* ── Synthèse : cards d'agrégats croisés ───────────────────── */
#page-reports .rpt-synth-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  padding: 14px;
}
@media (max-width: 900px) {
  #page-reports .rpt-synth-grid { grid-template-columns: 1fr; }
}
#page-reports .rpt-synth-card {
  background: var(--bg-deep);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  padding: 12px 14px;
}
#page-reports .rpt-synth-card .ttl {
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.7px;
  color: var(--text-3); margin-bottom: 8px;
  display: flex; align-items: center; gap: 6px;
}
#page-reports .rpt-synth-card .ttl .badge-cnt {
  margin-left: auto; font-size: 10px; color: var(--text-3); font-weight: 600;
}
#page-reports .rpt-synth-card .empty {
  font-size: 12px; color: var(--text-3); padding: 8px 0; font-style: italic;
}
#page-reports .rpt-bar-row {
  display: grid;
  grid-template-columns: 1fr 70px;
  gap: 8px;
  align-items: center;
  padding: 4px 0;
  font-size: 12px;
  border-bottom: 1px dashed var(--border);
}
#page-reports .rpt-bar-row:last-child { border-bottom: 0; }
#page-reports .rpt-bar-row .lbl {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-2);
  display: flex; align-items: center; gap: 8px;
}
#page-reports .rpt-bar-row .lbl .bar-wrap {
  flex: 1; min-width: 50px; height: 5px; background: var(--bg-2); border-radius: 99px; overflow: hidden;
}
#page-reports .rpt-bar-row .lbl .bar-wrap .fill {
  height: 100%; background: linear-gradient(90deg, var(--brand), var(--rpt-brand2)); border-radius: 99px;
}
#page-reports .rpt-bar-row .lbl .name {
  flex: 0 0 auto; max-width: 50%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#page-reports .rpt-bar-row .v {
  text-align: right;
  font-family: 'Consolas', monospace; font-weight: 700; color: var(--text);
}
#page-reports .rpt-bar-row .v small {
  font-size: 10px; color: var(--text-3); font-weight: 500; margin-left: 3px;
}

/* ── Modale Email (overlay) ──────────────────────────────── */
.rpt-email-bg {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.55);
  display: none; opacity: 0;
  z-index: 200; transition: opacity .2s;
}
.rpt-email-bg.show { display: flex; opacity: 1; align-items: center; justify-content: center; padding: 20px; }
.rpt-email-modal {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  width: 100%; max-width: 540px; max-height: 90vh;
  overflow-y: auto;
  padding: 20px 22px;
  display: flex; flex-direction: column; gap: 14px;
  color: var(--text);
}
.rpt-email-modal h3 {
  font-size: 15px; margin: 0;
  display: flex; align-items: center; gap: 8px;
}
.rpt-email-modal h3 svg { color: var(--brand); }
.rpt-email-modal .close-x {
  margin-left: auto;
  background: transparent; border: 1px solid var(--border-soft);
  width: 30px; height: 30px; border-radius: 8px;
  color: var(--text-2); cursor: pointer; font-size: 16px;
}
.rpt-email-modal .field { display: flex; flex-direction: column; gap: 5px; }
.rpt-email-modal .field label {
  font-size: 11px; font-weight: 700; color: var(--text-3);
  text-transform: uppercase; letter-spacing: 0.5px;
}
.rpt-email-modal input, .rpt-email-modal textarea {
  background: var(--bg-deep);
  border: 1px solid var(--border-soft);
  color: var(--text);
  padding: 8px 10px;
  border-radius: 7px;
  font-size: 13px;
  font-family: inherit;
}
.rpt-email-modal input:focus, .rpt-email-modal textarea:focus { outline: none; border-color: var(--brand); }
.rpt-email-modal textarea { min-height: 80px; resize: vertical; }
.rpt-email-modal .recipients-list {
  display: flex; flex-wrap: wrap; gap: 5px;
  min-height: 36px;
  padding: 6px;
  background: var(--bg-deep);
  border: 1px solid var(--border-soft);
  border-radius: 7px;
}
.rpt-email-modal .recipients-list .chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px;
  background: var(--brand-bg);
  border: 1px solid var(--brand);
  border-radius: 99px;
  font-size: 12px;
  color: var(--brand);
  font-weight: 600;
}
.rpt-email-modal .recipients-list .chip .rm {
  cursor: pointer; opacity: 0.6; font-size: 14px; line-height: 1;
}
.rpt-email-modal .recipients-list .chip .rm:hover { opacity: 1; }
.rpt-email-modal .recipients-list .input-inline {
  flex: 1; min-width: 120px;
  background: transparent; border: 0; padding: 4px;
  color: var(--text); font-size: 13px;
  font-family: inherit;
}
.rpt-email-modal .recipients-list .input-inline:focus { outline: none; }
.rpt-email-modal .defaults-row {
  display: flex; flex-wrap: wrap; gap: 5px;
}
.rpt-email-modal .defaults-row .chip {
  padding: 4px 9px;
  background: var(--bg-deep);
  border: 1px solid var(--border-soft);
  border-radius: 99px;
  font-size: 11.5px;
  color: var(--text-2);
  cursor: pointer;
}
.rpt-email-modal .defaults-row .chip:hover { color: var(--text); border-color: var(--brand); }
.rpt-email-modal .attach-row { display: flex; flex-wrap: wrap; gap: 8px; }
.rpt-email-modal .attach-row label {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 10px;
  background: var(--bg-deep);
  border: 1px solid var(--border-soft);
  border-radius: 7px;
  font-size: 12.5px;
  cursor: pointer;
  color: var(--text-2);
}
.rpt-email-modal .attach-row label.on {
  background: var(--brand-bg);
  border-color: var(--brand);
  color: var(--brand);
  font-weight: 600;
}
.rpt-email-modal .attach-row input { display: none; }
.rpt-email-modal .actions {
  display: flex; gap: 8px; justify-content: flex-end;
  padding-top: 6px;
}
.rpt-email-modal .actions .rpt-btn { padding: 9px 16px; }
.rpt-email-modal .warning {
  padding: 10px 12px;
  background: var(--brand-bg);
  border: 1px solid var(--brand);
  border-radius: 8px;
  font-size: 12px;
  color: var(--brand);
}

/* ── Modale Historique des envois email ────────────────── */
.rpt-hist-bg {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.55);
  display: none; opacity: 0;
  z-index: 200; transition: opacity .2s;
}
.rpt-hist-bg.show { display: flex; opacity: 1; align-items: center; justify-content: center; padding: 20px; }
.rpt-hist-modal {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  width: 100%; max-width: 720px; max-height: 90vh;
  display: flex; flex-direction: column;
  color: var(--text);
}
.rpt-hist-modal .head {
  display: flex; align-items: center; gap: 8px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  font-size: 15px; font-weight: 700;
}
.rpt-hist-modal .head svg { color: var(--brand); }
.rpt-hist-modal .head .close-x {
  margin-left: auto;
  background: transparent; border: 1px solid var(--border-soft);
  width: 30px; height: 30px; border-radius: 8px;
  color: var(--text-2); cursor: pointer; font-size: 16px;
}
.rpt-hist-modal .body {
  flex: 1; overflow-y: auto;
  padding: 8px 16px 16px;
}
.rpt-hist-item {
  border: 1px solid var(--border);
  background: var(--bg-deep);
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 8px;
  display: flex; gap: 10px; align-items: flex-start;
  font-size: 12.5px;
}
.rpt-hist-item .status {
  width: 24px; height: 24px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 800;
  flex: 0 0 auto;
}
.rpt-hist-item .status.sent {
  background: rgba(16,185,129,0.18); color: var(--rpt-green);
}
.rpt-hist-item .status.failed {
  background: rgba(220,38,38,0.18); color: var(--rpt-red);
}
.rpt-hist-item .info { flex: 1; min-width: 0; }
.rpt-hist-item .row1 { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.rpt-hist-item .when {
  font-weight: 700; color: var(--text); font-size: 12.5px;
}
.rpt-hist-item .when-rel { color: var(--text-3); font-size: 11px; font-weight: 500; }
.rpt-hist-item .source-badge {
  font-size: 10px; padding: 1px 6px; border-radius: 99px;
  background: var(--brand-bg); color: var(--brand);
  font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;
}
.rpt-hist-item .subj {
  font-weight: 600; color: var(--text);
  margin: 3px 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rpt-hist-item .meta {
  font-size: 11px; color: var(--text-2);
  display: flex; flex-wrap: wrap; gap: 10px;
}
.rpt-hist-item .meta b { color: var(--text); font-weight: 600; }
.rpt-hist-item .attach-tags {
  display: inline-flex; gap: 4px; margin-left: 4px;
}
.rpt-hist-item .attach-tag {
  font-size: 9.5px; padding: 1px 5px; border-radius: 4px;
  background: var(--bg-2); color: var(--text-2);
  text-transform: uppercase; font-weight: 700;
}
.rpt-hist-item .error-msg {
  margin-top: 4px;
  font-size: 11px; color: var(--rpt-red);
  background: rgba(220,38,38,0.08);
  padding: 4px 7px; border-radius: 5px;
  border-left: 2px solid var(--rpt-red);
}
.rpt-hist-item .actions {
  display: flex; flex-direction: column; gap: 4px;
  flex: 0 0 auto;
}
.rpt-hist-item .actions button {
  padding: 5px 10px;
  border-radius: 6px;
  border: 1px solid var(--border-soft);
  background: var(--bg-1);
  color: var(--text-2);
  font-size: 11px; font-weight: 600;
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 4px;
  font-family: inherit;
  white-space: nowrap;
}
.rpt-hist-item .actions button:hover { background: var(--panel-2); color: var(--text); border-color: var(--brand); }
.rpt-hist-item .actions button.primary {
  background: var(--brand-bg); color: var(--brand); border-color: var(--brand);
}
.rpt-hist-empty {
  padding: 30px 20px; text-align: center; color: var(--text-3);
  font-size: 13px;
}
.rpt-hist-empty svg { width: 32px; height: 32px; opacity: 0.5; margin-bottom: 8px; }
.rpt-hist-modal .head .count {
  margin-left: auto;
  font-size: 11px; color: var(--text-3); font-weight: 500;
  padding-right: 8px;
}

#page-reports .rpt-doc-note {
  margin-top: 16px;
  padding: 12px 16px;
  background: var(--bg-deep);
  border: 1px dashed var(--border-soft);
  border-radius: 10px;
  font-size: 11.5px;
  color: var(--text-2);                /* gris plus foncé → lisible en mode clair */
  line-height: 1.7;
}
#page-reports .rpt-doc-note b { color: var(--text); }

/* ═══════════════════════════════════════════════════════════════════
   CORRECTIFS TABLETTE — 2026-08-09
   ═══════════════════════════════════════════════════════════════════
   Audit mesuré en 768×1024 et 1024×768 : le responsive avait été pensé
   pour le téléphone (≤ 700 px) et le grand écran, et la tablette tombait
   dans le trou entre les deux.

   ⚠ Le diagnostic initial (« ça déborde sans défilement ») s'est révélé
   faux à la mesure pour deux des trois zones : elles défilent
   parfaitement. Ce qui manquait, c'est de le FAIRE SAVOIR — sur écran
   tactile la barre de défilement est un survol, mesuré à 0 px de hauteur
   réservée, donc invisible tant qu'on ne l'a pas déjà trouvée. D'où un
   voile de bord plutôt qu'un `overflow` de plus.
   La nav d'onglets, elle, était bien en `overflow: visible` : ses
   onglets de droite étaient réellement inatteignables. */

/* Voile de bord d'une zone à défilement horizontal.
   Les deux premières couches sont ancrées au CONTENU (`local`) : elles
   glissent avec lui et viennent MASQUER l'ombre quand on atteint le bord.
   Les deux suivantes, ancrées au CADRE (`scroll`), sont les ombres
   elles-mêmes. Résultat : l'ombre n'apparaît que du côté où il reste
   quelque chose à voir, et disparaît d'elle-même sinon. Aucun JS, et
   aucun effet quand la zone tient à l'écran. */
.tabs.scroll-x,
#page-reports .rpt-mode-grid.scroll-x,
#page-reports .rpt-tbl-wrap {
  overflow-x: auto;
  background:
    linear-gradient(to right, var(--scroll-x-bg, var(--panel)) 40%, transparent) left center,
    linear-gradient(to left,  var(--scroll-x-bg, var(--panel)) 40%, transparent) right center,
    radial-gradient(farthest-side at 0    50%, var(--scroll-edge), transparent) left center,
    radial-gradient(farthest-side at 100% 50%, var(--scroll-edge), transparent) right center,
    var(--scroll-x-bg, var(--panel));
  background-repeat: no-repeat;
  background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
  background-attachment: local, local, scroll, scroll;
}

/* ① La nav d'onglets. Mesuré : 1 333 px de contenu — elle ne tient donc
   PAS non plus sur un portable 1366×768, ce n'est pas qu'une affaire de
   tablette. En `overflow: visible`, 6 onglets sur 13 étaient hors de
   l'écran en portrait (4 en paysage) et la page ne défilait pas
   horizontalement : Caisse, Journal, Sites, Top et Paramètres étaient
   simplement hors d'atteinte. */
.tabs.scroll-x {
  overflow-y: hidden;               /* une barre de 44 px ne défile jamais en hauteur */
  scroll-behavior: smooth;
  overscroll-behavior-x: contain;   /* pas de « retour arrière » du navigateur au bout */
}
.tabs.scroll-x .tab { flex: 0 0 auto; }   /* jamais compressé : c'est le défilement qui gère */
/* Barre de défilement fine, aux couleurs du thème : la barre native pesait
   lourd sous une nav de 44 px (16 px de haut, avec ses flèches). Invisible de
   toute façon sur tablette, où c'est un survol.
   ⚠⚠ `scrollbar-width` DÉSACTIVE les `::-webkit-scrollbar` — les deux ne se
   cumulent pas (mesuré : `thin` → 11 px ; en neutralisant `thin`, on remonte à
   16 px, donc le `height: 6px` webkit n'était JAMAIS appliqué). C'est donc le
   duo standard `scrollbar-width` + `scrollbar-color` qui pilote ici, et lui
   seul : ne pas espérer régler la hauteur au pixel par le bloc webkit.
   Celui-ci ne sert que de repli pour les moteurs sans `scrollbar-width`
   (Safari < 18.2, qui équipe une partie des iPad). */
.tabs.scroll-x { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
.tabs.scroll-x::-webkit-scrollbar { height: 6px; }
.tabs.scroll-x::-webkit-scrollbar-track { background: transparent; }
.tabs.scroll-x::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; }
.tabs.scroll-x::-webkit-scrollbar-thumb:hover { background: var(--brand); }

/* ③ Les cartes de mode de la page Rapports (≤ 900 px, où elles passent en
   pastilles sur une ligne). Mesuré en 768 : 1 220 px pour 711 disponibles,
   4 modes sur 10 hors écran, et le défilement déjà en place.
   ⚠ Le fond du voile doit être celui du conteneur, sinon la bande de masquage
   se voit. Vérifié à la mesure : le panneau qui porte ces pastilles est en
   `--panel` (blanc en thème clair) — une première version posait `--bg-deep`
   ici et aurait peint une bande grise sur du blanc. La valeur par défaut de
   `--scroll-x-bg` est la bonne : rien à surcharger. */

/* ④ L'aperçu de TABLEAU des Rapports (2026-08-09). Mesuré en 768 : 2 540 px de
   contenu pour 711 disponibles — il défilait déjà, mais rien ne le disait, et
   sur une tablette la barre native est en surimpression (0 px réservé) donc
   invisible tant qu'on ne défile pas. Contrairement aux deux zones ci-dessus,
   celle-ci n'a pas de classe `.scroll-x` posée par le JS : la règle s'applique
   donc en direct, ce qui est sans risque — les deux dégradés de masquage sont
   en `background-attachment: local`, ils recouvrent exactement les ombres quand
   il n'y a rien à faire défiler. Aucun effet quand le tableau tient à l'écran.
   ⚠ Deux objections de l'audit levées À LA MESURE, pas par raisonnement :
   (a) « le conteneur a un fond transparent, le voile y peindrait une bande » —
       vrai du conteneur lui-même, mais le fond EFFECTIF derrière lui est
       `.rpt-preview-panel`, et il vaut `--panel` dans les DEUX thèmes (blanc en
       clair, #131C25 en sombre, vérifié en basculant `data-theme`). La valeur
       par défaut `var(--scroll-x-bg, var(--panel))` est donc déjà la bonne, et
       elle suit le thème toute seule.
   (b) « il défile aussi en Y, donc `local` dériverait » — faux : mesuré
       `scrollHeight === clientHeight`, ce tableau ne défile QU'EN X. */
/* ⑥ Le HEADER en tablette (701 → 900 px) — signalé par l'utilisateur sur
   capture, l'audit du 08/08 ne l'avait pas vu.
   Mesuré en 768 : `.logo` fait 61 px de haut et `#health` 58, dans un header
   qui en fait 56 — « GEI BasculPro · Central » et « Central · en ligne »
   passaient à la ligne et débordaient de leur barre.
   La cause n'est pas une largeur mal réglée : c'est que TOUS les enfants ont
   `flex-shrink: 1`. Chacun se comprime donc un peu, son texte se casse en
   plusieurs lignes, et la hauteur explose. Dans une barre à hauteur fixe,
   personne ne doit passer à la ligne — il faut DÉSIGNER qui absorbe le manque
   de place. Ici c'est le sélecteur de poste : il sait déjà se tronquer
   proprement (`.val` a un `text-overflow: ellipsis`).
   En dessous de 701 px, le mobile masque déjà `.health` et `.user-pill` : rien
   à faire, et on ne touche pas à son ticker `.hdr-central-name` en absolu. */
@media (min-width: 701px) and (max-width: 900px) {
  .hdr > * { flex-shrink: 0; white-space: nowrap; }
  .hdr .poste-select { flex-shrink: 1; min-width: 0; overflow: hidden; }
  /* « · Central » : redondant avec le badge d'état juste à côté. */
  .hdr .logo .sub { display: none; }
  /* L'avatar suffit à dire qui est connecté ; le nom reprend sa place ≥ 901. */
  .hdr .user-pill > span:not(.avatar) { display: none; }
  .hdr .user-pill { padding: 4px; }
}

/* ② La page Pesées passe en cartes dès 900 px (au lieu de 700).
   Mesuré en portrait 768 : la table fait 14 colonnes, déborde de 169 px, et
   ce sont Tare / Brut / Net / Valeur qui sortent du champ — c'est-à-dire le
   cœur de la pesée. Elle défile, mais l'opérateur n'a aucun moyen de le
   deviner. Le mode cartes existait déjà pour le téléphone : on l'étend à la
   tablette plutôt que d'inventer un troisième affichage.
   En paysage (1024) la table revient : là elle tient sans déborder (mesuré). */
@media (max-width: 900px) {
  #pesees-table-wrap { display: none; }
  #pesees-cards { display: flex; flex-direction: column; gap: 8px; }
}
@media (min-width: 901px) {
  #pesees-cards { display: none; }
}

/* Mouvements de stock : MÊME bascule tableau ⇄ cartes que les pesées.
   Signalé terrain le 2026-09-09 — « une section inutile en bas » : les cartes
   mobiles s'affichaient EN PLUS du tableau, à toutes les tailles, si bien que
   les 15 mouvements étaient listés deux fois de suite. #pesees-cards et
   #activity-cards avaient chacun leur règle de masquage ; celle de
   #stock-mvts-cards n'a jamais été écrite, et rien ne le signalait puisque
   .mcard n'est pas masquée par défaut. */
@media (max-width: 900px) {
  #stock-mvts-wrap { display: none; }
  #stock-mvts-cards { display: flex; flex-direction: column; gap: 8px; }
}
@media (min-width: 901px) {
  #stock-mvts-cards { display: none; }
}

/* Carte DENSE — tablette SEULEMENT (701 → 900 px).
   La carte d'origine est dessinée pour un téléphone de 360 px : à 711 px de
   large, la moitié est vide et on empile trois lignes pour rien. Mesuré :
   94 px par pesée, soit 3 pesées à l'écran. En une seule ligne on tombe à
   ~40 px, soit le double de pesées visibles.
   ⚠ Bornée à 701 px : en dessous (téléphone) la disposition d'origine
   reprend la main — une ligne unique n'y tiendrait évidemment pas. */
@media (min-width: 701px) and (max-width: 900px) {
  #pesees-cards .mcard {
    padding: 6px 12px;
    gap: 0 12px;
    grid-template-columns: auto minmax(0, 1.1fr) minmax(0, 1fr) auto;
    align-items: center;
  }
  #pesees-cards .mcard .plaque { grid-area: 1 / 1; }
  #pesees-cards .mcard div.meta:nth-of-type(1) { grid-area: 1 / 2; }
  #pesees-cards .mcard div.meta:nth-of-type(2) { grid-area: 1 / 3; }
  #pesees-cards .mcard .net { grid-area: 1 / 4; }
  /* Sur une seule ligne, un nom de client long doit se couper par la fin
     plutôt que pousser le net hors de l'écran. */
  #pesees-cards .mcard div.meta { flex-wrap: nowrap; overflow: hidden; white-space: nowrap; }
  #pesees-cards .mcard div.meta:nth-of-type(2) span:first-child { overflow: hidden; text-overflow: ellipsis; }
  /* Le mode suppression garde sa gouttière : sans ça, la case à cocher
     dessinée en ::before recouvrirait la plaque. */
  #pesees-cards .mcard.delmode { padding-left: 42px; }
}



/* ═══════════════════════════════════════════════════════════════════
   ONGLET BONS — sorti du <style> en ligne de dashboard.html le 2026-08-09
   (93 l.), parce que cette session en modifie la mise en page tablette et
   que la règle veut qu'on sorte une section avant d'y toucher.
   Collisions vérifiées avant déplacement : aucun de ces 36 sélecteurs
   n'est redéfini ailleurs, ni dans ce fichier ni dans les autres blocs
   <style> du <body> → remonter ces règles en amont du document ne change
   RIEN à la cascade.
   ═══════════════════════════════════════════════════════════════════ */
/* Carte de détail (droite) du master-detail : fond SÉPARÉ de la liste (gauche).
   S'applique aussi à la page Stock pour la cohérence. */
.stk-md-detail { background:var(--panel-2); border:1px solid var(--border); border-radius:10px; padding:16px; min-width:0; }
/* Cartes KPI du détail bon : contrastées dans la modale (sur --panel) ET inline (sur --panel-2) */
.bon-kpi { background:var(--panel-2); border:1px solid var(--border); box-shadow:0 1px 2px rgba(0,0,0,.06); }
.stk-md-detail .bon-kpi { background:var(--panel); }
.bons-md-searchinp { width:100%; padding:8px 10px; border:1px solid var(--border); border-radius:8px; background:var(--panel-2); color:var(--text); font-size:12.5px; box-sizing:border-box; }
.bons-md-filters { display:flex; flex-wrap:wrap; gap:6px; }
/* Chips theme-aware (lisibles en clair ET sombre) */
.bons-md-filters .chip { font-size:11px; font-weight:600; padding:4px 10px; border-radius:20px; border:1px solid var(--border); background:var(--panel-2); color:var(--text-2); cursor:pointer; }
.bons-md-filters .chip:hover { color:var(--text); border-color:var(--text-3); }
.bons-md-filters .chip.on { background:var(--brand); color:#fff; border-color:var(--brand); }
.bons-md-cat { padding:9px 12px; font-size:10.5px; font-weight:800; letter-spacing:.6px; text-transform:uppercase; color:#fff; display:flex; align-items:center; gap:7px; background:var(--brand,#C45200); position:sticky; top:0; z-index:1; cursor:pointer; user-select:none; }
.bons-md-cat:hover { filter:brightness(1.08); }
.bons-md-chev { color:#fff; flex:0 0 auto; transition:transform .15s; }
.bons-md-cat.closed .bons-md-chev { transform:rotate(-90deg); }
.bons-md-cat .cnt { margin-left:auto; font-family:var(--mono,Consolas,monospace); color:var(--brand); background:#fff; font-weight:700; border-radius:20px; padding:0 8px; font-size:10px; }
.bons-pli-pct { font-family:var(--mono,Consolas,monospace); font-size:11px; font-weight:700; text-align:right; min-width:42px; }
.bons-pli-pct small { display:block; font-size:9px; color:var(--text-3); font-weight:600; }
.bons-pli-bar { height:4px; background:var(--border); border-radius:3px; margin-top:5px; overflow:hidden; }
.bons-pli-bar > i { display:block; height:100%; border-radius:3px; }
/* ══ Bons — vue Cartes (catégories → grille) + Liste (dense repliable) · réplique desktop ══ */
.bons-2col { display:grid; grid-template-columns:230px 1fr; gap:14px; align-items:start; }
/* Repli en UNE colonne. ⚠ Le seuil était 760 px — huit pixels sous une tablette
   portrait (768). Exactement la même erreur que la LISTE des Bons corrigée la
   veille : le repli existait, il ne se déclenchait simplement jamais sur
   l'appareil auquel il était destiné.
   Mesuré en 768 AVANT correction : la colonne de gauche prenait ses 230 px
   fixes + 14 de gouttière, il ne restait que 439 px pour la grille de cartes
   sur les 683 disponibles ⇒ `repeat(auto-fill, minmax(280px,1fr))` ne pouvait
   rendre qu'UNE colonne. Ce n'est donc pas la hauteur des cartes qui était en
   cause (170 px, raisonnable) mais la LARGEUR volée par la nav.
   Seuil aligné sur 1010 px, celui déjà retenu pour la liste : une seule bascule
   pour toute la page, dans les deux modes d'affichage. */
@media (max-width:1010px){ .bons-2col{ grid-template-columns:1fr; } }

.bcat-nav { background:var(--panel-2); border:1px solid var(--border); border-radius:10px; overflow:hidden; position:sticky; top:8px; }
.bcat-item { display:flex; align-items:center; gap:10px; padding:12px 14px; border-bottom:1px solid var(--border); cursor:pointer; border-left:3px solid transparent; }
.bcat-item:last-child { border-bottom:none; }
.bcat-item:hover { background:var(--panel); }
.bcat-item.active { background:var(--brand-bg,rgba(196,82,0,.14)); border-left-color:var(--brand); }
.bcat-ic { width:30px; height:30px; border-radius:8px; display:flex; align-items:center; justify-content:center; font-size:15px; background:var(--panel); flex:0 0 auto; }
.bcat-item.active .bcat-ic { background:var(--brand-bg,rgba(196,82,0,.14)); }
.bcat-main { flex:1; min-width:0; }
.bcat-nom { font-weight:700; font-size:13px; color:var(--text); }
.bcat-sub { font-size:10.5px; color:var(--text-3); margin-top:1px; }
.bcat-dot { width:7px; height:7px; border-radius:50%; flex:0 0 auto; }
.bcat-cnt { font-family:Consolas,monospace; font-weight:800; font-size:16px; color:var(--text-2); }
.bcat-item.active .bcat-cnt { color:var(--brand); }

/* En dessous du seuil, la nav de catégories passe en BANDEAU HORIZONTAL
   défilant plutôt que de s'empiler telle quelle au-dessus de la grille :
   empilée, elle coûtait ~121 px de hauteur sur un écran où le premier bon
   n'apparaissait déjà qu'à 640 px. En bandeau, ~57 px, et la grille récupère
   les 683 px ⇒ deux colonnes de cartes au lieu d'une (mesuré : 335,5 px × 2).
   Même parti pris que la nav d'onglets : on défile, on ne comprime pas — un
   libellé de catégorie tronqué ne se lit plus. Barre fine pilotée par
   `scrollbar-width`/`scrollbar-color` (⚠ #194 : déclarer `scrollbar-width`
   ANNULE les `::-webkit-scrollbar`, inutile d'en poser un).
   Le repère visuel de l'élément actif bascule de la gauche vers le BAS : sur
   une rangée horizontale, un liseré à gauche ne désigne plus rien.
   ⚠ Ce bloc DOIT rester APRÈS les règles de base `.bcat-nav` / `.bcat-item`
   ci-dessus : à spécificité égale, c'est l'ordre du fichier qui tranche. Placé
   avant, son `overflow-x:auto` était écrasé par l'`overflow:hidden` de la règle
   de base — mesuré, le bandeau ne défilait pas (et la disposition en flex
   passait quand même, ce qui rendait le défaut discret). */
@media (max-width:1010px){
  .bcat-nav {
    position: static;                /* sticky n'a pas de sens sur un bandeau */
    display: flex; overflow-x: auto; overflow-y: hidden;
    scrollbar-width: thin; scrollbar-color: var(--border) transparent;
    overscroll-behavior-x: contain;
  }
  .bcat-item {
    flex: 0 0 auto;                  /* jamais compressé : c'est le défilement qui gère */
    padding: 8px 12px; gap: 8px;
    border-bottom: 3px solid transparent;
    border-left: 0;
    border-right: 1px solid var(--border);
  }
  .bcat-item:last-child { border-right: none; }
  .bcat-item.active { border-left-color: transparent; border-bottom-color: var(--brand); }
  .bcat-ic { width: 24px; height: 24px; font-size: 13px; border-radius: 6px; }
  .bcat-nom { font-size: 12px; white-space: nowrap; }
  .bcat-sub { display: none; }       /* « toutes catégories », « cumul » : redondant en chip */
  .bcat-cnt { font-size: 14px; }
}
/* Palette des tableaux « cahier », REPRISE de la Caisse (js/caisse-journal.js)
   comme la fiche de stock et le rapport d'écart — pas réinventée : une palette
   maison avait donné des fonds à 1,04 de contraste en mode sombre. Elle est
   définie ICI, dans la feuille de la page, et non empruntée au <style> d'un
   autre écran : la liste des bons ne doit pas dépendre de l'ouverture du Stock
   pour avoir ses couleurs. */
:root { --bl-th:#F5F2F1; --bl-hover:#F7E7DB; --bl-sep:#D8E2EE; --bl-sep2:#25374B; --bl-sep2-txt:#FFFFFF; --bl-filet:#CBD5E1; }
[data-theme="dark"] { --bl-th:#191D22; --bl-hover:#432C1E; --bl-sep:#243547; --bl-sep2:#3D5673; --bl-sep2-txt:#E5E7EB; --bl-filet:#334155; }

/* ══ VUE LISTE DES BONS — le tableau (2026-09-12) ══
   Même bois que la fiche de stock et « Commandé vs Chargé » : en-tête collant
   qui NOMME les colonnes, barres de catégorie repliables portant les totaux du
   groupe, pied collant. Palette reprise de la Caisse, comme les deux autres.
   ⚠ `table-layout:auto` : les colonnes se répartissent d'après le CONTENU. Les
   largeurs fixes de l'ancienne liste (`.blist-*`, plus bas) avaient été mesurées
   sans le badge de type, ajouté un mois plus tard dans la même colonne — le n°
   du bon en était chassé. Un tableau n'a pas cette dette. */
.bl-wrap { background:var(--panel); border:1px solid var(--border); border-radius:12px; overflow:hidden; }
/* ⭐ HAUTEUR : le plus de lignes possible d'un seul coup d'œil (demande de
   l'utilisateur, 2026-09-12). Mesuré sur une fenêtre de 974 px : 64 vh ne
   donnaient que 14 lignes alors que le cadre s'arrêtait à 11 px du bas — la
   place existait. Deux bornes, et c'est la plus petite qui gagne :
   · `84vh` pour garder un repère de page sur un très grand écran ;
   · `100vh − 110px` pour qu'en défilant, l'en-tête collant du tableau reste
     DANS l'écran — un tableau plus haut que la fenêtre colle son en-tête hors
     de vue et on perd le nom des colonnes en lisant.
   Même règle sur les trois tableaux « cahier » (fiche de stock, écart). */
.bl-scroll { max-height:min(84vh, calc(100vh - 110px)); min-height:320px; overflow:auto; overflow-anchor:none; scrollbar-width:thin; }
.bl-tbl { width:100%; border-collapse:collapse; font-size:12.5px; table-layout:auto; }
.bl-tbl th { position:sticky; top:0; z-index:3; background:var(--bl-th); text-align:left; padding:8px 10px; font-size:10.5px; text-transform:uppercase; letter-spacing:.04em; color:var(--text-2); border-bottom:2px solid var(--bl-filet); white-space:nowrap; }
.bl-tbl td { padding:6px 10px; border-bottom:1px solid var(--border); vertical-align:middle; }
/* ⭐ SÉPARATIONS VERTICALES entre colonnes. Sur dix colonnes, rien ne guidait
   l'œil d'un bout à l'autre d'une ligne — on lisait un client sur une ligne et
   son tonnage sur la suivante. Un filet discret suffit ; il ne touche PAS les
   barres de catégorie, qui n'ont qu'une cellule (`td + td` ne s'y applique pas). */
.bl-tbl thead th + th, .bl-tbl tbody tr.bl-op td + td { border-left:1px solid var(--border); }
/* `td.bl-r` et non `.bl-r` : la spécificité compte les CLASSES avant les
   éléments, un sélecteur à une classe perdrait contre `.bl-tbl td`. */
.bl-tbl th.bl-r, .bl-tbl td.bl-r { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
.bl-tbl td.bl-qty, .bl-tbl td.bl-pes { font-family:Consolas,monospace; font-weight:700; color:var(--text-2); }
.bl-tbl tr.bl-op { cursor:pointer; }
.bl-tbl tr.bl-op:hover td { background:var(--bl-hover); }
.bl-tbl td.bl-chk, .bl-tbl th.bl-chk { width:1%; padding-right:0; }
.bl-dot { display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:6px; vertical-align:middle; }
.bl-tbl td.bl-num { font-family:Consolas,monospace; font-size:12.5px; color:var(--text); white-space:nowrap; }
/* Le client sur UNE ligne : replié sur deux, il portait la ligne de 32 à 49 px.
   320 px laissent passer les noms les plus longs mesurés (0 tronqué sur 306
   bons) ; au-delà c'est le cadre qui défile de quelques pixels, et sous
   1 010 px la colonne Produit s'efface et rend la place. Le nom complet reste
   dans l'infobulle de la cellule, donc rien n'est perdu même tronqué. */
.bl-tbl td.bl-cli { color:var(--text-2); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:320px; }
/* ⭐ Le site sur la MÊME ligne que le client. Mesuré : en dessous, il portait la
   ligne de 33 à 46 px — 13 px par ligne pour une donnée secondaire, soit 7
   lignes de moins à l'écran (18 au lieu de 25 sur une fenêtre de 974 px). Rien
   n'est perdu : le site reste écrit, en gris, après un point médian. */
.bl-cli .bl-site { display:inline; margin-left:6px; font-size:10.5px; color:var(--text-3); }
.bl-cli .bl-site:before { content:"· "; }
/* `nowrap` : mesuré, un nom de produit replié sur deux lignes remontait la
   ligne de 33 à 49 px — un tiers de lignes en moins à l'écran pour rien. Si la
   largeur vient à manquer, c'est le cadre qui défile (il est en overflow:auto),
   et sous 1 010 px la colonne s'efface de toute façon. */
.bl-tbl td.bl-prod { color:var(--text-3); white-space:nowrap; }
.bl-av { width:170px; }
.bl-bar { display:block; width:100%; min-width:70px; height:7px; background:var(--panel-2); border-radius:4px; overflow:hidden; }
.bl-bar > i { display:block; height:100%; border-radius:4px; }
.bl-pill { display:inline-block; font-size:10.5px; font-weight:700; padding:1px 8px; border-radius:99px; white-space:nowrap; }
.bl-tbl td.bl-date { font-family:Consolas,monospace; font-size:11.5px; color:var(--text-2); white-space:nowrap; }
/* Une date DÉDUITE de la 1ʳᵉ pesée ne se présente pas comme une date saisie :
   elle est grisée, précédée d'un « ~ », et son infobulle dit d'où elle vient. */
.bl-tbl td.bl-date .bl-approx { color:var(--text-3); font-style:italic; cursor:help; }
.bl-tbl td.bl-date .bl-vide { color:var(--text-3); }
/* La barre de catégorie : fond LÉGER. L'aplat sombre est réservé au pied —
   répété à chaque groupe il pèserait plus que le tableau qu'il annonce. */
.bl-tbl tr.bl-sep td { padding:0; border-bottom:0; }
.bl-sepbar { display:flex; align-items:center; gap:9px; padding:6px 10px; background:var(--bl-sep); color:var(--text); border-top:1px solid var(--bl-filet); border-bottom:1px solid var(--bl-filet); cursor:pointer; }
.bl-sepbar:hover { filter:brightness(.97); }
.bl-sepbar:focus-visible { outline:2px solid var(--brand); outline-offset:-2px; }
.bl-sepbar .bl-ch { width:10px; font-size:11px; color:var(--text-3); }
.bl-sepbar .bl-ti { font-weight:700; font-size:12px; }
.bl-sepbar .bl-nb { font-size:11px; color:var(--text-3); }
.bl-sepbar .bl-tot { margin-left:auto; font-size:11.5px; font-family:Consolas,monospace; font-variant-numeric:tabular-nums; white-space:nowrap; }
.bl-sepbar .bl-tot .k { font-family:inherit; font-size:10.5px; text-transform:uppercase; letter-spacing:.04em; color:var(--text-3); margin:0 4px 0 10px; }
/* Le bon qui vient d'arriver clignote — même repère que les cartes, sinon la
   refonte en tableau l'aurait perdu en silence. */
.bl-tbl tr.bl-op.bon-flash-new { animation:bonFlashRowC 2.4s ease-out; }
.bl-foot { position:sticky; bottom:0; z-index:5; }
.bl-frow { display:flex; align-items:baseline; gap:16px; padding:7px 12px; background:var(--bl-sep2); color:var(--bl-sep2-txt); font-weight:800; font-size:12.5px; border-top:2px solid var(--bl-sep2); }
.bl-flab { text-transform:uppercase; font-size:10.5px; letter-spacing:.04em; font-weight:700; }
.bl-fn { margin-left:auto; font-family:Consolas,monospace; font-variant-numeric:tabular-nums; white-space:nowrap; }
.bl-fn + .bl-fn { margin-left:0; }
/* Ordre d'abandon quand la largeur manque — du moins utile au plus utile :
   le compte de pesées, puis le produit, puis la date de clôture. Le n°, le
   client, les tonnages et le statut ne partent jamais.
   ⚠ Scopé à `tr.bl-op` : les barres de catégorie n'ont qu'une cellule, une
   règle nth-child posée sur `tbody td` masquerait la mauvaise chose (#256). */
@media (max-width:1180px) {
  .bl-tbl thead th:nth-child(10), .bl-tbl tbody tr.bl-op td:nth-child(10) { display:none; }
}
@media (max-width:1010px) {
  .bl-tbl thead th:nth-child(4), .bl-tbl tbody tr.bl-op td:nth-child(4),
  .bl-tbl thead th:nth-child(9), .bl-tbl tbody tr.bl-op td:nth-child(9) { display:none; }
  .bl-av { width:110px; }
}
@media (max-width:700px) {
  /* Une table de 8 colonnes ne se lit pas sur un téléphone : chaque bon devient
     une carte, son statut à droite — la même bascule que la fiche de stock. */
  .bl-scroll { max-height:none; overflow:visible; }
  .bl-wrap { overflow:visible; }
  .bl-tbl thead { display:none; }
  .bl-tbl, .bl-tbl tbody, .bl-tbl tr, .bl-tbl td { display:block; }
  .bl-tbl tr.bl-op { display:grid; grid-template-columns:auto 1fr auto; gap:0 9px; padding:8px 11px; border-bottom:1px solid var(--border); }
  .bl-tbl tr.bl-op td { border:0; padding:0; min-width:0; }
  .bl-tbl tr.bl-op td.bl-chk { grid-area:1/1/3/2; align-self:center; }
  .bl-tbl tr.bl-op td.bl-num { grid-area:1/2; }
  /* Sur un téléphone la ligne est étroite : le site repasse EN DESSOUS, où la
     place verticale ne manque pas. */
  .bl-tbl tr.bl-op td.bl-cli { grid-area:2/2; font-size:12px; max-width:none; white-space:normal; }
  .bl-cli .bl-site { display:block; margin-left:0; }
  .bl-cli .bl-site:before { content:none; }
  .bl-tbl tr.bl-op td.bl-qty { grid-area:3/2; text-align:left; font-size:12px; }
  .bl-tbl tr.bl-op td.bl-st { grid-area:1/3; align-self:center; }
  .bl-tbl tr.bl-op td.bl-av { grid-area:4/1/4/4; width:auto; margin-top:5px; }
  /* Les deux dates sur une même ligne, sous la jauge, avec leur libellé — hors
     tableau, une date nue ne dit pas de quoi elle est la date. */
  .bl-tbl tr.bl-op td.bl-date { grid-row:5; text-align:left; font-size:11px; margin-top:3px; }
  .bl-tbl tr.bl-op td.bl-d1 { grid-column:1/3; }
  .bl-tbl tr.bl-op td.bl-d2 { grid-column:3; text-align:right; }
  .bl-tbl tr.bl-op td.bl-d1:before { content:"émis "; color:var(--text-3); }
  .bl-tbl tr.bl-op td.bl-d2:before { content:"clos "; color:var(--text-3); }
  .bl-tbl tr.bl-op td.bl-prod, .bl-tbl tr.bl-op td.bl-pes { display:none; }
  /* En carte, il n'y a plus de colonnes : les filets verticaux n'ont plus de
     sens et barreraient la carte au milieu. */
  .bl-tbl tbody tr.bl-op td + td { border-left:0; }
  /* La barre de catégorie passe sur deux niveaux : ses totaux ne tiennent pas
     à côté de son libellé sur 375 px, et ils débordaient hors de l'écran. */
  .bl-sepbar { flex-wrap:wrap; gap:4px 8px; }
  .bl-sepbar .bl-tot { margin-left:0; width:100%; }
  .bl-sepbar .bl-tot .k:first-child { margin-left:0; }
  .bl-frow { flex-wrap:wrap; gap:4px 12px; }
  .bl-fn { margin-left:0; }
}
@media print {
  .bl-scroll { max-height:none; overflow:visible; }
  .bl-tbl th, .bl-sepbar, .bl-frow { background:#fff !important; color:#000 !important; }
  .bl-sepbar { border-top:1px solid #000; border-bottom:1px solid #000; }
  .bl-frow { border-top:2px solid #000; }
}

/* ⛔ CODE MORT depuis le 2026-09-12 : la vue Liste des bons est un TABLEAU
   (`.bl-*`, ci-dessus). Ce bloc `.blist-*` n'est plus produit par
   central/bons-page.js — il est conservé un temps, pas maintenu. Ne pas s'y
   fier : ses largeurs en pixels sont précisément ce que la refonte a corrigé.
   ⚠ À ne pas confondre avec les `.blist-*` de css/app.css, qui servent le POSTE
   (js/bons.js) et sont, eux, bien vivants. */
.blist-wrap { background:var(--panel-2); border:1px solid var(--border); border-radius:10px; overflow:hidden; }
.blist-cat { display:flex; align-items:center; gap:8px; padding:8px 14px; font-size:10.5px; font-weight:800; letter-spacing:.6px; text-transform:uppercase; color:var(--brand); background:var(--brand-bg,rgba(196,82,0,.14)); border-top:1px solid var(--border); border-bottom:1px solid var(--border); border-left:3px solid var(--brand); cursor:pointer; user-select:none; position:sticky; top:0; z-index:1; }
.blist-cat:first-child { border-top:none; }
.blist-cat .cnt { margin-left:auto; font-family:Consolas,monospace; color:var(--text-2); background:var(--panel); border:1px solid var(--border); font-weight:700; border-radius:20px; padding:0 8px; font-size:10px; }
.blist-chev { flex:0 0 auto; color:var(--brand); transition:transform .15s; }
.blist-cat.closed .blist-chev { transform:rotate(-90deg); }
.blist-row { display:flex; align-items:center; gap:12px; padding:9px 14px; border-bottom:1px solid var(--border); border-left:3px solid transparent; cursor:pointer; }
.blist-row:hover { background:var(--panel); }
.blist-dot { width:8px; height:8px; border-radius:50%; flex:0 0 auto; }
/* Largeurs recalées sur le besoin RÉEL, mesuré sur les 382 bons d'Aicha
   (2026-08-09) : le n° demandait 58 px pour 150 réservés et le produit
   90 pour 130. Ces 75 px rendus à la jauge font passer le minimum de la
   ligne dense de 924 à 849 px — la marge en tablette paysage remonte de
   10 px (une barre de défilement suffisait à casser la mise en page) à
   85 px. Rien n'est tronqué de plus qu'avant. */
/* ⚠⚠ RE-MESURÉ le 2026-09-12. Les largeurs ci-dessus datent du 2026-08-09 et
   étaient justes CE JOUR-LÀ : « le n° demandait 58 px pour 150 réservés ». Le
   2026-09-09, le badge de TYPE (📤 SORTIE / 📥 ENTRÉE) a été ajouté DANS cette
   même colonne, sans la remesurer — il pèse 59 px à lui seul sur les 100
   restants. Résultat mesuré à 1 280 px : la colonne demandait 152 px pour 100
   réservés et n'affichait plus que « MG/… », c'est-à-dire plus de numéro de bon
   du tout, pendant que la JAUGE (flex:1) s'octroyait ~400 px.
   Règle qui en sort : ce qu'on ajoute dans une colonne doit être ajouté à sa
   largeur, et une jauge décorative ne prend pas la place d'une donnée. */
.blist-num { font-family:Consolas,monospace; font-weight:700; font-size:13px; color:var(--text); width:160px; flex:0 0 auto; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* Client et produit PARTAGENT le surplus au lieu d'être tronqués à largeur
   fixe pendant que la jauge s'étale : mêmes valeurs pour toutes les lignes,
   donc les colonnes restent alignées d'une ligne à l'autre. */
.blist-client { font-size:12px; color:var(--text-2); flex:2 1 150px; min-width:130px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.blist-prod { font-size:12px; color:var(--text-3); flex:1 1 105px; min-width:95px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.blist-qty { font-family:Consolas,monospace; font-size:12px; font-weight:700; color:var(--text-2); width:160px; text-align:right; flex:0 0 auto; }
/* La jauge NE GRANDIT PLUS (`flex:0 1`) : elle illustre un pourcentage qui est
   déjà écrit à côté, elle n'a pas à manger la place du texte. */
.blist-bar { flex:0 1 180px; min-width:60px; height:7px; background:var(--panel); border-radius:4px; overflow:hidden; }
.blist-bar > i { display:block; height:100%; border-radius:4px; }
/* 52 px ne tenaient que « ✓ Soldé » au pixel près — « ⛔ Dépassement » et
   « ✕ Annulé » passent aussi par cette colonne. */
.blist-pct { font-family:Consolas,monospace; font-weight:800; font-size:13px; width:64px; text-align:right; flex:0 0 auto; }
.blist-pes { font-size:10.5px; color:var(--text-3); width:56px; text-align:right; flex:0 0 auto; }
/* Petits écrans : la ligne dense (num+client+prod+qty+barre+%) débordait
   et coupait l'info à droite. On la reflow en CARTE grid (2-3 lignes) —
   num+% en tête, client+tonnage dessous, produit + barre pleine largeur.
   ⚠ Le seuil était à 760 px : la tablette portrait en fait 768, elle
   ratait donc le reflow de 8 px et perdait la jauge, le pourcentage et
   le nombre de pesées HORS ÉCRAN, sans aucun défilement pour les
   rattraper (mesuré le 2026-08-09 sur les 382 bons d'Aicha : 246 px de
   débordement, 289 jauges sur 290 inatteignables).
   Le seuil ne se devine pas, il se calcule : la ligne dense exige
   849 px (largeurs fixes + jauge 80 mini + gaps + padding), soit un
   viewport d'environ 940. On pose 1010 pour garder de l'air ; la
   tablette PAYSAGE (1024) reste donc en ligne dense, avec 85 px de
   marge mesurés. */
@media (max-width:1010px){
  .blist-pes{ display:none; }
  .blist-row{ display:grid; grid-template-columns:auto auto minmax(0,1fr) auto; grid-template-areas:"chk dot num pct" "chk dot client qty" "chk dot prod prod" "bar bar bar bar"; gap:3px 10px; align-items:baseline; padding:10px 13px; }
  .blist-row .bon-sel-chk{ grid-area:chk; align-self:center; }
  .blist-dot{ grid-area:dot; align-self:center; }
  .blist-num,.blist-client,.blist-prod,.blist-qty{ width:auto; }
  .blist-num{ grid-area:num; }
  .blist-client,.blist-qty{ display:block; }
  .blist-client{ grid-area:client; }
  .blist-prod{ grid-area:prod; }
  .blist-qty{ grid-area:qty; text-align:right; }
  .blist-pct{ grid-area:pct; text-align:right; width:auto; }
  .blist-bar{ grid-area:bar; min-width:0; margin-top:2px; }
}
@keyframes bonFlashCardC { 0%{ background:rgba(16,185,129,.24); box-shadow:0 0 0 2px rgba(16,185,129,.55); } 100%{ background:var(--bg-deep); box-shadow:none; } }
@keyframes bonFlashRowC { 0%{ background:rgba(16,185,129,.24); box-shadow:inset 3px 0 0 #16A34A; } 100%{ background:transparent; box-shadow:none; } }
.bon-card.bon-flash-new { animation:bonFlashCardC 2.4s ease-out; }
.blist-row.bon-flash-new { animation:bonFlashRowC 2.4s ease-out; }

/* ── BONS · disposition TABLETTE (701 → 1010 px) — validée le 2026-08-09 ──
   Le bloc @media ci-dessus est le reflow TÉLÉPHONE : quatre rangées par bon,
   soit 94 px pièce, soit 2 bons par écran de tablette. Correct sur 375 px,
   beaucoup trop lâche sur 711.
   Ici : une ligne d'informations + la jauge pleine largeur en dessous — le
   même motif que la carte de pesée validée le même jour. Environ 40 px par
   bon, donc 4× plus de bons à l'écran.
   ⚠ Le PRODUIT est retiré (décision assumée) : c'est le champ qui tenait le
   moins bien, et il reste lisible en ouvrant le bon. Le n°, le client, le
   tonnage, le pourcentage et la jauge — l'essentiel pour balayer une liste —
   sont tous conservés.
   ⚠ Borné à 701 px : en dessous, le reflow téléphone reprend la main. */
@media (min-width: 701px) and (max-width: 1010px) {
  .blist-row {
    display: grid;
    grid-template-columns: auto auto auto minmax(0, 1fr) auto auto;
    grid-template-areas: "chk dot num client qty pct" "bar bar bar bar bar bar";
    gap: 4px 10px; align-items: center; padding: 7px 12px;
  }
  .blist-row .bon-sel-chk { grid-area: chk; align-self: center; }
  .blist-dot   { grid-area: dot; align-self: center; }
  .blist-num   { grid-area: num;    width: auto; }
  .blist-client{ grid-area: client; width: auto; min-width: 0; }
  .blist-qty   { grid-area: qty;    width: auto; font-size: 11.5px; }
  .blist-pct   { grid-area: pct;    width: auto; }
  .blist-prod  { display: none; }
  .blist-pes   { display: none; }
  .blist-bar   { grid-area: bar; min-width: 0; height: 4px; margin-top: 1px; }
}

/* ── CONVOIS · carte d'expédition ────────────────────────────────────────
   Mise en page sortie des styles en ligne de convois-page.js le 2026-08-09.
   Les valeurs ci-dessous sont EXACTEMENT celles qui y étaient : le rendu sur
   grand écran est inchangé, seule la tablette gagne une variante (plus bas).
   Un style en ligne l'aurait interdit — une media query ne peut pas le reprendre. */
.exp-inner  { padding: 12px 14px; display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.exp-title  { min-width: 190px; }
.exp-stats  { display: flex; gap: 18px; flex-wrap: wrap; }
.exp-spacer { flex: 1; }

/* Disposition TABLETTE (≤ 1010 px) — validée le 2026-08-09.
   Mesuré en 768 : la carte faisait 112 px sur TROIS niveaux de repli, dont un
   n'accueillait que l'espaceur vide — le nom, les six chiffres et les trois
   boutons se répartissaient au hasard de la place restante.
   Ici, deux rangées franches obtenues par `order` (aucun conteneur en plus,
   donc aucun changement de balisage) : titre et actions sur la première, les
   six chiffres sur une grille régulière en dessous. Les colonnes s'alignent
   d'une carte à l'autre, ce qu'un repli libre ne permet jamais. */
@media (max-width: 1010px) {
  .exp-inner  { gap: 10px 12px; padding: 11px 13px; }
  .exp-title  { order: 1; flex: 1 1 auto; min-width: 0; }
  .exp-inner > button { order: 2; }
  .exp-spacer { display: none; }
  .exp-stats  { order: 3; flex: 1 0 100%; display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; }
}
/* Sous 560 px (téléphone), six colonnes deviennent illisibles : on passe à
   trois, soit deux rangées de chiffres. */
@media (max-width: 560px) {
  .exp-stats { grid-template-columns: repeat(3, 1fr); }
}

/* ── BONS · bandeau de KPI compact en tablette (≤ 1010 px) ───────────────
   Mesuré en 768 le 2026-08-09 : 6 cartes de 83 px sur deux rangées = 175 px,
   soit 17 % de la hauteur d'écran, et le haut de la LISTE DES BONS repoussé à
   767 px — il fallait défiler avant de voir le premier bon.
   Ces cartes empilent trois lignes (libellé / valeur / sous-titre). Sur une
   tablette, le libellé et la valeur tiennent côte à côte : on passe à ~40 px
   par carte, soit ~100 px rendus à la liste.
   ⚠ Le sous-titre (« sur 80 au total ») est masqué, pas supprimé : il revient
   dès 1011 px. C'est l'information la moins utile des trois — le total est
   déjà rappelé en tête de page.
   ⚠ Ces cartes sont CLIQUABLES (filtres) : on garde 40 px de haut, sous peine
   de fabriquer une cible impossible à viser au doigt.
   Scopé à #page-bons : les six autres .kpi-grid du dashboard ne bougent pas.

   ⚠ Le seuil est 1100 px, PAS 1010 : c'est la largeur à laquelle la grille
   passe de 6 colonnes à 3 (règle plus haut dans ce fichier), donc de UNE
   rangée à DEUX. Au-dessus, les six cartes tiennent sur une ligne et le
   sous-titre a toute sa place — rien à compacter. En dessous, on empile deux
   rangées de cartes trois fois plus larges que leur contenu (mesuré en 1024 :
   321 px de carte pour 165 px de texte, soit 129 px de vide chacune).
   ⚠ Une grille `auto-fit / minmax` a été essayée ici et MESURÉE PIRE (194 px
   contre 175) : à 1024 elle rend 5 colonnes pour 6 cartes — donc toujours deux
   rangées — avec des libellés qui se replient sur plus de lignes. L'idée
   paraissait meilleure ; le chiffre a tranché. */
@media (max-width: 1100px) {
  #page-bons .kpi-grid { gap: 8px; }
  #page-bons .kpi-grid .kpi {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 9px 12px; min-height: 40px;
  }
  #page-bons .kpi-grid .kpi-lbl { margin: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #page-bons .kpi-grid .kpi-val { margin: 0; flex: 0 0 auto; }
  #page-bons .kpi-grid .kpi-sub { display: none; }
}

/* ── STOCK · même bandeau, même traitement (2026-08-09) ──────────────────
   Mesuré en 768 : 5 cartes de 93 px sur deux rangées = 196 px, soit plus du
   DOUBLE du bandeau des Bons une fois celui-ci compacté (88 px), et le premier
   panneau repoussé à 666 px sur un écran de 1024.
   ⚠ Bloc SÉPARÉ et non un simple `#page-bons, #page-stock` : les deux pages
   n'utilisent pas les mêmes classes internes — Bons pose
   `.kpi-lbl/.kpi-val/.kpi-sub`, Stock pose `.label/.value/.delta` (vérifié dans
   le DOM, pas déduit). Un sélecteur mutualisé aurait compacté la BOÎTE en
   laissant ses trois enfants en disposition d'origine : carte plus basse, texte
   qui déborde. Le jour où les deux gabarits seront unifiés, ces deux blocs
   fusionneront — pas avant.
   Même seuil (1100 px) et même raison qu'aux Bons : c'est là que la grille
   passe de 6 colonnes à 3, donc d'une rangée à deux. */
@media (max-width: 1100px) {
  #page-stock .kpi-grid { gap: 8px; }
  #page-stock .kpi-grid .kpi {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 9px 12px; min-height: 40px;
  }
  #page-stock .kpi-grid .label { margin: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #page-stock .kpi-grid .value { margin: 0; flex: 0 0 auto; }
  #page-stock .kpi-grid .delta { display: none; }
}

/* ═══ Inventaire de parc (onglet Sites) ═════════════════════════════
   Étage ① des mises à jour à distance (2026-08-13) : quelle version
   tourne chez qui. Les couleurs passent par les tokens (--ok/--warn/…)
   pour rester lisibles dans les DEUX thèmes ; les fonds sont des
   teintes alpha de la couleur du statut, jamais --bg2/--surface sur un
   parent --bg2/--surface (gotcha #125 : survol/relief invisible en
   thème sombre). */
.parc-band {
  grid-column: 1/-1;
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px 16px;
  padding: 12px 16px; margin-bottom: 2px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
.parc-band .pb-title {
  font-size: 12px; font-weight: 700; color: var(--text-2);
  text-transform: uppercase; letter-spacing: .5px;
}
.parc-band .pb-counts { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.parc-band .pb-ref { font-size: 11px; color: var(--text-3); }
.parc-band .pb-ref b { color: var(--text-2); font-family: ui-monospace, Menlo, monospace; }
.parc-band .pb-spacer { flex: 1 1 auto; min-width: 0; }

/* Compteur par statut. Le nombre porte la couleur, pas le fond entier :
   une rangée de pastilles pleines se lit comme une alarme même quand
   tout va bien. */
.pb-c { display: inline-flex; align-items: baseline; gap: 5px; font-size: 11px; color: var(--text-3); }
.pb-c b { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.pb-c.ok b       { color: var(--ok); }
.pb-c.retard b   { color: var(--warn); }
.pb-c.inconnue b { color: var(--text-3); }
.pb-c.avance b   { color: var(--info); }

/* Badge de version sur une carte site. */
.pv-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 600; line-height: 1.4;
  font-family: ui-monospace, Menlo, monospace;
  border: 1px solid transparent; white-space: nowrap;
}
.pv-badge .pv-dot { width: 6px; height: 6px; border-radius: 50%; flex: 0 0 auto; }
/* Le TEXTE porte le token (donc suit le thème) ; le FOND est un rgba fixe à
   faible alpha, lisible sur clair comme sur sombre. Volontairement PAS de
   color-mix() : le reste de la feuille n'en utilise nulle part, et il exige
   Chrome 111+ — pas une hypothèse à prendre sur les tablettes de terrain. */
.pv-badge.a_jour   { color: var(--ok);     background: rgba(22,163,74,.12);  border-color: rgba(22,163,74,.32); }
.pv-badge.a_jour   .pv-dot { background: var(--ok); }
.pv-badge.retard   { color: var(--warn);   background: rgba(217,119,6,.14);  border-color: rgba(217,119,6,.34); }
.pv-badge.retard   .pv-dot { background: var(--warn); }
.pv-badge.avance   { color: var(--info);   background: rgba(2,132,199,.12);  border-color: rgba(2,132,199,.30); }
.pv-badge.avance   .pv-dot { background: var(--info); }
.pv-badge.inconnue { color: var(--text-3); background: rgba(148,163,184,.12); border-color: var(--border); }
.pv-badge.inconnue .pv-dot { background: var(--text-3); }
/* Licence expirée / invalide / à réactiver (#338) : le poste est verrouillé ou amputé. */
.pv-badge.bad      { color: var(--bad);    background: rgba(220,38,38,.12);  border-color: rgba(220,38,38,.34); }
.pv-badge.bad      .pv-dot { background: var(--bad); }
.pb-c.bad b        { color: var(--bad); }

/* « 2 versions vues » : les postes d'un même site ne sont pas alignés.
   C'est une INFORMATION, pas une faute → ton neutre, jamais rouge. */
.pv-multi {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 7px; border-radius: 999px; font-size: 10px; font-weight: 600;
  color: var(--text-2); background: var(--panel-2); border: 1px dashed var(--border);
  white-space: nowrap;
}

/* Rangée version dans la carte site : sous l'en-tête, au-dessus des KPI. */
.sitecard .pv-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 0 16px 10px;
}

@media (max-width: 700px) {
  .parc-band { gap: 8px 12px; padding: 10px 12px; }
  .parc-band .pb-spacer { flex-basis: 100%; height: 0; }
}
