﻿/* =============================================================================
   rail-modules.css — RAIL vertical à gauche des pages HORS dashboard
   -----------------------------------------------------------------------------
   Rail ÉTROIT (icônes seules, 64px), PLEINE HAUTEUR sous le header du haut. Au survol
   d'une icône, un TIROIR (.rail-flyout) glisse à sa droite — PAR-DESSUS le contenu —
   avec le libellé (même fond → on dirait que le pavé de l'icône s'allonge). Le contenu
   garde toute sa largeur (rail seulement 64px). Le tiroir est rendu sur <body>
   (position:fixed, positionné en JS, cf. <script> de _RailModules) → il échappe au
   clipping du rail scrollable. `pointer-events:none` → le clic passe au lien.

   Fond marine repris du thème (tokens --tg-sidebar-*, définis dans
   assets/src/scss/_theme.default.scss). Le shell legacy est en position:fixed
   (#header, #content, .titre-layout-page, #foot — assets/css/socle/shell.css) → on
   décale chaque élément fixe par `left`/`width`. Scopé à body.has-rail-modules.
   ============================================================================= */

.rail-modules {
    /* Palette alignée sur la sidebar du dashboard (aucune couleur en dur ici). */
    /* Fond = couleur du HEADER personnalisée par l'abonné (/Preferences → --tg-bandeau-fond),
       repli sur le marine de la charte. La perso du header pilote ainsi le rail. */
    --rail-bg: var(--tg-bandeau-fond, var(--tg-sidebar-bg));
    /* Texte/icônes du rail = couleur de texte perso abonné (--tg-bandeau-texte, /Preferences),
       REPLI sur le thème `--tg-sidebar-text` (= #CBD5E1, slate-300). → change avec Preferences ;
       #CBD5E1 par défaut. Le nom + l'avatar de l'utilisateur en bas font EXCEPTION (fixés clairs,
       cf. .rail-modules-user + flyout `.is-user`). */
    --rail-icon: var(--tg-bandeau-texte, var(--tg-sidebar-text));
    --rail-icon-hover: var(--tg-bandeau-texte, var(--tg-sidebar-text-hover));
    --rail-muted: var(--tg-sidebar-muted);
    --rail-hover-bg: var(--tg-sidebar-hover-bg);
    --rail-actif-bg: var(--tg-sidebar-active-bg);
    --rail-separateur: var(--tg-sidebar-divider);
    --rail-w: 64px;         /* largeur ÉTROITE (icônes seules) */
    --rail-header-h: 60px;  /* hauteur RÉELLE du header (#header/#topBlock = 60px) → pas d'empiètement */

    /* Pleine hauteur SOUS le header (pas coupé). */
    position: fixed;
    top: var(--rail-header-h);
    bottom: 0;
    left: 0;
    width: var(--rail-w);
    z-index: 1031; /* au-dessus de #header (z-index:999, socle/shell.css) */

    display: flex;
    flex-direction: column;
    align-items: stretch;
    padding-bottom: .5rem;

    background: var(--rail-bg);
    color: var(--rail-icon);
    overflow: hidden;
    /* Séparation rail / contenu, en DEUX couches : le filet clair de 1 px (le rail est sombre, il
       se détache ainsi de son propre fond) DOUBLÉ d’une ombre portée vers la droite, pour que le
       rail se lise comme une couche posée au-dessus du contenu — même relief que l’ombre basse du
       bloc d’en-tête (`--tg-chrome-ombre-bas`, assets/css/header-pages.css), ici tournée d’un quart
       de tour. Le rail étant au-dessus de `#content` (z-index 1031 contre `auto`), elle se voit.
       🛑 L’ombre doit sortir À DROITE SEULEMENT : le flou d’une ombre déborde de TOUS les côtés
       (il n’est pas orienté par le décalage), donc un simple `2px 0 6px` bavait aussi par le HAUT,
       et comme le rail passe au-dessus du header (1031 contre 999) la bavure se voyait en salissure
       sous le bandeau. Le quatrième nombre est un ÉTALEMENT NÉGATIF : il rétrécit l’ombre de 6 px
       sur les quatre côtés — elle rentre donc de 6 px sous le haut et le bas du rail, où le flou
       (± 3 px) ne la fait plus ressortir — et le décalage horizontal est augmenté d’autant (2 + 6)
       pour que le bord droit retombe exactement où il était. Rendu : une bande de ~5 px à droite,
       le miroir exact de l’ombre basse du bloc d’en-tête, et rien ailleurs.
       ⚠️ Ne pas « simplifier » en retirant l’étalement : le décalage seul ne borne rien.
       💡 `overflow: hidden` ci-dessus ne la rogne pas : il ne borne que les DESCENDANTS, jamais
       l’ombre propre de l’élément. */
    box-shadow: 1px 0 0 rgba(255, 255, 255, .05), 8px 0 6px -6px rgba(0, 0, 0, .08);
}

