/* ============================================================================
   AgentFlow · Console cabinet — COMPOSANTS
   Dépend de theme.css. Zéro librairie, zéro build. Charger dans cet ordre.
   ========================================================================== */

*{box-sizing:border-box}
html,body{margin:0}
body{
  /* Pas de fonts.googleapis.com : une console qui affiche « 100 % local (UE) »
     ne va pas chercher sa typo chez Google à chaque chargement. Pile système
     (Segoe UI Variable sur Windows, SF sur Mac) ; si Inter est auto-hébergé
     ou installé, il est pris en premier. Recette d'auto-hébergement : SKILL.md */
  font-family:'Inter var','Inter',-apple-system,BlinkMacSystemFont,'SF Pro Text',
    'Segoe UI Variable Text','Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;
  color:var(--ink); background:var(--bg);
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
  font-size:14px; line-height:1.5; letter-spacing:-.01em;
  background:
    radial-gradient(1200px 500px at 15% -10%, color-mix(in srgb,var(--royal) 7%,var(--bg)) 0%, transparent 55%),
    radial-gradient(1000px 480px at 100% 0%, color-mix(in srgb,var(--grad-from) 4%,var(--bg)) 0%, transparent 50%),
    var(--bg);
  background-attachment:fixed;
}
/* LARGEUR DES PAGES — 1200 px jusqu'au 15/08/2026, min(1600px,100%) depuis.
   Copie amont du kit servi (`console-os/deployer/kit-console.css`) : sans elle,
   le prochain build reposerait 1200 px par-dessus la flotte. Voir le bloc du
   meme nom dans le kit pour la mesure (hote de 1625 px a 1920, contenu arrete
   a 1200) et pour la raison de 1600 plutot que `none`.
   Le clamp de goutiere remplace le centrage qui faisait respirer le contenu
   sous 1600 px de place. */
.wrap{max-width:min(1600px,100%);margin:0 auto;padding:34px clamp(26px,2.2vw,44px) 72px}
/* `.wrap.wide` RETIRE : a 1200 de base il elargissait, a 1600 il retrecirait.
   Aucun code servi ne le posait (mesure du 15/08). */
.mono{font-variant-numeric:tabular-nums}
.hint{margin:0 0 16px;font-size:12.5px;color:var(--ink-3)}
.sec{font-size:12px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;
  color:var(--ink-3);margin:26px 2px 13px}

/* Accessibilité : un anneau de focus visible partout, jamais supprimé.
   :focus-visible → invisible à la souris, présent au clavier. */
:where(a,button,input,select,textarea,[tabindex]):focus-visible{
  outline:2px solid var(--royal); outline-offset:2px; border-radius:6px}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---------------------------------------------------------------- en-tête -- */
header{display:flex;align-items:center;justify-content:space-between;gap:16px;
  margin-bottom:28px;flex-wrap:wrap}
.brand{display:flex;align-items:center;gap:13px}
.logo{width:38px;height:38px;border-radius:11px;background:var(--grad);color:#fff;
  display:grid;place-items:center;font-weight:700;font-size:15px;letter-spacing:-.02em;
  box-shadow:var(--glow);flex:none}
