:root{
  --bg:#F6F7F9; --panel:#FFFFFF; --card:#FFFFFF; --line:#E4E6EB; --line2:#D2D5DC;
  --ink:#20232B; --mut:#7A7F8C; --sub:#4C505C;
  --accent:#544AE3; --accent-hi:#4238C9; --accent2:#7B72F0; --cyan:#0FA3B1;
  --ok:#1F9D61; --err:#D6455B; --warn:#B07C14;
  --radius:10px; font-family:"Space Grotesk",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --rail-bg:rgba(255,255,255,.72); --rail-ring:rgba(20,22,32,.06);
}
*{box-sizing:border-box} body{margin:0;background:var(--bg);color:var(--ink)}
/* L'attribut `hidden` doit toujours l'emporter. Sans cette règle, la moindre
   déclaration `display:` de la feuille (`.pickcard{display:flex}`,
   `.wiz-rail .wst{display:flex}`…) écrase le `display:none` du navigateur :
   l'élément reste visible alors que `el.hidden` vaut `true`. Un piège
   silencieux — le JS croit avoir masqué, l'écran montre le contraire. */
[hidden]{display:none!important}
a{color:var(--ink);text-decoration:none}
.mono{font-family:"IBM Plex Mono",ui-monospace,monospace;font-size:12px}

/* ---------- Barre supérieure type Odoo ---------- */
.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:4px;
  background:var(--panel);border-bottom:1px solid var(--line);padding:0 18px;height:50px}
