/* ========================================================================== */
    /* 🎨 INTERRUPTEURS SLIDE ON/OFF                                              */
    /* La définition complète (.switch / .switch .slider / dégradé activé) vit    */
    /* plus bas dans ce fichier (section "INTERRUPTEURS PERSONNALISÉS"). L'ancien  */
    /* bloc ici était un DOUBLON non scopé (`.slider`, `input:checked + .slider`  */
    /* sans préfixe `.switch`) : sa règle `input:checked + .slider:before { background-color:#111; }` */
    /* n'était concurrencée par AUCUNE règle plus bas (qui ne fixe que le transform */
    /* du bouton, pas sa couleur) et gagnait donc systématiquement -> c'est elle   */
    /* qui rendait le petit bouton du switch NOIR une fois activé, dans les deux   */
    /* thèmes. Supprimé pour ne garder qu'une seule définition, sans conflit.      */
    /* ========================================================================== */
    /* 🎨 ACCORDÉONS PERSONNALISÉS FLUIDES                                        */
    /* ========================================================================== */
    .custom-accordion {
      background: var(--card-bg);
      border: 1px solid var(--border-color);
      border-radius: 10px;
      overflow: hidden;
      margin-top: 12px;
      width: 100%;
      box-sizing: border-box;
      box-shadow: 0 4px 10px rgba(0,0,0,0.1);
    }

    .accordion-trigger {
      cursor: pointer;
      padding: 16px 18px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      user-select: none;
      background: var(--card-bg);
      transition: background 0.2s ease;
    }

    .accordion-trigger:hover {
      background: rgba(255, 255, 255, 0.04);
    }

    .acc-chevron {
      font-size: 11px;
      transition: transform 0.6s cubic-bezier(0.25, 1, 0.5, 1);
      color: var(--text-sub);
    }

    .custom-accordion.active .acc-chevron {
      transform: rotate(180deg);
      color: var(--gold-bright);
    }

    .accordion-panel {
      max-height: 0;
      overflow: hidden;
      transition: max-height 0.6s cubic-bezier(0.25, 1, 0.5, 1);
      background: var(--card-sub-bg);
    }

    .accordion-inner {
      padding: 15px;
    }

    /* ========================================================================== */
    /* 🐺 WOLF-HQ — VARIABLES DU THÈME GRAPHITE SOMBRE (PAR DÉFAUT)               */
    /* Gris neutres (pas de teinte bleutée) + orange loup en accent unique.       */
    /* ========================================================================== */
    :root {
      --bg-dark: #131417;
      --card-bg: #1c1d21;
      --card-sub-bg: #232428;
      --input-bg: #1f2024;
      --border-color: #2c2d31;
      --input-border: #3a3b40;
      --gold: #e8631c;
      --gold-bright: #ff7a29;
      --text: #f5f5f4;
      --text-sub: #a1a1aa;
      --nav-bg: #16171a;
      --header-bg: linear-gradient(180deg, #1c1d21 0%, #131417 100%);
      --accent-red: #c62828;
      --accent-orange: #ef6c00;
      --accent-green: #2e7d32;
      --accent-blue: #1565c0;
      --accent-purple: #6a1b9a;
      --accent-gold: #e8631c;
      /* Correctif du 28/08 (Michel : "l'encadré de la semaine de train est orange et jaune") :
         équivalent RGB de --accent-gold, pour construire des fonds translucides (rgba) qui
         correspondent VRAIMENT à --accent-gold au lieu du rgba(255,122,41,...) codé en dur utilisé
         jusqu'ici par endroits — qui correspond en réalité à --gold-bright (une teinte plus claire/
         jaune), d'où le mélange visible de deux oranges différents sur l'encadré de la semaine en
         cours (bordure en accent-gold + fonds internes en gold-bright). */
      --accent-gold-rgb: 232, 99, 28;
      /* 🩹 28/08/2026 (retour de Michel : bulles mail/stats de l'avatar Profil "noir sur fond
         noir") — cause réelle : le thème graphite actif (assets/css/theme-graphite.css) redéfinit
         --card-bg/--card-sub-bg en rgba TRANSLUCIDES (effet verre dépoli), très bien pour des
         cartes posées sur le fond de la page mais catastrophique pour un petit badge posé sur une
         PHOTO — la photo transparaissait à travers le badge. --badge-opaque-bg n'est volontairement
         PAS redéfini par theme-graphite.css : il reste un aplat opaque garanti dans tous les cas
         (voir .mailbox-icon-btn/.stats-icon-btn plus bas). */
      --badge-opaque-bg: #232428;
      --sidebar-bg: #17181b;
      --sidebar-bg-active: rgba(255,122,41,0.12);
      --topbar-bg: rgba(19,20,23,0.92);
      /* Dégradé du toggle "activé" (.switch) : orange plein (pas de dégradé), comme en thème
         clair ci-dessous — les deux bornes du gradient pointent vers la même couleur, donc le
         rendu est un aplat uni. Avant, le thème sombre pointait vers --accent-blue ici, ce qui
         rendait tous les interrupteurs BLEUS une fois activés au lieu d'orange (signalé par
         Michel) : mis en cohérence avec l'accent unique orange du reste du site. */
      --switch-on-debut: var(--gold-bright);
      --switch-on-fin: var(--gold-bright);
      /* 🔷 Accent cyan électrique — Centre de Commandement Analytique (Classements avancés +
         suivi de puissance) : réservé à ce qui doit ressortir du reste de l'appli (ex: "MOI"
         dans un classement), pour ne pas diluer l'accent orange unique utilisé partout ailleurs. */
      --cyan: #0891b2;
    }

    /* ========================================================================== */
    /* ☀️ WOLF-HQ — VARIABLES DU THÈME GRAPHITE CLAIR (gris neutre + orange loup) */
    /* ========================================================================== */
    body.light-theme {
      --bg-dark: #e4e4e7;
      --card-bg: #fafafa;
      --card-sub-bg: #eeeeef;
      --input-bg: #f4f4f5;
      --border-color: #d4d4d8;
      --input-border: #a1a1aa;
      --gold: #ea580c;
      --gold-bright: #f97316;
      --accent-blue: #475569;
      --accent-gold: #ea580c;
      /* Voir commentaire du même nom dans le thème sombre ci-dessus. */
      --accent-gold-rgb: 234, 88, 12;
      --badge-opaque-bg: #eeeeef;
      --sidebar-bg: #ffffff;
      --sidebar-bg-active: rgba(234,88,12,0.10);
      --topbar-bg: rgba(255,255,255,0.9);
      /* Toggle "activé" en orange PLEIN (pas de dégradé) en thème clair, comme demandé — les deux
         bornes du gradient pointent vers la même couleur, donc le rendu est un aplat uni. Avant,
         la 2e borne réutilisait --accent-blue (gris-ardoise sombre ici, pensé pour du texte/des
         bordures) ce qui donnait un dégradé orange -> presque noir sur le switch une fois activé. */
      --switch-on-debut: var(--gold-bright);
      --switch-on-fin: var(--gold-bright);
      --cyan: #06b6d4;
      --text: #18181b;
      --text-sub: #71717a;
      --nav-bg: #ffffff;
      /* Le header GARDE un fond sombre même en thème clair : il contient le visuel loup à droite,
         et un fond clair y créait une cassure nette (visible malgré le dégradé) là où l'image
         rejoint le fond de la bannière. */
      --header-bg: linear-gradient(180deg, #1c1d21 0%, #131417 100%);
      --choix-actif-bg: rgba(234, 88, 12, 0.10);
    }

    /* Le header restant sombre en thème clair, son texte et ses boutons ronds gardent leur
       habillage clair-sur-sombre d'origine (au lieu de var(--text)/var(--card-sub-bg) qui
       deviendraient sombres et invisibles sur ce fond resté sombre). */
    body.light-theme .header-date-text { color: #e2e8f0; }
    body.light-theme .header-icon-btn {
      background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.18); color: #fff;
    }
    body.light-theme .header-icon-btn:hover { border-color: rgba(255,255,255,0.35); }

    /* Fiches membres (page Membres) : la palette --mb-* pointe désormais directement sur les
       variables du thème (voir #pageMembresRoot plus bas), donc plus besoin d'une surcharge
       séparée ici pour le thème clair — elle suit automatiquement. */

    /* Boutons "principaux" (.btn-gold) : orange en thème clair, au lieu du jaune/or fixe qui
       ne s'accordait pas du tout avec un fond blanc. Le thème sombre garde son propre style
       (voir theme-graphite.css, dégradé orange loup avec halo). */
    body.light-theme .btn-gold {
      background: linear-gradient(135deg, #ea580c 0%, #fb923c 100%);
      color: #ffffff;
    }
    body.light-theme .btn-gold:hover {
      box-shadow: 0 4px 15px rgba(234, 88, 12, 0.3);
    }

    body {
      margin: 0; padding: 0 0 75px 0;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
      background-color: var(--bg-dark); color: var(--text);
      -webkit-user-select: none; user-select: none;
      transition: background-color 0.3s ease, color 0.3s ease;
    }

    .header {
      background: var(--header-bg);
      padding: 16px 15px; border-bottom: 2px solid var(--gold);
      /* Fixe en haut de l'écran pendant le défilement (demande explicite de Michel). Le correctif
         #5 était passé à "relative" pour stopper un bug où la bannière "remontait" au scroll — si
         ce bug revient avec "sticky", il faudra le diagnostiquer avec une capture précise plutôt
         que de sacrifier à nouveau l'effet fixe. */
      position: sticky; top: 0; z-index: 100; box-shadow: 0 4px 15px rgba(0,0,0,0.15);
      overflow: hidden;
    }

    /* 🐺 Portrait loup du header (wolf-hero.jpg) : le fondu sombre est déjà "cuit" dans l'image
       elle-même (dégradé naturel de gauche à droite). Sur mobile, l'image couvre TOUTE la largeur
       du bandeau (au lieu d'être cantonnée à une bande étroite sur la droite) pour que ce dégradé
       naturel se déroule sur toute la largeur au lieu d'être tronqué avant même d'apparaître
       (signalé par Michel). Aucun masque CSS nécessaire ici : la zone sombre de l'image assure
       elle-même le raccord avec --header-bg. */
    .header-mascotte {
      position: absolute; top: 0; left: 0; right: 0; height: 100%; width: 100%;
      object-fit: cover; object-position: 80% center;
      opacity: 0.96; pointer-events: none; z-index: 0;
    }
    @media (min-width: 960px) {
      /* Desktop : mise en page inchangée (image cadrée à droite, largeur fixe), avec un léger
         masque résiduel sur son bord gauche pour lisser l'écart de teinte avec --header-bg. */
      .header-mascotte {
        left: auto; right: 0; width: 620px; object-position: 68% center;
        -webkit-mask-image: linear-gradient(to right, transparent 0%, black 12%);
        mask-image: linear-gradient(to right, transparent 0%, black 12%);
      }
    }

    .header-container {
      max-width: 480px; margin: 0 auto;
      display: flex; flex-direction: column; gap: 4px;
      position: relative; z-index: 1;
    }

    .header-row-top { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
    .header-row-bottom { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
    /* Les deux lignes de date (texte principal + semaine calendaire) empilées verticalement,
       chacune tronquée indépendamment plutôt qu'une seule ligne trop longue qui déborde sur
       l'illustration du header (surtout sur petit écran). */
    /* flex: 0 1 auto (PAS 1 1 auto) : le bloc texte ne doit PAS s'étirer pour remplir toute la
       largeur de la ligne, sinon le badge PUSH/ÉCO suivant se retrouve plaqué tout à droite au
       lieu de rester juste à côté du texte "Semaine N". Il peut toujours rétrécir (flex-shrink:1)
       pour tronquer sur petit écran si le texte + le badge dépassent la largeur disponible. */
    .header-date-lines { display: flex; flex-direction: column; min-width: 0; flex: 0 1 auto; }
    .header-date-text {
      font-size: 11px; color: var(--text-sub); font-weight: 500;
      min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .header-date-cal {
      font-size: 10px; color: var(--text-sub); opacity: 0.75; font-weight: 500;
      min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .header-mode-badge {
      color: #0a1420; font-weight: 800; font-size: 10px; letter-spacing: 0.5px;
      padding: 2px 8px; border-radius: 20px; white-space: nowrap; flex-shrink: 0;
    }

    /* Rangée des boutons ronds (Thème / Langue / Discussions), sous la date — remplace les
       anciens menus déroulants "Préférences" du profil et de la page d'inscription.
       Couleurs liées aux variables de thème (jamais de blanc/jaune fixe) pour rester visibles
       et cohérentes dans les deux thèmes. */
    .header-row-icons { display: flex; justify-content: flex-start; gap: 10px; margin-top: 10px; }
    .header-icon-btn {
      width: 34px; height: 34px; border-radius: 50%; background: var(--card-sub-bg);
      border: 1px solid var(--border-color); color: var(--text); display: flex; align-items: center;
      justify-content: center; font-size: 16px; cursor: pointer; padding: 0; transition: border-color 0.12s ease;
    }
    .header-icon-btn:hover { border-color: var(--gold); }

    /* Liste d'options dans une modale (choix thème / choix langue) */
    .choix-liste { display: flex; flex-direction: column; gap: 8px; max-height: 60vh; overflow-y: auto; }

    /* Case à cocher / radio + libellé, correctement alignés (corrige le décalage observé dans les
       composeurs de message Admin/Super Admin : la case et le texte n'étaient pas alignés à cause
       du "stretch" par défaut du conteneur flex parent .row-flex, qui n'avait pas align-items:center). */
    .check-inline-label {
      display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: normal;
      cursor: pointer; user-select: none; flex: none;
    }
    .check-inline-label input[type="checkbox"],
    .check-inline-label input[type="radio"] {
      width: 16px; height: 16px; margin: 0; flex-shrink: 0; cursor: pointer; accent-color: var(--gold-bright);
    }
    .choix-option {
      display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-radius: 10px;
      background: var(--card-sub-bg); border: 1px solid var(--border-color); color: var(--text);
      font-size: 14px; font-weight: 600; cursor: pointer; text-align: left; width: 100%;
      transition: border-color 0.12s ease, background 0.12s ease;
    }
    .choix-option:hover { border-color: var(--gold); }
    .choix-option.actif { border-color: var(--gold-bright); background: var(--choix-actif-bg, rgba(255,122,41,0.12)); color: var(--gold-bright); }

    /* 💎 TITRE "CRISTAL ORANGE" — typographie réutilisable pour le nom du site (texte dynamique,
       défini par l'utilisateur dans la configuration). Appliquée au bandeau/header principal ET
       au titre de la page d'inscription/connexion (mêmes règles, une seule classe).
       (v3 — la v2, tout en blanc/argenté, ne reprenait pas le vrai orange de la charte (#f07822 /
       #ea580c, comme le bouton "Enregistrer") et son reflet — blanc sur une base déjà blanche —
       ne se voyait pas : orange remis en base, reflet qui traverse vraiment le texte.
       max-width réservant l'espace de l'illustration loup à droite (calc(100% - 130px)) : un nom
       de site long ("The Walking Dead") passe à la ligne au lieu de chevaucher l'image. */
    .site-title-glass {
      position: relative; display: inline-block;
      margin: 0; font-family: 'Black Ops One', 'Bebas Neue', sans-serif;
      font-size: clamp(1.4rem, 4vw, 2.2rem); letter-spacing: 3px; text-transform: uppercase;
      line-height: 1.15;
      flex: 1 1 auto; min-width: 0;
      max-width: calc(100% - 130px); white-space: normal; overflow-wrap: break-word; word-break: break-word;

      /* Verre orange : dégradé diagonal clippé dans le texte (orange charte -> blanc au centre
         -> orange charte -> orange plus sombre), dont on fait glisser la position pour simuler un
         reflet qui traverse le cristal. */
      background: linear-gradient(110deg, #ff7b25 0%, #ffae70 35%, #ffffff 50%, #ff7b25 65%, #c85000 100%);
      background-size: 250% 100%;
      -webkit-background-clip: text; background-clip: text;
      -webkit-text-fill-color: transparent; color: transparent;

      /* Ombre portée propre et unique, pour détacher le titre du fond sombre sans biseau interne. */
      filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.9));

      -webkit-animation: light-sweep 4s cubic-bezier(0.4, 0, 0.2, 1) infinite;
      animation: light-sweep 4s cubic-bezier(0.4, 0, 0.2, 1) infinite;
    }
    @-webkit-keyframes light-sweep {
      0% { background-position: 100% 0; }
      40%, 100% { background-position: -100% 0; }
    }
    @keyframes light-sweep {
      0% { background-position: 100% 0; }
      40%, 100% { background-position: -100% 0; }
    }
    @media (prefers-reduced-motion: reduce) {
      .site-title-glass { animation: none; -webkit-animation: none; }
    }

    /* Conservée : encore utilisée par le titre "hero" de l'assistant d'inscription
       (.wolf-onb-hero h1, balayage doré/blanc continu — habillage différent, volontairement
       laissé tel quel). */
    @keyframes header-title-shimmer {
      0% { background-position: 200% center; }
      100% { background-position: -200% center; }
    }

    .header-titles h1 { margin: 0; font-size: 16px; color: var(--gold-bright); letter-spacing: 1px; text-transform: uppercase; }
    .header-titles p { margin: 2px 0 0 0; font-size: 11px; color: var(--text-sub); }

    .header-controls { display: flex; gap: 6px; align-items: center; flex-shrink: 0; }

    .lang-select {
      background: var(--card-sub-bg); color: var(--text); border: 1px solid var(--gold);
      padding: 5px 22px 5px 8px;
      border-radius: 6px; font-size: 12px; outline: none; cursor: pointer;
      font-weight: bold;
    }

    @media (max-width: 360px) {
      .lang-select { padding: 4px 16px 4px 6px; font-size: 10px; }
      .header-controls { gap: 4px; }
    }

    .container { padding: 12px; max-width: 480px; margin: 0 auto; box-sizing: border-box; }

    /* Liens secondaires de la page Profil (connexion/inscription/mdp oublié/changer alliance) */
    .lien-pf-secondaire {
        display: inline-flex; align-items: center; gap: 5px;
        font-size: 11px; font-weight: 600; color: var(--text-sub);
        background: var(--card-sub-bg); border: 1px solid var(--border-color);
        padding: 6px 12px; border-radius: 20px; text-decoration: none;
        transition: all 0.15s ease;
    }
    .lien-pf-secondaire:hover { color: var(--accent-blue); border-color: var(--accent-blue); }

    /* ========================================================================== */
    /* 🌟 NAVIGATION TACTILE 3D EN TEMPS RÉEL (STYLE SMARTPHONE)                 */
    /* ========================================================================== */
    .container {
      perspective: 1000px; /* Donne l'effet de profondeur 3D */
      perspective-origin: 50% 50%;
      overflow-x: hidden;
      min-height: calc(100vh - 140px);
    }

    .app-page {
      display: none;
      width: 100%;
      box-sizing: border-box;
      transform-style: preserve-3d;
      will-change: transform, opacity;
      backface-visibility: hidden;
    }

    .app-page.active {
      display: block;
    }

    /* Transition plus lente et fluide lors de la libération du doigt */
    .app-page.smooth-transition {
      transition: transform 0.65s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.65s ease-out;
    }

    .card {
      background-color: var(--card-bg); border-radius: 12px; padding: 12px;
      margin-bottom: 12px; border: 1px solid var(--border-color); box-shadow: 0 4px 10px rgba(0,0,0,0.1);
    }
    .card-title { font-size: 13px; font-weight: bold; color: var(--gold); margin-bottom: 10px; text-transform: uppercase; letter-spacing: 0.5px; display: flex; justify-content: space-between; align-items: center; }

    /* 🎨 Liserés colorés pour les cartes "Top" (contribution/pompiers/éco) */
    .card-liser-gold { border-color: rgba(245,158,11,0.5) !important; box-shadow: 0 4px 14px rgba(245,158,11,0.12); }
    .card-liser-purple { border-color: rgba(168,85,247,0.5) !important; box-shadow: 0 4px 14px rgba(168,85,247,0.12); }
    .card-liser-green { border-color: rgba(16,185,129,0.5) !important; box-shadow: 0 4px 14px rgba(16,185,129,0.12); }

    .input-group { display: flex; flex-direction: column; gap: 5px; margin-bottom: 8px; }
    /* Met en avant le réglage "Mode d'attribution du Train" (le plus structurant de la page,
       change le comportement de toutes les sous-options) avec un halo lumineux doux et animé,
       pour qu'il attire l'œil avant le reste des réglages plutôt que de s'y fondre. */
    .input-group-highlight {
      padding: 10px 12px; border-radius: 10px; margin: 2px 0 12px;
      border: 1px solid var(--gold); background: rgba(232,99,28,0.06);
      box-shadow: 0 0 0 rgba(232,99,28,0.35);
      animation: lueurModeAttribution 2.6s ease-in-out infinite;
    }
    .input-group-highlight select { border-color: var(--gold-bright); }
    @keyframes lueurModeAttribution {
      0%, 100% { box-shadow: 0 0 4px rgba(232,99,28,0.25); }
      50% { box-shadow: 0 0 16px rgba(232,99,28,0.6); }
    }
    @media (prefers-reduced-motion: reduce) {
      .input-group-highlight { animation: none; box-shadow: 0 0 10px rgba(232,99,28,0.4); }
    }
    label { font-size: 10px; color: var(--text-sub); text-transform: uppercase; font-weight: bold; }
    /* 🩹 Correctif (28/08/2026, signalé par Michel) : "textarea" manquait de cette règle globale —
       seuls input et select héritaient du fond sombre (var(--input-bg)) ; toute <textarea> du site
       (ex: message du formulaire de contact, anciennement aussi les zones "Textes légaux" du Super
       Admin) retombait donc sur le fond blanc par défaut du navigateur, y compris en thème sombre.
       Ce n'était pas un problème de menu déroulant natif (déjà corrigé plus bas, voir
       "color-scheme") mais un oubli de sélecteur CSS. */
    input, select, textarea {
      background-color: var(--input-bg); border: 1px solid var(--input-border); color: var(--text);
      padding: 10px; border-radius: 8px; font-size: 14px; outline: none; box-sizing: border-box; width: 100%;
    }
    textarea { font-family: inherit; }
    input:focus, select:focus, textarea:focus { border-color: var(--gold); }
    .row-flex { display: flex; gap: 8px; }
    /* Seuils Ligue de Duel (Configurations avancées) : le libellé "Seuil contribution / semaine
       (K, R3)" est plus long que "Seuil VS / mois (M, R3)" et passe sur 2 lignes sur petit écran,
       ce qui décalait verticalement les deux champs de saisie l'un par rapport à l'autre — on
       empile les deux colonnes au lieu de les forcer côte à côte en dessous de 420px. */
    @media (max-width: 420px) {
      .row-flex-seuils-duel { flex-direction: column; }
    }
    /* Étape "Identité" de l'assistant (Tag à supprimer des imports / Symbole) : même souci que
       ci-dessus — "Tag à supprimer des imports" passe sur 2 lignes sur petit écran alors que
       "Symbole / emblème" reste sur 1, ce qui décale verticalement les deux champs de saisie l'un
       par rapport à l'autre (repéré par Michel : "les cases tag et symbole ne sont pas alignées
       sur smartphone"). Même correctif : on empile au lieu de forcer côte à côte en dessous de 480px. */
    @media (max-width: 480px) {
      .row-flex-identite-wz { flex-direction: column; }
    }

    /* ✅ Validation visuelle des champs (inscription membre + création alliance) */
    .champ-avec-icone { position: relative; }
    .champ-avec-icone input.champ-valide { padding-right: 34px; }
    .icone-validation { display: none; position: absolute; right: 10px; top: 50%; transform: translateY(-50%); color: #4ade80; font-size: 16px; pointer-events: none; }
    .icone-validation.visible { display: block; }
    /* 🩹 Correctif (signalé par Michel) : la bordure verte de ".champ-valide" ne s'appliquait
       QUE dans un ".champ-avec-icone" (champs e-mail avec la coche ✓) — le champ "Confirmer le
       mot de passe" n'a pas ce conteneur et ne passait donc jamais au vert même bien rempli.
       Règle globale (comme ".champ-invalide" juste en dessous, déjà globale) : s'applique
       partout, avec ou sans icône de coche à côté. */
    input.champ-valide { border-color: #4ade80 !important; }
    input.champ-invalide { border-color: #ef4444 !important; animation: secousseChamp 0.25s; }
    @keyframes secousseChamp { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }

    /* 👁️ Œil "afficher/masquer le mot de passe" — sur tous les champs de connexion/inscription */
    .champ-mdp-wrapper { position: relative; }
    .champ-mdp-wrapper input { padding-right: 38px; }
    .btn-oeil-mdp {
      position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
      background: none; border: none; color: var(--text-sub); cursor: pointer;
      font-size: 16px; padding: 0; width: 30px; height: 30px; border-radius: 6px;
      display: flex; align-items: center; justify-content: center;
    }
    .btn-oeil-mdp:hover, .btn-oeil-mdp:focus-visible { color: var(--gold-bright); background: rgba(232,99,28,0.08); }

    /* 🔒 Jauge de robustesse + critères du mot de passe — design "carte" avec dégradé animé */
    .pwd-panel {
      margin-top: 6px; padding: 10px 12px; border-radius: 10px;
      background: linear-gradient(145deg, var(--card-sub-bg), var(--input-bg));
      border: 1px solid var(--border-color);
    }
    .pwd-meter { height: 6px; border-radius: 4px; background: var(--input-bg); overflow: hidden; margin-bottom: 10px; }
    .pwd-meter-bar { height: 100%; width: 0%; border-radius: 4px; background: #ef4444; transition: width 0.3s ease, background-color 0.3s ease; }
    .pwd-criteres { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
    .pwd-criteres li {
      font-size: 10.5px; font-weight: bold; color: var(--text-sub); display: flex; align-items: center; gap: 4px;
      background: var(--input-bg); border: 1px solid var(--input-border); border-radius: 20px; padding: 4px 10px 4px 8px;
      transition: all 0.25s ease;
    }
    .pwd-criteres li i { font-size: 12px; transition: transform 0.25s ease; }
    .pwd-criteres li.ok { color: #08321b; background: #4ade80; border-color: #4ade80; box-shadow: 0 2px 8px rgba(74,222,128,0.35); }
    .pwd-criteres li.ok i { transform: scale(1.15); }

    /* 📸 Sélecteur de photos personnalisé (formulaire de contact) — remplace le rendu natif du navigateur */
    .photo-picker { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
    .photo-picker-compteur { font-size: 11px; color: var(--text-sub); font-weight: bold; }
    .photo-picker-apercu { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
    .photo-picker-vignette { position: relative; width: 64px; height: 64px; border-radius: 8px; overflow: hidden; background: var(--input-bg); border: 1px solid var(--input-border); }
    .photo-picker-vignette img { width: 100%; height: 100%; object-fit: cover; display: block; cursor: pointer; }
    .photo-picker-vignette .photo-picker-loading { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; color: var(--text-sub); }
    .photo-picker-vignette .photo-picker-retirer {
      position: absolute; top: -5px; right: -5px; background: #ef4444; color: #fff; border: none; border-radius: 50%;
      width: 18px; height: 18px; font-size: 11px; line-height: 1; cursor: pointer;
    }

    /* 🖼️ Visionneuse plein écran (photos jointes / reçues) — navigation façon carrousel */
    .visionneuse-overlay {
      display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.92); z-index: 3000;
      align-items: center; justify-content: center;
    }
    .visionneuse-overlay.visible { display: flex; }
    .visionneuse-image { max-width: 90vw; max-height: 85vh; border-radius: 8px; object-fit: contain; }
    .visionneuse-fermer { position: absolute; top: 16px; right: 16px; background: rgba(255,255,255,0.1); border: none; color: #fff; width: 36px; height: 36px; border-radius: 50%; font-size: 16px; cursor: pointer; }
    .visionneuse-nav { position: absolute; top: 50%; transform: translateY(-50%); background: rgba(255,255,255,0.1); border: none; color: #fff; width: 44px; height: 44px; border-radius: 50%; font-size: 20px; cursor: pointer; display: flex; align-items: center; justify-content: center; }
    .visionneuse-prev { left: 16px; }
    .visionneuse-next { right: 16px; }
    .visionneuse-compteur { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); color: #fff; font-size: 12px; background: rgba(255,255,255,0.1); padding: 4px 12px; border-radius: 20px; }

    /* ✉️ Boîte aux lettres (badge sur l'avatar profil + sur la barre de nav "Profil") */
    .avatar-wrapper-mailbox { position: relative; display: inline-block; }
    /* 🩹 28/08/2026, v2 (retour de Michel : ma 1ère tentative rendait "noir sur fond noir") —
       cause réelle du bug : j'utilisais var(--card-sub-bg)/var(--card-bg), qui sont des rgba
       TRANSLUCIDES dans le thème graphite actif (effet verre dépoli, voir theme-graphite.css) —
       posées sur la PHOTO de l'avatar (pas sur le fond de page), elles laissaient la photo
       transparaître à travers le badge au lieu de le couvrir, d'où le rendu illisible.
       Corrigé avec --badge-opaque-bg (aplat garanti opaque, jamais redéfini par le thème graphite)
       et un style repris À L'IDENTIQUE de .btn-dark-modern (bordure fine 1px, icône dorée en seule
       touche d'accent), comme demandé par Michel. Bulles légèrement agrandies (30px -> 34px) pour
       rester proportionnées au nouvel avatar plus grand (88px -> 112px, voir compte.php). */
    .mailbox-icon-btn, .stats-icon-btn {
      position: absolute; bottom: 4px; background: var(--badge-opaque-bg); border: 1px solid var(--border-color);
      color: var(--accent-gold); width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center;
      justify-content: center; cursor: pointer; font-size: 15px; padding: 0; box-shadow: 0 2px 6px rgba(0,0,0,0.35);
    }
    .mailbox-icon-btn { right: -6px; }
    .stats-icon-btn { left: -6px; }
    .mailbox-icon-btn:hover, .stats-icon-btn:hover { border-color: var(--accent-gold); color: var(--text); }
    .mailbox-badge {
      position: absolute; top: -6px; right: -8px; background: #ef4444; color: #fff; border-radius: 999px;
      min-width: 18px; height: 18px; box-sizing: border-box; font-size: 10px; font-weight: bold;
      display: flex; align-items: center; justify-content: center; padding: 0 4px; line-height: 1;
      transform-origin: top center; animation: badge-flotter 2.4s ease-in-out infinite;
    }
    /* Variante verte de .mailbox-badge pour la bulle "Membres en ligne" du header : c'est un
       statut permanent ("X connectés"), pas une notification à acquitter — vert plutôt que rouge,
       et pas d'animation "drapeau" (qui suggère une alerte à traiter). */
    .mailbox-badge-vert { background: #22c55e; animation: none; }
    /* 🚩 Toutes les bulles de notification "flottent" comme un petit drapeau au vent — appliqué à
       .mailbox-badge (avatar, cartes Super Admin) ET aux badges de nav gérés en JS (style inline). */
    @keyframes badge-flotter {
      0%, 100% { transform: translateY(0) rotate(0deg); }
      25%      { transform: translateY(-2px) rotate(-8deg); }
      50%      { transform: translateY(0) rotate(0deg); }
      75%      { transform: translateY(-1px) rotate(8deg); }
    }
    .message-item { background: var(--card-sub-bg); border-radius: 8px; padding: 10px; margin-bottom: 8px; border-left: 3px solid transparent; cursor: pointer; }
    .message-item.non-lu { border-left-color: #ef4444; }
    .message-item.non-lu .message-item-sujet { font-weight: bold; }
    .message-item-sujet { font-size: 13px; }
    .message-item-meta { font-size: 11px; color: var(--text-sub); margin-top: 2px; }

    /* Traduction à la demande (chat + messagerie interne + tutoriels) */
    .zone-traduction {
      display: none; margin-top: 4px; padding-top: 4px; border-top: 1px dashed rgba(128,128,128,0.35);
      font-size: 12px; font-style: italic; opacity: 0.85; color: inherit;
    }
    .btn-traduire {
      background: none; border: none; color: var(--text-sub); font-size: 11px; cursor: pointer;
      display: inline-flex; align-items: center; gap: 3px; padding: 2px 0; margin-top: 4px;
    }
    .btn-traduire:hover { color: var(--gold-bright); }
    /* Icône seule, à droite du message (chat) — sans texte "Traduire" à côté */
    .btn-traduire-icone {
      background: none; border: none; color: inherit; opacity: 0.55; font-size: 14px; cursor: pointer;
      padding: 0; flex-shrink: 0; line-height: 1; transition: opacity 0.12s ease;
    }
    .btn-traduire-icone:hover { opacity: 1; }

    /* 🟢 Statut de présence (en ligne / absent / hors ligne) — petit point sur l'avatar */
    .presence-dot {
      position: absolute; bottom: 0; right: 0; width: 12px; height: 12px; border-radius: 50%;
      border: 2px solid var(--card-bg); box-sizing: content-box;
    }
    .presence-dot.en_ligne { background: #4ade80; box-shadow: 0 0 6px rgba(74,222,128,0.7); }
    .presence-dot.absent { background: #f59e0b; }
    .presence-dot.hors_ligne { background: #6b7280; }
    .presence-dot-lg { width: 16px; height: 16px; border-width: 3px; }

    .btn {
      background: var(--card-bg); border: 1px solid var(--border-color); color: var(--text);
      padding: 12px; border-radius: 10px; font-weight: bold; font-size: 13px;
      display: flex; align-items: center; justify-content: center; gap: 6px;
      cursor: pointer; transition: transform 0.1s, filter 0.2s; width: 100%; box-sizing: border-box;
    }
    .btn:active { transform: scale(0.97); }
    .btn-gold { background: linear-gradient(135deg, #c94f0f 0%, #e8631c 100%); color: #000; border: none; font-size: 14px; padding: 12px; }
    /* 🩹 28/08/2026 (retour de Michel : "tout les bouton bleu faudrait les mettre en gris car la
       couleur bleu ne va pas avec le thème") — .btn-blue utilisait var(--accent-blue), qui vaut un
       vrai bleu (#3b82c4) dans le thème graphite actif (assets/css/theme-graphite.css) : détonne
       à côté du orange/gris du reste du site. Un premier passage l'avait fixé en gris acier plat
       (#52525b), mais Michel l'a ensuite pointé du doigt comme "ce gris-là" (boutons "Rejoindre"
       de la recherche d'alliance notamment) : terne, sans relief. Remplacé par le style
       "Dark Mode moderne" (.btn-dark-modern juste plus bas), déjà éprouvé et apprécié ailleurs sur
       le site — s'applique automatiquement partout où .btn-blue est utilisé (37 boutons, 14
       fichiers) sans toucher chaque fichier. */
    .btn-blue { background: var(--card-sub-bg); border: 1px solid var(--border-color); color: var(--text); }
    .btn-blue i { color: var(--accent-gold); }
    .btn-green { background-color: var(--accent-green); color: white; border: none; }
    .btn-purple { background-color: var(--accent-purple); color: white; border: none; }
    .btn-red { background-color: var(--accent-red); color: white; border: none; }
    /* 28/08/2026 (demande de Michel) : style "Dark Mode moderne" pour alléger l'orange vif sur les
       gros boutons pleins de l'écran Profil (ex: "Modifier mes informations") — fond gris acier
       sombre + bordure fine + texte clair, une seule touche d'accentuation (icône dorée). Le survol
       garde le comportement générique de .btn (léger zoom + halo), donc pas de :hover redéfini ici.
       L'orange plein (.btn-gold) reste réservé à l'élément actif / action critique (ex: connexion). */
    .btn-dark-modern { background: var(--card-sub-bg); border: 1px solid var(--border-color); color: var(--text); }
    .btn-dark-modern i { color: var(--accent-gold); }

    .driver-list, .top-list { display: flex; flex-direction: column; gap: 6px; }
    .driver-row, .top-item-row {
      display: flex; justify-content: space-between; align-items: center; gap: 10px;
      padding: 10px 12px; background-color: var(--card-sub-bg); border-radius: 8px;
      font-size: 13px; color: var(--text); border-left: 3px solid transparent;
      transition: transform 0.12s ease, border-color 0.12s ease;
    }
    .driver-row > span:first-child { flex-shrink: 0; }
    /* Nom du conducteur/VIP : couleur neutre par défaut (pas de bleu-sur-bleu) — l'accent de
       couleur (doré) est réservé au jour en cours et aux VIP, pour rester lisible et reposant.
       Alignement à droite + troncature propre si le nom (avec 🏆/✏️) est trop long pour la ligne. */
    .driver-name {
      color: var(--text); font-weight: 600; text-align: right;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
    }
    /* ✨ Jour ACTUEL (dynamique) : lueur douce qui "respire" au lieu d'une bordure statique */
    .driver-row.aujourdhui {
      background: linear-gradient(90deg, rgba(255,122,41,0.16) 0%, var(--card-sub-bg) 100%);
      border-left-color: var(--accent-gold);
      animation: pulse-aujourdhui 2.6s ease-in-out infinite;
    }
    .driver-row.aujourdhui .driver-name { color: var(--accent-gold); font-weight: bold; }
    @keyframes pulse-aujourdhui {
      0%, 100% { box-shadow: 0 0 0 rgba(255,122,41,0); transform: scale(1); }
      50% { box-shadow: 0 0 14px rgba(255,122,41,0.35); transform: scale(1.012); }
    }
    @media (prefers-reduced-motion: reduce) {
      .driver-row.aujourdhui { animation: none; }
    }

    /* 🎠 Carrousel horizontal Conducteurs + VIP (remplace les 2 listes verticales, trop hautes) */
    .train-carousel-viewport {
      overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; touch-action: pan-y;
      scrollbar-width: none; cursor: grab; user-select: none;
    }
    .train-carousel-viewport::-webkit-scrollbar { display: none; }
    .train-carousel-viewport:active { cursor: grabbing; }
    .train-carousel { display: flex; gap: 10px; padding: 2px 2px 6px; width: max-content; }
    .train-carte-jour {
      flex-shrink: 0; width: 132px; background: var(--card-sub-bg); border: 1px solid var(--border-color);
      border-radius: 10px; padding: 10px; display: flex; flex-direction: column; gap: 6px;
    }
    /* Variante plus large utilisée par les cartes "Top ... par semaine / du mois" (index.php) :
       nom + score doivent tenir sur UNE seule ligne (voir .train-carte-ligne-score ci-dessous),
       132px était trop étroit et forçait le score sur une ligne à part, visuellement décalé. */
    .train-carte-jour.train-carte-top { width: 190px; }
    /* Une ligne de classement (rang + nom à gauche, score à droite) sur UNE seule ligne, comme
       .top-item-row, au lieu de deux <div> empilées qui donnaient l'impression que le score
       "flottait" mal aligné sous le nom. */
    .train-carte-ligne-score {
      display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
      font-size: 12px; font-weight: 600; color: var(--text);
    }
    /* Colonne de rang à largeur fixe : sans elle, la largeur d'une médaille emoji (🥇🥈🥉) et
       celle d'un rang texte ("4.", "5.") diffèrent, ce qui décale le début du pseudo d'une ligne
       à l'autre selon le rang affiché. */
    .train-carte-ligne-score .train-carte-rang { flex-shrink: 0; width: 20px; text-align: center; }
    .train-carte-ligne-score .train-carte-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
    .train-carte-ligne-score .train-carte-score { flex-shrink: 0; color: var(--gold-bright); font-weight: bold; font-size: 11px; }
    .train-carte-jour.aujourdhui {
      background: linear-gradient(160deg, rgba(255,122,41,0.16) 0%, var(--card-sub-bg) 100%);
      border-color: var(--accent-gold);
    }
    .train-carte-jour-titre { font-size: 11px; font-weight: bold; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-sub); }
    .train-carte-jour.aujourdhui .train-carte-jour-titre { color: var(--accent-gold); }
    .train-carte-ligne {
      display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--text);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .train-carte-ligne i { flex-shrink: 0; color: var(--mb-blue); }
    .train-carte-ligne span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .train-carte-vip { color: var(--gold-bright); }
    .train-carte-vip i { color: var(--gold-bright); }

    /* 📅 Carrousel "Planning du mois" (accueil, Ligue de Duel avec date de départ connue) : une
       carte plus LARGE par semaine (au lieu d'une carte par jour), contenant les 7 jours de la
       semaine en lignes compactes — voir includes/modules/train.php::carteSemaineDuel(). */
    .train-carte-semaine-duel { width: 250px; gap: 4px; }
    /* Correctif du 28/08 : classe renommée de .brouillon à .semaine-actuelle — l'encadré doré suit
       désormais la vraie date du jour (voir includes/modules/train.php::carteSemaineDuel()) et non
       plus le statut de validation (qui le faisait disparaître dès qu'une semaine était validée). */
    .train-carte-semaine-duel.semaine-actuelle { border-color: var(--accent-gold); border-width: 2px; }
    .train-carte-semaine-duel.train-semaine-a-venir { opacity: 0.55; }
    .train-carte-semaine-plage { font-weight: normal; text-transform: none; letter-spacing: normal; opacity: 0.8; }
    .train-badge-a-venir {
      display: inline-block; font-size: 9px; font-weight: bold; text-transform: uppercase; color: var(--accent-gold);
      /* Correctif du 28/08 : fond dérivé de --accent-gold (voir --accent-gold-rgb) au lieu du
         rgba(255,122,41,...) codé en dur, qui correspondait en réalité à --gold-bright (une teinte
         différente) — d'où le "orange et jaune" mélangés signalé par Michel sur ce badge, affiché à
         l'intérieur même de l'encadré désormais toujours visible pour la semaine en cours. */
      background: rgba(var(--accent-gold-rgb), 0.14); border-radius: 4px; padding: 1px 5px; margin-left: 4px; vertical-align: middle;
    }
    .train-duel-jour-row {
      display: flex; align-items: center; gap: 6px; padding: 3px 0; border-top: 1px solid var(--border-color);
    }
    .train-duel-jour-row:first-child { border-top: none; }
    /* Correctif du 28/08 : même raison que .train-badge-a-venir ci-dessus — fond dérivé de
       --accent-gold plutôt qu'un rgba(255,122,41,...) codé en dur (= --gold-bright), pour que la
       ligne "aujourd'hui" à l'intérieur de l'encadré de la semaine en cours reste dans la MÊME
       teinte que sa bordure au lieu d'un orange légèrement différent. */
    .train-duel-jour-row.aujourdhui { background: rgba(var(--accent-gold-rgb), 0.10); border-radius: 6px; margin: 0 -4px; padding: 3px 4px; }
    .train-duel-jour-date { flex-shrink: 0; width: 46px; font-size: 10px; font-weight: bold; color: var(--text-sub); }
    .train-duel-jour-row .train-carte-ligne { flex: 1; min-width: 0; font-size: 11px; }

    /* 🖱️ Conducteurs/VIP glissables (liste de la modale "Modifier conducteur/VIP" ET tableau des 4
       semaines de #modalDuel, Ligue de Duel à cycle 4 semaines) — voir
       renderModifierPlanningListe()/chargerTableauMoisDuel()/initGlisserDeposer() dans
       includes/modules/train_admin.php. Un "slot" = un joueur d'un jour donné : glissable pour
       échanger avec un autre jour (même type, conducteur ou VIP) ; son crayon ✏️ édite SUR PLACE (le
       slot se transforme lui-même en champ de saisie, voir .train-drag-slot-edition ci-dessous —
       rien d'autre autour n'est masqué pendant l'édition). */
    .train-drag-slot {
      display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; padding: 3px 5px; border-radius: 6px;
      font-size: 11px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .train-drag-slot i:first-child { flex-shrink: 0; color: var(--mb-blue); }
    .train-drag-slot.train-carte-vip i:first-child { color: var(--gold-bright); }
    .train-drag-slot-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
    /* ⚠️ Correctif du 26/08 #6 — historique des tentatives précédentes sur mobile, gardé pour
       comprendre le choix final : #1 avait retiré touch-action:none en permanence (pour ne plus
       "attraper" tout scroll dès l'appui) au profit d'un armement différé ; #4/#5 avaient ensuite
       essayé de le réactiver "à la demande" (au moment de l'armement, puis sur toute la modale) une
       fois le doigt déjà posé — insuffisant sur mobile (Michel : "dès que je le sort de sa case ça le
       relâche et c'est la page qui slide"), car touch-action doit être fixé AVANT que le doigt ne
       touche l'écran pour être pris en compte sur ce geste (Safari iOS en particulier ignore un
       changement en cours de route). touch-action:none est donc SYSTÉMATIQUEMENT permanent ici : le
       navigateur ne prend plus jamais la main sur un geste qui démarre sur un joueur. En contrepartie,
       glisserPointerMove() (includes/modules/train_admin.php) reproduit lui-même le défilement de la
       modale à la main pour un simple swipe (avant l'armement du glisser), pour ne pas perdre la
       possibilité de faire défiler la liste sur mobile. -webkit-touch-callout évite le menu
       contextuel iOS ("Copier"/loupe) que l'appui maintenu pourrait sinon déclencher. */
    .train-drag-slot-modifiable { cursor: grab; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; touch-action: none; }
    .train-drag-slot-modifiable:active { cursor: grabbing; }
    /* ⚠️ Correctif du 26/08 #6 (Michel : "je pense que tu as mis deux fonctions sur le joueur. si je
       fais un clic rapide ça édite le joueur alors que ça devrait être sur l'icone pour éditer") :
       le crayon est désormais le SEUL déclencheur d'édition (voir son propre onclick direct dans
       includes/modules/train_admin.php, indépendant du glisser) — le reste du slot ne sert plus
       qu'au glisser. Zone de clic élargie autour du crayon (marge négative pour ne pas agrandir
       visuellement la rangée) pour rester réactif même sur un tap imprécis. */
    .train-drag-slot-editer { flex-shrink: 0; margin: -8px -6px -8px auto; padding: 8px 6px; opacity: 0.55; font-size: 13px; cursor: pointer; }
    /* NOUVEAU (27/08, demande de Michel : "j'aimerais pouvoir supprimer un joueur de la liste") :
       icône poubelle juste après le crayon — supprime le joueur de ce jour et décale toute la suite
       de la liste (même type, conducteur ou VIP) jusqu'à la fin du cycle (voir
       supprimerSlotGlisserUI()/supprimerConducteurOuVIPGlisser() dans
       includes/modules/train_admin.php / includes/train_logic.php). Le crayon garde son "margin-left:
       auto" pour se pousser à droite du nom ; la poubelle vient ensuite sans marge auto pour rester
       collée à côté (pas de second espace poussé par flex). */
    .train-drag-slot-supprimer { flex-shrink: 0; margin: -8px -6px -8px 0; padding: 8px 6px; opacity: 0.55; font-size: 13px; cursor: pointer; color: #ef4444; }
    /* Le slot glissé se déplace visuellement avec le doigt/curseur (voir glisserPointerMove() ->
       etat.source.style.transform) — position/z-index nécessaires pour qu'il passe bien AU-DESSUS
       des lignes voisines pendant ce déplacement, sinon il resterait masqué en dessous. */
    .train-drag-slot-dragging { opacity: 0.85; background: rgba(56,189,248,0.14); position: relative; z-index: 5; box-shadow: 0 4px 10px rgba(0,0,0,0.35); }
    .train-drag-slot-dropzone { outline: 2px dashed var(--accent-gold); outline-offset: -2px; background: rgba(255,122,41,0.14); }

    /* Édition sur place (voir activerEditionInline() dans includes/modules/train_admin.php) : le
       slot lui-même devient un mini-formulaire, sans rien masquer autour (demande de Michel du
       26/08 : "je ne veux pas que la première modale se ferme quand on édite"). */
    .train-drag-slot-edition { cursor: default; touch-action: auto; background: rgba(56,189,248,0.10); }
    .train-drag-slot-input {
      flex: 1; min-width: 0; font-size: 11px; padding: 3px 5px; border-radius: 5px; cursor: text;
      background: var(--input-bg); border: 1px solid var(--input-border); color: var(--text);
      user-select: text; -webkit-user-select: text;
    }
    .train-drag-slot-valider, .train-drag-slot-annuler { flex-shrink: 0; font-size: 15px; padding: 2px; cursor: pointer; }
    .train-drag-slot-valider { color: #22c55e; }
    .train-drag-slot-annuler { color: #ef4444; }

    /* "Historique des mois précédents" (Train > Historique) : une carte par membre, avec son nom,
       son total, et le détail des 5 scores hebdo en grille. Ces classes étaient utilisées côté JS
       (includes/modules/train.php) sans jamais avoir été stylées, d'où l'affichage brut/cassé. */
    .member-row-block {
      background: var(--card-sub-bg); border: 1px solid var(--border-color);
      border-radius: 10px; padding: 10px 12px; margin-bottom: 8px;
    }
    .member-header-info { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
    .member-header-info > span:first-child {
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1 1 auto;
    }
    .member-header-info > span:last-child { flex-shrink: 0; white-space: nowrap; }
    .member-scores-subgrid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; margin-top: 6px; }
    .score-box-cell {
      background: rgba(255,255,255,0.04); border-radius: 6px; padding: 6px 2px;
      text-align: center; font-size: 11px; font-weight: 600; color: var(--text);
    }
    @media (max-width: 360px) {
      .member-scores-subgrid { gap: 4px; }
      .score-box-cell { font-size: 9.5px; padding: 5px 1px; }
    }

    /* Desert Storm : bloc d'inscription assombri par un dégradé (pas un simple opacity plat) quand
       les inscriptions sont fermées et que le visiteur n'est pas déjà inscrit, pour bien signaler
       visuellement que ce n'est pas cliquable. */
    .ds-bloc-ferme { position: relative; pointer-events: none; border-radius: 10px; overflow: hidden; }
    .ds-bloc-ferme::after {
      content: ""; position: absolute; inset: 0; border-radius: 10px;
      background: linear-gradient(150deg, rgba(5,10,18,0.78) 0%, rgba(5,10,18,0.4) 60%, rgba(5,10,18,0.2) 100%);
      z-index: 2;
    }

    /* Modale "Archives Conducteurs & VIP" : les 2 colonnes (Conducteurs / VIP) ont besoin de
       min-width:0 pour que la troncature des noms fonctionne réellement en flexbox (sinon la
       colonne refuse de rétrécir sous la largeur de son contenu et déborde du cadre sur mobile).
       En dessous de 420px, on repasse en une seule colonne empilée pour laisser de la place aux noms. */
    .archives-planning-cols > div { min-width: 0; }
    @media (max-width: 420px) {
      .archives-planning-cols { flex-direction: column; }
    }

    /* Bouton "Enregistrer" flottant en bas d'une modale longue (ex: Configurations avancées) :
       reste toujours visible pendant le défilement, pas besoin de descendre tout en bas pour le trouver. */
    .modal-footer-sticky {
      position: sticky; bottom: -15px;
      margin: 16px -15px -15px; padding: 12px 15px calc(15px + env(safe-area-inset-bottom, 0px));
      background: var(--card-bg); border-top: 1px solid var(--border-color);
      border-radius: 0 0 14px 14px; box-shadow: 0 -6px 14px rgba(0,0,0,0.3);
    }

    .driver-row.vip-row { background: rgba(251, 191, 36, 0.08); border-left-color: var(--accent-gold); }
    .driver-row.vip-row .driver-name { color: var(--accent-gold); font-weight: bold; }
    /* Le jour VIP en cours garde la pulsation "aujourd'hui" (au lieu du fond statique VIP seul) */
    .driver-row.vip-row.aujourdhui {
      background: linear-gradient(90deg, rgba(255,122,41,0.28) 0%, rgba(255,122,41,0.08) 100%);
    }

    .top-grid { display: grid; grid-template-columns: 1fr; gap: 12px; }
    .top-item-row span:first-child { font-weight: 500; }
    .top-item-row span:last-child { color: var(--gold-bright); font-weight: bold; }

    /* ================================================================== */
    /* 🎮 ROSTER MEMBRES — la palette --mb-* pointait auparavant sur des     */
    /* couleurs fixes indépendantes du thème (bleu ciel #38bdf8 notamment), */
    /* ce qui détonnait avec le reste du site une fois le Centre Analytique */
    /* livré (accent cyan électrique) — elle est désormais alignée sur les  */
    /* variables du thème actif, y compris l'accent cyan partagé.          */
    /* ================================================================== */
    #pageMembresRoot {
      --mb-bg-card: var(--card-sub-bg); --mb-text: var(--text); --mb-text-sub: var(--text-sub);
      --mb-blue: var(--cyan, var(--accent-blue)); --mb-gold: var(--gold-bright); --mb-green: #10b981; --mb-red: #ef4444;
    }
    .roster-card {
      background: var(--mb-bg-card); border-radius: 12px; padding: 14px;
      margin-bottom: 10px; border: 1px solid var(--border-color); border-left: 3px solid var(--border-color);
      cursor: pointer; transition: transform 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
    }
    .roster-card:hover { transform: translateY(-1px); border-left-color: var(--mb-blue); }
    .roster-card.rang-R5 { border-left-color: var(--mb-gold); box-shadow: 0 0 14px rgba(245,158,11,0.1); }
    .roster-card.rang-R4 { border-left-color: var(--mb-blue); }

    .roster-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; }
    .roster-identity { display: flex; align-items: center; gap: 10px; min-width: 0; }
    .roster-avatar-mini {
      flex-shrink: 0; width: 38px; height: 38px; border-radius: 50%; position: relative;
      display: flex; align-items: center; justify-content: center; font-size: 15px; font-weight: 800;
      background: linear-gradient(145deg, rgba(34,211,238,0.25), rgba(34,211,238,0.06));
      border: 1px solid rgba(34,211,238,0.35); color: var(--mb-blue);
    }
    .roster-card.rang-R5 .roster-avatar-mini {
      background: linear-gradient(145deg, rgba(245,158,11,0.28), rgba(245,158,11,0.06));
      border-color: rgba(245,158,11,0.45); color: var(--mb-gold);
    }
    .roster-pseudo-line { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
    .roster-pseudo { font-size: 15px; font-weight: 800; color: var(--mb-text); }
    .roster-badge-rang {
      font-size: 10px; font-weight: 800; padding: 1px 7px; border-radius: 20px;
      background: rgba(148,163,184,0.15); color: var(--mb-text-sub); border: 1px solid rgba(148,163,184,0.3);
    }
    .roster-card.rang-R5 .roster-badge-rang { background: rgba(245,158,11,0.18); color: var(--mb-gold); border-color: rgba(245,158,11,0.4); }
    .roster-card.rang-R4 .roster-badge-rang { background: rgba(34,211,238,0.18); color: var(--mb-blue); border-color: rgba(34,211,238,0.4); }
    .roster-meta { font-size: 11px; color: var(--mb-text-sub); display: flex; align-items: center; gap: 10px; margin-top: 2px; flex-wrap: wrap; }
    .roster-meta i { margin-right: 3px; }

    .roster-status-col { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex-shrink: 0; }
    .roster-chat-btn {
      background: var(--card-sub-bg); border: 1px solid var(--border-color); color: var(--mb-blue);
      width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
      cursor: pointer; font-size: 13px; padding: 0; transition: transform 0.1s ease, border-color 0.1s ease;
    }
    .roster-chat-btn:hover { border-color: var(--mb-blue); transform: scale(1.08); }

    /* Boutons compacts "action" (fiche membre : Statistiques / Discuter) */
    .profil-action-btn {
      display: flex; flex-direction: column; align-items: center; gap: 6px; background: none; border: none;
      cursor: pointer; color: var(--text-sub); font-size: 11px; font-weight: bold; width: 82px;
    }
    .profil-action-icon {
      width: 52px; height: 52px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
      font-size: 20px; background: var(--card-sub-bg); border: 1px solid var(--border-color); color: var(--mb-blue);
      transition: transform 0.12s ease, border-color 0.12s ease;
    }
    .profil-action-btn:hover .profil-action-icon { transform: translateY(-2px); border-color: var(--mb-blue); }
    .profil-action-icon-gold { color: var(--gold-bright); }
    .profil-action-btn:hover .profil-action-icon-gold { border-color: var(--gold-bright); }

    /* Pill compact "Mes discussions" (page Membres) — remplace l'ancien gros bouton pleine largeur */
    .btn-chat-pill {
      background: var(--card-sub-bg); border: 1px solid var(--gold); color: var(--gold-bright);
      font-size: 12px; font-weight: bold; padding: 8px 16px; border-radius: 20px; cursor: pointer;
      display: inline-flex; align-items: center; gap: 6px;
      transition: border-color 0.12s ease;
    }
    .btn-chat-pill:hover { border-color: var(--gold-bright); }
    .roster-badge { font-size: 10px; font-weight: 800; padding: 3px 8px; border-radius: 6px; white-space: nowrap; display: inline-flex; align-items: center; gap: 4px; }
    .roster-badge.train-oui { background: rgba(16,185,129,0.16); color: var(--mb-green); border: 1px solid rgba(16,185,129,0.4); }
    .roster-badge.train-non { background: rgba(239,68,68,0.14); color: var(--mb-red); border: 1px solid rgba(239,68,68,0.35); }
    .roster-badge.vip { background: rgba(245,158,11,0.18); color: var(--mb-gold); border: 1px solid rgba(245,158,11,0.4); }

    .roster-power-bar-track {
      width: 100%; height: 6px; border-radius: 3px; margin-top: 9px; overflow: hidden;
      background: rgba(0,0,0,0.28); /* fondu noir semi-transparent sur le fond de carte : jamais gris, quel que soit l'écran */
    }
    .roster-power-bar-fill {
      height: 100%; border-radius: 3px;
      background: linear-gradient(90deg, #0e7490, var(--mb-blue) 55%, #67e8f9);
      box-shadow: 0 0 8px rgba(34,211,238,0.65), 0 0 2px rgba(103,232,249,0.8); /* effet "barre d'énergie" */
      transition: width 0.4s ease;
    }
    .roster-power-empty {
      display: flex; align-items: center; gap: 5px; margin-top: 9px;
      font-size: 10px; color: var(--mb-text-sub); font-style: italic;
    }
    .roster-power-empty i { font-size: 12px; opacity: 0.7; }
    .roster-power-label { font-size: 10px; color: var(--mb-text-sub); margin-top: 3px; display: flex; justify-content: space-between; }

    .roster-mystere { font-size: 11px; color: var(--mb-gold); margin-top: 9px; }

    .roster-weeks {
      display: flex; flex-wrap: nowrap; gap: 6px; margin-top: 8px;
      overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;
      scroll-snap-type: x proximity; padding-bottom: 2px;
      scrollbar-width: none; /* Firefox */
      cursor: grab; user-select: none;
      /* Le fondu (mask-image) est piloté dynamiquement en JS selon la position réelle du
         défilement (voir initFriseSemainesScroll) : à droite au départ, disparaît en bout de
         liste, et bascule à gauche une fois arrivé à la dernière semaine. */
    }
    .roster-weeks:active { cursor: grabbing; }
    .roster-weeks::-webkit-scrollbar { display: none; } /* Chrome/Safari/Android */
    .week-pill {
      display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 700;
      padding: 4px 8px; border-radius: 7px; background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08); color: var(--mb-text-sub);
      flex-shrink: 0; scroll-snap-align: start; white-space: nowrap;
    }
    .week-pill.tier-green { background: rgba(16,185,129,0.14); border-color: rgba(16,185,129,0.4); color: var(--mb-green); }
    .week-pill.tier-orange { background: rgba(245,158,11,0.14); border-color: rgba(245,158,11,0.4); color: var(--mb-gold); }
    .week-pill.tier-red { background: rgba(239,68,68,0.14); border-color: rgba(239,68,68,0.4); color: var(--mb-red); }
    .roster-weeks-empty { font-size: 11px; color: var(--mb-text-sub); font-style: italic; margin-top: 8px; }
    /* Détail "Contribution du mois" par semaine : replié par défaut, affiché seulement au clic
       sur le libellé "Contribution du mois" de la carte membre. */
    .roster-weeks-hidden { display: none; }
    .roster-contrib-mois-toggle { display: inline-flex; align-items: center; gap: 3px; }
    .roster-contrib-mois-toggle:hover { text-decoration: underline; }

    /* Sécurité écran étroit : jusqu'à 5 pastilles (S1 à S5) doivent rester lisibles sans écrasement */
    @media (max-width: 380px) {
      .week-pill { font-size: 10px; padding: 3px 6px; gap: 3px; }
      .roster-weeks { gap: 5px; }
    }

    .roster-pagination { display: flex; align-items: center; justify-content: center; gap: 12px; margin: 16px 0 4px; }
    .roster-pagination button {
      background: var(--mb-bg-card); border: 1px solid rgba(255,255,255,0.12); color: var(--mb-text);
      border-radius: 8px; padding: 8px 14px; font-size: 12px; font-weight: 700; cursor: pointer; display: flex; align-items: center; gap: 6px;
    }
    .roster-pagination button:disabled { opacity: 0.35; cursor: default; }
    .roster-pagination button:not(:disabled):hover { border-color: var(--mb-blue); color: var(--mb-blue); }
    .roster-pagination-info { font-size: 11px; color: var(--mb-text-sub); }

    .nav-bar {
      position: fixed; bottom: 0; left: 0; right: 0; height: 62px;
      background-color: var(--nav-bg); border-top: 1px solid var(--border-color);
      /* align-items: stretch (au lieu de "center") — TROUVÉ : c'était la vraie cause du rectangle
         "pas assez haut" avec du noir tout autour sur chaque capture d'écran. En mobile, .nav-bar
         passe en height:auto (voir media query plus bas, pour le confort tactile + l'encoche des
         téléphones) : avec align-items:center, chaque .nav-item gardait alors sa hauteur de
         CONTENU (icône + texte) au lieu de remplir la barre, et se retrouvait centré dedans avec de
         l'espace non teinté au-dessus/en dessous — quels que soient le fond ou le trait ajoutés
         PAR-DESSUS, l'item lui-même était trop petit. "stretch" force chaque item à occuper toute
         la hauteur réelle de la barre, quelle que soit sa hauteur (fixe en desktop, auto en
         mobile). */
      display: flex; justify-content: space-around; align-items: stretch; z-index: 1000;
      box-shadow: 0 -4px 10px rgba(0,0,0,0.1);
    }
    .nav-item { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--text-sub); font-size: 11px; font-weight: 500; cursor: pointer; flex: 1; gap: 3px; }
    .nav-item .icon { font-size: 18px; line-height: 1; }
    /* Onglet actif : même fond orange léger que le survol (.nav-item:hover, même rgba), mais
       étendu à TOUTE la case (pas un petit rectangle resserré autour du seul nom) + trait néon en
       haut, aligné sur la fine ligne orange du haut de la barre (.nav-bar border-top). */
    .nav-item.active { color: var(--gold-bright); background-color: rgba(212, 175, 55, 0.08); }
    .nav-item.active::before {
      content: '';
      /* Revenu à 60% centrés (left/right:20%) : la version pleine largeur testée entre-temps ne
         plaisait finalement pas à Michel, il préfère le trait plus court façon "soulignement". */
      position: absolute; top: 0; left: 20%; right: 20%; height: 3px;
      border-radius: 0 0 3px 3px;
      background: var(--gold-bright);
      box-shadow: 0 0 6px 1px var(--gold-bright), 0 0 14px 3px var(--gold-bright);
    }

    .toast-notification {
      position: fixed; top: 65px; left: 50%; transform: translateX(-50%);
      background: var(--card-bg);
      color: var(--gold-bright); border: 1px solid var(--gold);
      padding: 12px 20px; border-radius: 10px; box-shadow: 0 8px 25px rgba(0,0,0,0.3);
      font-size: 13px; font-weight: bold; z-index: 4000; display: none; text-align: center;
      max-width: 85%; pointer-events: none;
    }

    .modal { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.75); z-index: 2000; padding: 15px; align-items: center; justify-content: center; }
    .modal-content { background: var(--card-bg); border-radius: 14px; padding: 15px; width: 100%; max-width: 440px; border: 1px solid var(--gold); box-shadow: 0 10px 25px rgba(0,0,0,0.3); max-height: 90vh; overflow-y: auto; color: var(--text); }
    .loading-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(15,17,21,0.85); display: none; flex-direction: column; align-items: center; justify-content: center; z-index: 3000; }
    .spinner { width: 36px; height: 36px; border: 4px solid #333; border-top: 4px solid var(--gold); border-radius: 50%; animation: spin 1s linear infinite; }
    @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }

    /* ========================================================================== */
    /* 🌟 EFFETS DE SURBRILLANCE ET D'INTERACTION                                 */
    /* ========================================================================== */
    .btn:hover {
      filter: brightness(1.15);
      border-color: var(--gold-bright) !important;
      box-shadow: 0 0 12px rgba(212, 175, 55, 0.3);
    }
    .btn:active {
      transform: scale(0.96);
      filter: brightness(0.9);
    }
    .btn-sem-filter:not(.active):hover,
    .btn-statut-filter:not(.active):hover,
    .btn-train-filter:not(.active):hover,
    .btn-vip-filter:not(.active):hover {
      border-color: var(--gold) !important;
      color: var(--gold-bright) !important;
      background: rgba(212, 175, 55, 0.15) !important;
      box-shadow: 0 0 8px rgba(212, 175, 55, 0.25);
    }
    .btn-sem-filter:active, 
    .btn-statut-filter:active,
    .btn-train-filter:active,
    .btn-vip-filter:active {
      transform: scale(0.95);
    }
    .nav-item:hover {
      color: var(--gold-bright);
      background-color: rgba(212, 175, 55, 0.08);
    }
    .lang-select:hover, 
    select:hover, 
    input:hover {
      border-color: var(--gold-bright);
      box-shadow: 0 0 6px rgba(212, 175, 55, 0.25);
    }

    /* ========================================================================== */
    /* 📱 CARTES D'OPTIONS (VIP & MYSTÈRE - DISPOSITION MOBILE)                   */
    /* ========================================================================== */
    .options-toggle-group {
      display: flex;
      flex-direction: column;
      gap: 10px;
      margin-bottom: 15px;
      width: 100%;
    }

    .toggle-card {
      padding: 12px 15px;
      background-color: var(--card-sub-bg);
      border: 1px solid var(--border-color);
      border-radius: 10px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      transition: border-color 0.2s ease;
    }

    .toggle-card:hover {
      border-color: var(--gold);
    }

    .toggle-info {
      display: flex;
      flex-direction: column;
      gap: 2px;
    }

    .toggle-title {
      font-size: 12px;
      font-weight: bold;
      color: var(--gold-bright);
    }

    .toggle-subtitle {
      font-size: 10px;
      color: var(--text-sub);
    }

    @media (min-width: 600px) {
      .options-toggle-group {
        flex-direction: row;
      }
      .toggle-card {
        flex: 1;
      }
    }
/* Ajouts module Membres/Tops (roster + score des tops) */
.top-score { color: var(--gold-bright); font-weight: bold; }
.roster-list { display: flex; flex-direction: column; gap: 6px; max-height: 480px; overflow-y: auto; }
.roster-row { padding: 8px 10px; background-color: var(--card-sub-bg); border-radius: 6px; }
.roster-main { font-size: 13px; color: var(--text); }
.roster-sub { font-size: 11px; color: var(--text-sub); margin-top: 2px; }
.badge-role { font-size: 10px; padding: 1px 6px; border-radius: 10px; background: rgba(56,189,248,0.15); color: var(--gold-bright); margin-left: 4px; }

/* 🆕 Bulle "Nouveau" — repère un compte créé depuis moins de 7 jours (Comptes & Droits) */
.badge-nouveau-membre {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 9.5px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.4px;
  padding: 2px 7px; border-radius: 999px; margin-left: 6px;
  background: linear-gradient(135deg, #4ade80, #16a34a); color: #052e12;
  box-shadow: 0 0 8px rgba(74,222,128,0.45);
  animation: badge-flotter 2.4s ease-in-out infinite;
}
/* Carte "compte" (Comptes & Droits) mise en valeur pour un nouveau membre : liseré vert discret */
.card-sub-box.nouveau-membre { border-left: 3px solid #4ade80; }

/* ⭐ Bouton favori flottant sur les cartes de tutoriels */
.btn-favori-tuto {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  width: 30px; height: 30px; border-radius: 50%; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15,23,42,0.65); backdrop-filter: blur(4px);
  color: var(--text-sub); font-size: 15px;
  transition: transform 0.12s ease, color 0.12s ease, background 0.12s ease;
}
.btn-favori-tuto:hover { transform: scale(1.1); background: rgba(15,23,42,0.85); }
.btn-favori-tuto.actif { color: #1e1206; background: linear-gradient(135deg, #ffb27a, #f59e0b); box-shadow: 0 0 10px rgba(255,122,41,0.5); }

/* 🎯 Pastilles "cible du jour" (Caisses étoilées) : fond/contour orange (couleur de la charte,
   inchangée), icône + numéro de serveur en BLANC (le gris essayé ensuite manquait de peps ;
   retour au blanc, qui plaisait — seul le gras (800) était en cause, jugé trop épais/"choquant" :
   allégé en normal (400) pour un rendu plus fin, même couleur). */
.badge-cible {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 13px; font-weight: 400; padding: 7px 14px; border-radius: 20px;
  background: linear-gradient(135deg, rgba(255,122,41,0.28), rgba(255,122,41,0.1));
  border: 1px solid rgba(255,122,41,0.5);
  color: #ffffff;
  box-shadow: 0 2px 10px rgba(255,122,41,0.2), inset 0 1px 0 rgba(255,255,255,0.08);
  transition: transform 0.12s ease;
}
.badge-cible:hover { transform: translateY(-1px); }
.badge-cible i { font-size: 13px; }
/* 🩹 28/08/2026 (retour de Michel : "dans le théme claire les caisses étoilées on ne les voie pas
   le numéro quand c'est theme clair faudrait assombrir l'écriture en gris foncé") — le blanc fixe
   ci-dessus convient au thème sombre (fond de page sombre derrière le dégradé orange translucide de
   la pastille) mais devient illisible en thème clair (fond de page clair derrière ce même dégradé
   translucide, quasi blanc au total). Assombri uniquement en thème clair, via var(--text) (gris très
   foncé dans ce thème), sans toucher au rendu thème sombre. */
body.light-theme .badge-cible { color: var(--text); }

/* Grille de tuiles admin façon "app" (remplace les accordéons) */
.admin-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 16px; }

/* Panneau Super Admin */
.sa-stat-box {
    background: var(--card-sub-bg); border: 1px solid var(--border-color);
    border-radius: 10px; padding: 12px; text-align: center; position: relative;
}
.sa-alliance-card { background: var(--card-sub-bg) !important; transition: border-color 0.15s ease, transform 0.1s ease; }
.sa-alliance-card:hover { border-color: var(--gold); transform: translateY(-1px); }
.sa-pastille {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 10px; font-weight: 600; color: var(--text-sub);
    background: var(--card-sub-bg); border: 1px solid var(--border-color);
    padding: 4px 9px; border-radius: 20px; white-space: nowrap;
}
.sa-detail-grille { display: grid; grid-template-columns: 1fr; gap: 10px; font-size: 13px; }
.sa-detail-label {
    display: block; font-size: 10px; font-weight: bold; text-transform: uppercase;
    letter-spacing: 0.5px; color: var(--text-sub); margin-bottom: 2px;
}
.admin-tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; padding: 18px 8px; border-radius: 12px; border: none; cursor: pointer;
  color: #fff; font-weight: 700; font-size: 13px; text-align: center;
  box-shadow: 0 4px 10px rgba(0,0,0,0.25);
}
.admin-tile .tile-icon { font-size: 22px; }
.admin-tile:active { transform: scale(0.97); }
.admin-tile.disabled { opacity: 0.45; cursor: not-allowed; }
.admin-tile.tile-purple { background: var(--accent-purple); }
.admin-tile.tile-blue   { background: var(--accent-blue); }
.admin-tile.tile-green  { background: var(--accent-green); }
/* 🩹 28/08/2026 (retour de Michel, capture à l'appui : tuiles "Pillage / Config. avancées / Test
   SMTP / Gérer les archives") — l'ancien gris plat (#37415155) tranchait mal, terne à côté des
   tuiles couleur ci-dessous. Même style "Dark Mode moderne" que .btn-dark-modern (voir plus haut) :
   fond gris acier + bordure fine + icône dorée, plus soigné qu'un simple aplat gris. */
.admin-tile.tile-gray   { background: var(--card-sub-bg); border: 1px solid var(--border-color); color: var(--text); }
.admin-tile.tile-gray .tile-icon { color: var(--accent-gold); }

.admin-actions-box { border: 1px solid rgba(239,108,0,0.4); border-radius: 12px; padding: 14px; margin-bottom: 16px; }
.admin-actions-box .actions-title { color: #ef6c00; font-weight: 700; font-size: 13px; margin-bottom: 10px; display:flex; align-items:center; gap:6px; }

.modal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.modal-header h3 { margin: 0; font-size: 15px; color: var(--gold-bright); }
.modal-close { background: none; border: none; color: var(--text-sub); font-size: 20px; line-height: 1; cursor: pointer; padding: 4px 8px; }
.modal-close:hover { color: var(--text); }

/* Zones du tableau de bord admin (Planning / Accès rapide / Configuration) */
.admin-zone { border-radius: 12px; padding: 14px; margin-bottom: 16px; border: 1px solid var(--border-color); }
.admin-zone-title { font-size: 13px; font-weight: 800; margin-bottom: 12px; display: flex; align-items: center; gap: 6px; letter-spacing: 0.3px; }
.admin-zone-planning { background: rgba(2,132,199,0.08); border-color: rgba(2,132,199,0.35); }
.admin-zone-planning .admin-zone-title { color: var(--accent-blue); }
.admin-zone-rapide { background: rgba(74,222,128,0.06); border-color: rgba(74,222,128,0.3); }
.admin-zone-rapide .admin-zone-title { color: var(--accent-green); }
.admin-zone-config { background: rgba(148,163,184,0.06); border-color: var(--border-color); }
.admin-zone-config .admin-zone-title { color: var(--text-sub); }
.admin-zone .admin-grid { margin-bottom: 0; }

/* Couleurs supplémentaires pour varier les tuiles admin + effet de survol */
.admin-tile.tile-orange { background: linear-gradient(135deg, #ff7a29, #c94f0f); }
.admin-tile.tile-teal   { background: linear-gradient(135deg, #14b8a6, #0d9488); }
.admin-tile.tile-pink   { background: linear-gradient(135deg, #ec4899, #db2777); }
.admin-tile.tile-purple { background: linear-gradient(135deg, #a855f7, #7e22ce); }
.admin-tile.tile-blue   { background: linear-gradient(135deg, #38bdf8, #0284c7); }
.admin-tile.tile-green  { background: linear-gradient(135deg, #4ade80, #16a34a); }
.admin-tile.tile-red    { background: linear-gradient(135deg, #f87171, #dc2626); }

.admin-tile { position: relative; }
.admin-tile .tile-count-badge {
  position: absolute; top: 6px; right: 6px;
  background: #fff; color: #dc2626; font-size: 10px; font-weight: 800;
  border-radius: 20px; padding: 1px 6px; min-width: 15px; text-align: center; line-height: 1.5;
  box-shadow: 0 2px 6px rgba(0,0,0,0.3);
}

/* Mise en avant temporaire d'une tuile "nouveauté" (ex: Scanner Multi-Images) : halo lumineux
   pulsant + ruban "NEW" clignotant en diagonale dans le coin supérieur droit. Ajouter/retirer
   simplement les classes tile-glow / tile-has-ribbon (+ le <span class="tile-ribbon-new">) sur une
   tuile pour activer/désactiver l'effet — aucune dépendance au reste du CSS. */
.admin-tile.tile-has-ribbon { overflow: hidden; }
.admin-tile.tile-glow {
  animation: tile-glow-pulse 1.6s ease-in-out infinite;
}
@keyframes tile-glow-pulse {
  0%, 100% { box-shadow: 0 4px 10px rgba(0,0,0,0.25), 0 0 8px 2px rgba(251,191,36,0.55); }
  50%      { box-shadow: 0 4px 10px rgba(0,0,0,0.25), 0 0 22px 8px rgba(251,191,36,0.95); }
}
.admin-tile .tile-ribbon-new {
  /* Fixe (non clignotant) : Michel trouvait le clignotement fatiguant pour les yeux. Le halo
     pulsant de .tile-glow reste seul à animer la tuile. */
  position: absolute; top: 11px; right: -30px; width: 110px;
  transform: rotate(45deg); transform-origin: center;
  background: #dc2626; color: #fff; font-size: 10px; font-weight: 900;
  letter-spacing: 1px; text-align: center; padding: 2px 0;
  box-shadow: 0 2px 6px rgba(0,0,0,0.4); pointer-events: none; z-index: 2;
}

.admin-tile:not(.disabled):hover {
  filter: brightness(1.15);
  box-shadow: 0 6px 16px rgba(0,0,0,0.35);
  transform: translateY(-1px);
}
.btn:not(:disabled):hover {
  filter: brightness(1.12);
  box-shadow: 0 4px 14px rgba(0,0,0,0.3);
}
.admin-tile, .btn { transition: filter 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease; }

/* Bouton secondaire discret (ex: "Nouveau / Vider le formulaire") */
.btn-outline { background: transparent; color: var(--text-sub); border: 1px solid var(--border-color); }
.btn-outline:hover { background: rgba(255,255,255,0.05); color: var(--text); border-color: var(--gold); }

/* Interrupteur (toggle switch) style iOS, pour remplacer les cases à cocher en config */
.switch-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 0; }
.switch-row .switch-label { font-size: 13px; color: var(--text); font-weight: 600; }
.switch-row .switch-desc { font-size: 11px; color: var(--text-sub); margin-top: 2px; }
/* Le bloc texte (libellé + description) doit pouvoir rétrécir sous le toggle plutôt que de garder
   sa largeur de contenu naturelle : sans ça, la dernière ligne d'une description longue (ex:
   "Éco sur 6 jours") déborde du switch-row et se retrouve coupée sur petit écran. */
.switch-row > div:first-child { flex: 1 1 auto; min-width: 0; }
.switch-row .switch-desc, .switch-row .switch-label { overflow-wrap: break-word; word-wrap: break-word; }
.switch { position: relative; display: inline-block; width: 46px; height: 26px; flex-shrink: 0; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .slider { position: absolute; cursor: pointer; inset: 0; background-color: #3a4358; border-radius: 26px; transition: 0.25s; }
.switch .slider:before { position: absolute; content: ""; height: 20px; width: 20px; left: 3px; bottom: 3px; background-color: #fff; border-radius: 50%; transition: 0.25s; box-shadow: 0 1px 3px rgba(0,0,0,0.4); }
.switch input:checked + .slider { background: linear-gradient(135deg, var(--switch-on-debut), var(--switch-on-fin)); }
.switch input:checked + .slider:before { transform: translateX(20px); }
/* max-height généreux (pas juste "assez grand pour un cas simple") : plusieurs .switch-dependent
   sont IMBRIQUÉS (ex: le bloc Ligue de Duel contient lui-même le sous-bloc "Réordonner R5/R4/R3"),
   et l'ancien plafond de 500px sur le conteneur EXTÉRIEUR coupait net le contenu du sous-bloc une
   fois déplié (les cases de réordonnancement "disparaissaient" alors qu'elles étaient bien
   affichées, juste rognées par overflow:hidden du parent). */
.switch-dependent { max-height: 1500px; overflow: hidden; transition: max-height 0.35s ease, opacity 0.25s ease, margin 0.25s ease; opacity: 1; }
.switch-dependent.masque { max-height: 0; opacity: 0; margin: 0; pointer-events: none; }

/* Sections repliables de "Configurations avancées" (Identité / Planning Train / Règles / Sécurité) */
.config-section-body { padding-top: 12px; max-height: 3000px; overflow: hidden; transition: max-height 0.35s ease, opacity 0.25s ease, padding 0.25s ease, margin 0.25s ease; opacity: 1; }
.config-section-body.masque { max-height: 0; opacity: 0; padding-top: 0; margin: 0; pointer-events: none; }

/* Éditeur riche pour le contenu des tutoriels */
.rich-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-bottom: 6px; background: var(--card-sub-bg); padding: 6px; border-radius: 8px 8px 0 0; }
.rich-toolbar-group { display: contents; } /* les boutons deviennent des enfants directs de .rich-toolbar : le retour à la ligne se fait bouton par bouton (pas de vide), tout en gardant le regroupement visuel via la bordure ci-dessous */
.rich-toolbar-group > *:last-child { margin-right: 8px; padding-right: 8px; border-right: 1px solid var(--border-color); }
.rich-toolbar button { background: var(--input-bg); border: 1px solid var(--input-border); color: var(--text); border-radius: 5px; width: 30px; height: 30px; font-size: 14px; cursor: pointer; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.rich-toolbar button:hover { border-color: var(--gold); color: var(--gold-bright); }
.rich-toolbar button.actif { background: var(--gold-bright); color: #000; border-color: var(--gold-bright); }
.rich-toolbar button.rich-toolbar-danger:hover { border-color: #ef4444; color: #ef4444; }
.rich-toolbar input[type="color"] { width: 30px; height: 30px; padding: 0; border: 1px solid var(--input-border); border-radius: 5px; background: none; cursor: pointer; flex-shrink: 0; }
.rich-toolbar-select { width: 68px; flex-shrink: 0; background: var(--input-bg); border: 1px solid var(--input-border); color: var(--text); border-radius: 5px; height: 30px; font-size: 11px; padding: 0 2px; }
.rich-editor {
  min-height: 160px; max-height: 320px; overflow-y: auto;
  background: var(--input-bg); border: 1px solid var(--input-border); border-radius: 0 0 8px 8px;
  color: var(--text); padding: 10px; font-size: 13px; line-height: 1.6; outline: none;
}
.rich-editor img { max-width: 90%; height: auto; border-radius: 8px; cursor: grab; }
.rich-editor img.image-selectionnee { outline: 3px solid var(--gold-bright); cursor: grabbing; }
.rich-editor .video-embed-wrapper { cursor: default; border-radius: 8px; }
.rich-editor .video-embed-wrapper.image-selectionnee { outline: 3px solid var(--gold-bright); }
.video-embed-controls {
  position: absolute; top: 6px; right: 6px; z-index: 5;
  display: flex; gap: 4px;
}
.video-embed-controls button {
  width: 28px; height: 28px; border-radius: 5px; border: 1px solid rgba(255,255,255,0.25);
  background: rgba(8,12,20,0.75); backdrop-filter: blur(4px); color: #fff; font-size: 13px;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.video-embed-controls button:hover { background: rgba(8,12,20,0.92); }
.video-embed-controls button.video-embed-supprimer:hover { background: #ef4444; border-color: #ef4444; }
.rich-editor:empty:before { content: attr(data-placeholder); color: var(--text-sub); pointer-events: none; }

/* Style des champs de fichier natifs (upload avatar/image), au lieu du bouton gris par défaut du navigateur */
input[type="file"] {
  color: var(--text-sub); font-size: 12px;
}
input[type="file"]::file-selector-button,
input[type="file"]::-webkit-file-upload-button {
  background: linear-gradient(135deg, var(--switch-on-debut), var(--switch-on-fin));
  color: #fff; border: none; border-radius: 8px; padding: 9px 16px;
  font-weight: 700; font-size: 12px; cursor: pointer; margin-right: 10px;
  transition: filter 0.15s ease;
}
input[type="file"]::file-selector-button:hover,
input[type="file"]::-webkit-file-upload-button:hover { filter: brightness(1.15); }

/* ========================================================================== */
/* 🐺 WOLF-HQ — COQUILLE DESKTOP (sidebar + topbar) + BANNIÈRE                */
/* Purement additif : sur mobile (<960px), tout ceci reste masqué et l'appli  */
/* garde exactement son fonctionnement d'origine (header + nav-bar en bas).   */
/* ========================================================================== */

.wolf-sidebar, .wolf-topbar, .wolf-shell-toggle { display: none; }

@media (min-width: 960px) {
  body { padding-bottom: 0; }

  .wolf-sidebar {
    display: flex; flex-direction: column;
    position: fixed; top: 0; left: 0; bottom: 0; width: 250px; z-index: 900;
    background: var(--sidebar-bg); border-right: 1px solid var(--border-color);
    padding: 18px 14px; box-sizing: border-box; overflow-y: auto;
  }
  .wolf-sidebar-brand { display: flex; align-items: center; gap: 10px; padding: 4px 6px 18px; margin-bottom: 8px; border-bottom: 1px solid var(--border-color); }
  .wolf-sidebar-brand img { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
  .wolf-sidebar-brand-text { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
  .wolf-sidebar-brand-name { font-family: 'Bebas Neue', sans-serif; font-size: 20px; letter-spacing: 1px; color: var(--text); }
  .wolf-sidebar-brand-tag { font-size: 9px; color: var(--text-sub); text-transform: uppercase; letter-spacing: 1.5px; font-weight: 700; }

  .wolf-sidebar-nav { display: flex; flex-direction: column; gap: 3px; margin-top: 10px; flex: 1; }
  .wolf-sidebar-link {
    display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 10px;
    color: var(--text-sub); font-size: 13px; font-weight: 700; cursor: pointer; user-select: none;
    text-transform: uppercase; letter-spacing: 0.4px; transition: background 0.15s ease, color 0.15s ease;
    position: relative;
  }
  .wolf-sidebar-link i { font-size: 17px; width: 20px; text-align: center; flex-shrink: 0; }
  /* 🩹 28/08/2026 (retour de Michel : "le gris vraiment pas beau et aucun changement de couleur au
     passage de la souris") — l'ancien survol (fond var(--card-sub-bg), texte var(--text)) restait
     gris sur gris quasi identique au fond de la sidebar (var(--sidebar-bg)) en thème sombre, donc
     imperceptible. Remplacé par le même traitement orange déjà utilisé et éprouvé sur la barre de
     nav mobile (.nav-item:hover, juste au-dessus dans ce fichier) : accent net, cohérent avec
     .wolf-sidebar-link.active juste en dessous. */
  .wolf-sidebar-link:hover { background: rgba(212, 175, 55, 0.08); color: var(--gold-bright); }
  .wolf-sidebar-link.active { background: var(--sidebar-bg-active); color: var(--gold-bright); }
  .wolf-sidebar-link .mailbox-badge { position: static; margin-left: auto; animation: none; }

  .wolf-sidebar-foot { border-top: 1px solid var(--border-color); padding-top: 12px; margin-top: 10px; display: flex; align-items: center; gap: 10px; }
  .wolf-sidebar-foot-info { display: flex; flex-direction: column; min-width: 0; }
  .wolf-sidebar-foot-name { font-size: 12px; font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .wolf-sidebar-foot-role { font-size: 10px; color: var(--text-sub); text-transform: uppercase; }

  /* Contenu principal décalé pour laisser la place à la sidebar — uniquement si elle est
     réellement présente dans la page (visiteur connecté). Un visiteur non connecté (page
     Profil seule, pas de sidebar générée) garde une mise en page centrée normale. */
  body:has(.wolf-sidebar) > .header,
  body:has(.wolf-sidebar) > .wolf-topbar {
    margin-left: 250px;
  }
  /* .container a son propre calcul, PAS un simple margin-left comme le header/topbar ci-dessus :
     avec juste "margin-left: 250px", le margin-right restait "auto" (hérité de la règle mobile
     ".container { margin: 0 auto }") et un seul côté "auto" absorbe TOUT l'espace restant au lieu
     de centrer — sur un grand écran, le contenu se retrouvait collé à la sidebar avec un immense
     vide à droite ("tout est étiré, il y a des trous", signalé par Michel). Ce calc() centre le
     contenu dans l'espace réellement disponible (viewport moins la sidebar), comme prévu. */
  body:has(.wolf-sidebar) > .container {
    margin-left: calc(250px + max(0px, (100vw - 250px - 1180px) / 2));
    margin-right: auto;
  }

  .wolf-topbar {
    display: flex; align-items: center; justify-content: space-between; gap: 14px;
    background: var(--topbar-bg); border-bottom: 1px solid var(--border-color);
    padding: 10px 22px; position: sticky; top: 0; z-index: 800; backdrop-filter: blur(10px);
  }
  .wolf-topbar-status { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 700; color: var(--text-sub); }
  .wolf-topbar-status .dot { width: 8px; height: 8px; border-radius: 50%; background: #4ade80; box-shadow: 0 0 6px rgba(74,222,128,0.7); }
  .wolf-topbar-actions { display: flex; align-items: center; gap: 8px; }
  .wolf-topbar-actions .header-icon-btn { position: relative; }

  /* Bottom nav mobile masquée en desktop : la sidebar la remplace entièrement */
  .nav-bar { display: none; }

  /* Le header/bannière garde sa largeur pleine (moins la sidebar) et s'agrandit un peu */
  .header { padding: 26px 28px; }
  .header-container { max-width: none; }
  .container { max-width: 1180px; padding: 22px 28px; }
}

/* ========================================================================== */
/* 🐺 WOLF-HQ — Nav mobile bas : espacement (le style "actif" lui-même est     */
/* géré plus haut par .nav-item.active / .nav-item.active::before, commun aux  */
/* deux tailles d'écran)                                                      */
/* ========================================================================== */
@media (max-width: 959.98px) {
  /* Le 1er essai gardait un padding-top sur .nav-bar + une margin verticale sur .nav-item, ce qui
     décalait à la fois le fond orange (qui ne couvrait plus toute la case, un espace non teinté
     restait visible en haut/bas) ET le trait néon (visible flottant au-dessus de la barre au lieu
     d'être "sur" sa ligne du haut). Corrigé en supprimant tout espacement VERTICAL : .nav-item
     touche désormais directement le bord haut/bas de .nav-bar, donc le fond orange plein (actif ou
     survolé) remplit réellement toute la case, et le trait néon (top:0, par défaut, plus besoin de
     décalage négatif) tombe exactement sur le border-top de .nav-bar. Plus aucun espacement entre
     les onglets (gap retiré) : ils se touchent maintenant complètement, comme demandé par Michel. */
  .nav-bar { padding: 0 6px calc(6px + env(safe-area-inset-bottom, 0px)); gap: 0; height: auto; min-height: 62px; }
  .nav-item { margin: 0; transition: background 0.15s ease, color 0.15s ease; }
}

/* ========================================================================== */
/* 🐺 WOLF-HQ — Bannière d'accueil "hero" avec visuel loup                    */
/* ========================================================================== */
.wolf-hero-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin: 14px 0 4px; }
.wolf-hero-stat { background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 14px; padding: 14px; }
.wolf-hero-stat-top { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.wolf-hero-stat-icon { width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 16px; background: var(--card-sub-bg); color: var(--gold-bright); flex-shrink: 0; }
.wolf-hero-stat-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-sub); font-weight: 700; }
.wolf-hero-stat-value { font-size: 20px; font-weight: 800; color: var(--text); }
.wolf-hero-stat-sub { font-size: 11px; color: #4ade80; font-weight: 700; margin-top: 2px; }
.wolf-hero-stat-link { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 700; color: var(--gold-bright); margin-top: 8px; cursor: pointer; text-transform: uppercase; letter-spacing: 0.3px; }
.wolf-hero-stat-link:hover { text-decoration: underline; }

/* ========================================================================== */
/* 🐺 WOLF-HQ — Widget "Membres en ligne" (page Accueil)                      */
/* Réutilise le champ "presence" déjà calculé par api/membres_roster.php à    */
/* partir de derniere_activite (pas de nouvel endpoint) — comble le grand     */
/* vide à droite du contenu sur desktop tout en répondant à la demande de     */
/* Michel ("même pas de module pour voir les membres connectés").            */
/* ========================================================================== */
.wolf-online-list { display: flex; flex-direction: column; gap: 6px; max-height: 260px; overflow-y: auto; }
.wolf-online-row { display: flex; align-items: center; gap: 8px; padding: 7px 9px; border-radius: 8px; background: var(--card-sub-bg); font-size: 12.5px; font-weight: 600; color: var(--text); }
.wolf-online-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; box-shadow: 0 0 6px currentColor; }
.wolf-online-nom { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ========================================================================== */
/* 🐺 WOLF-HQ — Page d'inscription "gamer" (recherche / code / création)      */
/* ========================================================================== */
.wolf-onb-page { position: relative; }
.wolf-onb-hero {
  position: relative; border-radius: 18px; overflow: hidden; margin: 0 0 16px;
  background: var(--header-bg); border: 1px solid var(--border-color);
  padding: 26px 20px; text-align: center;
}
.wolf-onb-hero-badge {
  width: 92px; height: 92px; border-radius: 50%; margin: 0 auto 12px; display: block;
  border: 3px solid var(--gold-bright); box-shadow: 0 0 30px rgba(255,122,41,0.45); object-fit: cover;
}
.wolf-onb-hero h1 {
  font-family: 'Bebas Neue', sans-serif; font-size: clamp(26px, 7vw, 40px); letter-spacing: 2px; margin: 0 0 6px;
  background: linear-gradient(90deg, var(--gold-bright) 0%, #ffffff 50%, var(--gold-bright) 100%);
  background-size: 200% auto; -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;
  animation: header-title-shimmer 3s linear infinite; text-transform: uppercase;
}
.wolf-onb-hero p { font-size: 13px; color: var(--text-sub); margin: 0; max-width: 420px; margin: 0 auto; }

.wolf-onb-tile {
  display: flex; align-items: center; gap: 14px; padding: 18px 16px; border-radius: 14px;
  background: var(--card-bg); border: 1px solid var(--border-color); cursor: pointer; width: 100%; text-align: left;
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease; color: var(--text);
}
.wolf-onb-tile:hover { transform: translateY(-2px); border-color: var(--gold); box-shadow: 0 10px 24px rgba(0,0,0,0.25); }
.wolf-onb-tile-icon {
  width: 46px; height: 46px; border-radius: 12px; display: flex; align-items: center; justify-content: center;
  font-size: 21px; color: #fff; flex-shrink: 0;
}
.wolf-onb-tile-icon.ic-search { background: linear-gradient(135deg, #38bdf8, #0284c7); }
.wolf-onb-tile-icon.ic-key { background: linear-gradient(135deg, #14b8a6, #0d9488); }
.wolf-onb-tile-icon.ic-flag { background: linear-gradient(135deg, #ff7a29, #c94f0f); }
.wolf-onb-tile-title { font-size: 14px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.3px; }
.wolf-onb-tile-desc { font-size: 11.5px; font-weight: 500; color: var(--text-sub); margin-top: 2px; line-height: 1.4; }
.wolf-onb-tile i.ti-chevron-right { margin-left: auto; color: var(--text-sub); flex-shrink: 0; }

/* ========================================================================== */
/* 🐺 WOLF-HQ — Wizard de configuration serveur (R5, pas à pas, animé)        */
/* ========================================================================== */
.wolf-wizard-overlay {
  display: none; position: fixed; inset: 0; background: rgba(6,7,8,0.88); z-index: 5000;
  align-items: center; justify-content: center; padding: 14px; backdrop-filter: blur(4px);
}
.wolf-wizard-overlay.visible { display: flex; }
.wolf-wizard-box {
  width: 100%; max-width: 560px; max-height: 92vh; display: flex; flex-direction: column;
  background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 18px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5); overflow: hidden;
}
.wolf-wizard-head { padding: 18px 22px 0; flex-shrink: 0; }
/* "WOLF" garde la couleur de texte normale du thème ; seul "-HQ" reste en orange (demande de
   Michel : "le HQ doit être en orange et WOLF en noir" — en thème clair var(--text) EST déjà un
   noir quasi pur, en thème sombre c'est le blanc habituel du texte). Règle globale (pas limitée
   au desktop) : utilisée à la fois par la sidebar desktop et par l'en-tête de l'assistant, visible
   sur mobile aussi. */
.wolf-brand-hq { color: var(--gold-bright); }

.wolf-wizard-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.wolf-wizard-brand img { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; }
.wolf-wizard-brand span { font-family: 'Bebas Neue', sans-serif; font-size: 17px; letter-spacing: 1px; color: var(--text); }
.wolf-wizard-progress { display: flex; gap: 4px; margin-bottom: 16px; }
.wolf-wizard-progress-seg { flex: 1; height: 4px; border-radius: 4px; background: var(--border-color); overflow: hidden; }
.wolf-wizard-progress-seg > i { display: block; height: 100%; width: 0%; background: linear-gradient(90deg, var(--gold), var(--gold-bright)); transition: width 0.4s ease; border-radius: 4px; }
.wolf-wizard-progress-seg.done > i { width: 100%; }
.wolf-wizard-progress-seg.current > i { width: 100%; animation: wolfWizardPulse 1.4s ease-in-out infinite; }
@keyframes wolfWizardPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
.wolf-wizard-step-label { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: 1px; color: var(--gold-bright); margin-bottom: 4px; }
.wolf-wizard-title { font-size: 19px; font-weight: 800; margin: 0 0 4px; display: flex; align-items: center; gap: 8px; }
.wolf-wizard-subtitle { font-size: 12.5px; color: var(--text-sub); margin: 0 0 14px; line-height: 1.5; }

.wolf-wizard-body { padding: 4px 22px 18px; overflow-y: auto; flex: 1; }
.wolf-wizard-panel { display: none; animation: wolfWizardIn 0.35s ease; }
.wolf-wizard-panel.active { display: block; }
@keyframes wolfWizardIn { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: translateX(0); } }
@media (prefers-reduced-motion: reduce) { .wolf-wizard-panel { animation: none; } }

.wolf-wizard-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 14px 22px; border-top: 1px solid var(--border-color); flex-shrink: 0; background: var(--card-bg);
}
.wolf-wizard-foot .btn { width: auto; padding: 11px 20px; }
/* Écran de fin ("Aller au tableau de bord") : à ce moment "Passer"/"Précédent" sont display:none,
   il ne reste qu'un seul bouton visible — un centrage explicite est plus fiable que de compter
   sur le comportement par défaut de justify-content:space-between avec un seul élément restant
   (repéré par Michel : le bouton n'était pas centré). */
.wolf-wizard-foot-seul { justify-content: center; }

/* Sur smartphone, 3 boutons pouvaient se retrouver côte à côte à l'avant-dernière étape (Passer +
   Précédent + Terminer la configuration) et se faire écraser contre le bord de la modale (repéré
   par Michel : "le bouton est collé à droite"). On empile les boutons en pleine largeur en dessous
   de 480px — bonus : ça centre aussi de facto le bouton unique de l'écran de fin. */
@media (max-width: 480px) {
  .wolf-wizard-foot { flex-direction: column-reverse; align-items: stretch; gap: 8px; }
  .wolf-wizard-foot > div { flex-direction: column; gap: 8px; }
  .wolf-wizard-foot .btn { width: 100%; }
  .wolf-wizard-skip { text-align: center; }
}
.wolf-wizard-skip { background: none; border: none; color: var(--text-sub); font-size: 11.5px; font-weight: 700; cursor: pointer; text-decoration: underline; padding: 4px; }

.wolf-wizard-welcome { text-align: center; padding: 10px 0 4px; }
.wolf-wizard-welcome img { width: 96px; height: 96px; border-radius: 50%; margin: 0 auto 14px; border: 3px solid var(--gold-bright); box-shadow: 0 0 30px rgba(255,122,41,0.45); object-fit: cover; }
.wolf-wizard-recap { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; text-align: left; }
.wolf-wizard-recap-row { display: flex; justify-content: space-between; align-items: center; padding: 9px 12px; background: var(--card-sub-bg); border-radius: 9px; font-size: 12.5px; }
.wolf-wizard-recap-row span:first-child { color: var(--text-sub); font-weight: 600; }
.wolf-wizard-recap-row span:last-child { font-weight: 800; color: var(--text); }

.wolf-wizard-done { text-align: center; padding: 18px 0 4px; }
.wolf-wizard-done-icon {
  width: 76px; height: 76px; border-radius: 50%; margin: 0 auto 16px; display: flex; align-items: center; justify-content: center;
  font-size: 34px; color: #052e12; background: linear-gradient(135deg, #4ade80, #16a34a);
  box-shadow: 0 0 30px rgba(74,222,128,0.5); animation: wolfWizardPop 0.5s cubic-bezier(0.34,1.56,0.64,1);
}
@keyframes wolfWizardPop { 0% { transform: scale(0); } 70% { transform: scale(1.15); } 100% { transform: scale(1); } }

.wolf-confetti-piece {
  position: fixed; top: -10px; width: 8px; height: 14px; z-index: 5100; pointer-events: none;
  animation: wolfConfettiFall linear forwards;
}
@keyframes wolfConfettiFall {
  to { transform: translateY(110vh) rotate(600deg); opacity: 0.3; }
}
@media (prefers-reduced-motion: reduce) {
  .wolf-confetti-piece { display: none; }
}

/* ============================================================================
   🎯 CENTRE DE COMMANDEMENT ANALYTIQUE — Classements avancés + suivi de puissance
   (includes/modules/classements_avance.php). Styles de base cross-thème ; les
   accents "glow" spécifiques au thème sombre premium sont dans theme-graphite.css.
   ============================================================================ */
/* En-tête "HUD" : icône dans un badge dégradé + titre en texte dégradé cyan → or, pour un rendu
   plus "tactique premium" que le simple texte doré uni utilisé ailleurs dans l'app. */
.ca-hero-card { position: relative; overflow: hidden; border-color: rgba(34,211,238,0.35) !important; box-shadow: 0 4px 18px rgba(34,211,238,0.10); }
.ca-hero-icon {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border-radius: 9px; margin-right: 8px; flex-shrink: 0; font-size: 16px;
  background: linear-gradient(135deg, rgba(34,211,238,0.20), rgba(255,122,41,0.18));
  box-shadow: 0 0 12px rgba(34,211,238,0.22), inset 0 1px 1px 0 rgba(255,255,255,0.08);
}
.ca-hero-titre-texte {
  background: linear-gradient(90deg, var(--gold-bright), var(--cyan, #0891b2));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* Onglets TYPE / PÉRIODE en "segmented control" (fond creusé + boutons collés) plutôt qu'une
   simple rangée de boutons espacés — lecture plus rapide de l'état actif, look plus HUD. */
.ca-tab-group {
  margin-bottom: 10px; display: flex; gap: 4px; background: var(--card-sub-bg);
  padding: 4px; border-radius: 12px; border: 1px solid var(--border-color);
}
.ca-tab-group .btn { flex: 1; min-width: 80px; padding: 9px 6px; font-size: 12px; border-radius: 9px; }

.ca-classement-header {
  display: flex; justify-content: space-between; padding: 0 12px 6px; font-size: 10px;
  color: var(--text-sub); text-transform: uppercase; letter-spacing: 0.5px; font-weight: 700;
}
.ca-classement-row {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; margin-bottom: 6px;
  background-color: var(--card-sub-bg); border-radius: 10px; border-left: 3px solid transparent;
  transition: transform 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
.ca-classement-row:hover { transform: translateX(2px); }
/* Podium (rangs 1-3) : léger dégradé de fond assorti à la couleur du badge de rang, pour repérer
   le podium d'un coup d'œil dans la liste sans casser la lisibilité des lignes suivantes. */
.ca-classement-row.ca-rang-1 { background: linear-gradient(90deg, rgba(255,183,58,0.14) 0%, var(--card-sub-bg) 75%); }
.ca-classement-row.ca-rang-2 { background: linear-gradient(90deg, rgba(180,190,204,0.14) 0%, var(--card-sub-bg) 75%); }
.ca-classement-row.ca-rang-3 { background: linear-gradient(90deg, rgba(205,141,84,0.14) 0%, var(--card-sub-bg) 75%); }

/* Badge de rang circulaire — remplace l'ancien texte brut "#4" par une pastille cohérente avec
   les médailles du podium (émojis 🥇🥈🥉 pour 1-3, numéro pour le reste). */
.ca-rang {
  font-size: 12px; font-weight: 800; color: var(--text-sub); flex-shrink: 0;
  width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--card-bg); border: 1px solid var(--border-color);
}
.ca-rang-1 {
  font-size: 15px; background: linear-gradient(135deg, #ffe4a3 0%, #ff9d2e 100%); color: #3a2400;
  border-color: transparent; box-shadow: 0 0 12px rgba(255,183,58,0.45);
}
.ca-rang-2 {
  font-size: 15px; background: linear-gradient(135deg, #eef2f6 0%, #a7b2c0 100%); color: #1e293b;
  border-color: transparent; box-shadow: 0 0 10px rgba(160,172,190,0.4);
}
.ca-rang-3 {
  font-size: 15px; background: linear-gradient(135deg, #e0ac78 0%, #9a6531 100%); color: #2a1500;
  border-color: transparent; box-shadow: 0 0 10px rgba(180,110,50,0.4);
}
.ca-infos { flex: 1; min-width: 0; }
.ca-pseudo { font-size: 13px; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ca-sous-infos { font-size: 10px; color: var(--text-sub); margin-top: 1px; }
.ca-valeur { text-align: right; flex-shrink: 0; }
.ca-valeur-principale { font-size: 14px; font-weight: 800; color: var(--gold-bright); }
.ca-progression { font-size: 11px; font-weight: 700; margin-top: 1px; }
.ca-progression-positive { color: #4ade80; }
.ca-progression-negative { color: #f87171; }
.ca-progression-neutre { color: var(--text-sub); }

.ca-badge-moi {
  display: inline-block; font-size: 9px; font-weight: 800; letter-spacing: 0.5px; padding: 1px 6px;
  border-radius: 8px; margin-left: 6px; background: var(--cyan); color: #fff; vertical-align: middle;
}
.ca-classement-row.ca-ligne-moi { border-left-color: var(--cyan); background: rgba(8,145,178,0.10); }
.ca-mon-profil-card { position: relative; overflow: hidden; border-color: rgba(8,145,178,0.4) !important; box-shadow: 0 4px 14px rgba(8,145,178,0.12); }

.ca-form-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
.ca-form-row input {
  flex: 1; min-width: 130px; background: var(--input-bg); border: 1px solid var(--input-border);
  border-radius: 8px; padding: 10px 12px; color: var(--text); font-size: 13px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.ca-form-row input:focus { outline: none; border-color: var(--cyan, var(--accent-blue)); box-shadow: 0 0 0 3px rgba(34,211,238,0.15); }

.ca-membres-select { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.ca-chip {
  font-size: 11px; font-weight: 600; padding: 6px 12px; border-radius: 16px; border: 1px solid var(--border-color);
  background: var(--card-sub-bg); color: var(--text-sub); cursor: pointer; user-select: none;
  transition: all 0.15s ease;
}
.ca-chip:hover { border-color: var(--cyan, var(--accent-blue)); color: var(--text); transform: translateY(-1px); }
.ca-chip.active { background: var(--cyan); color: #fff; font-weight: 700; border-color: transparent; }

/* 🕐 HORLOGES ACCUEIL (heure serveur + heure locale du membre connecté, voir index.php et
   assets/js/pays.js) — structure de base cross-thème ici ; les accents "lueur" cyan premium du
   thème sombre sont dans theme-graphite.css (même principe que la section CENTRE DE
   COMMANDEMENT ANALYTIQUE juste au-dessus). */
.whq-horloges-card { position: relative; overflow: hidden; text-align: center; }
.whq-horloges-grid { display: flex; align-items: center; justify-content: center; gap: 14px; flex-wrap: wrap; padding: 6px 0 2px 0; }
.whq-horloge-bloc { flex: 1; min-width: 130px; max-width: 220px; }
.whq-horloge-label {
  display: flex; align-items: center; justify-content: center; gap: 5px; font-size: 11px; font-weight: 700;
  letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-sub); margin-bottom: 4px;
}
.whq-horloge-digits {
  font-family: 'Bebas Neue', sans-serif; font-size: 34px; font-weight: 700; letter-spacing: 2px;
  color: var(--text); line-height: 1.1; font-variant-numeric: tabular-nums;
}
.whq-horloge-serveur .whq-horloge-digits { color: var(--gold-bright); }
.whq-horloge-moi .whq-horloge-digits { color: var(--cyan, var(--accent-blue)); }
.whq-horloge-separateur { font-size: 18px; color: var(--text-sub); opacity: 0.5; }
.whq-train-horaire-ligne {
  display: flex; align-items: center; justify-content: center; gap: 18px; flex-wrap: wrap;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-color); font-size: 12px; color: var(--text-sub);
}
.whq-train-horaire-ligne strong { color: var(--text); font-weight: 700; }

/* 📌 PIED DE PAGE PUBLIC — minimaliste et discret (28/08/2026, demande de Michel), voir
   includes/footer_public.php. Remplace l'ancien bloc "carte" avec 3 gros boutons pleins, commun
   désormais à index.php (toutes pages principales, hors chaque .app-page) et inscription-alliance.php.
   .container réserve déjà 75px en bas pour .nav-bar (position:fixed, hors flux) : ce footer, ajouté
   en fin de .container, n'a donc pas besoin de marge supplémentaire pour ne pas passer dessous. */
.site-footer-public {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 6px; padding: 14px 10px 10px; margin-top: 6px;
  border-top: 1px solid var(--border-color);
}
.footer-lien {
  display: inline-flex; align-items: center; gap: 4px;
  background: none; border: none; padding: 2px 2px; margin: 0;
  font-size: 11px; font-weight: 500; color: var(--text-sub);
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.footer-lien i { font-size: 12px; }
.footer-lien:hover { color: var(--accent-gold); }
.footer-separateur { font-size: 11px; color: var(--text-sub); opacity: 0.5; }

/* 📌 SELECT — fond sombre cohérent sur le menu déroulant natif (28/08/2026, demande de Michel :
   le menu déroulant du champ "Objet" du formulaire "Signaler un problème" affichait un fond
   blanc/clair du navigateur en thème sombre). color-scheme indique au navigateur le thème du menu
   natif ; les règles sur "option" sont un filet de sécurité pour les navigateurs qui les respectent
   encore (Firefox notamment) — sans effet néfaste ailleurs. */
select { color-scheme: dark; }
body.light-theme select { color-scheme: light; }
select option {
  background-color: #1a1a1a; color: var(--text);
}
body.light-theme select option {
  background-color: #ffffff; color: var(--text);
}