.brand h1{font-size:19px;margin:0;font-weight:600;letter-spacing:-.022em;color:var(--ink)}
.brand p{margin:1px 0 0;font-size:13px;color:var(--ink-3);letter-spacing:-.01em}
.head-right{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.updated{font-size:12.5px;color:var(--ink-3)}
.updated b{color:var(--ink-2);font-weight:600}

/* ---------------------------------------------------------------- boutons --
   Loi : UN SEUL bouton en dégradé par écran (l'action primaire). Tout le
   reste est fantôme. Le destructif n'est jamais en dégradé. */
.btn{border:0;color:#fff;background:var(--grad);padding:9px 16px;border-radius:11px;
  font-size:13px;font-weight:600;cursor:pointer;font-family:inherit;letter-spacing:-.01em;
  display:inline-flex;align-items:center;gap:8px;text-decoration:none;white-space:nowrap;
  box-shadow:var(--shadow-btn);
  transition:transform var(--t-fast) ease, box-shadow var(--t-fast) ease}
.btn:hover{transform:translateY(-1px);box-shadow:var(--shadow-btn-h)}
.btn:active{transform:translateY(0)}
.btn:disabled{opacity:.55;cursor:default;transform:none;box-shadow:var(--shadow-btn)}

.btn.ghost{background:var(--surface);color:var(--ink-2);border:1px solid var(--border-2);
  box-shadow:none}
.btn.ghost:hover{background:var(--surface-2);transform:none;box-shadow:none}

.btn.danger{background:var(--err-bg);color:var(--err-tx);border:1px solid var(--err-br);
  box-shadow:none}
.btn.danger:hover{background:color-mix(in srgb,var(--err-dot) 12%,var(--surface));
  transform:none;box-shadow:none}

.btn.sm{padding:6px 10px;font-size:12px;border-radius:9px}
.btn.spin svg{animation:spin .8s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---------------------------------------------------------------- onglets --
   Le segmenté se pose aussi bien sur le blanc d'une barre d'OS que sur le gris
   d'une page : la piste est DESSINÉE (liseré), la pilule active porte une ombre
   ET un anneau, et l'inactif recule d'un ton. Le seul remplissage --surface-3
   ne suffit pas : sur du blanc il cesse de se voir (mesuré le 01/08 dans la
   barre de Surveillance, 2 % d'écart avec le fond, la pilule blanche tenue par
   une ombre unique). L'anneau est une BORDURE, pas une ombre : le style « doux »
   de l'OS impose box-shadow:none !important sur tout [role="tab"], une pilule qui
   ne tenait que par son ombre redevenait invisible (mesuré sur la démo le 01/08).
   Bordure transparente sur TOUS les onglets : l'actif ne décale personne. */
.tabs{display:flex;gap:3px;background:var(--surface-3);border:1px solid var(--border);
  border-radius:11px;padding:3px;margin-bottom:22px;width:fit-content;max-width:100%;
  overflow-x:auto}
.tab{border:1px solid transparent;background:transparent;color:var(--ink-3);padding:6px 15px;
  border-radius:8px;
  font-size:13.5px;font-weight:600;cursor:pointer;font-family:inherit;letter-spacing:-.01em;
  white-space:nowrap;transition:color var(--t-ui) ease,background var(--t-ui) ease,
  border-color var(--t-ui) ease,box-shadow var(--t-ui) ease}
.tab:hover{color:var(--ink-2);background:color-mix(in srgb,var(--ink) 4%,transparent)}
.tab[aria-selected="true"]{background:var(--surface);color:var(--ink);
  border-color:color-mix(in srgb,var(--ink) 13%,transparent);
  box-shadow:0 1px 2px rgba(16,24,40,.10)}
.vue{display:none} .vue.on{display:block}

/* ------------------------------------------------------------------- KPI ---
   4 tuiles max. UNE SEULE porte l'accent (.accent) : celle qui répond à la
   question que le cabinet se pose en ouvrant la page. */
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin-bottom:20px}
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  box-shadow:var(--shadow)}
.kpi{padding:20px 20px 18px;position:relative;overflow:hidden}
.kpi .lbl{font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3)}
.kpi .val{font-size:36px;font-weight:600;letter-spacing:-.03em;margin:9px 0 3px;line-height:1;
  font-variant-numeric:tabular-nums}
.kpi .sub{font-size:12.5px;color:var(--ink-3);letter-spacing:-.005em}
.kpi .sub b{color:var(--ok-tx);font-weight:600}
.kpi.accent .val{background:var(--grad-text);-webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent}
.kpi.accent::after{content:"";position:absolute;inset:0 0 auto 0;height:3px;background:var(--grad)}
.kpi.prio .val{color:var(--prio-tx)}
.kpi.alert .val{color:var(--err-tx)}

/* --------------------------------------------------------------- bandeaux --
   Un bandeau n'existe que s'il y a quelque chose à faire. Sinon il est absent
   (pas « tout va bien » en vert : c'est du bruit permanent). */
.banner{display:none;align-items:center;gap:13px;margin-bottom:20px;padding:15px 19px;
  border-radius:var(--radius);box-shadow:var(--shadow);border:1px solid transparent}
.banner.on{display:flex}
.banner .ic{width:34px;height:34px;border-radius:10px;color:#fff;display:grid;place-items:center;
  flex:none;font-size:16px;font-weight:700}
.banner .tt{font-weight:600;font-size:14px}
.banner .st{font-size:12.5px;margin-top:1px;opacity:.9}
.banner .go{margin-left:auto;font-size:13px;font-weight:600;white-space:nowrap}
.banner[data-s="err"]{background:var(--err-bg);border-color:var(--err-br);color:var(--err-tx)}
.banner[data-s="err"] .ic{background:var(--err-dot)}
.banner[data-s="warn"]{background:var(--warn-bg);border-color:var(--warn-br);color:var(--warn-tx)}
.banner[data-s="warn"] .ic{background:var(--warn-dot)}
.banner[data-s="info"]{background:var(--info-bg);border-color:color-mix(in srgb,var(--info-dot) 30%,var(--surface));color:var(--info-tx)}
.banner[data-s="info"] .ic{background:var(--info-dot)}
.banner[role="button"]{cursor:pointer;transition:filter var(--t-ui) ease}
.banner[role="button"]:hover{filter:brightness(.97)}

/* --------------------------------------------------------- tuiles cliquables */
/* `auto-fit`, PAS `auto-fill` (15/08) : a 1600 px, `auto-fill` fabrique les
   colonnes que la largeur permet et laisse vides celles qu'il ne peut pas
   remplir (3 tuiles serrees a gauche d'une grille de 6, moitie d'ecran
   vide sur Pilotage). `auto-fit` reduit les pistes vides a zero. */
.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(232px,1fr));gap:16px}
.tile{padding:17px 18px;cursor:pointer;position:relative;overflow:hidden;text-align:left;
  transition:transform var(--t-fast) ease, box-shadow var(--t-fast) ease}