/* ---- Zone FIGÉE en tête (Dashboard) : hors du flux défilant, donc toujours visible. ----
   `flex: 0 0 auto` — même principe que .rail-modules-bottom, qui est figée en bas. */
.rail-modules-tete {
    flex: 0 0 auto;
}

/* ---- Zone HAUTE défilante (Dashboard + modules) : seule à scroller si la liste est longue. ---- */
.rail-modules-top {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    /* Scrollbar MASQUÉE (défilement molette/trackpad) : aucune gouttière réservée → pas de
       « padding » à droite et largeur du rail CONSTANTE (scroll visible ou non). */
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.rail-modules-top::-webkit-scrollbar {
    width: 0;
    height: 0;
    display: none;
}

/* ---- Zone BASSE figée (Contact / Paramètres / Déconnexion), séparée par un liseret. ----
   `margin-top` : creuse un écart AVANT le séparateur. Comme la zone haute est en `flex:1 1 auto`
   (elle occupe tout l'espace restant), cette marge réduit d'autant la hauteur de la liste des
   modules → la liste ne touche plus le bloc bas, on a une vraie respiration liste / icônes+photo. */
.rail-modules-bottom {
    flex: 0 0 auto;
    padding-top: .5rem;
    border-top: 2px solid var(--rail-separateur);
}

/* La scrollbar de la zone haute est masquée (aucune gouttière) → plus besoin de compenser
   un décalage sur les icônes du bas : elles s'alignent naturellement sur celles du haut. */

.rail-modules-menu {
    margin: 0;
    padding: 0;
    list-style: none;
}

.rail-modules-menu li {
    margin: 0;
}

/* Icône du Dashboard : toujours en couleur « main » du thème (uniquement l'icône). */
#rail-modules .rail-dashboard svg,
#rail-modules .rail-dashboard [data-lucide] {
    color: var(--bs-main);
    transition: transform .15s ease;
}

/* Dashboard au survol : fond BLANC (icône) — on bat le hover marine générique (spécificité
   `.rail-modules-menu a.rail-dashboard`) — + léger ZOOM de l'icône. */
#rail-modules .rail-modules-menu a.rail-dashboard:hover,
#rail-modules .rail-modules-menu a.rail-dashboard.tiroir-actif {
    background: #fff;
}

#rail-modules .rail-modules-menu a.rail-dashboard:hover svg,
#rail-modules .rail-modules-menu a.rail-dashboard:hover [data-lucide],
#rail-modules .rail-modules-menu a.rail-dashboard.tiroir-actif svg,
#rail-modules .rail-modules-menu a.rail-dashboard.tiroir-actif [data-lucide] {
    color: var(--bs-main);
    transform: scale(1.18);
}

/* Titre de groupe dans le rail (icônes seules) : nom du groupe encadré par deux liserets
   (au-dessus et en-dessous). Petit texte, centré, qui tient dans la largeur du rail (peut passer
   sur plusieurs lignes plutôt que déborder). */
.rail-modules-groupe-titre {
    margin-top: .35rem;
    padding: .3rem 0; /* pas de padding horizontal : le texte occupe toute la largeur du rail */
    width: 100%;
    box-sizing: border-box;
    border-top: 1px solid var(--rail-separateur);
    border-bottom: 1px solid var(--rail-separateur);
    font-size: 8.5px;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: uppercase;
    text-align: center;
    color: var(--rail-muted);
    overflow-wrap: anywhere;
    hyphens: auto;
}

/* Titre de groupe CLIQUABLE : replie/déplie les modules du groupe (même geste que la barre latérale
   du dashboard). Le rail est trop étroit pour un chevron → l'état est marqué par la couleur. */
