:root {
    --background: #1a1b1e;
    /* Couleurs de texte Discord standard (demande 2026-10-12 "iso niveau
       style que desc" — écart trouvé par comparaison des styles calculés :
       desc utilise --text-main:#dbdee1/--text-muted:#949aa4 (Discord
       --text-normal/--text-muted), pas un blanc quasi pur comme ici avant.
       --primary reste blanc pur volontairement : c'est la couleur de FOND
       des éléments actifs/primaires (ex. .gb-nav-item.active), pas une
       couleur de texte — chez desc aussi .fside-item.active a
       background:#fff, sans rapport avec --text-main. */
    --foreground: #dbdee1;
    --card: oklch(0.205 0 0);
    --card-foreground: #dbdee1;
    --muted-foreground: #949aa4;
    --border: oklch(1 0 0 / 10%);
    --border-strong: oklch(1 0 0 / 22%);
    --primary: oklch(0.985 0 0);
    --primary-foreground: oklch(0.145 0 0);
    --secondary: oklch(0.269 0 0);
    --accent: oklch(0.269 0 0);
    --radius: 14px;
    --sidebar-w: 256px;

    /* aliases pour compat */
    --bg: var(--background);
    --text: var(--foreground);
    --text-muted: var(--muted-foreground);
}

* { box-sizing: border-box; }

body {
    background: var(--bg);
    color: var(--text);
    font-family: 'gg sans', 'Inter', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    min-height: 100vh;
    position: relative;
    overflow-x: hidden;
}

/* Fond façon desc.gg : lueurs radiales ambiantes fixes + grille subtile */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        radial-gradient(circle at 15% 20%, rgba(255,255,255,0.07), transparent 40%),
        radial-gradient(circle at 85% 80%, rgba(67,181,129,0.05), transparent 40%);
    z-index: -1;
    pointer-events: none;
}
.grid-bg {
    position: fixed;
    inset: 0;
    background-image:
        linear-gradient(to right, rgba(255,255,255,0.02) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(255,255,255,0.02) 1px, transparent 1px);
    background-size: 3rem 3rem;
    z-index: -2;
    pointer-events: none;
}

.gb-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    transition: transform .2s ease, border-color .2s ease;
}
.gb-card:hover {
    transform: translateY(-3px);
    border-color: var(--border-strong);
}

.gb-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
    border-radius: 999px;
    font-weight: 600;
    padding: .65rem 1.4rem;
    transition: transform .15s ease, opacity .15s ease, background .15s ease;
    border: 1px solid transparent;
}
.gb-btn:hover { transform: translateY(-2px); opacity: .92; }
.gb-btn:active { transform: translateY(0); }
.gb-btn-primary {
    background: var(--primary);
    color: var(--primary-foreground);
}
.gb-btn-ghost {
    background: transparent;
    border-color: var(--border-strong);
    color: var(--text);
}
.gb-btn-ghost:hover { background: rgba(255,255,255,.05); }
.gb-btn:disabled { opacity: .4; cursor: not-allowed; transform: none; }

.gb-badge {
    display: inline-flex; align-items: center; gap: .35rem;
    font-size: .72rem; font-weight: 600;
    padding: .25rem .6rem; border-radius: 999px;
    background: var(--secondary); color: var(--text);
    border: 1px solid var(--border);
}

.gb-fade-up { animation: gbFadeUp .6s ease both; }
@keyframes gbFadeUp {
    from { opacity: 0; transform: translateY(16px); }
    to { opacity: 1; transform: translateY(0); }
}

.gb-nav-blur {
    background: rgba(10,10,10,.75);
    backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--border);
}

.gb-input {
    background: var(--secondary);
    border: 1px solid var(--border);
    border-radius: 10px;
    color: var(--text);
    padding: .65rem 1rem;
}
.gb-input:focus { outline: none; border-color: var(--border-strong); }