.tile:hover{transform:translateY(-2px);box-shadow:var(--shadow-lift)}
.tile[aria-pressed="true"]{border-color:var(--royal);box-shadow:var(--ring)}
.tile .top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
.tile .nm{font-weight:600;font-size:14.5px;letter-spacing:-.015em}
.tile .cnt{font-size:34px;font-weight:600;letter-spacing:-.03em;line-height:1;margin:14px 0 2px;
  font-variant-numeric:tabular-nums}
.tile .cnt.n{background:var(--grad-text);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.tile .cnt.z{color:var(--ink-4)}
.tile .cl{font-size:12px;color:var(--ink-3)}

/* --------------------------------------------------------------- panneaux -- */
.row{display:grid;grid-template-columns:1.55fr 1fr;gap:18px;margin-bottom:20px}
/* Un enfant de grille a min-width:auto : il REFUSE de descendre sous son
   min-content et élargit la page entière au lieu de rétrécir. Douze étiquettes
   de dates en nowrap dans un graphe suffisent à faire déborder tout le site sur
   mobile. min-width:0 est la seule ligne qui l'empêche. */
.row > *{min-width:0}
.panel{padding:20px 22px}
.panel h3{margin:0 0 2px;font-size:15px;font-weight:600;letter-spacing:-.018em}

/* --------------------------------------------------------------- toolbar --- */
.toolbar{display:flex;align-items:center;justify-content:space-between;gap:14px;
  margin:24px 0 13px;flex-wrap:wrap}
.pills{display:flex;gap:8px;flex-wrap:wrap}
.pill{border:1px solid var(--border-2);background:var(--surface);color:var(--ink-2);
  padding:7px 14px;border-radius:22px;font-size:12.5px;font-weight:500;cursor:pointer;
  font-family:inherit;display:inline-flex;align-items:center;gap:7px;letter-spacing:-.005em;
  transition:background var(--t-ui) ease,border-color var(--t-ui) ease}
.pill:hover{background:var(--surface-2);border-color:var(--ink-4)}
.pill[aria-pressed="true"]{background:var(--grad);border-color:transparent;color:#fff;
  box-shadow:var(--shadow-btn);font-weight:600}
.pill .c{font-variant-numeric:tabular-nums;opacity:.62}
.pill[aria-pressed="true"] .c{opacity:.85}
.search{position:relative}
.search input{border:1px solid var(--border-2);border-radius:11px;padding:9px 13px 9px 35px;
  font-size:13px;width:262px;max-width:100%;background:var(--surface);color:var(--ink);
  outline:none;font-family:inherit;transition:border-color var(--t-ui) ease,box-shadow var(--t-ui) ease}
.search input::placeholder{color:var(--ink-3)}
.search input:focus{border-color:var(--royal);box-shadow:var(--ring)}
.search svg{position:absolute;left:11px;top:50%;transform:translateY(-50%);color:var(--ink-3)}
.fld{border:1px solid var(--border-2);border-radius:10px;padding:9px 13px;font-size:13px;
  font-family:inherit;background:var(--surface);color:var(--ink);outline:none;
  transition:border-color var(--t-ui) ease,box-shadow var(--t-ui) ease}
.fld:focus{border-color:var(--royal);box-shadow:var(--ring)}

/* --------------------------------------------------------------- tableau --- */
.tablecard{overflow:hidden}
/* Un en-tête collant (thead th ci-dessous) ne colle QUE dans un conteneur qui
   défile vraiment. Sans hauteur max, .tscroll grandit à la taille du tableau,
   ne défile jamais, et c'est la PAGE qui bouge : l'en-tête part en haut et le
   cabinet lit 300 lignes sans savoir quelle colonne il regarde. D'où le
   plafond. Une console qui veut un tableau court : --tscroll-max:none. */
.tscroll{overflow:auto;-webkit-overflow-scrolling:touch;max-height:var(--tscroll-max,64vh)}
table{width:100%;border-collapse:collapse}
thead th{text-align:left;font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
  color:var(--ink-3);padding:12px 18px;border-bottom:1px solid var(--border);background:var(--surface-2);
  white-space:nowrap;position:sticky;top:0;z-index:1}
tbody td{padding:13px 18px;border-bottom:1px solid var(--line);font-size:13px;vertical-align:middle}
tbody tr:last-child td{border-bottom:0}
tbody tr{transition:background .1s ease}
tbody tr:hover{background:var(--surface-2)}
tbody tr[data-open]{cursor:pointer}
tbody tr.prio{background:color-mix(in srgb,var(--prio-dot) 5%,var(--surface))}
tbody tr.prio:hover{background:color-mix(in srgb,var(--prio-dot) 9%,var(--surface))}
td.n,th.n{text-align:right;font-variant-numeric:tabular-nums}
td.z{color:var(--ink-4)}          /* un zéro s'écrit « · », il ne hurle pas */
.cell-when{color:var(--ink-2);white-space:nowrap;font-variant-numeric:tabular-nums}
.cell-2l small{display:block;color:var(--ink-3);font-size:11.5px;font-weight:400}

/* Tri : le th EST un bouton (clavier + lecteur d'écran), pas un th cliquable. */
th.sort{padding:0}
th.sort button{width:100%;display:flex;align-items:center;gap:5px;background:none;border:0;
  color:inherit;font:inherit;letter-spacing:inherit;text-transform:inherit;cursor:pointer;
  padding:12px 18px;white-space:nowrap}
th.n.sort button{justify-content:flex-end}
th.sort button:hover{color:var(--royal)}
th.sort button::after{content:"⇅";opacity:.3;font-size:9px}
th[aria-sort="ascending"] button::after{content:"↑";opacity:1;color:var(--royal)}
th[aria-sort="descending"] button::after{content:"↓";opacity:1;color:var(--royal)}

/* ------------------------------------------------------- puces & étiquettes --
   6 tons, pas un de plus. L'app mappe SES statuts métier dessus :
   <span class="badge" data-s="ok">Classée</span> */
.badge{display:inline-flex;align-items:center;gap:6px;padding:4px 10px 4px 9px;border-radius:20px;
  font-size:12px;font-weight:600;white-space:nowrap;letter-spacing:-.005em;
  background:var(--mut-bg);color:var(--mut-tx)}
.badge .dot{width:7px;height:7px;border-radius:50%;background:currentColor;opacity:.9;flex:none}
.badge[data-s="ok"]{background:var(--ok-bg);color:var(--ok-tx)}
.badge[data-s="ok"] .dot{background:var(--ok-dot);opacity:1}
.badge[data-s="info"]{background:var(--info-bg);color:var(--info-tx)}
.badge[data-s="info"] .dot{background:var(--info-dot);opacity:1}
.badge[data-s="warn"]{background:var(--warn-bg);color:var(--warn-tx)}
.badge[data-s="warn"] .dot{background:var(--warn-dot);opacity:1}
.badge[data-s="prio"]{background:var(--prio-bg);color:var(--prio-tx)}
.badge[data-s="prio"] .dot{background:var(--prio-dot);opacity:1}
.badge[data-s="err"]{background:var(--err-bg);color:var(--err-tx)}
.badge[data-s="err"] .dot{background:var(--err-dot);opacity:1}
.badge[data-s="mut"]{background:var(--mut-bg);color:var(--mut-tx)}
.badge[data-s="mut"] .dot{background:var(--mut-dot);opacity:1}

/* Identifiant (code dossier, n° de pièce) : teinte de marque, jamais un statut. */
.chip{display:inline-block;background:var(--grad-soft);color:var(--tint-tx);
  border:1px solid var(--tint-br);border-radius:8px;padding:3px 9px;font-size:12px;font-weight:600;
  font-variant-numeric:tabular-nums;letter-spacing:-.01em;white-space:nowrap}

/* ------------------------------------------------------- actions de ligne -- */
.kebab{border:0;background:transparent;color:var(--ink-3);font-size:17px;font-weight:700;
  width:28px;height:28px;border-radius:8px;cursor:pointer;line-height:1}
.kebab:hover{background:var(--mut-bg);color:var(--ink)}
.menu{position:fixed;z-index:60;background:var(--surface);border:1px solid var(--border);
  border-radius:12px;box-shadow:var(--shadow-pop);min-width:230px;padding:6px;display:none}
.menu.open{display:block}
.menu .mh{font-size:10.5px;color:var(--ink-3);padding:6px 10px 4px;text-transform:uppercase;
  letter-spacing:.04em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:280px}
.menu button{display:block;width:100%;text-align:left;border:0;background:transparent;color:var(--ink);
  padding:8px 10px;border-radius:8px;font-size:13px;cursor:pointer;font-family:inherit}
.menu button:hover{background:var(--surface-2)}
.menu button.danger{color:var(--err-tx)}
.menu button.danger:hover{background:var(--err-bg)}

/* ----------------------------------------------------------------- modale -- */
.ovl{position:fixed;inset:0;background:rgba(29,29,31,.45);backdrop-filter:blur(3px);
  display:none;align-items:center;justify-content:center;z-index:50;padding:24px}
.ovl.open{display:flex}
.modal{background:var(--surface);border-radius:18px;box-shadow:var(--shadow-modal);
  width:min(860px,100%);max-height:92vh;display:flex;flex-direction:column;overflow:hidden}
.modal.lg{width:min(1040px,100%)}
.modal-h{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:18px 22px;border-bottom:1px solid var(--border)}
.modal-h h3{margin:0;font-size:15.5px;font-weight:600;letter-spacing:-.018em}
.modal-x{border:0;background:var(--mut-bg);color:var(--ink-2);width:30px;height:30px;border-radius:9px;
  cursor:pointer;font-size:15px;line-height:1;display:grid;place-items:center;flex:none}
.modal-x:hover{background:var(--border)}
.modal-b{padding:18px 22px;overflow:auto}
.modal-b.split{display:grid;grid-template-columns:280px 1fr;gap:20px}
/* Pied de modale : message à gauche (margin-right:auto), actions à droite,
   la primaire toujours la plus à droite — c'est là que le pouce/curseur finit. */
.modal-f{display:flex;align-items:center;justify-content:flex-end;gap:10px;flex-wrap:wrap;
  padding:15px 22px;border-top:1px solid var(--border);background:var(--surface-2)}
.msg{font-size:12.5px;margin-right:auto}
.msg.ok{color:var(--ok-tx)} .msg.err{color:var(--err-tx)}
.meta{display:flex;flex-direction:column;gap:11px;font-size:13px}
.meta .k{font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3)}
.meta .v{margin-top:2px;color:var(--ink);word-break:break-word}
.prev{background:var(--surface-2);border:1px solid var(--border);border-radius:12px;min-height:300px;
  display:flex;align-items:center;justify-content:center;overflow:hidden}