.rail-modules-groupe-titre.rail-groupe-toggle {
    cursor: pointer;
    user-select: none;
    transition: color .12s ease;
}

.rail-modules-groupe-titre.rail-groupe-toggle:hover,
.rail-modules-groupe-titre.rail-groupe-toggle:focus-visible {
    color: var(--rail-icon);
}

/* Groupe replié : les modules sont masqués SAUF les ÉPINGLÉS (toujours visibles, cf. Modules-Epingles).
   Animation calquée sur la barre latérale du dashboard (`.dashboard-sidebar-groupe-modules.est-deplie`) :
   glissement max-height + fondu. ⚠️ On anime chaque <li> et NON la liste : les épinglés vivent dans la
   MÊME liste et doivent rester visibles (le dashboard, lui, les rend hors du conteneur repliable).
   `display:none` ne se transitionne pas → max-height/opacity. La borne haute = la hauteur d'un item
   (`.rail-modules-menu a { height: 44px }`), à garder synchronisée avec elle. */
.rail-modules-menu[data-groupe-modules] > li {
    overflow: hidden;
    max-height: 44px;
    opacity: 1;
    transition: max-height .28s ease, opacity .2s ease;
}

/* Restent visibles quand le groupe est replié : les ÉPINGLÉS **et** le module de la page COURANTE
   (`> a.active`, posé au rendu par RailItem) — on ne masque jamais l'écran où l'on se trouve. */
.rail-modules-menu.est-replie > li:not(.est-epingle):not(:has(> a.active)) {
    max-height: 0;
    opacity: 0;
}

/* Item = icône CENTRÉE dans le rail étroit. Le libellé n'est pas dans le rail : il s'affiche
   au survol dans le tiroir .rail-flyout. La barre d'accent de l'item actif est portée par le
   border-left ; on réserve un border-right transparent SYMÉTRIQUE pour que l'icône reste
   parfaitement centrée (sinon le seul border-left la décale de 3px → besoin d'un margin négatif). */
.rail-modules-menu a {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 44px;
    border-left: 3px solid transparent;
    border-right: 3px solid transparent;
    color: var(--rail-icon);
    text-decoration: none;
    transition: background-color .12s ease, color .12s ease;
}

/* Lucide rend un <svg> héritant de currentColor ; taille 18px (comme .dashboard-sidebar-menu a svg).
   ⚠️ Cibler `svg` ET `[data-lucide]` : Lucide remplace le <i> par un <svg> et lui RETIRE
   `data-lucide` — une règle qui ne viserait que l'attribut serait morte dès l'icône rendue.
   La transition sert le survol (zoom léger, plus bas) ; elle rend aussi FLUIDE le zoom du
   Dashboard, qui déclarait un `scale(1.18)` sans transition, donc sautait d'un coup. */
.rail-modules-menu a svg,
.rail-modules-menu a [data-lucide] {
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
    transition: transform .16s ease;
}

/* Libellé inline MASQUÉ : il s'affiche au survol dans le tiroir .rail-flyout (le flyout lit
   le libellé via `aria-label`). Le <span> reste dans le markup (cohérence) mais caché. */
.rail-modules-label {
    display: none;
}

/* #header impose `color:#fff` via #topBlock a ; on verrouille la palette du rail (spécificité ID). */
#rail-modules .rail-modules-menu a {
    color: var(--rail-icon);
}