/* Menus déroulants (<select>) : sans ça ils gardent la flèche/l'apparence
   native du navigateur (incohérente entre Chrome/Firefox/Safari, souvent
   moche sur fond sombre) — demande 2026-10-13, "amélioré et met du css sur
   les menu déroulants". appearance:none retire le style natif, chevron
   maison en background-image (pas de pseudo-élément : un <select> ne peut
   pas avoir de ::after). Le menu OUVERT (liste d'options) reste rendu par
   l'OS/navigateur, hors de portée du CSS — seul le bouton fermé est
   stylisable. */
select.gb-input {
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
    padding-right: 2.25rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23949aa4' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .75rem center;
    transition: border-color .15s ease, background-color .15s ease;
}
select.gb-input:hover { border-color: var(--border-strong); background-color: rgba(255,255,255,.04); }
select.gb-input:focus { border-color: var(--border-strong); }
select.gb-input option { background: var(--secondary); color: var(--text); }

.gb-gradient-text { color: var(--text); }

.gb-dot { background: var(--text); }

::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(255,255,255,.12); border-radius: 999px; }

/* --- Sidebar repliable/dépliable, façon beta.desc.gg (.fside) ---
   Même principe : repliée par défaut (icônes seules, 72px), un bouton
   bascule vers déployée (icônes + libellés, 256px), état persisté en
   localStorage. Simplifié par rapport à desc.gg : pas de popovers de
   sous-catégories (guildbox a 5-6 items de nav au total, pas des groupes
   de 3-4 items chacun) — chaque lien reste un lien direct dans les deux
   modes, juste son libellé qui apparaît/disparaît. */
:root { --sidebar-w-icon: 72px; }
.gb-sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: var(--sidebar-w-icon);
    display: flex;
    flex-direction: column;
    background: #08080a;
    border-right: 1px solid #000;
    z-index: 50;
    transform: translateX(-100%);
    transition: transform .25s ease, width .18s ease, background .18s ease;
}
.gb-sidebar.is-open { transform: translateX(0); }
@media (min-width: 1024px) {
    .gb-sidebar { transform: translateX(0); }
    .gb-content { margin-left: var(--sidebar-w-icon); transition: margin-left .18s ease; }
}
[data-gb-collapsed="0"] .gb-sidebar {
    width: var(--sidebar-w);
    background: rgba(15,16,19,.92);
    backdrop-filter: blur(14px);
    box-shadow: 8px 0 30px rgba(0,0,0,.5);
}
@media (min-width: 1024px) {
    [data-gb-collapsed="0"] .gb-content { margin-left: var(--sidebar-w); }
}

/* border-bottom TOUJOURS présente, repliée ou dépliée (demande 2026-10-13,
   "le trait blanc en haut de la navbar est pas aligné avec le trait du
   footer") : avant, seul le footer de la sidebar (.gb-sidebar-footer,
   border-top) gardait sa bordure dans les deux états — le header, lui, ne
   l'avait qu'en mode déplié (0px en repliée, le défaut), créant une
   asymétrie haut/bas. */
.gb-sidebar-header {
    flex: none; display: flex; flex-direction: column; align-items: center; gap: 8px;
    padding: 12px 0; justify-content: center;
    border-bottom: 1px solid var(--border);
}
[data-gb-collapsed="0"] .gb-sidebar-header { flex-direction: row; justify-content: space-between; padding: 0 .6rem 0 .9rem; height: 52px; }
.gb-sidebar-header .gb-brand-text { display: none; }
[data-gb-collapsed="0"] .gb-sidebar-header .gb-brand-text { display: inline; }

/* Logo + bouton bascule : mêmes gabarits/couleurs que beta.desc.gg
   (.fside-logo/.fside-toggle) — demande 2026-10-12 "iso niveau style que
   desc" puis "pas iso" (1er essai : icône FA générique dans une boîte
   carrée grise, alors que le vrai logo de desc est une IMAGE (SVG rond
   plein blurple) à 82% de la boîte, cf. captures comparatives desc.gg vs
   guildbox — c'était l'écart le plus visible). */
