/* ═══════════════════════════════════════════════════════════════════════════════
   RAIL ALLYO — LE fichier canonique, UNIQUE pour toutes les surfaces (23/07/2026,
   « j'en ai marre » des copies qui divergent). Servi par www.allyo.group/rail.css :
   le socle, dashboard.allyo.space, la marque blanche (même docroot) et les apps
   Next (app.allyo.pro…) le chargent — PLUS AUCUNE app ne garde sa copie locale.
   Toute évolution du rail se fait ICI et nulle part ailleurs.
   Variables attendues de l'hôte : --accent (couleur société). Tout le reste a un
   défaut intégré — le rail rend pareil quel que soit le thème de l'app hôte.
   ═══════════════════════════════════════════════════════════════════════════════ */

/* Hauteur : le rail S'ÉTEND sur TOUTE la hauteur de la page (Agentation Mathieu 27/07 :
   « s'il y a un scroll vertical, la navbar doit s'étendre pour que le bouton utilisateur
   et le + soient toujours en bas de page ») — align-self:stretch + min-height:100vh,
   jamais un height:100vh figé qui laisse une colonne vide sous le premier écran. */
/* Filet DÉFINITIF contre la colonne navy qui s'arrête avant le bas (signalé encore le
   03/08). `align-self:stretch` seul ne suffit pas : selon la page, la hauteur retenue par
   le navigateur pour un élément `sticky` étiré laisse une bande claire sous le rail. On
   peint donc la colonne sur le FOND DE LA PAGE, en `fixed` : cette bande navy couvre
   toujours toute la fenêtre, quoi que fasse la mise en page. Le rail se pose par-dessus,
   exactement aligné (mêmes 64 px) — la jointure est invisible.
   Ciblé par `:has(.rail)` : une page sans rail (webapp Chat, monitoring) reste intacte.
   Désactivé sous 641px, où le rail devient un tiroir hors-écran. */