/* Survol : MÊME fond que le tiroir .rail-flyout (effet « le pavé de l'icône s'allonge »).
   ⚠️ On DOIT utiliser la formule EXACTE du flyout (color-mix sur --tg-bandeau-fond) et non
   --rail-hover-bg : le flyout est rendu sur <body> et ne voit pas --rail-hover-bg (défini sur
   .rail-modules), il calcule donc sa couleur depuis les tokens :root → les deux doivent partager
   la même expression, sinon le fond de l'icône et celui de l'étiquette diffèrent. */
    #rail-modules .rail-modules-menu a:hover,
    #rail-modules .rail-modules-menu a.tiroir-actif {
        background: var(--rail-hover-bg);
        color: var(--rail-icon-hover);
    }

    /* Survol d'un MODULE : l'icône grandit légèrement, le temps que le fond change (.12s) et que le
       tiroir du libellé glisse (.rail-flyout, .16s) — même durée, les trois effets vont ensemble.
       Sans lui, seul le fond bougeait : le survol se remarquait à peine sur un rail d'icônes.
       🛑 Les trois liens NON-MODULES sont exclus, chacun ayant déjà son propre traitement, et deux
       d'entre eux étant le fruit d'un arbitrage à ne pas défaire : Dashboard (fond blanc + zoom 1.18),
       Paramètres (couleur seule — la rotation de l'engrenage a été RETIRÉE le 28/07/2026, rendu jugé
       instable) et Déconnexion (rouge + `rail-power-pulse`, qui pilote déjà `transform`). */
    #rail-modules .rail-modules-menu a:not(.rail-dashboard):not(.rail-parametres):not(.confirmdisconnect):hover svg,
    #rail-modules .rail-modules-menu a:not(.rail-dashboard):not(.rail-parametres):not(.confirmdisconnect):hover [data-lucide] {
        transform: scale(1.15);
    }

    /* Paramètres : pas de libellé au survol (classe rail-no-flyout, géré en JS), icône en couleur
       « main » du thème. PAS d'animation (contrairement à Déconnexion) : une rotation de
       l'engrenage a été tentée puis RETIRÉE le 2026-07-28 (rendu instable à l'écran). */
    #rail-modules .rail-modules-menu a.rail-parametres:hover {
        color: var(--bs-main);
    }

    /* Déconnexion : pas de libellé au survol (classe rail-no-flyout, géré en JS). L'icône « power »
       passe en ROUGE (danger) et joue un petit « pulse » (scale + léger pivot) au survol. */
    #rail-modules .rail-modules-menu a.confirmdisconnect:hover {
        color: var(--bs-danger, #dc3545);
    }

    #rail-modules .rail-modules-menu a.confirmdisconnect svg,
    #rail-modules .rail-modules-menu a.confirmdisconnect [data-lucide] {
        transition: transform .2s ease;
    }

        #rail-modules .rail-modules-menu a.confirmdisconnect:hover svg,
        #rail-modules .rail-modules-menu a.confirmdisconnect:hover [data-lucide] {
            animation: rail-power-pulse .55s ease;
        }

@keyframes rail-power-pulse {
    0% { transform: scale(1) rotate(0); }
    40% { transform: scale(1.22) rotate(-10deg); }
    70% { transform: scale(1.1) rotate(6deg); }
    100% { transform: scale(1) rotate(0); }
}

    /* Module courant : teinte orange + BARRE D'ACCENT gauche (3px) + icône orange. */
    #rail-modules .rail-modules-menu a.active {
        background: color-mix(in srgb, var(--rail-actif-bg) 16%, transparent);
        border-left-color: var(--rail-actif-bg);
        color: var(--rail-actif-bg);
    }

        #rail-modules .rail-modules-menu a.active:hover,
        #rail-modules .rail-modules-menu a.active.tiroir-actif {
            background: color-mix(in srgb, var(--rail-actif-bg) 24%, transparent);
        }

/* « Voir plus de modules » (14ᵉ item) : le chevron pivote à 180° quand la liste est dépliée. */
#rail-modules .rail-modules-plus-toggle svg,
#rail-modules .rail-modules-plus-toggle [data-lucide] {
    transition: transform .15s ease;
}

#rail-modules .rail-modules-plus-toggle.est-ouvert svg,
#rail-modules .rail-modules-plus-toggle.est-ouvert [data-lucide] {
    transform: rotate(180deg);
}

/* ---- Avatar utilisateur (bas) : pastille centrée (nom dans le tiroir au survol). ---- */
.rail-modules-user {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: .5rem 0 .25rem;
    /* Centré sur le RAIL ENTIER (64px) : la zone basse ne réserve plus de gouttière (seule la
       liste des 3 icônes la réserve via padding-right), donc l'avatar se centre naturellement. */
}

.rail-modules-user img,
.rail-modules-user .avatar-initiales {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 50%;
}

.rail-modules-user img {
    object-fit: cover;
    background: rgba(255, 255, 255, .1);
}

/* Repli initiales (pas de photo) : rond plein, initiales centrées. */
.rail-modules-user .avatar-initiales {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Pastille initiales : fond couleur « main » du thème, texte blanc (indépendant de la perso abonné). */
    background: var(--bs-main);
    color: #fff;
    line-height: 1;
    text-transform: uppercase;
}