.gb-brand { position: relative; display: flex; align-items: center; gap: 10px; text-decoration: none; color: inherit; }
.gb-brand:visited { color: inherit; }
.gb-logo {
    width: 48px; height: 48px; flex: none;
    display: flex; align-items: center; justify-content: center;
    border-radius: 14px; background: #2b2d31;
    transition: background .18s ease;
}
.gb-logo img { width: 82%; height: 82%; object-fit: contain; }
[data-gb-collapsed="0"] .gb-logo { width: 28px; height: 28px; border-radius: 8px; background: rgba(255,255,255,.03); border: 1px solid rgba(255,255,255,.14); }
[data-gb-collapsed="0"] .gb-logo img { width: 18px; height: 18px; }

/* Bascule repli/dépli en onglet collé au bord du panneau — même style que
   #btnToggleLeft dans l'éditeur desc-beta (.ed-panel-tab-left, cf.
   static/css/editor.css là-bas) — demande 2026-10-12 "je veux un bouton
   comme dans l'éditeur [...] par défaut la navbar dépliée". Remplace
   l'ancien bouton carré dans le header. Enfant direct de .gb-sidebar
   (position:fixed, sert de repère) : left:100% le colle au bord droit et
   le fait glisser automatiquement avec elle quand sa largeur transitionne
   (.gb-sidebar a déjà `transition: width .18s ease`), pas besoin de
   dupliquer ici les 2 valeurs de largeur repliée/dépliée. */