.prev img{max-width:100%;max-height:60vh;object-fit:contain;display:block}
.prev iframe{width:100%;height:60vh;border:0}
.prev .noprev{color:var(--ink-3);font-size:13px;text-align:center;padding:28px}

/* ------------------------------------------------------------------ toast --
   Le retour d'une action déclenchée HORS modale (menu ⋮, tuile) vient ici.
   Ne jamais l'écrire dans le pied de page : personne ne le lit. */
.toasts{position:fixed;right:18px;bottom:18px;z-index:80;display:flex;flex-direction:column;gap:8px;
  align-items:flex-end;pointer-events:none}
.toast{pointer-events:auto;background:var(--ink);color:var(--bg);font-size:13px;font-weight:500;
  padding:10px 14px;border-radius:11px;box-shadow:var(--shadow-pop);max-width:380px;
  display:flex;align-items:center;gap:9px;animation:toast-in .22s var(--ease)}
.toast.out{animation:toast-out .18s ease forwards}
.toast[data-s="ok"]{background:var(--ok-tx);color:#fff}
.toast[data-s="err"]{background:var(--err-tx);color:#fff}
@keyframes toast-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes toast-out{to{opacity:0;transform:translateY(6px)}}

/* ----------------------------------------------------------- progression --- */
.prog{display:none;align-items:center;gap:11px;margin-bottom:16px;padding:11px 15px;
  background:var(--surface);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow)}
.prog.on{display:flex}
.prog .track{flex:1;height:7px;background:var(--surface-3);border-radius:5px;overflow:hidden}
.prog .fill{height:100%;background:var(--grad);border-radius:5px;transition:width .4s ease}
.prog .txt{font-size:12.5px;color:var(--ink-2);white-space:nowrap;font-variant-numeric:tabular-nums}

/* --------------------------------------------------------------- graphes ---
   Aucune librairie. Des div et un SVG suffisent, et rien ne casse au build. */
.bars{display:flex;align-items:flex-end;gap:9px;padding-top:8px;height:172px}
.bar-col{flex:1;display:flex;flex-direction:column;align-items:center;gap:8px;min-width:0}
.bar-wrap{width:100%;height:140px;display:flex;flex-direction:column;align-items:center;
  justify-content:flex-end;position:relative}
/* Pas de `transition:height` ici : une barre est recréée par innerHTML à chaque
   rendu, elle NAÎT à sa hauteur finale — la transition ne se joue jamais. C'est
   de l'animation morte, qui fait croire que ça bouge alors que rien ne bouge.
   L'entrée animée est un opt-in `.bars.anim`, réservé aux pages qui NE se
   rafraîchissent PAS toutes seules (rapport statique). Sur une console en
   auto-refresh, elle rejouerait toutes les 20 s : un clignotement, pas une info. */
/* ⚠ .bar est réservé aux barres HTML de AF.bars(). NE JAMAIS la poser sur un
   <rect> SVG : en SVG, `width` est une PROPRIÉTÉ CSS qui écrase l'attribut de
   géométrie. Le rect ferait 66 % de la largeur du graphe pendant que son
   attribut width dirait encore 29 — un graphe faux qu'aucune mesure d'attribut
   ne peut détecter (vécu le 14/07 sur l'histogramme YRIA). Une barre SVG se
   nomme autrement (.hb) et se vérifie avec getBBox(), jamais getAttribute(). */
.bar{width:66%;max-width:34px;background:var(--grad);border-radius:7px 7px 4px 4px;min-height:2px;
  box-shadow:0 4px 12px color-mix(in srgb,var(--grad-to) 20%,transparent);
  transform-origin:bottom;transition:filter var(--t-fast) ease}
.bars.anim .bar{animation:bar-in var(--t-move) var(--ease) both}
@keyframes bar-in{from{transform:scaleY(0)}}
.bar.zero{background:var(--border);box-shadow:none}  /* un jour à zéro reste visible */
.bar-wrap:hover .bar{filter:brightness(1.08)}
.bar-v{font-size:10.5px;font-weight:600;color:var(--ink-2);margin-bottom:3px;
  font-variant-numeric:tabular-nums;min-height:14px}
.bar-x{font-size:11px;color:var(--ink-3);white-space:nowrap;text-align:center}
.bar-x small{display:block;color:var(--ink-4);font-size:9.5px;margin-top:1px}
.tip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);margin-bottom:7px;
  background:var(--ink);color:var(--bg);font-size:11.5px;font-weight:500;padding:5px 10px;
  border-radius:8px;white-space:nowrap;opacity:0;pointer-events:none;z-index:2;
  transition:opacity var(--t-fast) ease}