/* ---- Numéro de version applicative (tout en bas, sous l’avatar) ----
   Rendu par Parts/_VersionApplicative.cshtml, comme en bas de la barre latérale du dashboard
   (dashboard-sidebar.css, même taille). Il ne sert qu’à identifier la livraison sur une capture
   d’écran envoyée au support, d’où sa petite taille ; la page de connexion garde le sien à .75rem
   (login-split.css).
   Couleur des ICÔNES du rail, et non la teinte atténuée des titres de groupe : à 8 px, sur une
   capture compressée, le gris atténué ne se lit plus. La couleur suit ainsi la paire fond / texte
   personnalisée par l’abonné, seule paire dont le contraste est garanti.
   Centré sur toute la largeur du rail, et autorisé à passer à la ligne plutôt qu’à déborder :
   un numéro de build (v20260925.2) remplit presque les 64 px, et ne tient pas toujours dans les
   52 px du rail mobile. */
.rail-modules .tg-version-applicative {
    padding: .25rem .125rem 0;
    font-size: .5rem;
    line-height: 1.2;
    text-align: center;
    color: var(--rail-icon);
    overflow-wrap: anywhere;
}

/* Fonds OPAQUES partagés « icône survolée ↔ tiroir » — définis sur body.has-rail-modules car le
   flyout est rendu sur <body> (hors .rail-modules → ne verrait pas une variable scopée au rail).
   OPAQUES : le flyout flotte AU-DESSUS du contenu, il doit avoir exactement la même couleur que
   l'icône (posée, elle, sur le fond du rail) — un tint semi-transparent (--tg-sidebar-hover-bg)
   composité sur des fonds différents ne coïnciderait pas. rgb(2 9 64) = navy du thème (= couleur
   de --tg-sidebar-hover-bg sans son alpha .06). */
body.has-rail-modules {
    --rail-flyout-bg: color-mix(in srgb, rgb(2 9 64) 6%, var(--tg-bandeau-fond, var(--tg-sidebar-bg)));
    --rail-flyout-bg-active: color-mix(in srgb, var(--tg-bandeau-fond, var(--tg-sidebar-bg)), var(--tg-sidebar-active-bg) 24%);
}

/* ---- TIROIR (drawer) d'expansion au survol ----
   Panneau collé À DROITE de l'icône survolée (libellé), MÊME fond que l'icône au survol → on
   dirait que le pavé s'allonge. Rendu sur <body> (position:fixed, positionné en JS) → échappe
   au clipping du rail scrollable. Glisse + apparaît (effet tiroir). `pointer-events:none` → le
   clic passe au lien (la souris reste sur l'icône). */
.rail-flyout {
    position: fixed;
    /* Au-dessus du rail (1031) ET du fil d’Ariane (1032, assets/css/header-pages.css) : le tiroir
       se déploie à partir de l’icône survolée, donc il empiète sur la bande du fil d’Ariane quand
       c’est la PREMIÈRE icône du rail — la barre lui trancherait le haut si elle passait devant. */
    z-index: 1033;
    display: flex;
    align-items: center;
    padding: 0 1rem 0 .35rem;
    background: var(--rail-flyout-bg); /* = fond de l'icône au survol (même variable) */
    color: var(--tg-bandeau-texte, var(--tg-sidebar-text)); /* perso abonné, repli #CBD5E1 (sauf nom utilisateur, cf. .is-user) */
    /* Même taille que les textes du header du haut (menu modules = hérite 1rem) — pas .875rem. */
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
    border-radius: 0 8px 8px 0;
    box-shadow: 6px 0 18px rgba(0, 0, 0, .3);
    /* Découpe l'ombre AU RAS du bord GAUCHE (0) : sinon le flou (18px) déborde ~12px sur la
       moitié droite de l'icône survolée → halo sombre au raccord = illusion de couleur différente.
       Ombre conservée en haut/droite/bas (effet tiroir) mais nulle côté icône (raccord net). */
    clip-path: inset(-30px -30px -30px 0);
    /* Le tiroir est CLIQUABLE : le libellé relaie le clic vers l'item survolé (cf. JS de
       _RailModules). Il reste collé à l'icône → la souris ne « quitte » pas vraiment l'item. */
    pointer-events: auto;
    cursor: pointer;
    visibility: hidden;
    opacity: 0;
    transform: translateX(-10px); /* glisse depuis l'icône (effet tiroir) */
    transition: opacity .16s ease, transform .16s ease, visibility .16s;
}