.gb-panel-tab {
    position: absolute; left: 100%; top: 50%; transform: translateY(-50%);
    z-index: 9;
    width: 18px; height: 44px;
    display: flex; align-items: center; justify-content: center;
    background: linear-gradient(180deg, #1d2026, #181a1f);
    border: 1px solid var(--border); border-left: none;
    border-radius: 0 10px 10px 0;
    color: var(--text-muted); cursor: pointer;
    transition: color .15s ease, width .15s ease;
}
.gb-panel-tab:hover, .gb-panel-tab:focus-visible { color: var(--text); width: 22px; }
.gb-panel-tab i { font-size: 11px; }
@media (max-width: 1023px) { .gb-panel-tab { display: none; } }

.gb-sidebar-nav { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 12px 0; display: flex; flex-direction: column; align-items: center; gap: 8px; scrollbar-width: none; }
.gb-sidebar-nav::-webkit-scrollbar { display: none; }
[data-gb-collapsed="0"] .gb-sidebar-nav { align-items: stretch; padding: .6rem .5rem; }

/* Items de nav : mêmes gabarits que beta.desc.gg (.fside-item) — boîte
   pleine #2b2d31 au repos en mode replié (pas transparente), survol au
   blurple Discord #5865f2, actif en blanc plein, pastille indicatrice qui
   glisse depuis le bord gauche (::before) au survol/actif. */
.gb-nav-item {
    position: relative;
    display: flex; align-items: center; justify-content: center; gap: 10px;
    width: 48px; height: 48px; border-radius: 14px;
    font-size: 1.05rem; font-weight: 700; color: var(--text);
    background: #2b2d31;
    overflow: hidden;
    transition: background .18s ease, color .18s ease;
}
.gb-nav-item i { width: 1rem; text-align: center; color: inherit; flex: none; transition: color .15s ease; }
.gb-nav-item span { display: none; }
.gb-nav-item::before {
    content: '';
    position: absolute; left: -16px; top: 50%;
    width: 8px; height: 8px; background: #fff; border-radius: 0 4px 4px 0;
    opacity: 0; transform: translateY(-50%) scale(.4);
    transition: all .2s cubic-bezier(.4,0,.2,1);
}
.gb-nav-item:hover::before { opacity: 1; transform: translateY(-50%) scale(1); height: 20px; }
.gb-nav-item.active::before { opacity: 1; transform: translateY(-50%) scale(1); height: 40px; }
.gb-nav-item:hover { background: #5865f2; color: #fff; }
.gb-nav-item.active { background: #fff; color: #000; }
[data-gb-collapsed="0"] .gb-nav-item {
    width: 100%; height: 34px; justify-content: flex-start; padding: 0 10px; border-radius: 7px;
    font-size: .84rem; font-weight: 500; color: var(--text);
    background: transparent;
}
[data-gb-collapsed="0"] .gb-nav-item i { color: var(--text-muted); font-size: .82rem; }
[data-gb-collapsed="0"] .gb-nav-item::before { display: none; }
[data-gb-collapsed="0"] .gb-nav-item span { display: inline; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
[data-gb-collapsed="0"] .gb-nav-item:hover { background: rgba(255,255,255,.06); color: var(--text); }
[data-gb-collapsed="0"] .gb-nav-item:hover i { color: var(--text); }
[data-gb-collapsed="0"] .gb-nav-item.active { background: rgba(255,255,255,.09); color: var(--text); }
[data-gb-collapsed="0"] .gb-nav-item.active i { color: var(--text); }

/* Tooltip icône-seule (mode replié uniquement) — même principe que
   beta.desc.gg (.fside-item[data-tip]), délai avant apparition pour ne
   pas clignoter en scannant plusieurs icônes d'affilée. */
.gb-nav-item[data-tip]::after {
    content: attr(data-tip);
    position: absolute; left: calc(100% + 12px); top: 50%; transform: translateY(-50%);
    background: #111214; color: #fff; padding: .4rem .65rem; border-radius: 6px;
    font-size: .78rem; font-weight: 600; white-space: nowrap;
    box-shadow: 0 8px 20px rgba(0,0,0,.5);
    pointer-events: none; z-index: 9999; opacity: 0;
    transition: opacity .12s ease .35s;
}
.gb-nav-item[data-tip]:hover::after { opacity: 1; }
[data-gb-collapsed="0"] .gb-nav-item[data-tip]::after { content: none; }

/* min-height fixe (demande 2026-10-13, "c'est pas encore aligné" — un
   1er essai en ajustant juste le padding du footer principal avait réduit
   l'écart à 5px sans l'éliminer) : les deux footers (celui-ci et
   .gb-footer, static/css/style.css plus bas / templates/base.html) visent
   EXACTEMENT la même hauteur totale via cette valeur partagée, plus fiable
   qu'un padding ajusté à la main des deux côtés séparément. */
.gb-sidebar-footer { flex: none; min-height: 68px; padding: .6rem; border-top: 1px solid var(--border); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .4rem; }
[data-gb-collapsed="0"] .gb-sidebar-footer { align-items: stretch; padding: .6rem; }
/* Compte replié : avatar seul (centré, pas de nom/déconnexion visibles —
   un clic ouvrirait un popover dans un système plus complet ; guildbox
   garde l'avatar comme simple indicateur "connecté", le menu complet
   n'apparaît qu'en mode déplié). */
.gb-sidebar-footer .gb-account-expanded { display: none; }
[data-gb-collapsed="0"] .gb-sidebar-footer .gb-account-expanded { display: flex; }
.gb-sidebar-footer .gb-account-collapsed { display: flex; }
[data-gb-collapsed="0"] .gb-sidebar-footer .gb-account-collapsed { display: none; }
.gb-sidebar-footer .gb-btn-primary span { display: none; }
[data-gb-collapsed="0"] .gb-sidebar-footer .gb-btn-primary span { display: inline; }
.gb-sidebar-footer .gb-btn-primary { width: 48px; height: 48px; padding: 0; border-radius: 14px; }
[data-gb-collapsed="0"] .gb-sidebar-footer .gb-btn-primary { width: 100%; height: auto; border-radius: 999px; padding: .65rem 1.4rem; }

/* Bouton d'ouverture mobile flottant (même système que beta.desc.gg,
   .fside-mobile-toggle) : plus de barre d'en-tête, juste ce bouton fixe
   en haut à gauche, visible sous le breakpoint lg (cf. classe Tailwind
   lg:hidden posée sur le bouton lui-même). */
.gb-mobile-toggle {
    display: flex; align-items: center; justify-content: center;
    position: fixed; top: .75rem; left: .75rem; z-index: 48;
    width: 2.1rem; height: 2.1rem;
    border: 1px solid var(--border); border-radius: 8px;
    background: rgba(15,16,19,.92);
    backdrop-filter: blur(8px);
    color: var(--text-muted);
    box-shadow: 0 4px 16px rgba(0,0,0,.35);
}
.gb-mobile-toggle:hover { color: var(--text); }

.gb-sidebar-backdrop {
    display: none;
    position: fixed; inset: 0; background: rgba(0,0,0,.5);
    z-index: 45; backdrop-filter: blur(1px);
}
.gb-sidebar-backdrop.is-open { display: block; }

/* --- Plein écran sans scroll de page --- */
html, body { height: 100%; overflow: hidden; }
.gb-content { height: 100vh; height: 100dvh; display: flex; flex-direction: column; overflow: hidden; }
/* scrollbar-gutter:stable (audit 2026-10-13, "la barre de défilement de
   cette page longue réduit la largeur disponible [...] décalage de 5px
   [sur /tos]") : .gb-main est le VRAI conteneur qui scrolle (overflow-y
   ici, pas html) — sans ce gutter réservé, une page assez longue pour
   avoir une scrollbar visible perd ~15px de largeur utile par rapport à
   une page courte qui n'en a pas, décalant tout son contenu centré. */
.gb-main { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow-y: auto; scrollbar-gutter: stable; }
.gb-main > section { width: 100%; }
.gb-footer { flex: none; min-height: 68px; display: flex; align-items: center; border-top: 1px solid var(--border); }

/* Ecrans bas : on masque les textes secondaires pour éviter tout scroll */
@media (max-height: 820px) { .gb-hide-short { display: none !important; } }
@media (max-height: 820px) {
    .gb-main > section { padding-top: .5rem; padding-bottom: .5rem; }
    .gb-input { padding-top: .45rem; padding-bottom: .45rem; }
    .gb-ts-row { padding: .35rem .7rem !important; }
    .gb-icon-btn { width: 1.7rem !important; height: 1.7rem !important; }
}
.gb-icon-btn { width: 2rem; height: 2rem; }

/* Mobile (<1024px, seuil où la sidebar redevient un panneau hors-écran
   ouvert/fermé par le bouton flottant) : toujours en mode libellés
   complets quel que soit l'état replié/déplié persisté depuis le desktop
   — même principe que beta.desc.gg (cf. commentaire équivalent dans son
   style.css). Un panneau mobile ouvert en pur icônes serait illisible, le
   repli n'a de sens QUE comme gain de place permanent sur grand écran.
   Sélecteurs identiques à [data-gb-collapsed="0"] ci-dessus, dupliqués ici
   (pas une seule déclaration partagée) : ce bloc doit gagner en mobile
   MÊME quand data-gb-collapsed="1" est posé sur body, donc ne peut pas
   dépendre de cet attribut. */
@media (max-width: 1023px) {
    .gb-sidebar { width: min(82vw, 280px) !important; background: rgba(15,16,19,.92); backdrop-filter: blur(14px); }
    .gb-sidebar-header { flex-direction: row; justify-content: space-between; padding: 0 .6rem 0 .9rem; height: 52px; border-bottom: 1px solid var(--border); }
    .gb-sidebar-header .gb-brand-text { display: inline; }
    .gb-logo { width: 28px; height: 28px; border-radius: 8px; background: rgba(255,255,255,.03); border: 1px solid rgba(255,255,255,.14); }
    .gb-logo img { width: 18px; height: 18px; }
    .gb-sidebar-nav { align-items: stretch; padding: .6rem .5rem; }
    .gb-nav-item {
        width: 100%; height: 34px; justify-content: flex-start; padding: 0 10px; border-radius: 7px;
        font-size: .84rem; font-weight: 500; color: var(--text); background: transparent;
    }
    .gb-nav-item i { color: var(--text-muted); font-size: .82rem; }
    .gb-nav-item::before { display: none; }
    .gb-nav-item span { display: inline; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .gb-nav-item:hover { background: rgba(255,255,255,.06); color: var(--text); }
    .gb-nav-item:hover i { color: var(--text); }
    .gb-nav-item.active { background: rgba(255,255,255,.09); color: var(--text); }
    .gb-nav-item.active i { color: var(--text); }
    .gb-nav-item[data-tip]::after { content: none; }
    .gb-sidebar-footer { align-items: stretch; padding: .6rem; }
    .gb-sidebar-footer .gb-account-expanded { display: flex; }
    .gb-sidebar-footer .gb-account-collapsed { display: none; }
    .gb-sidebar-footer .gb-btn-primary span { display: inline; }
    .gb-sidebar-footer .gb-btn-primary { width: 100%; height: auto; border-radius: 999px; padding: .65rem 1.4rem; }
}

/* --- Cartes de serveurs : inclinaison 3D + lueur qui suit le curseur
   (demande 2026-10-12, "utilise reactbits pour améliorer le visuel" —
   effet porté en vanilla JS/CSS, pas de dépendance React/Three.js pour une
   simple interaction de carte, cohérent avec le reste du site (rendu
   Jinja, cf. templates/_server_card.html) et avec les fonds desc.gg du
   même jour, eux aussi portés en vanilla plutôt qu'en React malgré la
   source reactbits.dev). Classe DÉDIÉE .gb-server-card (pas .gb-card
   directement, utilisée partout sur le site pour des cartes génériques
   sans rapport — messages flash, formulaires, dashboard) : seules les
   cartes de l'annuaire/landing reçoivent cet effet. */
.gb-server-card {
    position: relative;
    overflow: hidden;
    transform-style: preserve-3d;
    transition: transform .15s ease, border-color .2s ease;
    will-change: transform;
}
/* Remplace le hover générique .gb-card:hover (translateY seul) : le tilt
   dynamique posé en JS (voir plus bas) assigne directement `transform`,
   qui entrerait en conflit/flicker avec la règle CSS :hover si on la
   laissait active en plus. */
.gb-server-card:hover { border-color: var(--border-strong); }
/* Lueur radiale centrée sur la position du curseur (--mx/--my, mises à
   jour en JS à chaque mousemove) — masquée tant qu'aucun survol n'a eu
   lieu (opacity 0 par défaut, cf. script), jamais de glow figé au centre
   avant la première interaction. */
.gb-server-card::before {
    content: '';
    position: absolute; inset: 0;
    background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 50%), rgba(255,255,255,.08), transparent 65%);
    opacity: 0;
    transition: opacity .25s ease;
    pointer-events: none;
}
.gb-server-card:hover::before { opacity: 1; }
/* Les enfants (icône, texte, badges...) restent dans leur propre plan —
   sans translateZ ils suivraient platement la rotation de la carte entière
   (effet "feuille plate inclinée"), avec elle se détachent légèrement en
   profondeur (vrai effet de carte 3D, cf. reactbits "Tilted Card"). */
.gb-server-card > * { transform: translateZ(18px); }
@media (prefers-reduced-motion: reduce) {
    .gb-server-card { transition: none; }
    .gb-server-card > * { transform: none; }
}
/* Tactile : pas de survol réel, le tilt resterait figé sur la dernière
   position touchée au lieu de revenir au neutre — mieux vaut le garder
   purement statique (le translateY/border-color générique de .gb-card
   reste quand même actif, cf. règle de base plus haut dans ce fichier). */
@media (hover: none) {
    .gb-server-card { transform: none !important; transition: none; }
    .gb-server-card > * { transform: none !important; }
    .gb-server-card::before { display: none; }
}

/* --- Bordure animée (effet "Border Beam" reactbits.dev), demande
   2026-10-12 "sur les card du landing" — un 2e effet, en plus du tilt+
   glow ci-dessus, UNIQUEMENT sur les cartes de la page d'accueil
   (.gb-landing-card, posée par templates/index.html seul via
   card_extra_class — les cartes de /explore gardent juste le tilt). Un
   point lumineux tourne en continu le long du contour de la carte,
   indépendant du survol (contrairement au tilt/glow, actif en permanence
   — la landing n'a que 4 cartes à la fois, assez peu pour que l'animation
   continue reste discrète plutôt que surchargée). */
/* 2 essais précédents écartés : (a) double mask xor en mélangeant
   -webkit-mask-composite:xor et mask-composite:exclude sur la MÊME règle
   (incohérent, chaque propriété de composite doit accompagner SA propre
   propriété de mask, pas l'autre) → rendu invisible ; (b) gradient posé
   derrière la carte via z-index négatif → un conic-gradient remplit toute
   sa boîte en tranches angulaires depuis le CENTRE (ce n'est pas un
   anneau) : le triangle perçait visuellement loin dans la carte, pas
   juste un fin liseré sur le bord. Version actuelle : double mask xor
   avec les 2 syntaxes (standard + -webkit-) correctement appariées
   chacune à son propre -composite. */
@property --gb-beam-angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}
.gb-landing-card {
    position: relative;
}
.gb-landing-card::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 2px;
    background: conic-gradient(from var(--gb-beam-angle), transparent 0%, transparent 80%, rgba(255,255,255,.95) 92%, rgba(255,255,255,.4) 97%, transparent 100%);
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    pointer-events: none;
    animation: gb-beam-spin 4s linear infinite;
}
@keyframes gb-beam-spin { to { --gb-beam-angle: 360deg; } }
@media (prefers-reduced-motion: reduce) {
    .gb-landing-card::after { animation: none; display: none; }
}

/* --- Fond de la landing : cartes de serveurs flottantes, même pattern que
   beta.desc.gg (.hero-bg-cards/.hbc-*, static/css/landing.css) — demande
   2026-10-12 "le même style de landing que desc [...] et les card en
   fond, rien d'autre" (remplace le carrousel 3D ET le fond Aurora
   essayés avant, aucun des deux n'est ce que fait réellement desc.gg ici).
   Couleurs reprises des tokens du site (--card/--border/--text-muted) au
   lieu des valeurs desc codées en dur, pour rester cohérent avec le reste
   de guildbox. */
.hero-bg-cards {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
    -webkit-mask-image: radial-gradient(ellipse 62% 55% at 50% 40%, transparent 34%, #000 78%);
    mask-image: radial-gradient(ellipse 62% 55% at 50% 40%, transparent 34%, #000 78%);
}
.hbc-card {
    --rot: 0deg;
    --scale: 1;
    position: absolute;
    width: 188px;
    padding-bottom: 16px;
    border-radius: var(--radius);
    background: var(--card);
    border: 1px solid var(--border);
    box-shadow: 0 18px 44px -12px rgba(0,0,0,.55);
    text-align: center;
    opacity: .55;
    animation: hbc-float 9s ease-in-out infinite;
    will-change: transform;
    overflow: hidden;
}
@keyframes hbc-float {
    0%, 100% { transform: translateY(0) rotate(var(--rot)) scale(var(--scale)); }
    50% { transform: translateY(-20px) rotate(var(--rot)) scale(var(--scale)); }
}
.hbc-banner {
    height: 56px;
    background: linear-gradient(135deg, rgba(88,101,242,.45), rgba(148,156,247,.25));
}
.hbc-avatar {
    width: 46px; height: 46px;
    margin: -23px auto 0;
    border-radius: 12px;
    border: 3px solid var(--card);
    background: var(--secondary);
    overflow: hidden;
}
.hbc-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hbc-name {
    margin-top: 7px;
    padding: 0 12px;
    font-size: .82rem; font-weight: 700; color: var(--card-foreground);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hbc-handle {
    font-size: .7rem; color: var(--muted-foreground);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    padding: 0 12px;
}
.hbc-links { display: flex; flex-direction: column; gap: 6px; padding: 10px 16px 0; }
.hbc-links span { height: 14px; border-radius: 7px; background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.05); }

/* Positions / variations (8 cartes) — mêmes coordonnées que desc.gg */
.hbc-1 { top: 7%;  left: 3%;   --rot: -5deg; --scale: .95; animation-duration: 10s; }
.hbc-2 { top: 5%;  right: 8%;  --rot: 4deg;  --scale: 1.02; animation-duration: 12s; animation-delay: -3s; }
.hbc-3 { top: 40%; left: -2%;  --rot: 6deg;  --scale: .88; animation-duration: 9s;  animation-delay: -5s; }
.hbc-4 { top: 36%; right: 2%;  --rot: -4deg; --scale: .92; animation-duration: 11s; animation-delay: -7s; }
.hbc-5 { top: 70%; left: 9%;   --rot: 3deg;  --scale: .85; animation-duration: 13s; animation-delay: -2s; }
.hbc-6 { top: 66%; right: 11%; --rot: -6deg; --scale: .9;  animation-duration: 10.5s; animation-delay: -8s; }
.hbc-7 { top: 6%;  left: 24%;  --rot: 3deg;  --scale: .8;  animation-duration: 11.5s; animation-delay: -4s; }
.hbc-8 { top: 68%; right: 30%; --rot: -3deg; --scale: .78; animation-duration: 12.5s; animation-delay: -6s; }

@media (max-width: 1280px) { .hbc-7, .hbc-8 { display: none; } }
@media (max-width: 1000px) { .hbc-3, .hbc-4 { display: none; } }
@media (max-width: 720px)  { .hero-bg-cards { display: none; } }
@media (prefers-reduced-motion: reduce) {
    .hbc-card { animation: none; }
}

/* --- Membres ayant un profil desc.gg, sur la fiche serveur (demande
   2026-10-12) — carte bannière+avatar, même langage visuel que .hbc-card
   (landing) mais statique/cliquable, pas animée/décorative. */
.dm-section { margin-top: 1.5rem; }
.dm-title { font-size: .85rem; font-weight: 700; margin-bottom: .6rem; }
.dm-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.dm-card {
    width: 128px;
    border-radius: var(--radius);
    background: var(--card);
    border: 1px solid var(--border);
    overflow: hidden;
    text-decoration: none;
    padding-bottom: 10px;
    transition: border-color .2s ease, transform .2s ease;
}
.dm-card:hover { border-color: var(--border-strong); transform: translateY(-2px); }
.dm-banner {
    height: 42px;
    background: linear-gradient(135deg, rgba(88,101,242,.45), rgba(148,156,247,.25));
    background-size: cover; background-position: center;
}
.dm-avatar {
    width: 42px; height: 42px;
    margin: -21px auto 0;
    border-radius: 12px;
    border: 3px solid var(--card);
    background: var(--secondary);
    overflow: hidden;
}
.dm-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dm-name {
    margin-top: 6px; padding: 0 8px;
    font-size: .76rem; font-weight: 600; color: var(--card-foreground);
    text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