.bar-wrap:hover .tip,.bar-wrap:focus-within .tip{opacity:1}
/* Une infobulle centrée sur la 1re/dernière colonne dépasse du panneau et
   allonge la page. On l'ancre au bord au lieu de la centrer. */
.bar-col:first-child .tip{left:0;transform:none}
.bar-col:last-child .tip{left:auto;right:0;transform:none}
.bar-g{font-size:10px;font-weight:700;color:var(--ok-tx);background:var(--ok-bg);border-radius:20px;
  padding:1px 7px;margin-bottom:4px;font-variant-numeric:tabular-nums;white-space:nowrap}
.bar-g.z{color:var(--ink-3);background:var(--surface-3);font-weight:600}

/* barre empilée + légende (répartition) */
.stack{height:9px;border-radius:6px;background:var(--surface-3);overflow:hidden;display:flex;margin-bottom:12px}
.stack span{height:100%}
.stack.anim span{animation:seg-in var(--t-move) var(--ease) both}
@keyframes seg-in{from{width:0}}
.legend{display:flex;flex-direction:column;gap:12px}
.legend .li{display:flex;align-items:center;gap:10px;font-size:13px}
.legend .dot{width:9px;height:9px;border-radius:3px;flex:none}
.legend .nm{color:var(--ink-2);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.legend .n{font-weight:600;font-variant-numeric:tabular-nums}

/* barres horizontales (charge par personne) */
.hbars{display:flex;flex-direction:column;gap:13px}
.hbar{display:grid;grid-template-columns:110px 1fr 168px;align-items:center;gap:13px;
  border-radius:10px;padding:5px 7px;margin:-5px -7px;text-align:left;background:none;border:0;
  font:inherit;color:inherit;width:calc(100% + 14px);cursor:pointer;
  transition:background var(--t-fast) ease}
.hbar:hover{background:var(--surface-2)}
.hbar:hover .who{color:var(--royal)}
.hbar .who{font-weight:600;font-size:13.5px;letter-spacing:-.01em}
.hbar .who small{display:block;color:var(--ink-3);font-weight:400;font-size:11px;letter-spacing:0}
.hbar .track{height:26px;background:var(--surface-3);border-radius:8px;overflow:hidden;display:flex}
.hbar .seg{height:100%}
.hbars.anim .seg{animation:seg-in var(--t-move) var(--ease) both}
.hbar .num{display:flex;align-items:baseline;gap:7px;justify-content:flex-end}
.hbar .num b{font-size:19px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.hbar .num small{font-size:11.5px;color:var(--ink-3)}
.hbar .num .tr{color:var(--ok-tx);font-weight:600;font-size:12px}
.lg{display:flex;gap:16px;margin-top:16px;font-size:12px;color:var(--ink-3);flex-wrap:wrap}
.lg i{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:5px;
  vertical-align:-1px;font-style:normal}

/* jauges + sparkline */
.gauges{display:flex;gap:26px;justify-content:center;padding:6px 0 16px;flex-wrap:wrap}
.gauge{text-align:center}
.gauge svg{display:block;margin:0 auto 7px}
.gauges.anim circle.v{animation:gauge-in var(--t-move) var(--ease) both}
@keyframes gauge-in{from{stroke-dashoffset:var(--c)}}
.gauge .gv{font-size:19px;font-weight:600;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.gauge .gl{font-size:11px;color:var(--ink-3);margin-top:2px}
.spark{display:flex;align-items:flex-end;gap:5px;height:56px;padding:6px 0}
.spark i{flex:1;background:var(--grad);border-radius:4px 4px 2px 2px;min-height:3px;position:relative;
  font-style:normal}
.spark i.z{background:var(--border)}
.spark i small{position:absolute;top:-15px;left:50%;transform:translateX(-50%);font-size:10px;
  color:var(--ink-3);font-variant-numeric:tabular-nums}

/* ------------------------------------------------ vide / squelette / pied -- */
.empty{padding:52px 20px;text-align:center;color:var(--ink-3)}
.empty .big{font-size:34px;margin-bottom:8px;color:var(--ink-4)}
.empty .t{font-size:15px;font-weight:600;color:var(--ink-2);margin-bottom:3px}
.skel td{padding:13px 18px}
.skel i{display:block;height:11px;border-radius:6px;background:var(--surface-3);
  animation:pulse 1.1s ease-in-out infinite}
@keyframes pulse{50%{opacity:.45}}
.foot{margin-top:16px;font-size:12px;color:var(--ink-3);text-align:center}

/* ============================================================================
   PAGE DE LOGIN — accueil du cabinet.
   Style Hermès : une page CLAIRE, la marque du cabinet en accent, son logo en
   filigrane, une carte blanche posée dessus. Accueillant sans être chargé.
   Tout dérive des 3 couleurs de theme.css. Le logo se pose en 1 variable.
   ========================================================================== */

/* La scène : occupe l'écran, centre la carte, et porte les ambiances de marque.
   `--brand-logo` (url d'une image) OU rien → repli sur la pastille d'initiales. */
.login{min-height:100vh;min-height:100dvh;display:grid;place-items:center;
  padding:24px;position:relative;overflow:hidden;isolation:isolate}

/* Deux halos de marque + un lavis très doux : la page respire la couleur du
   cabinet sans jamais la saturer (on n'est pas dans une bannière marketing). */
.login::before{content:"";position:absolute;inset:0;z-index:-2;
  background:
    radial-gradient(1100px 620px at 12% -8%,  color-mix(in srgb,var(--grad-to) 20%,var(--bg)) 0%, transparent 55%),
    radial-gradient(1000px 640px at 100% 108%, color-mix(in srgb,var(--grad-from) 16%,var(--bg)) 0%, transparent 55%),
    var(--surface-2)}

/* Le logo du cabinet EN FILIGRANE, dominant mais discret : grand, très pâle,
   légèrement incliné, derrière la carte. C'est ce qui rend la page « à eux ». */
.login-wm{position:absolute;z-index:-1;inset:0;display:grid;place-items:center;
  pointer-events:none;overflow:hidden}
.login-wm .mark{width:min(58vw,560px);height:min(58vw,560px);border-radius:28%;
  display:grid;place-items:center;color:#fff;font-weight:800;
  font-size:min(26vw,240px);letter-spacing:-.04em;background:var(--grad);
  transform:rotate(-8deg);opacity:.06;filter:blur(.5px)}
.login-wm img{width:min(60vw,600px);max-width:none;opacity:.05;transform:rotate(-8deg);
  filter:grayscale(.2)}

/* La carte : blanche, posée, l'objet net au milieu du flou. */
.login-card{position:relative;z-index:1;width:min(416px,100%);
  background:var(--surface);border:1px solid var(--border);border-radius:22px;
  box-shadow:var(--shadow-modal);padding:38px 36px 30px;
  animation:login-rise .5s var(--ease) both}
@keyframes login-rise{from{opacity:0;transform:translateY(12px)}}
/* Liseré de marque en tête de carte — le seul trait de couleur franc. */
.login-card::before{content:"";position:absolute;inset:0 0 auto 0;height:4px;
  border-radius:22px 22px 0 0;background:var(--grad)}

.login-head{text-align:center;margin-bottom:24px}
/* Le logo net du cabinet : image (.login-logo img) ou pastille d'initiales. */
.login-logo{width:60px;height:60px;border-radius:16px;margin:0 auto 15px;
  display:grid;place-items:center;color:#fff;font-weight:700;font-size:23px;
  letter-spacing:-.03em;background:var(--grad);box-shadow:var(--glow);overflow:hidden}
.login-logo img{width:100%;height:100%;object-fit:contain;padding:8px;background:var(--surface)}
.login-head h1{margin:0;font-size:21px;font-weight:600;letter-spacing:-.022em;color:var(--ink)}
.login-head p{margin:5px 0 0;font-size:13.5px;color:var(--ink-3);letter-spacing:-.01em}

.login-form{display:flex;flex-direction:column;gap:15px}
.field{display:flex;flex-direction:column;gap:6px}
.field label{font-size:11.5px;font-weight:600;letter-spacing:.03em;text-transform:uppercase;color:var(--ink-3)}
.field .fld{width:100%;padding:11px 13px;font-size:14px;border-radius:11px}
/* Champ mot de passe : l'œil de bascule vit DANS le champ, à droite. */
.field.pw{position:relative}
.field.pw .fld{padding-right:44px}
.field.pw .eye{position:absolute;right:6px;bottom:5px;width:32px;height:32px;border:0;
  background:transparent;color:var(--ink-3);border-radius:8px;cursor:pointer;
  display:grid;place-items:center}
.field.pw .eye:hover{background:var(--surface-3);color:var(--ink-2)}

/* Message d'erreur : présent SEULEMENT en cas d'échec (pas de bloc vide réservé). */
.login-err{display:none;align-items:center;gap:9px;font-size:12.8px;font-weight:500;
  color:var(--err-tx);background:var(--err-bg);border:1px solid var(--err-br);
  border-radius:11px;padding:10px 13px}
.login-err.on{display:flex}
.login-err svg{flex:none}

.login-form .btn{width:100%;justify-content:center;padding:12px;font-size:14px;margin-top:3px}
.login-aux{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:2px}
.login-aux a{font-size:12.5px;color:var(--royal);text-decoration:none;font-weight:500}
.login-aux a:hover{text-decoration:underline}
.login-check{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--ink-2);cursor:pointer;user-select:none}
.login-check input{width:15px;height:15px;accent-color:var(--royal);cursor:pointer}

/* Pied : la réassurance (souveraineté des données), pas une pub. */
.login-foot{margin-top:22px;padding-top:16px;border-top:1px solid var(--line);
  text-align:center;font-size:11.5px;color:var(--ink-3);line-height:1.55}
.login-foot .lock{display:inline-flex;align-items:center;gap:5px}

/* Étape 2FA (code e-mail) : même carte, on masque le formulaire, on montre le code.
   La console 2MLEC en a besoin ; les autres laissent [data-step] sur "login". */
.login[data-step="code"] .step-login{display:none}
.login:not([data-step="code"]) .step-code{display:none}
.code-inputs{display:flex;gap:9px;justify-content:center;margin:6px 0 2px}
.code-inputs input{width:46px;height:54px;text-align:center;font-size:22px;font-weight:600;
  font-variant-numeric:tabular-nums;border:1px solid var(--border-2);border-radius:12px;
  background:var(--surface);color:var(--ink);outline:none;font-family:inherit;
  transition:border-color var(--t-ui) ease,box-shadow var(--t-ui) ease}
.code-inputs input:focus{border-color:var(--royal);box-shadow:var(--ring)}
.login-back{display:block;margin:14px auto 0;background:none;border:0;font:inherit;
  font-size:12.5px;color:var(--ink-3);cursor:pointer}
.login-back:hover{color:var(--ink-2)}

/* --------------------------------------------------------------- réactif --- */
@media(max-width:880px){
  .kpis{grid-template-columns:repeat(2,1fr)}
  .row{grid-template-columns:1fr}
  .modal-b.split{grid-template-columns:1fr}
  .hbar{grid-template-columns:1fr;gap:6px}
  .hbar .num{justify-content:flex-start}
  .search input{width:100%}
  .search{flex:1;min-width:180px}
  .hide-sm{display:none}
  .wrap{padding:22px 16px 56px}
  /* Le graphe défile DANS son panneau : écrasé sur 12 colonnes de 18 px, il ne
     dit plus rien. Colonnes à largeur plancher + défilement du seul ruban.
     L'infobulle disparaît : elle serait rognée par le défilement, et le tactile
     n'a pas de survol — la valeur est déjà écrite au-dessus de la barre. */
  .bars{overflow-x:auto;overflow-y:hidden;height:190px;padding-bottom:6px}
  .bar-col{flex:0 0 30px}
  .tip{display:none}
  .login-card{padding:30px 22px 24px;border-radius:18px}
}

/* ------------------------------------------------------- accessibilité ------
   Un cabinet peut avoir un collaborateur sensible au mouvement. On coupe tout,
   on ne « réduit » pas : une barre qui grandit en 450 ms n'a aucune valeur
   informative, seule la hauteur finale compte. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
  .btn:hover,.tile:hover{transform:none}
}

/* ------------------------------------------------------------- impression --
   Les cabinets impriment. Sans ça, la page sort avec les boutons et le fond. */
@media print{
  body{background:#fff}
  .wrap{max-width:none;padding:0}
  header .head-right,.tabs,.toolbar,.kebab,.btn,.menu,.ovl,.toasts,.prog,.banner .go{display:none!important}
  .card{box-shadow:none;border:1px solid #ddd;break-inside:avoid}
  thead th{position:static}
  tbody tr{break-inside:avoid}
  .kpi.accent .val{-webkit-text-fill-color:currentColor;color:#000}
}

@media (prefers-reduced-motion:reduce){[class*="spin"],[class*="spin"] svg{animation-duration:.8s!important;animation-iteration-count:infinite!important}} /* #46 spinners immunises reduced-motion */

/* ─── UN TABLEAU QUI DÉFILE LE DIT ─────────────────────────────────────────
   Mesuré le 18/08 sur l'iPad de CERFIN (1024 px) : la Collecte tranchait la
   colonne « DOCUMEN… » en plein mot, et la colonne STATUT comme les boutons
   d'action « ⋮ » étaient hors de vue, à 164 px à droite. Le tableau défilait
   bien dans sa boîte — la page, elle, ne débordait pas — mais RIEN ne le
   disait : ni ombre, ni barre visible sur tactile, ni colonne coupée qui
   suggère une suite. Un contenu joignable dont l'accès est invisible est un
   contenu perdu.

   Ombres de défilement en CSS pur, sans JS ni écouteur : les deux dégradés
   blancs sont en `background-attachment: local` (ils SUIVENT le contenu) et
   masquent l'ombre quand on est au bout ; les deux radiaux sont en `scroll`
   (ils restent collés au bord). L'ombre n'apparaît donc que du côté où il
   RESTE quelque chose à voir, et disparaît d'elle-même en fin de course.

   `--tscroll-fond` permet à une carte non blanche de donner sa couleur : un
   dégradé qui part d'un blanc sur un fond gris ferait une bande sale. */
.tscroll{
  --tscroll-fond:#fff;
  background:
    linear-gradient(to right, var(--tscroll-fond) 30%, rgba(255,255,255,0)) left center,
    linear-gradient(to left,  var(--tscroll-fond) 30%, rgba(255,255,255,0)) right center,
    radial-gradient(farthest-side at 0 50%,   rgba(15,23,42,.26), rgba(15,23,42,0)) left center,
    radial-gradient(farthest-side at 100% 50%,rgba(15,23,42,.26), rgba(15,23,42,0)) right center;
  background-repeat:no-repeat;
  background-size:44px 100%,44px 100%,19px 100%,19px 100%;
  background-attachment:local,local,scroll,scroll;
}