.rail-flyout.est-ouvert {
    visibility: visible;
    opacity: 1;
    transform: translateX(0);
}

/* Module actif (page courante) : tiroir raccord avec l'item actif survolé (24% orange),
   TEXTE en couleur « main » du thème (--bs-main). */
.rail-flyout.is-active {
    background: var(--rail-flyout-bg-active); /* = fond de l'item actif survolé (même variable) */
    color: var(--bs-main);
}

/* Tiroir du Dashboard : fond BLANC (raccord avec le fond blanc de l'icône au survol) + texte main. */
.rail-flyout.is-dashboard {
    background: #fff;
    color: var(--bs-main);
}

/* Tiroir du NOM utilisateur (avatar bas) : EXCEPTION → fond BLANC (le pavé de l'avatar n'a pas
   de fond de survol coloré comme les icônes) + texte sombre pour rester lisible. Posé par le JS
   (classe is-user) au survol de .rail-modules-user. */
    .rail-flyout.is-user {
        background: #fff;
        color: var(--tg-sidebar-text-strong);
    }

/* =============================================================================
   Décalage du shell fixe vers la droite (largeur ÉTROITE du rail seulement ; le tiroir
   flotte par-dessus le contenu, il ne le repousse pas). Scopé à body.has-rail-modules.
   ============================================================================= */
.has-rail-modules {
    --rail-w: 64px;
}

/* Header du haut : PLEINE LARGEUR (le rail est sous lui, à gauche). */
.has-rail-modules #header {
    left: 0;
    width: 100%;
}

/* Header de la MÊME couleur que le rail / la sidebar (= couleur du bandeau perso abonné,
   --tg-bandeau-fond, repli marine) → chrome cohérente (header + rail = un seul bloc). #topBlock
   pose déjà son fond depuis teogest-fonctionnel.css (var --tg-bandeau-fond) ; on garde la surcharge
   scopée aux pages à rail (spécificité 1,1,0) pour rester explicite. */
.has-rail-modules #topBlock,
.has-rail-modules #header {
    background: var(--tg-bandeau-fond, var(--tg-sidebar-bg));
}

/* Fil d'Ariane + contenu + barre de boutons : bornés par le rail à GAUCHE et le BORD DROIT de la
   fenêtre. Les trois partagent exactement la même géométrie horizontale — c'est le contrat : aucun
   coin découvert en bas-droite pour #foot, le trait (border-bottom) du fil d'Ariane qui file tout à
   droite, et un #content dont le bord droit s'aligne enfin sur les deux autres.

   🛑 Ne PAS revenir à `width: calc(97% - var(--rail-w))`. Cette réserve de 3 % (vestige de l'ancienne
   `.helperDiv` flottante à droite) est PROPORTIONNELLE au viewport, alors que la respiration du
   contenu est en pixels : le vide à droite valait `0,03 × largeur − marge`, soit 26 px à 1366 mais
   62 px à 2560, pendant que la gauche restait fixe. Aucune valeur de marge ne peut équilibrer une
   largeur en pourcentage (il faudrait `marge = 1,5 % de la largeur`) — d'où des écrans qui
   paraissaient toujours décadrés, et une scrollbar de #content (interne, sur son bord droit)
   décollée du bord de la fenêtre de plusieurs dizaines de pixels.
   La respiration horizontale est désormais un PADDING porté par `#content` lui-même
   (`--tg-content-ecart-x`, assets/css/socle/shell.css) : interne au conteneur de défilement, donc la
   scrollbar reste collée au bord et l'écart gauche/droite est constant quelle que soit la largeur
   d'écran. Corollaire : plus besoin de recentrer les index à la main (l'ancienne règle
   `#content:has(> .tg-index-wrap) { right:0; margin-inline:auto }` a été retirée, sans largeur
   excédentaire elle n'aurait plus d'effet). */
.has-rail-modules .titre-layout-page,
.has-rail-modules #content,
.has-rail-modules #foot {
    left: var(--rail-w);
    right: 0;
    width: auto;
}

/* Repli mobile : rail un peu plus étroit. */
@media (max-width: 767px) {
    .rail-modules {
        --rail-w: 52px;
    }

    .has-rail-modules {
        --rail-w: 52px;
    }
}