.topbar .logo{font-size:19px;margin-right:14px}
.topbar a.menu{padding:6px 11px;border-radius:7px;color:var(--sub);font-size:13.5px;white-space:nowrap}
.topbar a.menu:hover{background:var(--bg);color:var(--ink)}
.topbar a.menu.active{background:#EEEDFC;color:var(--accent);font-weight:600}
.topbar .spacer{margin-left:auto}
.topbar .userzone{display:flex;align-items:center;gap:10px}
.topbar .userzone form{margin:0}
.topbar .userzone button{padding:6px 12px;font-size:13px}
.badge{font-size:11px;color:var(--accent);background:#EEEDFC;border:1px solid #D8D5F8;border-radius:999px;padding:3px 10px;white-space:nowrap}

/* ---------- Sous-menu d'application (onglets contextuels de la page) ----------
   `top:0` : la barre horizontale au-dessus (`.topbar`, 50px) a été remplacée
   par le rail vertical, qui ne réserve plus de hauteur en haut de page —
   l'ancien décalage de 50px laissait un vide fantôme au-dessus du sous-menu. */
/* Pas de fond : seuls les liens, sur la couleur de page — la lecture tient
   à la couleur/graisse du texte et au trait sous l'onglet actif, pas à une
   pastille pleine (qui, en plus, était en hex fixe et cassait en sombre). */
.subnav{position:sticky;top:0;z-index:19;display:flex;align-items:center;gap:4px;
  background:transparent;padding:0 18px;height:44px;overflow-x:auto}
.subnav-home{display:flex;align-items:center;padding:6px 10px;
  color:var(--mut);font-size:13px;white-space:nowrap;transition:color .12s ease}
.subnav-home:hover{color:var(--ink)}
.subnav-sep{width:1px;height:20px;background:var(--line);margin:0 8px;flex-shrink:0}
.subnav-tab{padding:6px 12px;color:var(--sub);font-size:13.5px;white-space:nowrap;
  position:relative;transition:color .12s ease}
.subnav-tab:hover{color:var(--ink)}
.subnav-tab.active{color:var(--accent);font-weight:600}
.subnav-tab.active::after{content:'';position:absolute;left:12px;right:12px;bottom:-1px;
  height:2px;border-radius:2px;background:var(--accent)}

.logo{display:flex;align-items:center;gap:1px;font-weight:700;letter-spacing:-0.02em;color:var(--ink)}
.logo-dot{display:inline-flex;align-items:center;margin:0 1px}
.logo-dot i:first-child{border-radius:50%;background:var(--accent2);display:inline-block}
.logo-dot i:last-child{border-radius:50%;border:3px solid var(--cyan);box-sizing:border-box;display:inline-block;background:transparent}

/* Épuré : le contenu utilise la largeur disponible plutôt que de rester
   dans une colonne étroite centrée — surtout sensible sur les listes
   (profils, historique) qui perdaient beaucoup de place de chaque côté. */
main{padding:28px 40px 60px;max-width:none}
main.auth{max-width:420px;margin:8vh auto;padding:28px 20px}
h1{font-size:22px;margin:0 0 20px} h2{font-size:16px;color:var(--sub);font-weight:600}
.flash{padding:10px 14px;border-radius:8px;margin-bottom:14px;font-size:14px}
.flash.error,.flash.err{background:#FCEDEF;color:#A82B3F;border:1px solid #F3C6CD}
.flash.ok{background:#E8F6EF;color:#186A44;border:1px solid #BEE5D2}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:18px 20px;margin-bottom:16px;box-shadow:0 1px 2px rgba(24,26,32,.04)}
label{display:block;font-size:13px;color:var(--mut);margin:12px 0 5px}
input,select,textarea,button{font:inherit}
input,select,textarea{width:100%;padding:9px 11px;background:#fff;border:1px solid var(--line2);border-radius:8px;color:var(--ink)}
input:focus,select:focus,textarea:focus{outline:2px solid #C9C4F6;border-color:var(--accent2)}
/* Cases à cocher et radios : dessinées à la main (le style générique input
   ci-dessus en faisait des rectangles avec un glyphe natif décentré). */
/* !important : plusieurs gabarits posent style="width:auto" en inline sur
   les cases (héritage de l'époque où le style générique input s'appliquait). */
input[type=checkbox],input[type=radio]{appearance:none;width:16px !important;height:16px;
  padding:0;margin:0;flex:none;vertical-align:middle;border:1.5px solid var(--line2);
  border-radius:4px;background:#fff;cursor:pointer;position:relative}
input[type=radio]{border-radius:50%}
input[type=checkbox]:hover,input[type=radio]:hover{border-color:var(--accent2)}
input[type=checkbox]:checked{background:var(--accent);border-color:var(--accent)}
input[type=checkbox]:checked::after{content:"";position:absolute;left:4.5px;top:1.5px;
  width:4px;height:8px;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(43deg)}
input[type=radio]:checked{border:5px solid var(--accent)}
button,.btn{background:var(--accent);border:none;color:#fff;padding:9px 16px;border-radius:8px;cursor:pointer;font-size:14px;display:inline-block}
button:hover,.btn:hover{background:var(--accent-hi)}
button.ghost,.btn.ghost{background:#fff;border:1px solid var(--line2);color:var(--sub)}
button.ghost:hover,.btn.ghost:hover{background:var(--bg);color:var(--ink);border-color:var(--line2)}
button.danger{background:#fff;border:1px solid #F0C3CB;color:var(--err)}
button.danger:hover{background:#FCEDEF;border-color:var(--err)}
table{width:100%;border-collapse:collapse;font-size:13px}
th,td{text-align:left;padding:9px 10px;border-bottom:1px solid var(--line)}
th{color:var(--mut);font-weight:600}
.pill{font-size:11px;padding:2px 9px;border-radius:999px;border:1px solid var(--line2);color:var(--sub)}
.pill.success,.pill.créé{color:var(--ok);border-color:#BEE5D2;background:#E8F6EF}
.pill.error,.pill.échec{color:var(--err);border-color:#F3C6CD;background:#FCEDEF}
.pill.running,.pill.pending{color:var(--warn);border-color:#EBD9AC;background:#FBF3DF}
.pill.cancelled{color:var(--mut)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.muted{color:var(--mut);font-size:13px}
.right{text-align:right}
.checklist{max-height:280px;overflow:auto;border:1px solid var(--line);border-radius:8px;padding:6px;background:#fff}
.checklist label{display:flex;gap:8px;align-items:center;margin:0;color:var(--ink);padding:4px 6px}
.checklist input{width:auto}
.plans{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.log{max-height:420px;overflow:auto;font-size:12px}
.progress{height:10px;background:var(--bg);border:1px solid var(--line);border-radius:999px;overflow:hidden}
.progress>span{display:block;height:100%;background:var(--accent);width:0;transition:width .35s ease}

/* ---------- Jauge de quota mensuel (volume de propagation) ----------
   Discrète à dessein : une ligne d'information, pas une carte — elle ne
   doit pas concurrencer visuellement le contenu de la page. */
.quota-gauge{padding:0;margin-bottom:18px;width:100%;max-width:360px;text-align:left}
.quota-gauge-head{display:flex;align-items:center;justify-content:space-between;
  font-size:11.5px;color:var(--mut);margin-bottom:5px}
.quota-gauge-bar{height:3px;background:var(--line-soft,var(--line));border-radius:999px;overflow:hidden}
.quota-gauge-fill{display:block;height:100%;background:var(--accent2,var(--accent));transition:width .35s ease}
.quota-gauge-fill--warn{background:var(--warn)}
.steprail{display:flex;flex-wrap:wrap;gap:6px;margin-top:12px}
.steprail .st{font-size:11px;padding:3px 9px;border-radius:999px;border:1px solid var(--line2);color:var(--mut)}
.steprail .st.done{color:var(--ok);border-color:#BEE5D2}
.steprail .st.active{color:var(--accent);border-color:var(--accent)}
.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:10px;margin-top:12px}
.pickcard{display:flex;flex-direction:column;gap:3px;background:#fff;border:1px solid var(--line2);border-radius:8px;padding:10px 12px;cursor:pointer}
.pickcard:hover{border-color:var(--accent2)}
.pickcard:has(input:checked){border-color:var(--accent);background:#F7F6FE}
.pickcard input{width:auto;margin-bottom:2px}
.pickcard-title{color:var(--ink);font-size:14px}
.accordion{border:1px solid var(--line);border-radius:8px;margin-top:10px;background:#fff}
.accordion summary{list-style:none;display:flex;justify-content:space-between;align-items:center;padding:12px 14px;cursor:pointer;color:var(--ink);font-weight:600;font-size:14px}
.accordion summary::-webkit-details-marker{display:none}
.accordion summary::before{content:"▸";margin-right:8px;color:var(--mut);display:inline-block;transition:transform .15s}
.accordion[open] summary::before{transform:rotate(90deg)}
.accordion .acc-actions a{font-size:12px;font-weight:400;color:var(--accent);margin-left:12px}
.accordion .cards{padding:0 14px 14px}

/* ---------- Accueil : grille d'applications (type Odoo) ----------
   Centré (verticalement dans le cadre disponible, horizontalement dans une
   largeur raisonnable) plutôt que collé en haut à gauche avec un grand vide
   autour — `min-height` + flex centre sans empêcher le défilement si le
   nombre de tuiles (variable : admin vs client) dépasse l'écran. */
.home-hero{min-height:calc(100svh - 80px);display:flex;flex-direction:column;
  justify-content:center;padding:20px 0;text-align:left}
.home-body{width:100%;max-width:1180px;margin:0 auto}
.apps-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));
  gap:28px 20px;justify-items:stretch;justify-content:center;width:100%}
.app-tile{display:flex;flex-direction:column;align-items:center;gap:10px;width:100%;
  text-align:center;font-size:13.5px;color:var(--sub);border-radius:14px;padding:14px 6px;
  transition:transform .15s ease, box-shadow .15s ease}
.app-tile:hover{background:var(--card);box-shadow:0 6px 20px rgba(24,26,32,.10);transform:translateY(-2px)}
:root[data-theme="dark"] .app-tile:hover{background:var(--surface-hi);box-shadow:0 6px 24px rgba(0,0,0,.4)}
.app-tile .tile-icon{width:68px;height:68px;border-radius:18px;display:flex;align-items:center;
  justify-content:center;box-shadow:0 1px 3px rgba(24,26,32,.10)}
.app-tile .tile-icon svg{width:32px;height:32px}
.app-tile.locked-app{opacity:.5;filter:grayscale(.55)}
.app-tile.locked-app:hover{opacity:.85;filter:grayscale(.2);transform:none}
.app-tile .tile-lock{font-size:11px;color:var(--warn)}
/* palettes de tuiles */
.tint-violet{background:#EEEDFC}.tint-teal{background:#DFF5F0}.tint-orange{background:#FDEEDC}
.tint-pink{background:#FBE7F0}.tint-blue{background:#E3EEFB}.tint-green{background:#E5F5E7}
.tint-yellow{background:#FBF3D9}.tint-red{background:#FCE9E7}.tint-slate{background:#EAECF2}

/* ---------- Réassurance sécurité (saisie de clés API) ---------- */
.security-box{background:#F3F1FD;border:1px solid #DAD5F7;border-radius:var(--radius);
  padding:18px 20px;margin-top:18px;display:flex;flex-direction:column;gap:14px}
.security-box-head{display:flex;gap:14px;align-items:flex-start}
.security-box-head h3{margin:0 0 3px;font-size:15px;color:var(--ink)}
.security-box-head p{margin:0;font-size:13px;color:var(--mut)}
.security-box-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.security-box-list li{font-size:13.5px;line-height:1.55;color:var(--sub);padding-left:24px;position:relative}
.security-box-list li::before{content:'✓';position:absolute;left:0;top:0;color:var(--accent);font-weight:700}
.security-box-list li b{color:var(--ink)}

/* Cadenas dessiné en CSS pur (aucune image/icône externe) : anse + corps. */
.css-lock{width:34px;height:34px;position:relative;flex:none;margin-top:2px}
.css-lock::before{content:'';position:absolute;top:0;left:7px;width:20px;height:15px;
  border:3px solid var(--accent);border-bottom:none;border-radius:11px 11px 0 0;box-sizing:border-box}
.css-lock::after{content:'';position:absolute;bottom:0;left:2px;width:30px;height:19px;
  background:var(--accent);border-radius:5px}

/* ---------- Wizard par étapes (one-page) ---------- */
.wiz-rail{display:flex;gap:4px;flex-wrap:wrap;margin-bottom:18px}
.wiz-rail .wst{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--mut);
  padding:7px 12px;border-radius:999px;border:1px solid var(--line);background:#fff}
.wiz-rail .wst b{display:inline-flex;width:20px;height:20px;border-radius:50%;align-items:center;
  justify-content:center;font-size:11px;background:var(--bg);color:var(--mut);font-weight:600}
.wiz-rail .wst.active{color:var(--accent);border-color:var(--accent)}
.wiz-rail .wst.active b{background:var(--accent);color:#fff}
.wiz-rail .wst.done{color:var(--ok);border-color:#BEE5D2}
.wiz-rail .wst.done b{background:var(--ok);color:#fff}
.wiz-panel{display:none}
.wiz-panel.current{display:block}
.wiz-nav{display:flex;justify-content:space-between;align-items:center;margin-top:18px}

/* Fonctions non incluses dans le palier : grisées + cadenas + upsell. */
.locked{position:relative;opacity:.45;filter:grayscale(.6);pointer-events:none;user-select:none}
.lock-badge{
  display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;
  color:var(--warn);background:#FBF3DF;border:1px solid #EBD9AC;
  border-radius:999px;padding:3px 9px 3px 7px;pointer-events:auto;opacity:1;
  filter:none;text-decoration:none;white-space:nowrap;
}
.lock-badge:hover{background:#F6E9C8;color:var(--warn)}
.locked-row{display:flex;align-items:center;gap:10px;padding:9px 12px;border:1px solid var(--line);
  border-radius:8px;background:#fff;opacity:.55;filter:grayscale(.5)}
.locked-row .lock-badge{opacity:1;filter:none}
.nav-lock{display:flex;align-items:center;gap:6px;padding:6px 11px;
  border-radius:7px;color:var(--mut);font-size:13.5px;opacity:.65;white-space:nowrap}
.nav-lock:hover{opacity:1;background:var(--bg)}

/* ===================================================================== *
 * Allègement visuel — tokens de densité + composant « arbre de sélection »
 * Ces règles arrivent après les précédentes : elles les affinent sans
 * réécrire l'existant (une seule source de vérité, pas de fork de fichier).
 * ===================================================================== */
:root{
  --line-soft:#EDEFF2;      /* filet interne, plus doux que --line */
  --surface:#FAFBFC;        /* fond inerte : en-têtes, barres d'outils */
  --surface-hi:#F2F3F6;     /* survol neutre */
  --accent-soft:#F4F3FE; --accent-tint:#EEEDFC;
  --accent-line:#D8D5F8; --accent-ring:#C9C4F6;
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px; --s6:24px;
  --r-xs:4px; --r-sm:6px; --r-md:8px; --r-lg:12px; --r-pill:999px;
  --sh-1:0 1px 2px rgba(24,26,32,.05);
  --sh-2:0 4px 14px -4px rgba(24,26,32,.12), 0 1px 3px rgba(24,26,32,.05);
  --t-xs:11px; --t-sm:12px; --t-md:13px; --t-base:14px; --t-lg:16px;
  --fw-med:500; --fw-semi:600; --row-h:30px; --dur:.14s;
}

/* Bordure OU ombre, jamais les deux : le double cadre est ce qui « charge »
   le plus une page dense. */
.card{border-color:var(--line-soft);box-shadow:none;padding:var(--s4) var(--s5);
  margin-bottom:var(--s3);border-radius:var(--r-lg)}
.card .card{border:0;border-top:1px solid var(--line-soft);border-radius:0;
  padding:var(--s3) 0 0;margin:var(--s3) 0 0;background:transparent}
h1{font-size:20px;letter-spacing:-.02em;font-weight:var(--fw-semi);margin:0 0 var(--s5)}
h2{font-size:var(--t-base);color:var(--ink);font-weight:var(--fw-semi);margin:0 0 var(--s2)}
.card > h2:first-child{margin-top:0}

/* Un filet par ligne plutôt qu'un filet par cellule. */
table{font-size:var(--t-md)}
th,td{padding:7px 10px;border-bottom:0}
tbody tr{border-bottom:1px solid var(--line-soft)}
tbody tr:last-child{border-bottom:0}
th{font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.04em;
  border-bottom:1px solid var(--line)}

.pickcard{border-color:var(--line-soft);border-radius:var(--r-md);padding:var(--s2) var(--s3);
  transition:border-color var(--dur),background var(--dur)}
.pickcard:hover{border-color:var(--line2);background:var(--surface)}
.pickcard:has(input:checked){border-color:var(--accent2);background:var(--accent-soft)}
.pickcard-title{font-size:var(--t-md);font-weight:var(--fw-med)}
.wiz-rail .wst{font-size:var(--t-sm);padding:5px 10px;border-radius:var(--r-sm);
  border-color:transparent;background:var(--surface)}
.wiz-rail .wst.active{background:var(--accent-tint);border-color:var(--accent-line)}
.wiz-rail .wst b{width:17px;height:17px;font-size:10px}

/* --------------------------------------------------------------------- *
 * Arbre de sélection : application > modèle > éléments.
 * Structure <details>/<summary> : repli natif, accessible au clavier,
 * fonctionnel même si le JS ne charge pas (tout reste coché et soumis).
 * --------------------------------------------------------------------- */
.tree{border:1px solid var(--line-soft);border-radius:var(--r-md);background:#fff;
  font-size:var(--t-md);margin-top:var(--s3);overflow:hidden}
.tree-tools{display:flex;align-items:center;gap:var(--s2);padding:var(--s2);
  background:var(--surface);border-bottom:1px solid var(--line-soft);flex-wrap:wrap}
.tree-search{flex:1;min-width:180px;height:28px;padding:0 var(--s2);font-size:var(--t-md);
  border-radius:var(--r-sm);border-color:var(--line-soft)}
.tree-sum{color:var(--mut);font-size:var(--t-sm);white-space:nowrap}
.tbtn{background:#fff;border:1px solid var(--line2);color:var(--sub);
  font-size:var(--t-sm);padding:3px var(--s2);border-radius:var(--r-sm);cursor:pointer}
.tbtn:hover{background:var(--surface-hi);color:var(--ink)}

.tnode > summary{display:flex;align-items:center;gap:var(--s2);list-style:none;
  height:var(--row-h);padding:0 var(--s2);cursor:pointer;color:var(--sub);user-select:none}
.tnode > summary::-webkit-details-marker{display:none}
.tnode > summary::before{content:"";width:5px;height:5px;flex:none;margin:0 2px;
  border-right:1.5px solid var(--mut);border-bottom:1.5px solid var(--mut);
  transform:rotate(-45deg);transition:transform var(--dur)}
.tnode[open] > summary::before{transform:rotate(45deg)}
.tnode > summary:hover{background:var(--surface-hi);color:var(--ink)}
.tnode-app > summary{font-weight:var(--fw-semi);color:var(--ink);
  border-top:1px solid var(--line-soft);height:34px}
.tree > .tnode-app:first-of-type > summary{border-top:0}
.tnode-app[open] > summary{background:var(--accent-tint);color:var(--accent)}
.tnode-model > summary{font-weight:var(--fw-med)}
.tnode-app > .tbody{padding-left:var(--s3)}
.tnode-model > .tbody{margin-left:var(--s4);border-left:1px solid var(--line-soft);
  padding:2px 0 var(--s2) var(--s2)}
.tname{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:46%}
.tmeta{color:var(--mut);font-size:var(--t-xs)}
.tflag{font-size:10px;color:var(--accent);background:var(--accent-tint);
  border-radius:var(--r-pill);padding:1px 7px}
.tcount{margin-left:auto;flex:none;font-size:var(--t-xs);font-variant-numeric:tabular-nums;
  color:var(--accent-hi);background:var(--accent-tint);border-radius:var(--r-pill);
  padding:1px 7px}
.tcount.is-off{color:var(--mut);background:var(--surface-hi)}

.tleaf{display:flex;align-items:center;gap:var(--s2);margin:0;height:26px;
  padding:0 var(--s2);border-radius:var(--r-xs);cursor:pointer;color:var(--ink)}
.tleaf:hover{background:var(--surface-hi)}
.tleaf[hidden],.tnode[hidden]{display:none}
.tleaf-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:52%}
.tleaf-sub{color:var(--mut);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tleaf:has(input:not(:checked)){color:var(--mut)}
.tleaf:has(input:not(:checked)) .tleaf-title{text-decoration:line-through;
  text-decoration-color:var(--line2)}

/* Case à cocher tri-state, dessinée sans image ni dépendance. */
.tree input[type=checkbox]{appearance:none;flex:none;width:15px;height:15px;margin:0;
  border:1.5px solid var(--line2);border-radius:var(--r-xs);background:#fff;
  cursor:pointer;position:relative;transition:background var(--dur),border-color var(--dur)}
.tree input[type=checkbox]:hover{border-color:var(--accent2)}
.tree input[type=checkbox]:focus-visible{outline:2px solid var(--accent-ring);outline-offset:1px}
.tree input:checked,.tree input:indeterminate{background:var(--accent);border-color:var(--accent)}
.tree input:checked::after{content:"";position:absolute;left:4px;top:1px;width:4px;height:8px;
  border:solid #fff;border-width:0 1.6px 1.6px 0;transform:rotate(42deg)}
.tree input:indeterminate::after{content:"";position:absolute;left:2px;top:5.5px;
  width:8px;height:1.6px;background:#fff;border-radius:1px}
.tcheck{display:flex;margin:0;padding:0}

/* Rail d'étapes : ce sont des <button role="tab"> (accessibles au clavier),
   il faut donc neutraliser le style de bouton par défaut. */
.wiz-rail .wst{font:inherit;font-size:var(--t-sm);color:var(--mut);cursor:pointer;
  text-align:left;line-height:1.2}
.wiz-rail .wst.active{color:var(--accent)}
.wiz-rail .wst.done{color:var(--ok)}

/* Focus visible sur tous les contrôles, pas seulement les champs de saisie. */
a:focus-visible,button:focus-visible,.btn:focus-visible,summary:focus-visible,
.app-tile:focus-visible,.pickcard:focus-within{outline:2px solid var(--accent);outline-offset:2px}
input:focus,select:focus,textarea:focus{outline-color:var(--accent);outline-offset:1px}

/* Contraste : #7A7F8C plafonnait à ~3.9:1 sur blanc (échec AA sous 18px). */
:root{--mut:#666B78; --warn:#8A6110}

@media (prefers-reduced-motion:reduce){
  *{transition:none !important;animation:none !important;scroll-behavior:auto !important}
}

/* Icône d'application dans l'arbre (image Odoo, ou pastille à l'initiale). */
.tapp-icon{width:18px;height:18px;flex:none;border-radius:var(--r-xs);object-fit:contain}
.tapp-icon--txt{display:inline-flex;align-items:center;justify-content:center;
  background:var(--accent-tint);color:var(--accent);font-size:10px;font-weight:var(--fw-semi)}
.tapp-icon[hidden]{display:none}

/* ---------- Comparaison de deux instances ---------- */
.compare-picker{display:grid;grid-template-columns:1fr auto 1fr;gap:14px;align-items:end}
.compare-picker label{display:block}
.compare-arrow{padding-bottom:10px;color:var(--mut);font-size:20px}
.verdict{margin:0 0 12px;padding:9px 12px;border-radius:8px;font-size:13.5px}
.verdict.ok{background:#E8F6EF;border:1px solid #BEE5D2;color:#14603C}
.verdict.warn{background:#FBF3DF;border:1px solid #EBD9AC;color:#7A5610}
table.cmp{width:100%;border-collapse:collapse;font-size:13px}
table.cmp th{text-align:left;font-weight:600;color:var(--sub);background:var(--surface);
  border-bottom:1px solid var(--line);padding:7px 9px}
table.cmp td{padding:7px 9px;border-bottom:1px solid var(--line-soft);vertical-align:top}
table.cmp .cell-diff{background:#FBF3DF;color:#7A5610}
table.cmp .cell-miss{background:#FCEDEF;color:#8E2635}
table.cmp .cell-extra{background:#EEEDFC;color:#38309B}
.cmp-totals{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:14px}
.cmp-totals .tot{border:1px solid var(--line);border-radius:8px;padding:10px 12px;background:var(--surface)}
.cmp-totals .tot b{display:block;font-size:22px;line-height:1.2}
.cmp-totals .tot span{font-size:12px;color:var(--mut)}
.cmp-totals .ident b{color:var(--ok)}
.cmp-totals .diff b{color:var(--warn)}
.cmp-totals .miss b{color:var(--err)}
.cmp-totals .extra b{color:var(--accent)}
h3.cat{font-size:13.5px;margin:16px 0 6px;color:var(--sub)}
ul.cmp-list{margin:0;padding-left:18px;columns:2;font-size:12px;color:var(--sub)}
ul.cmp-list li{margin:2px 0;break-inside:avoid}
@media (max-width:820px){
  .compare-picker{grid-template-columns:1fr}
  .compare-arrow{display:none}
  .cmp-totals{grid-template-columns:repeat(2,1fr)}
  ul.cmp-list{columns:1}
}

/* Encart « Fichiers produits » du lanceur de script (xlsx, pdf…) : une ligne
   par fichier, avec aperçu quand c'est affichable et bouton de téléchargement
   explicite (voir le script de scripts_result.html pour la boîte
   « Enregistrer sous »). */
.filebox{border:1px solid var(--line);border-radius:8px;background:var(--surface);
  padding:10px 12px;margin:0 0 14px}
.filebox-head{font-size:12px;font-weight:600;color:var(--sub);margin-bottom:8px}
.filerow{display:flex;align-items:center;gap:10px;padding:6px 0;font-size:13px}
.filerow + .filerow{border-top:1px solid var(--line-soft,var(--line))}
.filerow .spacer{flex:1}
.filerow .filename{font-weight:500;overflow-wrap:anywhere}
.filerow .fileext{font-size:10px;font-weight:700;letter-spacing:.04em;color:var(--accent);
  border:1px solid var(--line2);border-radius:4px;padding:2px 6px;background:#fff;flex:none}
.filerow .dl-status{font-size:11.5px;min-width:0;overflow-wrap:anywhere}
@media (max-width:820px){
  .filerow{flex-wrap:wrap}
  .filerow .spacer{display:none}
}

/* ---------- Comparateur de vues héritées ---------- */
/* Deux colonnes de blocs xpath déplaçables : à gauche ce que la source
   propose, à droite le résultat qui sera écrit en destination. L'ordre
   vertical de la colonne de droite EST l'ordre d'application des patchs par
   Odoo — la mise en page doit donc rendre cet ordre évident et le curseur
   d'insertion parfaitement lisible pendant un glisser. */
.vc-head{display:flex;justify-content:space-between;align-items:center;
  gap:var(--s2);flex-wrap:wrap}
.vc-tabs{display:flex;gap:var(--s1);flex-wrap:wrap;margin:var(--s3) 0 var(--s2);
  border-bottom:1px solid var(--line-soft);padding-bottom:var(--s2)}
.vc-tab{padding:5px var(--s3);border:1px solid var(--line2);background:#fff;
  border-radius:var(--r-pill);color:var(--sub);font-size:var(--t-md);
  cursor:pointer;width:auto}
.vc-tab:hover{background:var(--surface-hi);color:var(--ink)}
.vc-tab.on{background:var(--accent-tint);border-color:var(--accent2);
  color:var(--accent-hi);font-weight:var(--fw-semi)}

.vc-view{border:1px solid var(--line-soft);border-radius:var(--r-md);
  margin-bottom:var(--s2);background:#fff}
.vc-view > summary{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;
  padding:var(--s2) var(--s3);cursor:pointer;list-style:none;color:var(--ink)}
.vc-view > summary::-webkit-details-marker{display:none}
.vc-view > summary:hover{background:var(--surface-hi)}
.vc-kind{font-size:var(--t-xs);color:var(--accent);background:var(--accent-tint);
  border-radius:var(--r-pill);padding:1px 8px;flex:none}
.vc-flags{margin-left:auto;font-size:var(--t-xs);color:var(--warn);
  background:#FDF6E4;border-radius:var(--r-pill);padding:1px 8px}
.vc-note{margin:0 var(--s3) var(--s3);font-size:var(--t-sm)}
.vc-note.ok{color:var(--ok)}

.vc-cols{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3);
  padding:0 var(--s3) var(--s3)}
.vc-col h4{margin:0 0 var(--s2);font-size:var(--t-sm);color:var(--mut);
  font-weight:var(--fw-semi);text-transform:uppercase;letter-spacing:.04em}
.vc-list{min-height:80px;padding:var(--s2);border:1px dashed var(--line2);
  border-radius:var(--r-md);background:var(--bg)}
.vc-list[data-role="dest"]{background:var(--accent-soft)}
.vc-list.vc-over{border-color:var(--accent2);background:var(--accent-tint)}

.vc-block{background:#fff;border:1px solid var(--line);border-left:3px solid var(--line2);
  border-radius:var(--r-sm);padding:var(--s2);margin-bottom:var(--s2);cursor:grab}
.vc-block:active{cursor:grabbing}
.vc-block.vc-dragging{opacity:.4}
.vc-block.vc-placed{opacity:.5}
/* La couleur du liseré dit d'où vient le bloc et s'il est à trancher. */
.vc-block.vc-different{border-left-color:var(--warn)}
.vc-block.vc-only_source{border-left-color:var(--accent)}
.vc-block.vc-only_dest{border-left-color:var(--cyan)}
.vc-block.vc-identique{border-left-color:var(--ok)}

.vc-bhead{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.vc-grip{color:var(--line2);flex:none;cursor:grab}
.vc-pos{font-size:var(--t-xs);color:var(--sub);background:var(--surface-hi);
  border-radius:var(--r-xs);padding:1px 6px;flex:none}
.vc-expr{font-size:var(--t-xs);color:var(--ink);overflow-wrap:anywhere;flex:1;min-width:0}
.vc-st{font-size:var(--t-xs);color:var(--mut);flex:none}
.vc-x{width:auto;flex:none;padding:0 6px;border:0;background:transparent;
  color:var(--mut);cursor:pointer;font-size:var(--t-sm)}
.vc-x:hover{color:var(--err)}
.vc-prev{font-size:var(--t-xs);margin-top:2px}
.vc-xml{margin:var(--s1) 0 0;padding:var(--s2);background:var(--bg);
  border-radius:var(--r-xs);font-size:var(--t-xs);max-height:140px;overflow:auto;
  white-space:pre-wrap;overflow-wrap:anywhere;color:var(--sub)}

/* Curseur d'insertion pendant le glisser : c'est lui qui matérialise
   « j'intercale ce patch ICI, entre ces deux-là ». */
.vc-marker{height:3px;margin:var(--s1) 0;border-radius:2px;background:var(--accent);
  box-shadow:0 0 0 3px var(--accent-tint)}

@media (max-width:820px){
  .vc-cols{grid-template-columns:1fr}
}

/* ---------- Comparateur de vues : bilan et comparaison côte à côte ---------- */
.vc-summary{display:flex;flex-wrap:wrap;gap:var(--s2);margin:var(--s2) 0 var(--s3)}
.vc-chip{font-size:var(--t-sm);padding:2px var(--s3);border-radius:var(--r-pill);
  background:var(--surface-hi);color:var(--sub)}
.vc-chip b{font-variant-numeric:tabular-nums;color:var(--ink)}
.vc-chip.warn{background:#FDF6E4;color:var(--warn)}
.vc-chip.ok{background:#E8F6EE;color:var(--ok)}
.vc-chip.err{background:#FCEBEE;color:var(--err)}
.vc-chip.muted{background:transparent}
.vc-unmatched{margin:0 0 var(--s3);font-size:var(--t-md)}
.vc-unmatched > summary{cursor:pointer;color:var(--sub)}
.vc-unmatched ul{margin:var(--s2) 0 0;padding-left:var(--s5)}

.vc-diff{margin:0 var(--s3) var(--s3);border:1px solid var(--line);
  border-radius:var(--r-sm);overflow:auto;max-height:520px;font-size:var(--t-xs)}
.vc-diff-row{display:grid;grid-template-columns:1fr 1fr}
.vc-diff-row > *{margin:0;padding:1px var(--s2);white-space:pre-wrap;
  overflow-wrap:anywhere;min-height:1.4em}
.vc-diff-row > :first-child{border-right:1px solid var(--line-soft)}
.vc-diff-head{position:sticky;top:0;background:var(--surface-hi);
  font-weight:var(--fw-semi);color:var(--sub);font-size:var(--t-sm)}
.vc-diff-head > *{white-space:normal}
.vc-d-chg pre{background:#FDF6E4}
.vc-d-del > :first-child{background:#FCEBEE}
.vc-d-add > :last-child{background:#E8F6EE}
.vc-diff-gap{padding:2px var(--s2);text-align:center;color:var(--mut);
  background:var(--bg);font-size:var(--t-xs)}
.vc-overwrite{display:flex;align-items:center;gap:var(--s2);margin:0 var(--s3) var(--s3);
  font-size:var(--t-md);color:var(--ink);cursor:pointer}
.vc-overwrite input{width:auto;flex:none}

/* ---------- Ajuster les vues : atelier ---------- */
.va-picks{max-height:260px;overflow:auto;border:1px solid var(--line-soft);
  border-radius:var(--r-md);margin:var(--s2) 0 var(--s3)}
.va-pickrow{display:flex;align-items:center;gap:var(--s2);margin:0;padding:4px var(--s3);
  cursor:pointer;color:var(--ink);font-size:var(--t-md);border-bottom:1px solid var(--line-soft)}
.va-pickrow:last-child{border-bottom:0}
.va-pickrow:hover{background:var(--surface-hi)}
.va-pickrow[hidden]{display:none}
.va-pickrow input{width:auto;flex:none}
.va-toolbar{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin:var(--s3) 0}
.va-actions{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;margin:0 0 var(--s3)}
.va-status.ok{color:var(--ok)} .va-status.warn{color:var(--warn)} .va-status.err{color:var(--err)}
.va-badge{margin-left:auto;font-size:var(--t-xs);padding:1px 8px;border-radius:var(--r-pill);
  background:var(--surface-hi);color:var(--sub)}
.va-badge:empty{display:none}
.va-badge.ok{background:#E8F6EE;color:var(--ok)} .va-badge.err{background:#FCEBEE;color:var(--err)}
.va-badge.todo{background:#FDF6E4;color:var(--warn)}
.va-validate{display:flex;align-items:center;gap:var(--s2);margin:0 var(--s3) var(--s3);
  padding-top:var(--s2);border-top:1px solid var(--line-soft);color:var(--ink);
  font-size:var(--t-md);cursor:pointer}
.va-validate input{width:auto;flex:none}
.va-pickbox{display:flex;align-items:center;gap:4px;margin:0;font-size:var(--t-xs);
  color:var(--accent-hi);cursor:pointer;flex:none}
.va-pickbox input{width:auto}
.va-act{font-size:var(--t-xs);flex:none;border-radius:var(--r-pill);padding:0 7px}
.va-act:empty{display:none}
.va-act.va-add{background:#E8F6EE;color:var(--ok)} .va-act.va-replace{background:#FDF6E4;color:var(--warn)}
.va-act.va-skip{background:var(--surface-hi);color:var(--mut)}
.va-edited{box-shadow:0 0 0 2px var(--accent-tint)}
.va-edit{margin-top:var(--s2)}
.va-edit textarea{width:100%;font-family:ui-monospace,Menlo,monospace;font-size:var(--t-xs)}
.va-edit-msg{font-size:var(--t-xs);min-height:1em} .va-edit-msg.err{color:var(--err)}
.va-issues{margin:0 var(--s3)}
.va-issue{font-size:var(--t-sm);padding:3px var(--s2);border-radius:var(--r-xs);margin-bottom:3px}
.va-issue.error{background:#FCEBEE;color:var(--err)} .va-issue.warning{background:#FDF6E4;color:var(--warn)}
.va-issue.info{background:var(--surface-hi);color:var(--sub)} .va-issue.ok{background:#E8F6EE;color:var(--ok)}
.va-result{margin-top:var(--s3);font-size:var(--t-md)}

.va-model{display:flex;align-items:center;gap:var(--s2);margin:0;font-size:var(--t-sm);color:var(--sub)}
.va-model input{width:auto;padding:4px 8px;font-size:var(--t-sm)}
.va-gate{flex-basis:100%;font-size:var(--t-sm);min-height:0}
.va-gate:empty{display:none} .va-gate.warn{color:var(--warn)}
.va-force{flex-basis:100%;display:flex;align-items:center;gap:var(--s2);margin:0;padding:var(--s2) var(--s3);
  background:#FCEBEE;border-radius:var(--r-sm);color:var(--err);font-size:var(--t-md);cursor:pointer}
.va-force input{width:auto;flex:none}
.va-force[hidden]{display:none}

/* Un bouton verrouillé doit LE PARAÎTRE : sans cela, « Appliquer » grisé par le
   garde-fou ressemble à un bouton actif qui ne répond pas. */
.va-actions button:disabled{opacity:.4;cursor:not-allowed;filter:grayscale(.4)}

/* =====================================================================
 * Thème sombre — mêmes variables, valeurs différentes. `data-theme="dark"`
 * est posé sur <html> avant le premier paint (script inline en tête de
 * base.html) pour éviter le flash de thème clair. Le choix est persisté
 * dans localStorage par `uiActions.toggleTheme` (voir ui.js).
 * ===================================================================== */
:root[data-theme="dark"]{
  --bg:#0B0D14; --panel:#12162A; --card:#12162A; --line:#232A46; --line2:#2E3459;
  --ink:#EDEFF7; --mut:#8D93AE; --sub:#C4C8DB;
  --accent:#6C63F0; --accent-hi:#7D74FF; --accent2:#8B85F5; --cyan:#4FD2E8;
  --ok:#3ECF8E; --err:#F26D7E; --warn:#E8B13A;
  --line-soft:#1C2136; --surface:#111420; --surface-hi:#171C33;
  --accent-soft:rgba(108,99,240,.16); --accent-tint:rgba(108,99,240,.18);
  --accent-line:#3A3568; --accent-ring:#4A4380;
  /* Vraie « dynamic island » : capsule sombre translucide, pas un panneau
     plein — proche du noir quelle que soit la teinte du fond derrière. */
  --rail-bg:rgba(8,9,15,.68); --rail-ring:rgba(255,255,255,.07);
}
:root[data-theme="dark"] input,:root[data-theme="dark"] select,:root[data-theme="dark"] textarea{
  background:var(--surface);color:var(--ink);border-color:var(--line2)}
:root[data-theme="dark"] .card,:root[data-theme="dark"] .tree,:root[data-theme="dark"] .accordion,
:root[data-theme="dark"] .checklist,:root[data-theme="dark"] .vc-view,
:root[data-theme="dark"] .locked-row,:root[data-theme="dark"] .filebox{background:var(--panel)}
:root[data-theme="dark"] .pickcard,:root[data-theme="dark"] .vc-block,:root[data-theme="dark"] .tbtn{background:var(--surface)}
:root[data-theme="dark"] .pickcard:has(input:checked){background:var(--accent-soft)}
:root[data-theme="dark"] button.ghost,:root[data-theme="dark"] .btn.ghost{background:var(--surface);color:var(--sub)}
:root[data-theme="dark"] .badge{background:var(--accent-tint);border-color:var(--accent-line)}
:root[data-theme="dark"] .flash.error,:root[data-theme="dark"] .flash.err{background:rgba(242,109,126,.12);color:#FF9CAA;border-color:rgba(242,109,126,.35)}
:root[data-theme="dark"] .flash.ok{background:rgba(62,207,142,.12);color:#7EE6B4;border-color:rgba(62,207,142,.35)}
:root[data-theme="dark"] .pill.success,:root[data-theme="dark"] .pill.créé{background:rgba(62,207,142,.14);border-color:rgba(62,207,142,.4)}
:root[data-theme="dark"] .pill.error,:root[data-theme="dark"] .pill.échec{background:rgba(242,109,126,.14);border-color:rgba(242,109,126,.4)}
:root[data-theme="dark"] .pill.running,:root[data-theme="dark"] .pill.pending{background:rgba(232,177,58,.14);border-color:rgba(232,177,58,.4)}
:root[data-theme="dark"] .security-box{background:var(--accent-soft);border-color:var(--accent-line)}
:root[data-theme="dark"] .security-box-head h3{color:var(--ink)}
:root[data-theme="dark"] .tint-violet,:root[data-theme="dark"] .tint-teal,:root[data-theme="dark"] .tint-orange,
:root[data-theme="dark"] .tint-pink,:root[data-theme="dark"] .tint-blue,:root[data-theme="dark"] .tint-green,
:root[data-theme="dark"] .tint-yellow,:root[data-theme="dark"] .tint-red,:root[data-theme="dark"] .tint-slate{
  background:var(--surface-hi);filter:saturate(1.4)}
:root[data-theme="dark"] table.cmp .cell-diff{background:rgba(232,177,58,.14)}
:root[data-theme="dark"] table.cmp .cell-miss{background:rgba(242,109,126,.14)}
:root[data-theme="dark"] table.cmp .cell-extra{background:rgba(108,99,240,.16)}
:root[data-theme="dark"] .vc-d-chg pre{background:rgba(232,177,58,.14)}
:root[data-theme="dark"] .vc-d-del > :first-child{background:rgba(242,109,126,.14)}
:root[data-theme="dark"] .vc-d-add > :last-child{background:rgba(62,207,142,.14)}
/* Un thème complet pour chaque écran spécialisé (comparateur de vues, arbre
   de sélection…) demanderait de reprendre chaque teinte codée en dur une à
   une ; les règles ci-dessus couvrent la chrome commune et les statuts les
   plus visibles, le reste hérite des variables et reste lisible mais moins
   peaufiné — à affiner écran par écran si besoin. */

/* =====================================================================
 * Rail de navigation vertical — capsule flottante translucide façon
 * « dynamic island » (fond verre dépoli, pas un panneau plein), ancrée en
 * haut plutôt que centrée verticalement pour ne pas laisser de vide au-dessus.
 * ===================================================================== */
.rail{position:fixed;left:20px;top:28px;z-index:40;
  width:72px;display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:14px 0;border-radius:999px;background:var(--rail-bg);
  -webkit-backdrop-filter:blur(20px) saturate(1.4);backdrop-filter:blur(20px) saturate(1.4);
  box-shadow:0 20px 44px -18px rgba(24,26,32,.35),0 0 0 1px var(--rail-ring)}
:root[data-theme="dark"] .rail{box-shadow:0 20px 50px -14px rgba(0,0,0,.6),0 0 0 1px var(--rail-ring)}
.rail-logo{display:flex;align-items:center;justify-content:center;margin-bottom:10px}
.rail-sep{width:28px;height:1px;background:var(--line);margin:6px 0}
.rail-item{width:48px;height:48px;border-radius:13px;display:flex;align-items:center;justify-content:center;
  color:var(--mut);position:relative;border:none;background:transparent;cursor:pointer;padding:0;
  transition:background .12s ease,color .12s ease}
.rail-item svg{width:22px;height:22px}
.rail-item:hover{background:var(--surface-hi);color:var(--ink)}
.rail-item.active{background:var(--accent-tint);color:var(--accent)}
.rail-item.active::before{content:'';position:absolute;left:-13px;top:50%;transform:translateY(-50%);
  width:3px;height:18px;border-radius:2px;background:var(--accent)}
.rail form{margin:0}
/* Bouton de thème : deux tracés, un seul visible selon `data-theme`. */
.rail-item .icon-sun{display:none}
:root[data-theme="dark"] .rail-item .icon-moon{display:none}
:root[data-theme="dark"] .rail-item .icon-sun{display:block}
/* Info-bulle au survol (desktop uniquement) : le libellé apparaît comme une
   goutte qui s'ouvre à côté de l'icône — le rail n'ayant plus de fond ni de
   texte, c'est elle qui porte l'information. */
@media (hover:hover) and (pointer:fine){
  .rail-item[data-label]::after{content:attr(data-label);position:absolute;left:calc(100% + 12px);top:50%;
    transform:translateY(-50%) scale(.85);transform-origin:left center;
    background:var(--ink);color:var(--bg);font-size:12.5px;font-weight:600;white-space:nowrap;
    padding:7px 13px;border-radius:20px;opacity:0;pointer-events:none;
    transition:opacity .14s ease,transform .16s cubic-bezier(.34,1.5,.5,1);
    box-shadow:0 10px 24px -8px rgba(0,0,0,.35);z-index:41}
  .rail-item[data-label]:hover::after{opacity:1;transform:translateY(-50%) scale(1)}
  .rail-more[open] > summary[data-label]::after{display:none}
}
/* « Plus » : disclosure native (<details>/<summary>), donc utilisable même
   si le CSP bloque un script inline — cohérent avec .burger/.accordion. */
.rail-more{position:relative}
.rail-more > summary{list-style:none}
.rail-more > summary::-webkit-details-marker{display:none}
.rail-flyout{position:absolute;left:60px;top:0;min-width:230px;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:8px;
  box-shadow:0 24px 50px -20px rgba(24,26,32,.4);display:flex;flex-direction:column;gap:1px}
:root[data-theme="dark"] .rail-flyout{box-shadow:0 24px 50px -16px rgba(0,0,0,.6)}
.rail-flyout a,.rail-flyout .rail-flyout-locked{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:9px 12px;border-radius:8px;color:var(--sub);font-size:13.5px;white-space:nowrap}
.rail-flyout a:hover{background:var(--surface-hi);color:var(--ink)}
.rail-flyout .rail-flyout-locked{opacity:.6}
.rail-flyout .lock-badge{margin:0}
.rail-flyout hr{border:none;border-top:1px solid var(--line);margin:6px 4px}
.rail-flyout-label{font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--mut);
  padding:8px 12px 2px}

/* La page réserve l'espace du rail plutôt que de le laisser recouvrir le
   contenu : appliqué via la classe posée sur <body> quand l'utilisateur est
   connecté (voir base.html). */
body.has-rail main{padding-left:116px}
body.has-rail .subnav{padding-left:116px}
@media (max-width:760px){
  /* Barre basse, défilable horizontalement plutôt que compressée : avec le
     thème, le compte et la déconnexion en plus des 5 raccourcis, tout ne
     tient pas sur 375px de large — mieux vaut glisser que casser. */
  .rail{left:0;right:0;top:auto;bottom:0;width:auto;flex-direction:row;align-items:center;
    gap:2px;padding:8px 14px calc(8px + env(safe-area-inset-bottom));
    border-radius:22px 22px 0 0;box-shadow:0 -10px 30px -10px rgba(0,0,0,.25);
    overflow-x:auto;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch;
    justify-content:flex-start}
  .rail-logo{display:none}
  .rail-sep{display:none}
  .rail-item{width:44px;height:44px;flex:none}
  .rail-item svg{width:19px;height:19px}
  .rail-item.active::before{left:50%;top:-9px;transform:translateX(-50%);width:16px;height:3px}
  .rail-flyout{left:auto;right:0;top:auto;bottom:56px}
  body.has-rail main{padding-left:34px;padding-bottom:96px}
  body.has-rail .subnav{padding-left:18px}
}

/* =====================================================================
 * Notifications — pile de « toasts » en haut à droite, plutôt que des
 * bandeaux plein-large intercalés dans le contenu.
 * ===================================================================== */
.toast-stack{position:fixed;top:20px;right:20px;z-index:120;display:flex;flex-direction:column;
  gap:10px;max-width:360px;pointer-events:none}
.toast-stack .flash{pointer-events:auto;margin:0;box-shadow:0 16px 34px -14px rgba(24,26,32,.3);
  display:flex;align-items:flex-start;gap:10px;border-radius:10px}
:root[data-theme="dark"] .toast-stack .flash{box-shadow:0 16px 40px -12px rgba(0,0,0,.6)}
.toast-stack .flash .toast-x{margin-left:auto;flex:none;background:none;border:none;padding:0;
  color:inherit;opacity:.6;cursor:pointer;font-size:15px;line-height:1}
.toast-stack .flash .toast-x:hover{opacity:1}
@media (max-width:560px){.toast-stack{left:16px;right:16px;top:16px;max-width:none}}