@media (min-width:641px){
  body:has(> .app > .rail){
    background-image:linear-gradient(to right,var(--navy,#0c1c39) 0 64px,transparent 64px);
    background-repeat:no-repeat;background-attachment:fixed}
}
.rail{position:sticky;top:0;flex:0 0 auto;align-self:stretch;width:64px;min-height:100vh;background:var(--navy,#0c1c39);display:flex;flex-direction:column;align-items:center;padding:14px 0 16px;gap:6px;z-index:40;font-family:'Plus Jakarta Sans',system-ui,sans-serif}
.rail .brand{width:42px;height:42px;border-radius:13px;display:grid;place-items:center;background:var(--accent,#0c1c39);color:#fff;margin-bottom:14px;box-shadow:0 8px 20px -8px rgba(0,0,0,.5);text-decoration:none}
.rail .brand svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.rail .brand img{width:34px;height:34px;object-fit:contain;display:block}
.rail .nav,.rail .rnav{display:flex;flex-direction:column;align-items:center;gap:6px;width:100%}
.rail .foot{display:flex;flex-direction:column;align-items:center;gap:5px;width:100%;margin-top:auto;
  /* FLOTTANT EN BAS DE LA PAGE (Agentation Mathieu 03/08) — donc en bas de la navbar.
     `position:sticky` ne suffisait pas : sur une page longue, le rail étiré (align-self:
     stretch) est plus haut que la fenêtre et le pied restait accroché au milieu. `fixed`
     le plaque à l'écran quoi qu'il arrive, sans dépendre de la hauteur du contenu ni
     d'un éventuel overflow d'un ancêtre. Largeur = celle du rail. Fond navy : masque les
     icônes de nav qui passent dessous. Le tiroir mobile reprend la main plus bas. */
  position:fixed;left:0;bottom:0;width:64px;background:var(--navy,#0c1c39);
  padding-bottom:16px;z-index:41}
.r-item{position:relative;width:46px;height:46px;border:0;background:transparent;border-radius:13px;display:grid;place-items:center;color:#8a98b5;cursor:pointer;text-decoration:none;transition:background .15s,color .15s}
.r-item svg{width:21px;height:21px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;transition:transform .22s cubic-bezier(.34,1.56,.64,1)}
.r-item:hover{color:#fff;background:rgba(255,255,255,.08)}
.r-item.on{color:#fff;background:var(--accent,#0c1c39);box-shadow:0 8px 20px -10px rgba(0,0,0,.6)}
.r-item .tip{position:absolute;left:calc(100% + 11px);top:50%;transform:translateY(-50%) translateX(-5px);background:var(--navy,#0c1c39);color:#fff;font-size:.76rem;font-weight:600;white-space:nowrap;padding:6px 10px;border-radius:8px;opacity:0;pointer-events:none;transition:opacity .14s,transform .14s;box-shadow:0 10px 26px -8px rgba(0,0,0,.55);z-index:50}
.r-item .tip:after{content:"";position:absolute;right:100%;top:50%;transform:translateY(-50%);border:5px solid transparent;border-right-color:var(--navy,#0c1c39)}
.r-item:hover .tip,.r-item:focus-visible .tip{opacity:1;transform:translateY(-50%) translateX(0)}
.r-item:hover svg,.r-item:focus-visible svg{transform:scale(1.18)}
.r-item:active svg{transform:scale(.9);transition-duration:.08s}
@media (prefers-reduced-motion: reduce){
  .r-item svg{transition:none}
  .r-item:hover svg,.r-item:focus-visible svg,.r-item:active svg{transform:none}
}
.r-item .rbadge{position:absolute;top:5px;right:5px;background:#ef4444;color:#fff;font-size:.6rem;font-weight:800;min-width:15px;height:15px;border-radius:999px;display:grid;place-items:center;padding:0 3px}
/* Séparateur du rail SUPPRIMÉ (Agentation Mathieu 03/08 « ce trait blanc horrible ») :
   le <span class="sep"> reste dans le balisage de toutes les surfaces (socle, tenant,
   Supply, Support…) mais ne dessine plus rien — un simple espace avant le pied. */
.rail .sep{display:block;width:0;height:0;margin:5px 0;background:none}
.r-ava{width:34px;height:34px;border-radius:50%;object-fit:cover;display:block;box-shadow:0 0 0 2px var(--accent,#0c1c39)}
.r-ava.ph{display:grid;place-items:center;background:var(--accent,#0c1c39);color:#fff;font-size:.8rem;font-weight:800}
img.r-ava{background:#fff}

/* ── Switcher de modules (sous la marque) ── */
/* Tailles en px (base 16), PAS en rem : le switcher doit rester identique au tenant
   (référence) même dans les apps qui montent la racine html en clamp (Support, Espace
   client, allyo.cloud). Ne pas repasser en rem, sinon le menu regrossit sur ces hôtes. */
.swwrap{position:relative;width:100%;display:flex;justify-content:center;margin-bottom:6px}
.swpop{position:absolute;left:calc(100% + 11px);top:0;width:230px;background:var(--card,#111a2e);border:1px solid var(--line,rgba(255,255,255,.10));border-radius:14px;box-shadow:0 18px 50px -12px rgba(0,0,0,.45);padding:11.2px;opacity:0;visibility:hidden;transform:translateY(-6px);transition:.16s;z-index:60}
.swpop.open{opacity:1;visibility:visible;transform:none}
.swpop-head{font-size:11.2px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--muted,#8ea2c8);padding:3.2px 6.4px 8.8px;border-bottom:1px solid var(--line,rgba(255,255,255,.10));margin-bottom:6.4px}
.swpop-empty{font-size:12.8px;color:var(--muted,#8ea2c8);text-align:center;padding:16px 8px;line-height:1.5}
.swpop-item{display:flex;align-items:center;gap:10.4px;padding:8.8px 8px;border-radius:10px;color:var(--ink,#eaf0fb);text-decoration:none;transition:background .13s}
.swpop-item+.swpop-item{margin-top:2.4px}
.swpop-item:hover{background:var(--surf,#16213a)}
.swpop-item .swi{flex:0 0 auto;width:34px;height:34px;border-radius:9px;display:grid;place-items:center;background:var(--surf,#16213a);color:var(--accent,#4fe3c1)}
.swpop-item .swi svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.swpop-item b{display:block;font-size:13.76px;font-weight:700;line-height:1.2}
/* Description du module MASQUÉE (Agentation Mathieu 27/07 : « juste le nom ») —
   le markup <em> reste dans les hôtes, la règle canonique le cache partout. */
.swpop-item em{display:none}
.swpop-item.off{opacity:.55;cursor:default}
/* Tout petit coin « nouvel onglet » : discret, visible au survol de la ligne. */
.swnb{flex:0 0 auto;margin-left:auto;width:20px;height:20px;border-radius:6px;display:grid;place-items:center;color:var(--faint,#5f7099);opacity:0;transition:.13s}
.swpop-item:hover .swnb{opacity:1}
.swnb:hover{color:var(--mint,#4fe3c1);background:var(--surf,#16213a)}
.swnb svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

/* ── Fiche utilisateur (bas du rail) ── */
.uwrap{position:relative;width:100%;display:flex;justify-content:center}
.upop{position:absolute;left:calc(100% + 11px);bottom:0;width:230px;background:var(--card,#111a2e);border:1px solid var(--line,rgba(255,255,255,.10));border-radius:14px;box-shadow:0 18px 50px -12px rgba(0,0,0,.45);padding:.7rem;opacity:0;visibility:hidden;transform:translateY(6px);transition:.16s;z-index:60}
.upop.open{opacity:1;visibility:visible;transform:none}
.upop .uhead{display:flex;align-items:center;gap:.6rem;padding:.3rem .4rem .6rem;border-bottom:1px solid var(--line,rgba(255,255,255,.10));margin-bottom:.4rem}
.upop .uhead .av{width:38px;height:38px;border-radius:50%;object-fit:cover;flex:0 0 auto;background:var(--accent,#0c1c39);color:#fff;display:grid;place-items:center;font-weight:800;font-size:.85rem}
.upop .uhead b{font-size:.85rem;color:var(--ink,#eaf0fb);display:block;line-height:1.2}
.upop .uhead span{font-size:.72rem;color:var(--muted,#8ea2c8)}
.upop a,.upop button.upop-item{display:flex;align-items:center;gap:.55rem;width:100%;padding:.5rem .55rem;border-radius:9px;font-size:.84rem;font-weight:600;color:var(--ink,#eaf0fb);background:none;border:0;cursor:pointer;text-align:left;font-family:inherit}
.upop a:hover,.upop button.upop-item:hover{background:var(--surf,#16213a)}
.upop a svg,.upop button svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.upop .danger{color:#dc2626}
.upop-sep{display:block;height:1px;background:var(--line,rgba(255,255,255,.10));margin:.4rem .3rem}
/* Entrée réservée titulaire/Superadmin (menu OU rail) : icône dans l'accent, pour
   la distinguer d'un coup d'œil des entrées ouvertes à tous (demande Mathieu 27/07). */
.upop .priv,.r-item.priv{color:var(--accent,#0c1c39)}

/* ── Chat (pied du rail) : panneau flottant, jamais de navigation — on reste dans le
   module où l'on est (demande Mathieu 27/07). Même mécanique que .upop (position,
   transition), mais plus large/haut pour accueillir l'iframe du chat. ── */
.chwrap{position:relative;width:100%;display:flex;justify-content:center}
.chpop{position:absolute;left:calc(100% + 11px);bottom:0;width:380px;height:min(600px,80vh);
  display:flex;flex-direction:column;background:var(--card,#111a2e);border:1px solid var(--line,rgba(255,255,255,.10));
  border-radius:14px;box-shadow:0 18px 50px -12px rgba(0,0,0,.45);opacity:0;visibility:hidden;
  transform:translateY(6px);transition:.16s;z-index:60;overflow:hidden}
.chpop.open{opacity:1;visibility:visible;transform:none}
.chpop-head{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;gap:.5rem;
  padding:.65rem .8rem;border-bottom:1px solid var(--line,rgba(255,255,255,.10));font-size:.85rem;
  font-weight:700;color:var(--ink,#eaf0fb)}
.chpop-nb{display:grid;place-items:center;width:26px;height:26px;border-radius:8px;color:var(--muted,#8ea2c8)}
.chpop-nb:hover{color:var(--mint,#4fe3c1);background:var(--surf,#16213a)}
.chpop-nb svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.chpop-frame{flex:1;width:100%;border:0;background:var(--card,#111a2e)}
.r-item.priv:hover{color:var(--accent,#0c1c39)}

/* ── Un SEUL gabarit de rail, à toutes les largeurs d'écran (demande Mathieu 27/07 :
   le rail doit être identique partout, la règle mobile ≤560px qui le resserrait
   créait un « rail différent » selon la fenêtre — supprimée, ne pas la remettre). ── */

/* ── Dérouleur d'outils (pied de rail) : Drive · Chat · Boîte mail · Thème repliés
   derrière UN bouton (demande Mathieu 27/07 — gain de place). Témoin rouge sur le
   bouton fermé s'il y a du nouveau (chat ou mail). Dépliage HORIZONTAL (27/07 :
   « rail horizontal pas vertical ») : les icônes jaillissent en rangée à DROITE du
   bouton, à ressort et en cascade, dans une pastille navy flottante. Chaque icône
   (sauf Thème) s'ouvre en _parent au clic, ou en _blank via le mini-bouton .rnb au
   survol (même esprit que .swnb du switcher). ── */
.twrap{position:relative;width:100%;display:flex;justify-content:center}
/* Ouverture/fermeture pilotée par GSAP (Agentation 03/08) — le JS de rail-tools.php anime
   le panneau et chaque icône en cascade. Le CSS ne pose que l'état FERMÉ ; sans GSAP
   (fichier bloqué, connexion coupée), la classe .open suffit à tout afficher. */
.tpanel{position:absolute;left:calc(100% + 11px);bottom:0;display:flex;flex-direction:row;
  align-items:center;gap:6px;padding:6px;background:var(--navy,#0c1c39);border-radius:14px;
  box-shadow:0 14px 34px -10px rgba(0,0,0,.6);border:1px solid rgba(255,255,255,.08);
  opacity:0;visibility:hidden;z-index:60}
.twrap.open .tpanel{opacity:1;visibility:visible}
/* Infobulles : au-DESSUS des icônes (à droite elles chevaucheraient l'icône suivante). */
.tpanel .r-item .tip{left:50%;top:auto;bottom:calc(100% + 9px);
  transform:translateX(-50%) translateY(4px)}
.tpanel .r-item:hover .tip,.tpanel .r-item:focus-visible .tip{transform:translateX(-50%) translateY(0)}
/* Dérouleur ouvert : l'infobulle « Outils » du bouton + n'a plus lieu d'être (le panneau la recouvre). */
.tbtn .tip{display:none}
.tpanel .r-item .tip:after{right:auto;left:50%;top:100%;
  transform:translateX(-50%);border:5px solid transparent;border-top-color:var(--navy,#0c1c39);border-right-color:transparent}
.tbtn svg{transition:transform .3s cubic-bezier(.34,1.56,.64,1)}
.twrap.open .tbtn svg{transform:rotate(45deg)}
/* Notifications du dérouleur (Agentation 03/08) : le « + » replié porte le TOTAL, tous
   canaux confondus (Drive, Chat, Boîte mail, réponses aux bugs) ; une fois ouvert, c'est
   l'ICÔNE concernée qui passe en rouge. Plus aucune pastille sur les icônes : elle se
   posait au même endroit que le mini-bouton « nouvel onglet » (.rnb). */
/* Bouton du dérouleur : un CERCLE (le trait, pas un disque plein — Agentation 03/08).
   Le rouge des notifications ne touche QUE LE TRAIT : le chiffre garde la couleur du
   rail. Jamais de fond. */
.tball{width:22px;height:22px;border-radius:50%;border:1.7px solid currentColor;
  background:none;display:grid;place-items:center;font:800 10px/1 system-ui,sans-serif;
  transition:border-color .15s}
.tball.on{border-color:#ef4444}
/* Contenu du rond : la clé à molette au repos, le CHIFFRE à sa place dès qu'une
   notification tombe (Agentation 03/08) — les deux ne coexistent jamais. */
.tball>*{grid-area:1/1}
.tball .tico{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}
.tball .tnum{display:none;font:inherit}
.tball.on .tico{display:none}
.tball.on .tnum{display:block}
.tpanel .r-item.neuf{color:#ef4444}
.tpanel .r-item.neuf:hover{color:#fff;background:#ef4444}
/* .tdot conservé pour les surfaces pas encore migrées — plus posé par ggRailTools. */
.tdot{position:absolute;top:5px;right:5px;width:9px;height:9px;border-radius:50%;
  background:#ef4444;box-shadow:0 0 0 2px var(--navy,#0c1c39)}
.twrap.open .tbtn .tdot{display:none}
.rnb{position:absolute;top:2px;right:2px;width:16px;height:16px;border-radius:5px;
  display:grid;place-items:center;color:#aab7d4;background:rgba(255,255,255,.14);
  opacity:0;transition:opacity .13s;cursor:alias}
.tpanel .r-item:hover .rnb{opacity:1}
.rnb:hover{color:#fff;background:rgba(255,255,255,.28)}
.rnb svg{width:10px;height:10px;fill:none;stroke:currentColor;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;transform:none !important}
@media (prefers-reduced-motion: reduce){
  .tpanel,.tpanel .r-item,.tbtn svg{transition:none}
}

/* ── Repasse mobile (27/07 soir). Le GABARIT du rail ne bouge PAS (64px partout —
   décision ci-dessus, intacte) : on borne seulement ce qui en SORT pour que plus
   aucun panneau ne dépasse de l'écran d'un téléphone (360-430px, moins le rail). ── */
@media (max-width:640px){
  .swpop,.upop{width:min(230px,calc(100vw - 86px));max-height:min(72vh,540px);overflow-y:auto}
  .chpop{width:min(380px,calc(100vw - 86px))}
  .tpanel{max-width:calc(100vw - 86px);flex-wrap:wrap;justify-content:flex-start}
}
/* Tactile (pas de survol) : les infobulles hover restent collées après un tap (état
   hover rémanent iOS/Android) → neutralisées ; les mini-boutons « nouvel onglet »
   révélés au survol seraient des cibles invisibles → visibles en permanence. */
@media (hover:none){
  .r-item .tip,.tpanel .r-item .tip{display:none}
  .swnb,.rnb{opacity:.7}
}

/* ── SMARTPHONE (<8", demande Mathieu 27/07 soir) : le rail n'est PLUS fixe — il
   devient un TIROIR. Un bouton flottant en bas à gauche (à la place de l'icône user)
   l'ouvre en SURVOL de la page ; un clic sur un lien du rail charge la page pleine
   largeur et replie le tiroir. Le bouton/backdrop sont injectés par le JS de chaque
   surface (classes .rail-mtoggle / .rail-mbg) — desktop strictement inchangé. ── */
@media (max-width:640px){
  .rail{position:fixed;left:0;top:0;bottom:0;height:100dvh;z-index:85;
    transform:translateX(-102%);transition:transform .22s ease;
    box-shadow:0 0 60px rgba(0,0,0,.5)}
  .rail.mob-open{transform:none}
  /* Le pied redevient SOLIDAIRE du tiroir : en `fixed` il resterait affiché à l'écran
     alors que le rail est translaté hors champ. */
  .rail .foot{position:static;width:100%;padding-bottom:16px}
  .rail-mtoggle{position:fixed;left:12px;bottom:calc(12px + env(safe-area-inset-bottom,0px));
    z-index:86;width:50px;height:50px;border-radius:16px;border:0;cursor:pointer;
    background:var(--accent,#0c1c39);color:#fff;display:grid;place-items:center;
    box-shadow:0 10px 28px -8px rgba(0,0,0,.55)}
  .rail-mtoggle svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.8;
    stroke-linecap:round;stroke-linejoin:round}
  .rail-mbg{position:fixed;inset:0;z-index:84;background:rgba(3,8,20,.45);
    opacity:0;pointer-events:none;transition:opacity .2s}
  .rail-mbg.on{opacity:1;pointer-events:auto}
}
@media (min-width:641px){.rail-mtoggle,.rail-mbg{display:none}}
@media (prefers-reduced-motion:reduce){.rail,.rail-mbg{transition:none}}
