/* ============================================================================
   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;
}
.wrap{max-width:1200px;margin:0 auto;padding:34px 26px 72px}
/* Tableau de plus de 6 colonnes qui tronque son contenu : .wrap.wide.
   Au-delà, retirer une colonne plutôt qu'élargir encore. */
.wrap.wide{max-width:1440px}
.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 -- */
.tabs{display:flex;gap:5px;background:var(--surface-3);border-radius:12px;padding:4px;
  margin-bottom:22px;width:fit-content;max-width:100%;overflow-x:auto}
.tab{border:0;background:transparent;color:var(--ink-2);padding:8px 18px;border-radius:9px;
  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}
.tab:hover{color:var(--ink)}
.tab[aria-selected="true"]{background:var(--surface);color:var(--ink);box-shadow:0 1px 3px rgba(16,24,40,.12)}
.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 */
.tiles{display:grid;grid-template-columns:repeat(auto-fill,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 */
