/* ==========================================================================
   1. CONFIGURATION GLOBALE & RESET
   ========================================================================== */
.no-scrollbar { scrollbar-width: none; -ms-overflow-style: none; }
.no-scrollbar::-webkit-scrollbar { display: none; }

/* Ascenseur horizontal fin doré — onglet Amis */
.custom-scrollbar-h {
    scrollbar-width: thin;
    scrollbar-color: rgba(251,191,36,.3) transparent;
}
.custom-scrollbar-h::-webkit-scrollbar { height: 4px; }
.custom-scrollbar-h::-webkit-scrollbar-track { background: transparent; }
.custom-scrollbar-h::-webkit-scrollbar-thumb {
    background: rgba(251,191,36,.3);
    border-radius: 999px;
}
.custom-scrollbar-h::-webkit-scrollbar-thumb:hover {
    background: rgba(251,191,36,.6);
}

/* Ascenseur fin bleu — modale Aide */
.aide-scroll {
    scrollbar-width: thin;
    scrollbar-color: rgba(96,165,250,.3) transparent;
}
.aide-scroll::-webkit-scrollbar { width: 4px; }
.aide-scroll::-webkit-scrollbar-track { background: transparent; }
.aide-scroll::-webkit-scrollbar-thumb {
    background: rgba(96,165,250,.3);
    border-radius: 999px;
}
.aide-scroll::-webkit-scrollbar-thumb:hover {
    background: rgba(96,165,250,.65);
}

/* Ascenseur fin doré — utilisé dans les onglets du menu user */
.custom-scrollbar {
    scrollbar-width: thin;
    scrollbar-color: rgba(251,191,36,.3) transparent;
}
.custom-scrollbar::-webkit-scrollbar { width: 4px; }
.custom-scrollbar::-webkit-scrollbar-track { background: transparent; }
.custom-scrollbar::-webkit-scrollbar-thumb {
    background: rgba(251,191,36,.3);
    border-radius: 999px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
    background: rgba(251,191,36,.6);
}

/* Appliqué au modal-box lui-même quand il scrolle (menu user, create account) */
.screen-menu-user .modal-box,
.screen-create-account .modal-box {
    scrollbar-width: thin;
    scrollbar-color: rgba(251,191,36,.25) transparent;
}
/* Fenêtres user / lobby / rematch : les ajustements d'échelle après affichage
   (changement d'onglet, contenu tardif) sont lissés au lieu de sauter d'un coup. */
.screen-menu-user .modal-box,
.screen-lobby .modal-box,
.screen-rematch .modal-box { transition: transform .25s ease; }
.screen-menu-user .modal-box::-webkit-scrollbar,
.screen-create-account .modal-box::-webkit-scrollbar { width: 4px; }
.screen-menu-user .modal-box::-webkit-scrollbar-track,
.screen-create-account .modal-box::-webkit-scrollbar-track { background: transparent; }
.screen-menu-user .modal-box::-webkit-scrollbar-thumb,
.screen-create-account .modal-box::-webkit-scrollbar-thumb {
    background: rgba(251,191,36,.25);
    border-radius: 999px;
}
.screen-menu-user .modal-box::-webkit-scrollbar-thumb:hover,
.screen-create-account .modal-box::-webkit-scrollbar-thumb:hover {
    background: rgba(251,191,36,.5);
}
:root {
    /* Valeurs AVANT que le JS n'applique un tapis (applyTapis) : fond sombre neutre,
       accordé à l'écran de connexion. Sans ça, un tapis bleu s'affichait le temps
       du chargement (le v-cloak masque #app, mais pas le fond du body). */
    --tapis-url: none;
    --tapis-color: #0e0814;
    --panel-bg: #eafa7f;
    /* Dimensions réactives des cartes / conteneurs de mains */
    --card-w: 120px;
    --card-h: 175px;
    --hand-w: 800px;
    /* Safe-areas iPhone (encoche, barre home) — lues aussi par app.js pour le scale */
    --safe-top:    env(safe-area-inset-top, 0px);
    --safe-left:   env(safe-area-inset-left, 0px);
    --safe-right:  env(safe-area-inset-right, 0px);
    --safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* Panneaux d'angle du plateau : dégagés de la barre d'état (heure/batterie) et
   de l'encoche en plein écran iOS. Les panneaux ayant un `zoom`, le décalage
   est divisé par --panel-zoom pour correspondre à la vraie safe-area physique. */
.ui-panel.corner-tl { top:  calc(var(--safe-top,0px)    / var(--panel-zoom,1)) !important;
                      left: calc(var(--safe-left,0px)   / var(--panel-zoom,1)) !important; }
.ui-panel.corner-tr { top:  calc(var(--safe-top,0px)    / var(--panel-zoom,1)) !important;
                     right: calc(var(--safe-right,0px)  / var(--panel-zoom,1)) !important; }

body {
    background-color: var(--tapis-color);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    overflow: hidden;
    user-select: none; /* Empêche la sélection de texte */
    font-family: 'Arial', sans-serif;
    margin: 0;
    /* iOS Safari grossit de lui-même le texte de certains blocs (« text
       autosizing »), en paysage surtout. L'application dessine des panneaux
       de largeur fixe : un texte agrandi sans que son cadre bouge en sort ou
       passe à la ligne. On lui rend sa taille nominale — le zoom du lecteur,
       lui, continue de fonctionner. */
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

/* Le tapis n'est le décor QUE de la table de jeu. Connexion, salon, hub et
   revanche peignent déjà leur propre fond par-dessus (cf. `.screen-*` plus
   bas) : le tapis n'y était jamais destiné à être vu. Il ne le devenait que
   dans l'interstice des transitions entre deux écrans, où plus aucun fond ne
   le couvrait — d'où l'apparition brève et incongrue avant le salon.
   La classe est posée sur <body> par app.js selon l'écran courant. */
body.tapis-on {
    background-image: var(--tapis-url);
}

/* iPhone Safari : 100vh déborde sous la barre d'adresse.
   `dvh` (dynamic) suit la zone visible — mais il la suit EN CONTINU : chaque
   fois que Safari rétracte ou réaffiche sa barre d'adresse, la hauteur du
   <body> change, donc celle de `.modal-overlay` (inset:0), donc la position
   de tout ce qui y est centré verticalement. D'où un écran qui tressaute,
   typiquement au retour en portrait, orientation où la barre est présente et
   réagit aux gestes.
   `svh` (small) est la hauteur barre VISIBLE : c'est la même valeur que dvh
   dans son état le plus contraint, mais elle ne bouge jamais. L'application
   étant en `overflow: hidden` et ne défilant pas, elle n'a rien à gagner aux
   quelques pixels que dvh récupère quand la barre se rétracte — et beaucoup à
   perdre à se redimensionner sous les doigts du joueur.
   Le repli sur dvh reste pour les navigateurs qui ignorent svh. */
@supports (height: 100dvh) {
    body.h-screen { height: 100dvh; }
}
@supports (height: 100svh) {
    body.h-screen { height: 100svh; }
}


/* Cache l'application tant que VueJS n'est pas chargé */
[v-cloak] { display: none !important; }

/* Transitions VueJS standards (Fade) */
.fade-enter-active, .fade-leave-active { transition: opacity 0.4s; }
.fade-enter-from, .fade-leave-to { opacity: 0; }


/* ==========================================================================
   2. INTERFACE UTILISATEUR (PANNEAUX, BOUTONS, MODALES)
   ========================================================================== */

/* --- Panneaux d'infos (Coins de l'écran) --- */
/* Gabarit STRICTEMENT commun aux quatre coins : même largeur, même hauteur,
   même bandeau, même fond. Les quatre rectangles s'alignent deux à deux, en
   largeur comme en hauteur — c'est ce qui fait qu'ils se lisent comme un même
   dispositif et non comme quatre encarts.
   Les 150 px d'origine venaient du panneau de score et de ses trois colonnes ;
   une fois « Victoires » retiré, plus rien ne les justifiait : le dernier pli
   n'occupe que 50 px de haut, le contrat une soixantaine.
   `zoom` met le tout à l'échelle (voir --panel-zoom, calculé dans app.js). */
/* Bandeau de titre des panneaux de coin — « MANCHE N° 4 », « DERNIER PLI »,
   « NOUS », « EUX ». Il tient sur une ligne, toujours : le cadre a une largeur
   fixe, et un titre replié y mange la place réservée au contenu. Le libellé
   est court par construction ; s'il fallait un jour rogner, ce serait sur
   l'interlettrage, pas sur le nombre de lignes. */
.ui-panel > div:first-child span { white-space: nowrap; }

.ui-panel {
    width:  200px;
    height: 128px;
    zoom: var(--panel-zoom, 1);
    background-color: var(--panel-bg, #eafa7f) !important;
    border: 1.5px solid rgba(0,0,0,0.22);
    color: #1a1008;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    box-shadow: 0 4px 14px rgba(0,0,0,0.35);
    z-index: 60;
}

/* Panneaux de score (NOUS / EUX, en bas).
   Ils portaient trois colonnes — Victoires, Total, Donne. Le compteur de
   victoires n'apprenait rien pendant la partie (il ne bouge qu'à la fin, et
   l'écran de fin de partie l'affiche déjà) ; les deux données restantes
   tiennent en deux lignes, ce qui laisse enfin de la place aux libellés.
   La hauteur de 128 px vient de là : mesuré, les deux lignes occupent 63 px
   et le corps en offre 77, soit 7 px de respiration de part et d'autre.

   Ligne « libellé à gauche, valeur à droite ». L'alignement des valeurs sur
   le bord droit permet de comparer NOUS et EUX d'un panneau à l'autre sans
   chercher : les chiffres sont à la même distance du bord de l'écran. */
.panel-score-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}
.panel-score-row + .panel-score-row {
    border-top: 1px solid rgba(0,0,0,0.12);
    padding-top: 5px;
    margin-top: 5px;
}
.panel-score-label {
    font-size: 15px;          /* 12px auparavant : à zoom 0,62 il tombait à
                                 7,4 px, illisible sur téléphone. */
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    white-space: nowrap;
}
.panel-score-value {
    font-weight: 900;
    line-height: 1;
    font-variant-numeric: tabular-nums;   /* les chiffres ne dansent pas
                                             quand le score change */
}
/* Le score de la partie prime sur les points de la donne en cours : c'est
   l'écart de corps qui le dit, pas une couleur. */
.panel-score-value.v-total { font-size: 27px; }
.panel-score-value.v-deal  { font-size: 22px; font-weight: 800; }

/* Le preneur, sous le contrat (panneau haut gauche) : une pastille pleine
   NOUS ou EUX, aux couleurs des panneaux de score du bas, puis le pseudo.
   « Par Martine » demandait de lire un nom puis de se souvenir de son camp ;
   la pastille se lit sans réfléchir. */
.contrat-camp {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    max-width: 100%;
    padding: 0 4px;
    font-size: 14px;
    font-weight: 800;
}
.contrat-camp-pill {
    flex: none;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 900;
    letter-spacing: .08em;
    color: #fff;
    line-height: 1.4;
}
.contrat-camp.nous .contrat-camp-pill { background: #1e3a8a; }   /* text-blue-900 des panneaux */
.contrat-camp.eux  .contrat-camp-pill { background: #7f1d1d; }   /* text-red-900 */
.contrat-camp.nous .contrat-camp-nom  { color: #1e3a8a; }
.contrat-camp.eux  .contrat-camp-nom  { color: #7f1d1d; }
/* Téléphone en paysage : au zoom de plancher (0,62), « Enchères en cours… »,
   « (Aucun pli) », le nom du preneur et le classement du tarot tombaient à
   7-9 px. Agrandis ici, ils font environ 11 px à l'écran ; les panneaux
   gardent leurs dimensions (quatre lignes de classement tiennent dans 80). */
@media (max-height: 500px) and (orientation: landscape) {
    .ui-panel .text-sm { font-size: 18px; }
    .contrat-camp { font-size: 18px; }
    .contrat-camp-pill { font-size: 15px; }
    .ui-panel .tarot-classement-ligne { font-size: 17px; line-height: 1.12; }
    .ui-panel .tarot-coin-preneur-nom { font-size: 18px; }
}
.contrat-camp-nom {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Les panneaux du bas descendent jusqu'au bord de l'écran, à leur taille
   normale. Ils en étaient écartés de toute la hauteur de la barre d'accueil,
   ce qui les laissait flotter ; on ne protège plus rien de ce côté, car ils
   sont en `pointer-events: none` — aucun geste à préserver.
   Les safe-areas LATÉRALES, elles, restent nécessaires : couché, l'iPhone
   place son encoche sur un côté, et un panneau ancré à 0 s'y ferait rogner.
   La division par --panel-zoom vaut comme pour les panneaux hauts : le panneau
   étant zoomé, une valeur brute ne correspondrait pas à la safe-area
   physique. */
.ui-panel.corner-bl,
.ui-panel.corner-br { bottom: 0 !important; }
.ui-panel.corner-bl { left:  calc(var(--safe-left,0px)  / var(--panel-zoom,1)) !important; }
.ui-panel.corner-br { right: calc(var(--safe-right,0px) / var(--panel-zoom,1)) !important; }

/* --- Modales (Login / Lobby / Fin de partie) --- */
.modal-overlay {
    position: absolute; inset: 0;
    background-color: rgba(0,0,0,0.7);
    z-index: 100;
    display: flex; align-items: center; justify-content: center;
    pointer-events: auto;
}

.modal-box {
    background: rgba(14, 8, 20, 0.93);
    border: 1px solid rgba(251, 191, 36, 0.22);
    border-radius: 16px;
    box-shadow:
        0 0 0 1px rgba(255,255,255,.03),
        0 24px 60px rgba(0,0,0,0.7),
        0 0 80px rgba(251,191,36,.05);
    backdrop-filter: blur(24px) saturate(1.4);
    -webkit-backdrop-filter: blur(24px) saturate(1.4);
    padding: 1.5rem;
    text-align: center;
    color: white;
    width: 500px; max-width: 95%;
    position: relative;
}

/* --- Signal de défilement ------------------------------------------------
   Mesuré : sur un iPhone en paysage, l'écran de découverte n'affiche que 35 %
   de son contenu, et l'écran d'inscription un tiers. Rien ne le disait — la
   fenêtre paraissait complète, bouton compris, alors qu'il restait les deux
   tiers en dessous.
   `position: sticky` colle ce voile au bas de la zone visible pendant qu'on
   défile, et la marge négative l'empêche d'ajouter la moindre hauteur au
   contenu. La classe est posée par app.js, seul à pouvoir comparer la hauteur
   du contenu à celle de la fenêtre. */
.modal-box.peut-defiler::after {
    content: '▾';
    display: block;
    position: sticky;
    bottom: -1px;
    height: 46px;
    margin-top: -46px;
    /* Un simple assombrissement ne suffisait pas : la fenêtre est déjà sombre,
       et un dégradé vers sa propre couleur ne se voyait pas. Le chevron doré
       dit explicitement qu'il y a une suite. */
    background: linear-gradient(to bottom, rgba(10,5,16,0), rgba(10,5,16,.94) 55%, rgba(10,5,16,.99));
    color: var(--gold, #fbbf24);
    font-size: 17px;
    line-height: 68px;      /* pousse le chevron vers le bas du voile */
    text-align: center;
    text-shadow: 0 1px 6px rgba(0,0,0,.9);
    border-radius: 0 0 15px 15px;
    pointer-events: none;
    opacity: 1;
    transition: opacity .2s ease;
    animation: defileHint 1.8s ease-in-out infinite;
}
@keyframes defileHint {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(3px); }
}
@media (prefers-reduced-motion: reduce) {
    .modal-box.peut-defiler::after { animation: none; }
}
/* Arrivé en bas, le voile n'a plus rien à annoncer : il s'efface. */
.modal-box.peut-defiler.fin-de-course::after { opacity: 0; }
/* Titre « CoinchePassion » (style landing), à cheval sur le liseré du bloc profil
   (le bloc le plus haut du hub). Ce bloc est en retrait du bord qui défile, donc
   le débordement vers le haut n'est pas rogné. Fond sombre discret pour masquer le
   trait doré derrière le texte — pas de bordure ni d'ombre : ce n'est pas un cadre. */
.hub-brand {
    position: absolute; top: 0; left: 20px; transform: translateY(-50%);
    z-index: 6;
    display: flex; align-items: center; gap: 1px;
    font-size: 1.05rem; font-weight: 900; letter-spacing: -.03em;
    color: #fff; white-space: nowrap;
    background: #120a1c; padding: 0 9px;
    text-shadow: 0 2px 6px rgba(0,0,0,.6);
    cursor: default;
}
.hub-brand-gold { color: #fbbf24; text-shadow: 0 2px 6px rgba(0,0,0,.7), 0 0 14px rgba(251,191,36,.35); }

/* ── Jeu en cours ──────────────────────────────────────────────────────────
   Pendant droit de `.hub-brand`, même traitement exactement : à cheval sur le
   liseré, à même le fond du panneau, en POSITION ABSOLUE — la rangée du haut
   est déjà pleine, tout élément dans le flux la décalerait.
   Sobre à dessein : la marque est la vedette, ceci n'est qu'un repère. Le nom
   reprend sa coupe (dernier mot en or, comme « Coinche·Passion »). */
.hub-jeu {
    position: absolute; top: 0; right: 20px; transform: translateY(-50%);
    z-index: 6;
    display: flex; align-items: center; gap: 7px;
    font-size: 0.82rem; font-weight: 900; letter-spacing: -.02em;
    color: #fff; white-space: nowrap;
    background: #120a1c; padding: 0 9px;
    text-shadow: 0 2px 6px rgba(0,0,0,.6);
    cursor: pointer;          /* la plaque entière ouvre le choix du jeu */
}
.hub-jeu-label { color: rgba(255,255,255,.72); }
.hub-jeu-gold  { color: #fbbf24; text-shadow: 0 2px 6px rgba(0,0,0,.7), 0 0 12px rgba(251,191,36,.3); }
/* ── Les deux pastilles d'action de la rangée du haut ──────────────────────
   « Changer › » sous le jeu à droite, « Rejoindre › » sous la marque à gauche.
   Elles se font face au bout de la même ligne : la moindre différence de
   graisse, de teinte ou d'assise saute aux yeux. D'où UNE SEULE recette pour
   les deux, et le chevron sur les deux — c'est la même promesse, « il y a un
   écran derrière ».

   `font-family: inherit` n'est pas cosmétique : un <button> n'hérite PAS de la
   police de la page, il prend celle de l'agent (Arial). Sans cette ligne les
   deux pastilles s'écrivent dans une autre fonte que tout le reste du hub —
   c'était le cas des deux, et cela se voyait sans qu'on sache d'où ça venait. */
.hub-jeu-btn,
.hub-cp-appel {
    display: inline-flex; align-items: center; gap: 2px;
    padding: 2px 6px 2px 7px; border-radius: 5px;
    font-family: inherit;
    font-size: 0.5rem; font-weight: 900; letter-spacing: .1em; text-transform: uppercase;
    background: rgba(251,191,36,.14);
    border: 1px solid rgba(251,191,36,.45);
    color: #fbbf24;
    cursor: pointer; text-shadow: none; white-space: nowrap;
    transition: background .15s, border-color .15s, color .15s;
}
.hub-jeu-btn svg,
.hub-cp-appel svg { width: 7px; height: 7px; flex-shrink: 0; }
/* C'est la PLAQUE entière qui s'éclaire, pas seulement la pastille : c'est le
   nom qu'on regarde et qu'on vise, la pastille n'est que la cible clavier. */
.hub-jeu:hover .hub-jeu-btn,
.hub-jeu-btn:hover,
.hub-cp:hover .hub-cp-appel { background: rgba(251,191,36,.28); border-color: #fbbf24; }
/* LE SIGNE PRÉCÈDE LE MOT, et c'est un changement de sens : ce qui suit un
   nom se lit comme une décoration, ce qui le précède le signe. La place était
   tenue par le joker — mais le joker porte les huit grades du joueur, et un
   même dessin ne peut pas dire à la fois « le site » et « votre niveau ».
   Il reste partout ailleurs : grades, accueil, réseaux, leçons. */
.hub-brand-signe {
    width: 22px; height: 22px; border-radius: 50%; margin-right: 8px;
    box-shadow: 0 2px 8px rgba(0,0,0,.45);
    transition: transform .8s cubic-bezier(.2,.8,.3,1);
}
.hub-brand:hover .hub-brand-signe { transform: rotate(360deg) scale(1.12); }

/* ── Écusson du club Coinche Passion ───────────────────────────────────────
   Même diamètre que le signe de marque, pour que la ligne se lise d'un bloc.
   En or de la marque : c'est une distinction, pas une alerte — d'où l'absence
   de rouge ou de vert.
   Il n'apparaît QUE pour un membre, et le survol l'annonce en le soulevant
   légèrement, comme le signe tourne. */
.hub-cp {
    display: inline-flex; align-items: center; gap: 6px;
    height: 22px; margin-left: 6px; padding: 0;
    /* Sans cela, la pastille qu'il contient hériterait l'Arial de CE bouton-ci
       et son `font-family: inherit` ne servirait à rien. */
    font-family: inherit;
    background: none; border: 0; cursor: pointer; flex-shrink: 0;
    transition: transform .35s cubic-bezier(.2,.8,.3,1), filter .35s ease;
    filter: drop-shadow(0 2px 6px rgba(0,0,0,.5));
}
/* Le disque garde sa taille quoi qu'il arrive : c'est le bouton qui s'allonge
   quand il porte un libellé, pas l'écusson qui rétrécit.
   ENFANT DIRECT, impérativement : en descendant, ce sélecteur attrapait aussi
   le chevron de la pastille et le gonflait à 22 px — même spécificité que
   `.hub-cp-appel svg`, et déclaré après, donc c'est lui qui l'emportait. */
.hub-cp > svg { width: 22px; height: 22px; display: block; flex-shrink: 0; }
.hub-cp-fond   { fill: #1a1205; }
.hub-cp-anneau { fill: none; stroke: #fbbf24; stroke-width: 3; }
/* LE SIGNE DE L'INFINI, TRACÉ ET NON ÉCRIT. Deux raisons, et les deux
   comptent : Georgia ne contient pas U+221E — une partie des machines aurait
   affiché un rectangle vide —, et un tracé garde son épaisseur exacte à
   toutes les tailles, ce qu'une police ne promet pas.
   Il a remplacé les lettres « CP », qui désignaient le SITE et non
   l'abonnement, et dont le rond doré se confondait avec le signe de marque
   posé à 22 px sur la même ligne du hub. */
.hub-cp-inf {
    fill: none; stroke: #fbbf24; stroke-width: 2.8; stroke-linecap: round;
}
.hub-cp:hover { transform: translateY(-2px) scale(1.12);
                filter: drop-shadow(0 3px 10px rgba(251,191,36,.55)); }

/* ── L'écusson éteint ──────────────────────────────────────────────────────
   Le MÊME dessin, en argent, partout où il désigne ce qu'ouvre l'Illimité à
   quelqu'un qui n'y est pas encore : la marque du hub, une vignette
   d'avatar, un onglet. Un seul jeu de couleurs pour les trois — l'or dit
   « c'est à vous », l'argent « c'est dans l'Illimité ».
   Le sélecteur est nu (`.verrouille`) mais ne peut pas déborder : il ne
   touche que des enfants `hub-cp-*`, qui n'existent que dans cet écusson. */
.verrouille .hub-cp-anneau { stroke: rgba(255,255,255,.55); }
.verrouille .hub-cp-inf    { stroke: rgba(255,255,255,.55); }
.verrouille .hub-cp-fond   { fill:   rgba(10,10,14,.85); }
/* Éteint, il ne se dore pas au survol : il se réveille en blanc. */
.hub-cp.verrouille:hover { filter: drop-shadow(0 3px 10px rgba(255,255,255,.35)); }

/* ── L'appel à rejoindre ───────────────────────────────────────────────────
   Un disque muet ne se clique pas : il se lit comme un état — « vous n'en êtes
   pas » — et non comme une porte. Le verbe manquait. Il est ici en pastille,
   dans le vocabulaire déjà employé par `.hub-jeu-btn` à l'autre bout de la
   même rangée : contour or, capitales minuscules, transparent.
   Une différence, et elle est voulue : celle-là est DORÉE AU REPOS, quand
   l'autre attend d'être trouvée. C'est la seule chose du hub qui doive appeler.
   Le mot est « Rejoindre » et non « Rejoindre CP » : l'écusson qui le précède
   dit déjà CP, l'écrire deux fois de suite serait un bégaiement.
   Son habillage est plus haut, partagé avec « Changer › ». */
/* Libellé en main, le bouton ne bondit plus : à cette largeur le grossissement
   ferait sauter la ligne de la marque. Il s'éclaire, et cela suffit. */
.hub-cp.avec-appel:hover { transform: translateY(-1px); }

/* ── Écusson sur une vignette d'avatar ─────────────────────────────────────
   EN BAS À DROITE : le coin haut droit porte déjà la pastille des avatars
   configurables, et deux marques au même endroit se cacheraient.

   Pour qui n'est PAS membre, l'écusson passe à l'argent plutôt que de
   disparaître : il faut que le visage soit visible et désirable — c'est ce
   qu'on gagne en adhérant. Le griser entièrement ou le retirer reviendrait à
   ne rien proposer du tout. */
.avatar-cp-badge {
    position: absolute; right: 7px; bottom: 7px;
    width: 26px; height: 26px; z-index: 4; pointer-events: none;
    filter: drop-shadow(0 2px 5px rgba(0,0,0,.7));
}
/* (les couleurs de l'état éteint sont plus haut, communes à tous les écussons) */

/* ── Teintes réservées au club ─────────────────────────────────────────────
   Une pastille de 24 px ne peut pas porter d'écusson lisible : c'est un LISERÉ
   doré qui la distingue, doublé d'un point à l'angle. Discret par nécessité —
   il y en a trois par palette, soit douze dans la fenêtre.

   Pour un non-membre la teinte reste VISIBLE et cliquable : elle n'est ni
   grisée ni masquée. Comme pour les visages, c'est elle l'argument ; le clic
   explique au lieu d'interdire. */
.teinte-cp {
    position: relative;
    box-shadow: 0 0 0 1px rgba(251,191,36,.85), 0 0 7px rgba(251,191,36,.35);
}
/* ⚠️ LE POINT RESTE À L'INTÉRIEUR DE LA PASTILLE. Débordant de 2 px, il
   suffisait à faire apparaître un ascenseur dans la colonne des teintes : le
   conteneur est en `overflow-y: auto`, et un élément absolu qui dépasse y crée
   un défilement même sans rien ajouter au flux. */
.teinte-cp::after {
    content: ''; position: absolute; right: 1px; bottom: 1px;
    width: 6px; height: 6px; border-radius: 50%;
    background: #fbbf24; box-shadow: 0 0 0 1px rgba(0,0,0,.55);
}
/* Verrouillée : l'or passe à l'argent, comme sur les écussons. */
.teinte-cp-verrou { box-shadow: 0 0 0 1px rgba(255,255,255,.55); }
.teinte-cp-verrou::after { background: rgba(255,255,255,.65); }
/* Rotation déclenchée au clic sur un élément de la partie haute du hub */
.hub-brand-signe.spin { animation: hubBrandSigneSpin .8s cubic-bezier(.2,.8,.3,1); }
@keyframes hubBrandSigneSpin {
    from { transform: rotate(0) scale(1); }
    60%  { transform: rotate(360deg) scale(1.18); }
    to   { transform: rotate(360deg) scale(1); }
}

/* ── Marque « CoinchePassion » au-dessus des fenêtres ───────────────────────
   Hors de la boîte, centrée, à même le fond : elle appartient au site et non au
   formulaire, et elle dit où l'on est à quelqu'un qui arrive souvent d'un lien
   reçu par courrier, sans contexte. Elle remplace le joker seul qui flottait
   dans la boîte et ne nommait rien.
   L'empilement se fait en colonne : la marque et la boîte ne peuvent donc pas
   se recouvrir, même sur un petit écran ou quand le formulaire s'allonge. */
.modal-overlay.screen-login,
.modal-overlay.screen-create-account { flex-direction: column; }
.modal-brand {
    display: inline-flex; align-items: center; flex-shrink: 0;
    margin-bottom: 1.1rem;
    font-size: 1.5rem; font-weight: 900; letter-spacing: -.03em;
    color: #fff; white-space: nowrap; text-decoration: none;
    text-shadow: 0 2px 10px rgba(0,0,0,.75);
}
.modal-brand-gold { color: #fbbf24; text-shadow: 0 2px 8px rgba(0,0,0,.8), 0 0 18px rgba(251,191,36,.4); }
.modal-brand-signe {
    width: 30px; height: 30px; border-radius: 50%; margin-right: 10px;
    box-shadow: 0 2px 10px rgba(0,0,0,.5);
    transition: transform .8s cubic-bezier(.2,.8,.3,1);
}
.modal-brand:hover .modal-brand-signe { transform: rotate(360deg) scale(1.12); }

/* Pastille « C » d'un avatar configurable sélectionné : pulsation pour inviter au clic */
.avatar-config-pulse { animation: avatarConfigPulse 1.15s ease-in-out infinite; }
.avatar-config-pulse:hover { animation: none; }
@keyframes avatarConfigPulse {
    0%, 100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(74,222,128,0.55); }
    50%      { transform: scale(1.18); box-shadow: 0 0 10px 4px rgba(74,222,128,0.85); }
}

/* Retour à l'accueil — présent sur la connexion, le sélecteur de joueur et
   l'inscription. À 12 px et 55 % de blanc, c'était une sortie de secours que
   personne ne voyait : sur ce public, une porte de sortie invisible se traduit
   par une fermeture d'onglet.

   Positionné en ABSOLU dans le coin haut-gauche de la modale : en flux, le
   bouton ajoutait une quarantaine de pixels de hauteur et faisait apparaître
   des barres de défilement. Il se loge ici dans la bande du logo, qui est plus
   haute que lui et centré horizontalement — aucun recouvrement, aucune hauteur
   consommée. */
.back-to-home {
    position: absolute;
    /* À GAUCHE, à la hauteur du titre. Le calcul : 1,5 rem de remplissage de la
       boîte + la moitié de la ligne du titre (1,3 rem, interligne ~1,2) place
       son centre à ~2,25 rem ; le lien faisant ~1,25 rem de haut, il s'aligne
       à 1,6 rem.
       Pas en bas : le bas appartient au bouton principal (« Connexion »,
       « Jouer »), et une sortie posée à côté se toucherait par erreur juste
       avant de valider — on perdrait la saisie. */
    top: 1.6rem; left: 1.1rem;
    z-index: 2;
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 0.9rem; font-weight: 700;
    color: rgba(255,255,255,.55);
    text-decoration: none;
    padding: 2px;
    transition: color .15s;
}
.back-to-home:hover { color: #facc15; }

/* Accueil de la donne de découverte : quatre visages à toucher. Le cadre non
   sélectionné reste sobre, le choix se voit d'un coup d'œil — c'est le seul
   geste demandé avant les cartes. */
.essai-visage {
    width: 84px; height: 84px;
    border-radius: 14px;
    overflow: hidden;
    border: 3px solid rgba(255, 255, 255, .15);
    background: #1a1c2e;
    transition: all .15s;
}
.essai-visage img { width: 100%; height: 100%; object-fit: cover; object-position: center top; display: block; }
.essai-visage:hover { border-color: rgba(251, 191, 36, .55); transform: translateY(-2px); }
.essai-visage.choisi {
    border-color: #facc15;
    box-shadow: 0 0 18px rgba(250, 204, 21, .45);
}

/* ── Sélecteur de joueur (« QUI JOUE ? ») ──────────────────────────────────
   Une seule ligne quelle que soit le nombre de comptes de l'appareil (4 au
   plus) : au-delà de deux, .cp-dense rétrécit les vignettes au lieu de les
   replier. Les tailles sont en clamp() pour tenir aussi sur un téléphone. */
.choose-player-list {
    display: flex; flex-wrap: nowrap; justify-content: center;
    align-items: flex-start; gap: 18px; margin: 8px 0 20px;
}
.choose-player-list .cp-item {
    display: flex; flex-direction: column; align-items: center; gap: 8px; min-width: 0;
}
.choose-player-list .cp-btn {
    display: flex; flex-direction: column; align-items: center; gap: 12px;
    background: transparent; border: none; padding: 0; cursor: pointer;
    min-width: 140px; max-width: 100%;
}
.choose-player-avatar {
    position: relative; overflow: hidden;
    width: 120px; height: 120px;
    border-radius: 16px; border: 3px solid #facc15;
    box-shadow: 0 0 18px rgba(250, 204, 21, 0.3);
    background: #1a1c2e;
    transition: box-shadow .2s, transform .15s;
}
.choose-player-avatar:hover {
    box-shadow: 0 0 26px rgba(250, 204, 21, .55);
    transform: translateY(-2px);
}
.cp-name {
    color: #fbbf24; font-weight: 900; font-size: 1.35rem; letter-spacing: .02em;
    max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Sélecteur à deux classes : .form-link, défini plus bas, l'emporterait sinon. */
.choose-player-list .cp-forget { font-size: 0.95rem; }

.choose-player-list.cp-dense { gap: clamp(8px, 2.5vw, 16px); }
.choose-player-list.cp-dense .cp-btn { min-width: 0; gap: 8px; }
.choose-player-list.cp-dense .choose-player-avatar {
    width: clamp(52px, 17vw, 96px); height: clamp(52px, 17vw, 96px);
    border-width: 2px; border-radius: 12px;
}
.choose-player-list.cp-dense .cp-name {
    font-size: clamp(.72rem, 3vw, 1.05rem);
    max-width: clamp(52px, 17vw, 96px);
}
/* Au-delà de quatre comptes (poste de test, DEVICE_MAX_ACCOUNTS = 10) : UNE
   SEULE RANGÉE, toujours — on se reconnaît d'un coup d'œil sur une ligne, pas
   dans une grille. Les vignettes se partagent la largeur (jusqu'à dix), le
   prénom se coupe s'il le faut. */
.choose-player-list.cp-nombreux {
    flex-wrap: nowrap; gap: 6px; width: 100%; max-width: 100%;
}
.choose-player-list.cp-nombreux .cp-item { flex: 1 1 0; min-width: 0; }
.choose-player-list.cp-nombreux .cp-btn { width: 100%; }
.choose-player-list.cp-nombreux .choose-player-avatar {
    width: clamp(40px, 8vw, 72px); height: clamp(40px, 8vw, 72px);
    border-width: 2px; border-radius: 10px;
}
.choose-player-list.cp-nombreux .cp-name { font-size: clamp(.6rem, 1.4vw, .85rem); max-width: 100%; }
.choose-player-list.cp-nombreux .cp-forget { font-size: .75rem; }
/* La fenêtre s'élargit avec la rangée : 420 px suffisent à quatre comptes,
   pas à dix. Bornée à l'écran, elle reste centrée. */
.screen-login .modal-box.cp-large { max-width: min(94vw, 960px); }
/* Le lien de retrait passe sur deux lignes plutôt que de forcer la colonne. */
.choose-player-list.cp-dense .cp-forget {
    font-size: clamp(.62rem, 2.4vw, .8rem); line-height: 1.15;
    max-width: clamp(60px, 19vw, 100px); white-space: normal;
}

.modal-title {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-size: 1.3rem;
    font-weight: 900;
    color: #fbbf24;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: 1.2rem;
    text-shadow: none;
}

/* --- Éléments de Formulaire --- */
.btn-action {
    background: rgba(251,191,36,.18);
    color: #fbbf24;
    border: 1px solid rgba(251,191,36,.45);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-weight: 900; font-size: 0.95rem; letter-spacing: .06em;
    padding: 12px 24px; border-radius: 10px;
    width: 100%; cursor: pointer;
    box-shadow: 0 4px 16px rgba(251,191,36,.1);
    transition: all .15s;
}
.btn-action:hover {
    background: rgba(251,191,36,.28);
    border-color: rgba(251,191,36,.7);
    transform: translateY(-1px);
    box-shadow: 0 6px 20px rgba(251,191,36,.2);
}
.btn-action:active { transform: translateY(0); }
.btn-action:disabled { opacity: .45; cursor: not-allowed; transform: none; }

.btn-secondary {
    background: rgba(255,255,255,.07);
    color: rgba(255,255,255,.7);
    border: 1px solid rgba(255,255,255,.18);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-weight: 900; font-size: 0.95rem; letter-spacing: .06em;
    padding: 12px 24px; border-radius: 10px;
    width: 100%; cursor: pointer;
    transition: all .15s;
}
.btn-secondary:hover {
    background: rgba(255,255,255,.13);
    border-color: rgba(255,255,255,.35);
    color: white;
    transform: translateY(-1px);
}
.btn-secondary:active { transform: translateY(0); }

.input-text {
    width: 100%;
    padding: 0.875rem 1rem;
    border-radius: 0.5rem;
    background: rgba(15, 23, 42, 0.6);
    border: 1px solid rgba(148, 163, 184, 0.3);
    color: white;
    font-size: 1.1rem;
    transition: all 0.15s;
    font-family: inherit;
}

.input-text::placeholder {
    color: rgba(148, 163, 184, 0.5);
}

.input-text:focus {
    outline: none;
    background: rgba(15, 23, 42, 0.9);
    border-color: rgba(148, 163, 184, 0.6);
    box-shadow: 0 0 8px rgba(148, 163, 184, 0.2);
}

.input-uppercase {
    text-transform: uppercase;
}

.password-input-wrapper {
    position: relative;
    display: flex;
    align-items: center;
}

.password-input-wrapper .input-text {
    /* Place du bouton : figée, pour que le texte ne saute jamais. */
    padding-right: 46px;
}

/* Bascule « voir / masquer » : un œil au trait, ni emoji ni couleur propre.
   L'emoji rendait un dessin différent sur chaque système — jaune sur Android,
   bleuté sur iOS, minuscule sur Windows — et sa taille variait avec la police.
   Un tracé SVG est identique partout et suit la couleur du texte.
   40 px de côté : la cible se touche sans viser, alors que le trait reste fin. */
.password-toggle {
    position: absolute;
    right: 0.35rem; top: 50%; transform: translateY(-50%);
    width: 40px; height: 40px;
    display: flex; align-items: center; justify-content: center;
    background: none; border: none; padding: 0;
    color: rgba(148, 163, 184, 0.65);
    cursor: pointer;
    border-radius: 999px;
    transition: color .15s, background .15s;
}
.password-toggle svg { width: 21px; height: 21px; display: block; }
.password-toggle:hover  { color: rgba(226, 232, 240, 1); background: rgba(255,255,255,.07); }
.password-toggle:active { background: rgba(255,255,255,.14); }

.input-text-sm {
    width: 100%; padding: 7px 10px; margin-bottom: 8px;
    border-radius: 6px; border: 2px solid #facc15;
    background: rgba(0,0,0,0.3); color: white;
    font-size: 0.95rem; text-align: center; font-weight: bold;
}
.input-text-sm:focus { outline: none; background: rgba(0,0,0,0.5); }


/* ==========================================================================
   3. CARTES ET DISTRIBUTION
   ========================================================================== */

/* --- Carte Standard --- */
.card-img {
    position: absolute;
    width: var(--card-w); height: var(--card-h);
    border-radius: 8px;
    box-shadow: -3px 3px 6px rgba(0,0,0,0.4);
    background-color: #f0f0f0;  /* Couleur de fond légère au lieu du blanc pur */
    background-image: linear-gradient(
        90deg,
        #f0f0f0 0%,
        #e8e8e8 50%,
        #f0f0f0 100%
    );
    background-size: 200% 100%;
    animation: card-loading 1.5s ease-in-out infinite;
    object-fit: fill;
    transform-origin: center center;
    border: 1px solid #ddd;  /* Bordure légère pour définition */
    /* Position et rotation gérées par JS via style inline (left, top, --rot) */
    transform: rotate(var(--rot));
    transition: left 0.5s cubic-bezier(0.19, 1, 0.22, 1),
                top  0.5s cubic-bezier(0.19, 1, 0.22, 1),
                transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
    will-change: transform, left, top;
    -webkit-user-drag: none;
}

/* Animation de "skeleton loader" pendant le chargement des images */
@keyframes card-loading {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* Une fois l'image chargée, arrêter l'animation et avoir le fond correct */
.card-img.loaded {
    background-image: none !important;
    animation: none !important;
    background-color: white;
    border: none;  /* Enlever la bordure une fois chargée */
}


/* --- Interaction (Main du joueur) --- */
.card-img.interactive { 
    pointer-events: auto; 
    cursor: pointer;
    /* Optimisation pour éviter le délai de clic sur mobile */
    touch-action: manipulation; 
}

/* --- VERSION ORDINATEUR (Souris uniquement) --- */
@media (hover: hover) {
    .card-img.interactive:hover {
        /* translateY AVANT rotate = remontée en coordonnées écran, indépendante de la rotation */
        transform: translateY(calc(var(--card-h) * -0.12)) rotate(var(--rot)) scale(1.08);
        z-index: 100 !important;
        box-shadow: 0 0 25px rgba(255,255,0,0.9);
        border: 2px solid gold;
        transition: transform 0.1s ease-out, box-shadow 0.1s ease-out;
    }
    /* Le clic conserve la position levée — pas de retour arrière */
    .card-img.interactive:active {
        transform: translateY(calc(var(--card-h) * -0.12)) rotate(var(--rot)) scale(1.08);
        z-index: 100 !important;
        box-shadow: 0 0 25px rgba(255,255,0,0.9);
        border: 2px solid gold;
        filter: brightness(1.15);
        transition: none;
    }
}

/* --- VERSION TACTILE (iPad / Mobile) --- */
@media (hover: none) {
    .card-img.interactive:active {
        filter: brightness(1.2);
        transform: rotate(var(--rot)) scale(0.95);
        transition: transform 0.1s;
        z-index: 100 !important;
    }
}

/* --- La carte qu'on vient de jouer ---------------------------------------
   APRES `.loaded` ET `.interactive:hover`, et ce n'est pas un hasard : a
   specificite egale c'est l'ordre du fichier qui tranche, et ces deux-la
   remettraient la bordure et la position de repos.

   `carte-partante` REPREND EXACTEMENT le releve du survol. Le clic pose
   `isProcessing`, qui retire `interactive` et donc le `:hover` : sans cette
   classe, la carte retombait dans son cran avant meme d'etre mesuree, et le
   vol partait vingt pixels sous le point que l'oeil suivait.

   `carte-envolee` l'efface SANS la retirer : elle garde sa place, et
   l'eventail ne se referme qu'a l'atterrissage. Le refermer au depart faisait
   glisser toute la main pendant le vol — `.card-img` transitionne `left`/`top`
   sur 0,5 s, tout juste la duree du trajet — et deux mouvements simultanes ne
   laissent plus rien a quoi accrocher le regard. */
.card-img.carte-partante {
    transform: translateY(calc(var(--card-h) * -0.12)) rotate(var(--rot)) scale(1.08);
    z-index: 100 !important;
    box-shadow: 0 0 25px rgba(255,255,0,0.9);
    border: 2px solid gold;
    /* Rapide, et non les 0,5 s de `.card-img` : au doigt, ou le `:active`
       tactile RETRECIT la carte au lieu de la lever, ce releve est le seul
       accuse de reception du clic. Il doit venir tout de suite. */
    transition: transform 0.12s ease-out;
}
.card-img.carte-envolee {
    opacity: 0;
    /* Instantane : la copie volante prend le relais dans la meme image, et un
       fondu laisserait voir les deux cartes a la fois. */
    transition: none;
}

/* --- Carte Non Jouable (Grisée) --- */
.card-img.dimmed {
    opacity: 1 !important;        /* On garde l'opacité à 100% pour ne pas voir à travers */
    filter: brightness(60%);      /* On baisse la luminosité (effet ombre) */
    cursor: not-allowed !important;
    transition: all 0.2s ease;
    /* Pas de changement d'échelle pour garder l'alignement parfait */
}

/* --- Paquet du Donneur (Effet 3D) --- */
.dealer-deck-container {
    position: relative;
    width: var(--card-w); height: var(--card-h);
}
.deck-card-slice {
    position: absolute; left: 0; bottom: 0;
    width: 100%; height: 100%;
    background-image: var(--back-url, url('/static/cards/back_vert.webp'));
    background-size: cover;
    border-radius: 8px; border: 1px solid #ccc;
    box-shadow: 1px 1px 2px rgba(0,0,0,0.2);
}
.dealer-pos {
    position: absolute; z-index: 15; pointer-events: none;
    display: flex; align-items: center; justify-content: center;
}

/* --- Conteneurs des Mains --- */
.hand-container {
    position: absolute;
    display: flex; justify-content: center; align-items: flex-end;
    width: var(--hand-w); height: 250px;
    pointer-events: none;
}

/* --- Carte Volante (Animation distribution/pli) --- */
.flying-card {
    position: absolute;
    width: var(--card-w); height: var(--card-h);
    background-color: white; 
    border-radius: 8px; border: 2px solid white;
    box-shadow: 0 5px 15px rgba(0,0,0,0.3);
    z-index: 150; 
    transform-origin: center center;
    transition: all 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
    overflow: hidden; 
}
.flying-card img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}

/* --- CARTES SUPPLEMENT (2 cartes reçues après enchères) --- */
.supplement-overlay {
    position: fixed;
    bottom: 200px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 210;
    display: flex;
    gap: 14px;
    pointer-events: none;
}
.supplement-card {
    width: var(--card-w);
    height: var(--card-h);
    border-radius: 8px;
    background: white;
}

/* --- CARTE GAGNANTE DU PLI --- */
.trick-card-winner {
    z-index: 100 !important; /* Passe devant tout le monde */
    transform: rotate(var(--rot)) scale(1.1) !important;
    box-shadow: 0 0 25px rgba(255, 215, 0, 0.8) !important; /* Halo Doré */
    border: 3px solid #facc15 !important;
    transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}


/* ==========================================================================
   BLOC JOUEUR FIXE (Nom + Enchère)
   ========================================================================== */

.player-card {
    position: absolute;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background: transparent;
    border: none;
    box-shadow: none;
    z-index: 50;
    pointer-events: none;
}

/* GESTION DU NOM (Coupe si trop long) */
.player-name {
    width: 95%;            /* Prend presque toute la largeur */
    text-align: center;
    color: white;
    font-weight: bold;
    font-size: 0.9rem;
    
    /* Le secret pour les noms longs : "Jean-Christophe..." */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis; 
}

/* L'ENCHÈRE (Pastille attachée en bas) */
.player-bid-badge {
    position: absolute;
    bottom: calc(-1 * var(--bid-badge-offset, 24px));
    left: 50%;
    transform: translateX(-50%);
    zoom: calc(var(--panel-zoom, 1) * 1.4);

    background-color: #f3f4f6;
    color: #1f2937;
    border: 2px solid #333;
    border-radius: 12px;

    /* Largeur PLANCHER, pas largeur fixe : « 120 ♥ » occupe toujours les mêmes
       115 px, mais un libellé plus long (GÉNÉRALE) pousse le badge au lieu de
       se faire rogner par l'overflow. */
    min-width: 115px;
    width: auto;
    max-width: 160px;
    height: 28px;
    padding: 0 4px;
    overflow: hidden;

    display: flex;
    justify-content: center;
    align-items: center;

    font-size: 0.75rem;
    font-weight: 800;
    white-space: nowrap;
    box-shadow: 0 2px 4px rgba(0,0,0,0.4);
    z-index: 55;
}

/* Le badge d'enchère du TAROT : le badge ENTIER prend la couleur du contrat
   (`data-contrat`, posé par `contratBadge` ; la gamme de la fenêtre du
   contrat). Une pastille colorée dans le badge blanc de la coinche faisait
   deux cadres l'un dans l'autre (18/10/2026). PASSE garde le badge blanc.
   L'étoile violette du chelem prend un halo blanc : elle se lit ainsi sur le
   vert, le jaune, l'orange et le rose. */
.player-bid-badge.badge-tarot {
    background: linear-gradient(180deg, var(--ct-a), var(--ct-b));
    color: var(--ct-texte, #fff);
}
.player-bid-badge .bid-tarot {
    font-weight: 900; font-size: .78rem;
    text-shadow: var(--ct-ombre, 0 1px 1px rgba(0,0,0,.35));
}
.player-bid-badge .bid-tarot-chelem {
    color: #a855f7; margin-left: 4px; font-size: .85rem;
    text-shadow: 0 0 2px #fff, 0 0 3px #fff;
}

/* On s'assure que les images à l'intérieur (les couleurs) ne cassent pas la hauteur */
.player-bid-badge img {
    height: 14px;
    width: 14px;
    margin-left: 4px;
    display: block;
}

/* VARIANTE : Badge au-dessus (Pour le joueur SUD) */
.player-card.badge-top .player-bid-badge {
    bottom: auto;
    top: calc(-1 * var(--bid-badge-offset, 24px));
}


/* ==========================================================================
   ÉTAT ACTIF (C'est à mon tour)
   ========================================================================== */
.active-turn {
    box-shadow: 0 0 15px rgba(255, 215, 0, 0.8), 0 0 30px rgba(255, 140, 0, 0.6);
    /* On remplace transform: scale(1.1); par la propriété native scale */
    scale: 1.1; 
    z-index: 50;
}

/* Animation de réflexion (Anneaux) */
.active-turn::after {
    content: '';
    position: absolute;
    inset: -3px;
    border-radius: 10px;
    border: 2px dashed #fbbf24;
    opacity: 0.6;
    animation: thinking-spin 4s linear infinite;
    pointer-events: none;
}
.active-turn::before {
    content: '';
    position: absolute;
    inset: -3px;
    border-radius: 10px;
    border-top: 2px solid white;
    border-bottom: 2px solid white;
    border-left: 2px solid transparent;
    border-right: 2px solid transparent;
    opacity: 0.4;
    animation: thinking-spin 1.5s linear infinite reverse;
    pointer-events: none;
}

.active-turn .player-name {
    color: #fbbf24;
    text-shadow: 0 0 5px rgba(251, 191, 36, 0.8);
}

@keyframes thinking-spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}
@keyframes spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@keyframes popIn {
    from { transform: scale(0); opacity: 0; }
    to { transform: scale(1); opacity: 1; }
}

/* --- Icône SVG dans le badge (Coeur, Pique...) --- */
.bid-icon {
    height: 1.2em;
    width: auto;
    vertical-align: middle;
    margin-left: 4px;
    margin-bottom: 2px;
    display: inline-block;
    filter: drop-shadow(0 1px 1px rgba(0,0,0,0.3));
}


/* ==========================================================================
   5. INTERFACE D'ENCHÈRES
   ========================================================================== */

.bid-overlay {
    /* 210, comme .announcement-overlay : les deux fenêtres jouent le même rôle
       — on y déclare quelque chose au milieu du plateau — et doivent donc se
       placer au même niveau. À 80, celle-ci passait SOUS les avatars (z=110),
       qui la recouvraient en partie. 210 est aussi la strate que la convention
       du projet réserve aux overlays. */
    position: absolute; inset: 0; z-index: 210;
    background-color: transparent; /* Pas de fond gris, on voit le jeu */
    pointer-events: none; /* Click-through */
    
    /* MODIFICATION ICI : CENTRAGE TOTAL */
    display: flex; 
    justify-content: center; 
    align-items: center; /* C'est ce qui centre verticalement */
}

/* Animation d'entrée/sortie spécifique aux enchères */
.bid-anim-enter-active, .bid-anim-leave-active { transition: opacity 0.3s ease; }
.bid-anim-enter-from, .bid-anim-leave-to { opacity: 0; }

/* ── Enchères de la BELOTE ─────────────────────────────────────────────────
   Deux tours de parole : la carte retournée, puis les trois couleurs qui
   restent. La boîte garde une HAUTEUR FIXE d'un tour à l'autre — sans quoi les
   boutons du bas remonteraient sous le curseur au passage du premier au
   second, et un clic destiné à « Passe » tomberait ailleurs. */
.bid-box.be-box { text-align: center; }
.be-titre {
    color: rgba(255,255,255,.72);
    font-size: 0.78rem; font-weight: 900;
    text-transform: uppercase; letter-spacing: .08em;
    margin-bottom: 10px; min-height: 1.1em;
}
/* La retourne est posée sur le TAPIS, au centre, pendant toute la phase
   d'enchères : les autres joueurs annoncent « Passe » ou « Je prends », ce qui
   n'a aucun sens sans voir la carte. Elle emprunte `.card-img` — c'est une
   carte comme les autres, à la même taille. */
/* Décalée d'une DEMI-LARGEUR DE CARTE vers la gauche : la fenêtre d'enchères
   occupe la place symétrique à sa droite, et l'ensemble reste centré. */
.be-retourne-tapis {
    position: relative; z-index: 60;
    transform: translateX(calc(-1 * var(--card-w, 90px) / 2));
}

/* La fenêtre s'ouvre À CÔTÉ de la carte, jamais dessus. */
.bid-overlay.be-overlay {
    justify-content: flex-start;
    padding-left: calc(50% + 14px);
}

/* Largeur d'UNE CARTE, exactement.
   La boîte est mise à l'échelle par `zoom: --panel-zoom * 1.4` : une largeur
   posée ici s'affiche multipliée par ce facteur. Pour obtenir --card-w à
   l'écran, il faut donc la diviser par le zoom.

   Le sélecteur porte DEUX classes : `.bid-box` déclare `width: min(420px,90vw)`
   plus bas dans ce fichier, et l'emporterait à spécificité égale. */
.bid-box.be-box {
    width: calc(var(--card-w, 90px) / var(--panel-zoom, 1) / 1.4);
    padding: 10px;
}
/* Une colonne d'une carte de large : les boutons d'action s'empilent — un
   libellé comme « JE PRENDS » ne tient pas à côté de « PASSE ». */
.bid-box.be-box .bid-actions-row { flex-direction: column; gap: 8px; }
.bid-box.be-box .bid-actions-row > button { width: 100%; }

/* Les trois couleurs, EN LIGNE. Elles se partagent la largeur disponible au
   lieu d'une taille fixe : à 56 px chacune, elles déborderaient d'une boîte
   large d'une seule carte — et sur téléphone, plus rien ne serait cliquable. */
.be-suits {
    display: flex; flex-direction: row;
    gap: 6px; align-items: center; justify-content: center;
    margin-bottom: 10px;
}
.be-suits .btn-suit {
    flex: 1 1 0; min-width: 0;
    width: auto; height: auto; aspect-ratio: 1;
    border-radius: 9px;
}
.be-suits .btn-suit img { width: 68%; height: 68%; }

.bid-box {
    pointer-events: auto;
    zoom: calc(var(--panel-zoom, 1) * 1.4);
    margin-bottom: 0;
    width: min(420px, 90vw);
    background: rgba(14, 8, 20, 0.93);
    border: 1px solid rgba(251,191,36,.22);
    border-radius: 16px;
    padding: 14px;
    box-shadow:
        0 0 0 1px rgba(255,255,255,.03),
        0 20px 60px rgba(0,0,0,0.7),
        0 0 60px rgba(251,191,36,.06);
    backdrop-filter: blur(20px) saturate(1.5);
    -webkit-backdrop-filter: blur(20px) saturate(1.5);
    animation: slideUpFade 0.3s ease-out;
}

@keyframes slideUpFade {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
}

/* Compteur de points */
.bid-counter {
    display: flex; align-items: center; justify-content: center;
    gap: 10px; margin-bottom: 10px;
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.08);
    padding: 8px; border-radius: 10px;
}
.bid-value-display {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-size: 2rem; font-weight: 900;
    color: #fbbf24; width: 80px; text-align: center;
}
.btn-counter {
    background: rgba(59,130,246,.2); color: white; font-weight: 900; font-size: 1.2rem;
    width: 32px; height: 32px; border-radius: 50%;
    border: 1px solid rgba(59,130,246,.35); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: all 0.15s;
}
.btn-counter:hover { background: rgba(59,130,246,.4); }
.btn-counter:active { transform: scale(0.9); }
.btn-counter:disabled { opacity: 0.3; cursor: not-allowed; }

/* --- Choix de la couleur -------------------------------------------------
   Les boutons avaient un fond blanc à 9 % sur le fond sombre de la fenêtre :
   les enseignes SVG, dessinées en noir (pique, trèfle) ou en rouge, s'y
   perdaient. Le halo blanc de 5 px qu'elles portaient pour compenser ne
   faisait que les délaver au lieu de les détacher.
   Le fond est désormais clair, ce qui suffit à les faire ressortir sans
   artifice — l'ombre portée discrète remplace le halo. */
.bid-suits-grid {
    display: flex; justify-content: center; gap: 8px; margin-bottom: 10px;
}
.btn-suit {
    width: 56px; height: 56px;
    border-radius: 12px;
    cursor: pointer; display: flex; align-items: center; justify-content: center;
    background: var(--suit-bg);
    border: 1.5px solid var(--suit-bd);
    transition: all .15s;
}
.btn-suit img {
    width: 38px; height: 38px; object-fit: contain;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,.35));
}

/* Les quatre couleurs partagent le même fond : ce sont les enseignes qui les
   distinguent, pas le bouton. Seul le Sans-Atout se détache, parce qu'il n'est
   pas une couleur mais un contrat d'une autre nature. */
.btn-suit {
    --suit-bg: #e6ecf3;
    --suit-bd: #93a3b8;
}
.btn-suit[data-suit="SA"] {
    --suit-bg: #ded3f7;
    --suit-bd: #9280c4;
}
/* Tout Atout : même statut que le Sans-Atout — un contrat d'une autre nature
   qu'une couleur —, mais une teinte distincte, sans quoi les deux boutons
   voisins ne se distingueraient que par deux lettres. */
.btn-suit[data-suit="TA"] {
    --suit-bg: #f7e3cf;
    --suit-bd: #c49a6c;
}

.btn-suit:hover {
    filter: brightness(1.07);
    transform: translateY(-2px);
}

/* Sélection : un contour franc plutôt qu'une nuance de fond. Sur des boutons
   qui ont désormais tous la même teinte, seul un trait net dit lequel est
   retenu — une variation de clarté serait invisible d'un coup d'œil.
   Trois marqueurs se cumulent pour qu'elle se voie sans être cherchée : un
   contour épais, un second liseré posé à l'extérieur, et le bouton qui grossit
   en se soulevant. L'agrandissement reste sous les 8 px de gouttière qui
   séparent les boutons — la carte choisie ne mord pas sur ses voisines. */
.btn-suit.selected {
    border-color: #fbbf24;
    border-width: 5px;
    transform: translateY(-5px) scale(1.14);
    box-shadow: 0 0 0 3px rgba(251,191,36,.5),
                0 0 30px rgba(251,191,36,.85),
                0 8px 18px rgba(0,0,0,.55);
}

/* Boutons d'Action (Valider, Passe, Coinche) */
.bid-actions-row { display: flex; justify-content: space-between; gap: 8px; }

.btn-take, .btn-pass, .btn-coinche {
    flex: 1; padding: 9px 0;
    font-weight: 800; font-size: 0.88rem;
    border-radius: 10px; cursor: pointer; border: none;
    text-transform: uppercase; letter-spacing: .05em;
    transition: all .2s ease;
}

.btn-take {
    background: rgba(34,197,94,.85);
    color: white; border-bottom: none;
    box-shadow: 0 4px 14px rgba(34,197,94,.3);
}
.btn-take:hover:not(:disabled) {
    background: #22c55e;
    transform: translateY(-1px);
    box-shadow: 0 6px 18px rgba(34,197,94,.45);
}
.btn-take:disabled { filter: grayscale(1); opacity: 0.4; cursor: not-allowed; }

.btn-coinche {
    background: rgba(239,68,68,.85);
    color: white; border-bottom: none;
    box-shadow: 0 4px 14px rgba(239,68,68,.3);
}
.btn-coinche:hover {
    background: #ef4444;
    transform: translateY(-1px);
    box-shadow: 0 6px 18px rgba(239,68,68,.45);
}
.btn-coinche.active { animation: pulse 1s infinite; }

.btn-pass {
    background: rgba(107,114,128,.25);
    color: rgba(255,255,255,.75);
    border: 1.5px solid rgba(255,255,255,.15);
    border-bottom: 1.5px solid rgba(255,255,255,.15);
}
.btn-pass:hover { background: rgba(107,114,128,.45); transform: translateY(-1px); }

.btn-take:active, .btn-pass:active, .btn-coinche:active {
    transform: translateY(0); border-bottom-width: 0; margin-top: 0;
}


/* ==========================================================================
   6. SYSTÈME DE NOTIFICATIONS (TOASTS)
   ========================================================================== */

.message-toast {
    position: absolute;
    zoom: calc(var(--panel-zoom, 1) * 1.4);
    padding: 10px 24px;
    border-radius: 12px;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-weight: 800;
    font-size: 1rem;
    text-align: center;
    /* 700 : au-dessus des modales de jeux de jetons (z-600) pour rester visible
       pendant une partie de roue/manchot/etc. (sous le popup badge z-9000) */
    z-index: 700; pointer-events: none;
    white-space: nowrap;
    transition: opacity 0.3s;
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}

.msg-type-info {
    background: rgba(14, 8, 20, 0.90);
    color: #93c5fd;
    border: 1px solid rgba(99,179,237,.3);
    font-size: 1rem;
    font-weight: 800;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    box-shadow: 0 8px 28px rgba(0,0,0,0.55);
}

.msg-type-announce {
    background: rgba(14, 8, 20, 0.90);
    color: #fbbf24;
    border: 1px solid rgba(251,191,36,.35);
    font-size: 1.6rem;
    font-weight: 900;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    box-shadow: 0 0 30px rgba(251,191,36,.15), 0 8px 28px rgba(0,0,0,0.55);
}

.msg-type-error {
    background: rgba(14, 8, 20, 0.90);
    color: #fca5a5;
    border: 1px solid rgba(239,68,68,.3);
    font-size: 1rem;
    font-weight: 800;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    box-shadow: 0 8px 28px rgba(0,0,0,0.55);
}

.msg-type-success {
    background: rgba(14, 8, 20, 0.90);
    color: #86efac;
    border: 1px solid rgba(34,197,94,.3);
    font-size: 1rem;
    font-weight: 800;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    box-shadow: 0 8px 28px rgba(0,0,0,0.55);
}

/* Positions relatives */
.msg-pos-center { top: 50%; left: 50%; }


/* --- Fenêtre d'Annonces (Style identique aux Enchères) --- */

/* --- Overlay transparent pour les Annonces (Comme les Enchères) --- */
.announcement-box {
    zoom: calc(var(--panel-zoom, 1) * 1.4);
    width: min(500px, 95vw);
    background: rgba(14, 8, 20, 0.93);
    border: 1px solid rgba(251,191,36,.2);
    border-radius: 16px;
    padding: 20px;
    box-shadow:
        0 0 0 1px rgba(255,255,255,.03),
        0 20px 60px rgba(0,0,0,0.7),
        0 0 60px rgba(251,191,36,.06);
    backdrop-filter: blur(20px) saturate(1.5);
    -webkit-backdrop-filter: blur(20px) saturate(1.5);
    text-align: center;
    color: white;
    pointer-events: auto;
}

.announcement-title {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    color: #fbbf24;
    font-size: 1rem;
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: .12em;
    margin-bottom: 16px;
    border-bottom: 1px solid rgba(255,255,255,.08);
    padding-bottom: 10px;
}

.announcement-row {
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 10px;
    padding: 10px 15px;
    margin-bottom: 8px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.announcement-name {
    font-weight: 800;
    color: rgba(255,255,255,.9);
    font-size: 1rem;
    text-transform: uppercase;
    letter-spacing: .04em;
}


.mini-card-list {
    display: flex;
    gap: 4px;
    align-items: center;
}


/* 33×50 (au lieu de 40×60) : les quatre cartes du pli occupent 144 px, ce qui
   tient dans les 200 px du gabarit commun — c'est cette contrainte qui fixait
   auparavant la largeur des quatre panneaux à 264 px. Le rapport 1/1,515 reste
   celui d'une carte. */
.mini-card-img {
    width: 33px;
    height: 50px;
    background-color: white;
    border-radius: 3px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.5);
    border: 1px solid #ccc;
}

.announcement-actions {
    display: flex;
    gap: 20px;
    justify-content: center;
    margin-top: 25px;
}

/* Boutons plus modernes */
.btn-declare {
    background: linear-gradient(to bottom, #22c55e, #16a34a);
    color: white; font-weight: bold; padding: 10px 25px; border-radius: 5px;
    box-shadow: 0 4px 0 #15803d; transition: transform 0.1s;
}
.btn-declare:active { transform: translateY(2px); box-shadow: 0 1px 0 #15803d; }

.btn-hush { 
    background: linear-gradient(to bottom, #9ca3af, #6b7280);
    color: white; font-weight: bold; padding: 10px 25px; border-radius: 5px;
    box-shadow: 0 4px 0 #4b5563; transition: transform 0.1s;
}
.btn-hush:active { transform: translateY(2px); box-shadow: 0 1px 0 #4b5563; }
.btn-hush:hover { background: #6b7280; }


/* --- NOUVEAU STYLE RECAPITULATIF --- */
.recap-box {
    zoom: calc(var(--panel-zoom, 1) * 1.4);
    background: rgba(17, 17, 26, 0.97);
    border: 1px solid rgba(255, 255, 255, 0.14);
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.8), inset 0 0 0 1px rgba(255, 255, 255, 0.05);
    border-radius: 16px;
    /* Plus de padding sur la boîte : les bandeaux vont d'un bord à l'autre,
       comme sur la fiche challenge dont ce bilan reprend la présentation. */
    padding: 0;
    /* `hidden` en X pour que les bandeaux respectent les coins arrondis, mais
       `auto` en Y : en paysage sur téléphone le bilan dépasse la hauteur utile
       et se faisait trancher, pied compris.
       La division par le zoom n'est pas cosmétique : `max-height` s'exprime en
       unités locales, que le zoom multiplie ensuite. Sans elle, une boîte
       plafonnée à 92 dvh se rend à 92 dvh × 1,4 et dépasse largement l'écran —
       c'est ce qu'on observait sur un iPhone SE, 773 px rendus pour 667
       disponibles. Le pied collant (voir `.recap-foot`) complète le dispositif
       en gardant « Continuer » sous la main quand le contenu défile. */
    overflow-x: hidden;
    overflow-y: auto;
    max-height: calc(92dvh / var(--panel-zoom, 1) / 1.4);
    color: white;
    max-width: 560px;
    width: 95%;
    position: relative;
    backdrop-filter: blur(10px);
}

/* ── Bilan de manche : bandeau de verdict ─────────────────────────────────
   Le résultat était noyé au milieu du tableau. Il devient l'en-tête, et sa
   couleur donne l'issue de la manche avant même la lecture des chiffres. */
.recap-banner {
    padding: 0.7rem 1.1rem;
    text-align: center;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.recap-banner.ok   { background: rgba(6, 95, 70, 0.35); }
.recap-banner.fail { background: rgba(153, 27, 27, 0.32); }
.recap-banner-sub {
    font-size: 0.62rem; font-weight: 800;
    text-transform: uppercase; letter-spacing: .16em;
    color: rgba(255, 255, 255, 0.45);
}
.recap-banner-title {
    font-size: 1.15rem; font-weight: 900;
    text-transform: uppercase; letter-spacing: .06em;
    margin-top: 2px;
}
.recap-banner.ok   .recap-banner-title { color: #6ee7b7; }
.recap-banner.fail .recap-banner-title { color: #fca5a5; }

/* Contrat : posé en tête de la colonne du preneur. Sa position dit qui a
   demandé — plus besoin de l'écrire. La case reste haute même vide, sinon les
   deux colonnes se décalent. */
.recap-contract-slot {
    min-height: 34px;
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 4px;
}
.recap-contract-pill {
    display: inline-flex; align-items: center; gap: 7px;
    background: #fff; color: #000;
    font-weight: 900; font-size: 1.05rem;
    border-radius: 8px; padding: 3px 12px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, .45);
}

/* Grille deux colonnes — la première colonne du tableau était vide une ligne
   sur deux ; les libellés passent à l'intérieur de chaque cellule. */
.recap-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: rgba(255,255,255,.08); }
.recap-col  { background: rgba(17, 17, 26, .97); padding: 0.55rem 0.9rem; }
.recap-col-head {
    text-align: center; font-weight: 900; font-size: 0.9rem;
    text-transform: uppercase; letter-spacing: .08em;
    padding-bottom: 4px; margin-bottom: 4px;
    border-bottom: 1px solid rgba(255,255,255,.1);
}
.recap-col-head.us   { color: #60a5fa; }
.recap-col-head.them { color: #f87171; }
.recap-line {
    display: flex; align-items: baseline; justify-content: space-between;
    font-size: 0.82rem; padding: 2px 0;
}
.recap-line-label { color: rgba(255,255,255,.5); }
.recap-line-val   { font-weight: 700; font-variant-numeric: tabular-nums; }
.recap-line.sum {
    border-top: 1px solid rgba(255,255,255,.12);
    margin-top: 3px; padding-top: 4px; font-weight: 900;
}
/* --- Le total brut qui EXPLIQUE le verdict ------------------------------
   Le bandeau dit déjà « réussi » ou « chuté » ; ceci désigne le chiffre qui
   en a décidé — celui du preneur, ou celui de la défense quand c'est elle qui
   est passée devant (cf. `recapCause`, app.js).

   OR ET NON VERT/ROUGE, à dessein : la même valeur est une réussite pour un
   camp et une déconvenue pour l'autre. Une couleur de verdict mentirait donc
   à l'un des deux, et ferait double emploi avec le bandeau. L'or ne dit
   qu'une chose — « c'est ici que ça s'est joué » —, vraie des deux côtés.

   ⚠️ RIEN ICI NE CHANGE LA HAUTEUR NI LA LARGEUR DE LA LIGNE. Ni `font-size`,
   ni `padding`, ni `margin` : la fenêtre est déjà dense, et le moindre
   décalage y introduirait un défilement. L'emphase passe par `transform`
   (hors flux), la couleur et l'ombre. */
.recap-line.sum.cause .recap-line-val {
    color: #fbbf24;
    display: inline-block;              /* pour que `transform` s'applique */
    transform-origin: right center;     /* les chiffres restent alignés à droite */
    text-shadow: 0 0 14px rgba(251,191,36,.55);
    animation: recap-cause-pulse 1.1s ease-in-out 3;
}
.recap-line.sum.cause .recap-line-label { color: rgba(251,191,36,.75); }

/* Trois battements, puis le calme : une pulsation sans fin fatigue et gêne la
   lecture des autres chiffres, alors qu'il s'agit d'attirer l'œil une fois. */
@keyframes recap-cause-pulse {
    0%, 100% { transform: scale(1);    text-shadow: 0 0 14px rgba(251,191,36,.55); }
    50%      { transform: scale(1.18); text-shadow: 0 0 22px rgba(251,191,36,.95); }
}
@media (prefers-reduced-motion: reduce) {
    .recap-line.sum.cause .recap-line-val { animation: none; }
}

/* Le cumul d'avant la manche est du contexte : discret, il ne doit pas
   concurrencer les deux chiffres qui comptent. */
.recap-line.prev { font-size: 0.74rem; opacity: .65; }

/* Les deux chiffres décisifs d'une fin de manche : ce qu'on vient de marquer,
   et où l'on en est. Eux seuls sont en gros caractères. */
.recap-line.gain,
.recap-line.total {
    display: block; text-align: center;
    margin-top: 6px; padding: 0;
}
.recap-line.gain .recap-line-label,
.recap-line.total .recap-line-label {
    display: block;
    font-size: 0.62rem; font-weight: 900;
    text-transform: uppercase; letter-spacing: .1em;
}
.recap-line.gain .recap-line-val,
.recap-line.total .recap-line-val {
    display: block; line-height: 1.05;
}
.recap-line.gain  .recap-line-label { color: rgba(251, 191, 36, .75); }
.recap-line.gain  .recap-line-val   { color: #fbbf24; font-size: 1.75rem; font-weight: 900; }
.recap-line.total .recap-line-label { color: rgba(255, 255, 255, .5); }
.recap-line.total .recap-line-val   { font-size: 2rem; font-weight: 900; }
.recap-col.us   .recap-line.total .recap-line-val { color: #60a5fa; }
.recap-col.them .recap-line.total .recap-line-val { color: #f87171; }

/* Progression vers le score cible : dit d'un coup d'œil où en est la partie. */
.recap-progress { height: 4px; border-radius: 2px; background: rgba(255,255,255,.1); overflow: hidden; margin-top: 5px; }
.recap-progress > div { height: 100%; border-radius: 2px; transition: width .6s ease; }
.recap-col.us   .recap-progress > div { background: linear-gradient(90deg, #2563eb, #60a5fa); }
.recap-col.them .recap-progress > div { background: linear-gradient(90deg, #b91c1c, #f87171); }
.recap-target { font-size: 0.6rem; color: rgba(255,255,255,.35); text-align: right; margin-top: 2px; }

/* Pied : compte à rebours, pastilles de validation, bouton */
/* Le pied reste au bas de la fenêtre. Le bilan d'une manche chargée — annonces,
   belote, détail des deux camps — dépasse la hauteur utile d'un téléphone en
   paysage : « Continuer » se retrouvait alors sous la ligne de flottaison d'un
   contenu qui défile, et le décompte tournait sans qu'on puisse l'arrêter. */
.recap-foot {
    padding: 0.6rem 1.1rem 0.75rem;
    border-top: 1px solid rgba(255,255,255,.1);
    position: sticky;
    bottom: 0;
    background: rgba(17, 17, 26, 0.97);
    z-index: 1;
}

/* Pied du bilan : les pastilles « prêt » à gauche, « Continuer » à droite.
   Le bloc des pastilles porte `flex:1` mais gardait le `min-width:auto` par
   défaut : il refusait donc de descendre sous la largeur de son contenu — le
   libellé « n/m prêts » plus une pastille de 28 px par joueur — et poussait le
   bouton hors de la boîte, que son `overflow:hidden` rognait net. D'où un
   « Continuer » coupé sur téléphone.
   `min-width:0` lui rend sa souplesse ; `flex-wrap` sert de filet quand même
   cela ne suffit pas, le bouton passant alors sous les pastilles plutôt que
   de disparaître. */
.recap-foot-row { flex-wrap: wrap; }
.recap-pastilles { min-width: 0; flex-wrap: wrap; }

/* Le macaron du résultat (Réussi/Chuté) */
.result-badge {
    display: inline-block;
    padding: 4px 12px;
    border-radius: 4px;
    font-weight: 900;
    font-size: 0.9rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    box-shadow: 0 2px 10px rgba(0,0,0,0.3);
}
.result-success {
    background: linear-gradient(135deg, #065f46, #059669);
    border: 1px solid #34d399;
    color: #ecfdf5;
}
.result-fail {
    background: linear-gradient(135deg, #7f1d1d, #dc2626);
    border: 1px solid #f87171;
    color: #fef2f2;
}

.btn-timer {
    background: #2563eb; /* Bleu */
    color: white;
    font-weight: bold;
    font-size: 1.2rem;
    padding: 12px 0;
    width: 100%;
    border-radius: 8px;
    border: none;
    border-bottom: 4px solid #1e40af;
    cursor: pointer;
    margin-top: 10px;
    transition: all 0.1s;
}
.btn-timer:active { transform: translateY(2px); border-bottom-width: 0; margin-top: 14px; }

/* --- Formulaire Challenge (admin) --- */
.challenge-input {
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.15);
    border-radius: 6px;
    color: #fff;
    padding: 6px 10px;
    font-size: 12px;
    width: 100%;
    outline: none;
    transition: border-color 0.15s;
}
.challenge-input:focus { border-color: rgba(234,179,8,0.6); }
.challenge-input option { background: #1f2937; color: #fff; }
.challenge-checkbox {
    width: 14px; height: 14px;
    accent-color: #eab308;
    cursor: pointer;
}

/* --- Fond commun aux fenêtres qui passent devant le plateau ---
   Trois s'en servent : présentation des annonces, bilan de manche, modale de
   synchronisation. Une seconde règle identique existait juste au-dessus, dont
   TOUTES les propriétés étaient écrasées par celle-ci : elle annonçait un fond
   transparent et des clics traversants, c'est-à-dire l'inverse de ce qui
   s'appliquait. Elle a été retirée.
   La présentation des annonces lève le voile par `.sans-voile` (plus bas) :
   c'est la seule dont l'essentiel se trouve DERRIÈRE elle. */
.announcement-overlay {
    position: fixed; /* Fixe par rapport à l'écran */
    inset: 0;        /* Prend tout l'écran (Top/Bottom/Left/Right = 0) */
    z-index: 210;    /* Au-dessus des avatars et du recap de manche */

    /* Grisé pour détacher la boîte du plateau. */
    background-color: rgba(0, 0, 0, 0.4);

    /* Centrage du contenu (La boîte de dialogue) */
    display: flex;
    align-items: center;
    justify-content: center;

    /* Le plateau ne se joue pas tant que la fenêtre est là. */
    pointer-events: auto;
}


.msg-type-urgent {
    /* Rouge sombre élégant au lieu du rouge vif */
    background: linear-gradient(135deg, #b91c1c 0%, #7f1d1d 100%); 
    color: white;
    
    /* Bordure plus fine */
    border: 2px solid #facc15; 
    border-radius: 8px;
    
    /* Taille réduite (était 2.5rem) */
    font-size: 1.5rem !important; 
    padding: 8px 20px;
    
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    
    /* Ombres plus douces */
    text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
    box-shadow: 0 5px 15px rgba(0,0,0,0.4);
    
    z-index: 300;
    
    /* Juste une petite entrée dynamique, sans pulsation infinie */
    animation: pop-in 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

@keyframes pop-in {
    from { transform: translate(-50%, -50%) scale(0.8); opacity: 0; }
    to { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}

/* --- BULLES DE DIALOGUE (COMIC STYLE) --- */

/* Quand un player-hud contient une bulle active, il passe au premier plan —
   mais SOUS les fenêtres de jeu (210 : enchères, annonces). À 250, la bulle
   « Passe » d'un robot se posait sur le bouton PASSE (25/10/2026). Le badge
   d'enchère du joueur redit ce que la bulle cachée disait. */
.player-hud:has(.speech-bubble) {
    z-index: 209;
}
/* …sauf au-dessus d'un BILAN (fin de manche de la coinche et du tarot) : les
   répliques y commentent la manche et disparaissent vite, et sous la fenêtre
   on ne les lisait plus du tout (décision du 25/10/2026). */
body:has(.announcement-overlay .recap-box) .player-hud:has(.speech-bubble) {
    z-index: 250;
}

.speech-bubble {
    position: absolute;
    zoom: calc(var(--panel-zoom, 1) * 1.4);

    background: #ffffff;
    color: #1a1a1a;

    padding: 12px 20px;
    border-radius: 12px;
    font-family: 'Arial Black', 'Verdana', sans-serif;
    font-weight: 900;
    font-size: 1.1rem;
    line-height: 1.1;
    text-align: center;
    white-space: nowrap;

    border: 3px solid #000;
    box-shadow: 4px 4px 0px rgba(0,0,0,0.3);

    z-index: 500;
    min-width: 100px;
}

/* --- LE PETIT TRIANGLE (POINTE) --- */
/* On utilise un hack CSS avec des bordures pour faire le triangle */

/* J0 : Bulle au-dessus, flèche en bas pointant vers le joueur */
.bubble-bottom { 
    bottom: 110%; 
    left: 50%; 
    transform: translateX(-50%); 
    margin-bottom: 25px; /* L'espacement que tu avais défini */
}
.bubble-bottom::after { 
    content: ''; 
    position: absolute; 
    top: 100%; 
    left: 50%; 
    transform: translateX(-50%);
    border-width: 12px 12px 0 12px; /* Triangle de 12px pointant vers le bas */
    border-style: solid;
    border-color: #000 transparent transparent transparent; /* Couleur noire en haut */
}
/* J1 : Bulle à gauche du joueur, flèche à droite pointant vers lui */
.bubble-right { right: 110%; top: 50%; transform: translateY(-50%); }
.bubble-right::after { left: 100%; top: 50%; margin-top: -6px; border-width: 6px 0 6px 6px; }

/* J2 : Bulle en-dessous du joueur, flèche en haut pointant vers lui */
.bubble-top { top: 140%; left: 50%; transform: translateX(-50%); }
.bubble-top::after { content: ''; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%);
    border-width: 0 12px 12px 12px; /* Triangle de 12px pointant vers le haut */
    border-style: solid;
    border-color: transparent transparent #000 transparent; /* Couleur noire en bas */
}
/* J3 : Bulle à droite du joueur, flèche à gauche pointant vers lui */
.bubble-left { left: 110%; top: 50%; transform: translateY(-50%); }
.bubble-left::after { right: 100%; top: 50%; margin-top: -6px; border-width: 6px 6px 6px 0; }

.bubble-left::after {
    content: ''; position: absolute; left: -12px; top: 50%;
    transform: translateY(-50%);
    border-width: 12px 12px 12px 0; /* Triangle plus gros */
    border-style: solid;
    border-color: transparent #000 transparent transparent;
}

.bubble-right::after {
    content: ''; position: absolute; right: -12px; top: 50%;
    transform: translateY(-50%);
    border-width: 12px 0 12px 12px;
    border-style: solid;
    border-color: transparent transparent transparent #000;
}

/* 3. Joueur HAUT (Bulle en dessous) */
.bubble-top {
    top: 140%; /* Un peu plus bas */
    left: 50%;
    transform: translateX(-50%);
}

/* 4. Joueur BAS/MOI (Bulle au dessus) */
.bubble-bottom {
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    margin-bottom: 25px; /* Plus d'espace avec la main */
}

.pop-enter-active, .pop-leave-active { 
    transition: opacity 0.2s ease-out, transform 0.2s ease-out; 
}

/* État de départ/fin : Invisible et légèrement plus petit */
.pop-enter-from, .pop-leave-to { 
    opacity: 0; 
    /* On évite de toucher au translate ici pour ne pas casser le centrage */
    /* On joue juste sur l'échelle très légèrement pour un effet de "zoom in" subtil */
    /* Note : Si cela cause encore un micro-décalage, supprimez la partie 'scale(0.9)' */
    transform: scale(0.9); 
}


.msg-type-round-start {
    background: rgba(14, 8, 20, 0.88);
    border: 1px solid rgba(251, 191, 36, 0.35);
    border-radius: 16px;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-size: 1.4rem !important;
    font-weight: 900;
    color: #fbbf24;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    padding: 12px 36px !important;
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    box-shadow: 0 8px 32px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,.04) inset;
    text-shadow: none;
    z-index: 1000;
    animation: toast-enter 0.25s ease-out;
}

@keyframes toast-enter {
    from { opacity: 0; transform: translate(-50%, -60%) scale(0.95); }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

.fullscreen-btn {
    position: fixed;
    top: 2px;
    right: 2px;
    z-index: 1000;
    padding: 2px 4px;
    background: transparent;
    border: none;
    color: rgba(255, 255, 255, 0.55);
    cursor: pointer;
    transition: color 0.2s ease;
    line-height: 1;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.6));
}

.fullscreen-btn:hover {
    color: rgba(255, 255, 255, 0.95);
}

.quit-btn {
    padding: 1px 4px;
    line-height: 1;
    background: transparent;
    border: none;
    cursor: pointer;
    color: rgba(127, 29, 29, 0.55);
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.6));
    transition: color 0.2s ease;
}

.quit-btn:hover {
    color: rgba(127, 29, 29, 0.95);
}

/* BARRE D'ICÔNES LATÉRALE GAUCHE */
/* Barre d'outils de jeu : bouton FAB centré en bas, menu déployé vers le haut.
   left:0/right:0 + justify-center pour un centrage fiable indépendant du zoom.
   pointer-events:none sur le conteneur pour ne pas bloquer les cartes ; réactivé
   sur les enfants interactifs uniquement. */
/* bottom fixe, sans env(safe-area-inset-bottom) : sur iOS la safe-area basse
   (barre home) décalait la barre de ~20px vers le haut, la laissant flotter.
   Choix assumé : la barre est au ras du bas, comme sur desktop. */
.game-toolbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 3px;
    z-index: 205;
    display: flex;
    justify-content: center;
    pointer-events: none;
}
.game-toolbar > * { pointer-events: auto; }
/* `.game-toolbar .sidebar-popout` ne mordait plus : les popouts sont désormais
   téléportés vers <body> et ne descendent plus de la barre. Le
   `pointer-events` vit maintenant sur la classe elle-même (voir plus bas). */
/* Pas de zoom / backdrop-filter / transform sur les ancêtres des popouts :
   ces propriétés créent un « containing block » qui casserait le position:fixed
   (centrage viewport) des panneaux Son / Dire / Disposition imbriqués. */
.toolbar-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}
.toolbar-tools {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 4px;
    max-width: 92vw;
    /* Cadre resserré : les 7 px de marge haute et basse s'ajoutaient à la
       hauteur des boutons et repoussaient d'autant la main de Sud. Le cadre
       reste lisible avec 4, et rend 6 px au plateau. */
    padding: 4px 9px;
    background: rgba(10, 10, 20, 0.92);
    border: 1px solid rgba(255,255,255,0.16);
    border-radius: 14px;
    box-shadow: 0 4px 18px rgba(0,0,0,0.5);
}
.toolbar-tools .sidebar-divider { width: 1px; height: 28px; margin: 0 3px; }
.sidebar-btn {
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: rgba(255,255,255,0.06);
    border-radius: 9px;
    cursor: pointer;
    color: rgba(255, 255, 255, 0.82);
    transition: background 0.15s, color 0.15s, transform 0.1s;
    filter: drop-shadow(0 1px 3px rgba(0,0,0,0.6));
    flex-shrink: 0;
}
.sidebar-btn:hover {
    background: rgba(255, 255, 255, 0.18);
    color: #ffffff;
    transform: scale(1.08);
}
.sidebar-btn:disabled {
    opacity: 0.25;
    cursor: default;
    background: transparent;
}
.sidebar-btn:disabled:hover {
    background: transparent;
    color: rgba(255, 255, 255, 0.25);
    transform: none;
}

/* Astuce plein écran (coach-mark one-shot) : halo pulsé + bulle d'invitation */
@keyframes fsHintPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(251, 191, 36, 0.55); }
    50%      { box-shadow: 0 0 0 9px rgba(251, 191, 36, 0); }
}
.sidebar-btn.fs-hint-pulse {
    background: rgba(251, 191, 36, 0.22);
    color: #fff;
    animation: fsHintPulse 1.4s ease-out infinite;
}
.fs-hint-bubble {
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
    white-space: nowrap;
    background: #fbbf24;
    color: #1a1206;
    font-weight: 900;
    font-size: 0.8rem;
    padding: 8px 12px;
    border-radius: 10px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
    cursor: pointer;
    z-index: 206;
    animation: fsHintBubbleIn 0.25s ease-out;
}
.fs-hint-bubble::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-top-color: #fbbf24;
}
@keyframes fsHintBubbleIn {
    from { opacity: 0; transform: translateX(-50%) translateY(4px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* Tour guidé (coach-marks séquentiels) : overlay non bloquant (le clic traverse
   pour laisser essayer l'élément), anneau pulsé + bulle dorée. */
.coach-overlay { position: fixed; inset: 0; z-index: 9998; pointer-events: none; }
.coach-ring {
    position: fixed;
    border: 3px solid #fbbf24;
    border-radius: 12px;
    animation: coachRingPulse 1.4s ease-out infinite;
    pointer-events: none;
}
@keyframes coachRingPulse {
    0%, 100% { box-shadow: 0 0 0 3px rgba(251,191,36,0.30), 0 0 18px rgba(251,191,36,0.45); }
    50%      { box-shadow: 0 0 0 8px rgba(251,191,36,0.05), 0 0 26px rgba(251,191,36,0.65); }
}
.coach-bubble {
    position: fixed;
    max-width: 240px;
    text-align: center;
    background: #fbbf24;
    color: #1a1206;
    font-weight: 900;
    font-size: 0.82rem;
    line-height: 1.3;
    padding: 9px 13px;
    border-radius: 11px;
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.55);
    pointer-events: none;
    animation: coachBubbleIn 0.2s ease-out;
}
@keyframes coachBubbleIn { from { opacity: 0; } to { opacity: 1; } }
.sidebar-btn.sidebar-btn-active {
    background: rgba(251, 191, 36, 0.25);
    color: #fbbf24;
}
.sidebar-btn.quit-sidebar {
    color: #f87171;
    background: rgba(220, 38, 38, 0.18);
}
.sidebar-btn.quit-sidebar:hover {
    background: rgba(220, 38, 38, 0.4);
    color: #fca5a5;
    transform: scale(1.08);
}
.sidebar-divider {
    width: 28px;
    height: 1px;
    background: rgba(255, 255, 255, 0.18);
    margin: 4px 0;
}

/* ==========================================================================
   FENÊTRES DE LA BARRE D'OUTILS — « Dire… », « Son », « Disposition »
   --------------------------------------------------------------------------
   Les trois avaient chacune leur largeur écrite en dur (220, 260, 280 px) et
   tout leur contenu en style en ligne. Rien ne réagissait au format : sur un
   téléphone les pastilles de message tombaient à 23 px de haut, soit la moitié
   de ce qu'un doigt demande, et sur un grand écran les fenêtres restaient
   minuscules.

   Deux régimes, un seul jeu de règles :
   — téléphone (petit côté < 500 px) : feuille ancrée en bas, pleine largeur ;
   — partout ailleurs : fenêtre flottante centrée, qui grandit par paliers.
   ========================================================================== */
:root {
    --popout-w:  360px;   /* largeur cible de la fenêtre flottante */
    --popout-fs: 13px;    /* corps de référence ; tout le contenu en dérive */
}

.sidebar-popout {
    position: fixed;
    left: 50%;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 100px);
    transform: translateX(-50%);
    pointer-events: auto;
    /* Au-dessus des fenêtres de jeu — enchères, déclaration et présentation
       des annonces, fin de manche — qui partagent toutes le palier 210. Le
       palier reste sous les modales de challenge (265 et plus) et sous les
       toasts (300), qui doivent continuer de tout couvrir.
       Ce chiffre ne suffit que depuis que les popouts sont téléportés vers
       <body> : tant qu'ils descendaient de `.game-toolbar`, celle-ci leur
       imposait son contexte d'empilement (position:fixed + z-index:205) et
       les confinait sous les enchères, quel que soit leur propre z-index. */
    z-index: 215;
    width: min(92vw, var(--popout-w));
    max-height: 76vh;
    overflow-y: auto;
    font-size: var(--popout-fs);
    background: rgba(15, 23, 42, 0.97);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 14px;
    padding: 14px 16px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.7);
}

/* --- Contenu commun aux trois fenêtres --- */
.popout-title {
    font-size: 1.08em;
    font-weight: 900;
    color: var(--gold, #fbbf24);
    text-transform: uppercase;
    letter-spacing: .08em;
    margin-bottom: 12px;
    padding-right: 22px;        /* laisse la place à la croix de fermeture */
}
.popout-close {
    position: absolute;
    top: 8px; right: 10px;
    display: flex; align-items: center; justify-content: center;
    width: 30px; height: 30px;
    background: none; border: none;
    color: rgba(255, 255, 255, 0.45);
    font-size: 1.15em; line-height: 1;
    cursor: pointer; border-radius: 50%;
}
.popout-close:hover { color: #fff; background: rgba(255, 255, 255, 0.1); }

.popout-cat {
    font-size: .8em;
    font-weight: 700;
    color: rgba(255, 255, 255, 0.4);
    text-transform: uppercase;
    letter-spacing: .06em;
    margin-bottom: 5px;
}
/* Pastille de message. `min-height` plutôt qu'une hauteur fixe : le texte reste
   maître, on garantit seulement une surface touchable. */
.popout-chip {
    display: inline-flex; align-items: center;
    min-height: 30px;
    padding: 4px 12px;
    background: rgba(255, 255, 255, 0.07);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 20px;
    color: #fff;
    font-size: .88em;
    cursor: pointer;
    white-space: nowrap;
    transition: background .15s;
}
.popout-chip:hover { background: rgba(251, 191, 36, 0.2); }

.popout-emoji {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 30px; min-height: 30px;
    background: none; border: none;
    font-size: 1.35em; line-height: 1;
    cursor: pointer; border-radius: 6px;
    transition: transform .1s, background .1s;
}
.popout-emoji:hover { transform: scale(1.25); background: rgba(255, 255, 255, 0.08); }

/* Ligne de réglage : libellé à gauche, contrôle à droite. */
.popout-line {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
    min-height: 34px;
}
.popout-line-label { font-size: 1em; color: rgba(255, 255, 255, 0.85); }

/* Interrupteur des réglages du son.
   Les trois dimensions passent par des variables : agrandir l'interrupteur au
   doigt ne demande alors que de les redéfinir, la course du curseur suit
   toute seule. Elle était auparavant écrite en dur (`left: calc(100% - 21px)`)
   et n'aurait pas survécu à un changement de taille. */
.popout-switch {
    --sw-w: 44px;
    --sw-h: 24px;
    --sw-k: 18px;
    position: relative;
    flex-shrink: 0;
    width: var(--sw-w);
    height: var(--sw-h);
    border: none;
    border-radius: calc(var(--sw-h) / 2);
    background: rgba(255, 255, 255, 0.2);
    cursor: pointer;
    transition: background .2s;
}
.popout-switch-knob {
    position: absolute;
    width: var(--sw-k);
    height: var(--sw-k);
    top:  calc((var(--sw-h) - var(--sw-k)) / 2);
    left: calc((var(--sw-h) - var(--sw-k)) / 2);
    background: #fff;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    transition: left .2s;
}
.popout-switch.is-on .popout-switch-knob {
    left: calc(var(--sw-w) - var(--sw-k) - (var(--sw-h) - var(--sw-k)) / 2);
}
/* Choix de disposition des cartes.
   `auto-fit` plutôt que deux colonnes figées : les quatre vignettes se rangent
   d'elles-mêmes selon la place. Sur la feuille d'un téléphone en paysage elles
   tiennent sur une seule ligne, là où deux colonnes laissaient les trois quarts
   de la largeur inutilisés ; en portrait elles retombent sur deux colonnes. */
.popout-presets {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 10px;
}
.popout-preset-label {
    font-size: .82em;
    color: rgba(255, 255, 255, 0.75);
    font-weight: 600;
}

/* Liste de morceaux : même traitement que les autres contrôles. */
.popout-select {
    width: 100%;
    background: rgba(255, 255, 255, 0.07);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 8px;
    padding: 7px 9px;
    font-size: .88em;
    min-height: 34px;
}

/* --- Paliers grands écrans ---
   Même principe que les cartes et les panneaux de coin, déjà proportionnels :
   une fenêtre figée à 360 px paraît perdue sur un 27 pouces. */
@media (min-width: 1600px) and (min-height: 900px) {
    :root { --popout-w: 400px; --popout-fs: 14px; }
}
@media (min-width: 2200px) and (min-height: 1200px) {
    :root { --popout-w: 440px; --popout-fs: 15px; }
}

/* --- Téléphone : feuille ancrée en bas ---
   La double condition reproduit « petit côté < 500 px » : elle attrape aussi
   bien l'iPhone en portrait (390 de large) qu'en paysage (390 de haut), sans
   toucher une tablette en 1024×768.
   Pleine largeur : les pastilles de message se rangent alors sur plusieurs
   colonnes au lieu de s'empiler, et il reste de la place pour des cibles
   réellement touchables. */
@media (max-width: 500px), (max-height: 500px) {
    /* La fenêtre d'enchère reste CENTRÉE : remontée en haut, elle recouvrait
       l'enchère de Nord, affichée juste sous son avatar. C'est sa hauteur
       qu'il fallait réduire, pas sa position.
       Le compteur pesait 92 px sur les 306 de la fenêtre, à lui seul près du
       tiers : le pavé - / valeur / + n'a pas besoin de cette ampleur au doigt,
       les cibles restent au-dessus de 40 px une fois le zoom appliqué. */
    .bid-box { padding: 10px; }
    /* `!important` : le compteur porte aussi `mb-4` de Tailwind, injecté après
       cette feuille et donc gagnant à spécificité égale. */
    .bid-counter { padding: 4px; margin-bottom: 6px !important; gap: 8px; }
    .bid-value-display { font-size: 1.5rem; }
    /* 46 px LOCAUX, soit 40 à l'écran sous le zoom de 0,868 : à 28, le « − »
       et le « + » ne faisaient que 24 px, quoi qu'en disait la note ci-dessus.
       PASSE, COINCHE et VALIDE passent de 30 à 36 px de haut. */
    .btn-counter { width: 46px; height: 46px; font-size: 1.3rem; }
    .bid-box .btn-take, .bid-box .btn-pass, .bid-box .btn-coinche { padding-top: 13px; padding-bottom: 13px; }
    .bid-suits-grid { margin-bottom: 6px; }
    /* Belote, second tour : les trois couleurs EN COLONNE, sur la largeur
       d'une carte et 44 px de haut à l'écran. En ligne, elles ne faisaient
       que 16 px de côté. */
    .bid-box.be-box .be-suits { flex-direction: column; }
    .bid-box.be-box .be-suits .btn-suit {
        width: 100%; flex: none; aspect-ratio: auto;
        height: calc(44px / (var(--panel-zoom, 1) * 1.4));
    }
    .bid-box.be-box .be-suits .btn-suit img { width: auto; height: 70%; }

    /* Bilan de manche : le pied resserre ses marges latérales. Sur un écran
       étroit, « Continuer » dépassait encore de quelques pixels et se faisait
       rogner par l'`overflow` de la boîte. */
    .recap-foot { padding-left: 0.6rem; padding-right: 0.6rem; }
    .recap-pastilles { overflow: hidden; }

    .sidebar-popout {
        /* Les safe-areas LATÉRALES, et pas seulement celle du bas : la page est
           servie en `viewport-fit=cover`, si bien qu'un iPhone couché place son
           encoche sur un côté. Ancrée à 0, la feuille passait dessous et s'y
           faisait rogner. Les marges sont nulles sur un appareil sans encoche,
           donc la pleine largeur est préservée partout ailleurs. */
        left:  var(--safe-left, 0px);
        right: var(--safe-right, 0px);
        width: auto;
        transform: none;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 58px);
        max-height: calc(100dvh - 76px);
        border-radius: 16px 16px 0 0;
        border-left: none; border-right: none; border-bottom: none;
        padding: 12px 16px 14px;
        font-size: 14px;
    }
    .popout-title { margin-bottom: 8px; }
}

/* ==========================================================================
   BARRE D'OUTILS VERTICALE — téléphone en paysage (25/10/2026)
   --------------------------------------------------------------------------
   Centrée en bas, la barre se posait sur la moitié basse de la main de Sud et
   captait les touchers : il ne restait qu'une bande de 56 px de chaque carte
   (coinche), et la rangée des atouts du tarot n'en gardait que 26 à 30 — le
   Petit ne se distinguait plus que par le tri. Sur un écran de 375 à 390 px
   de haut, remonter la main l'aurait jetée sur le pli.
   La barre se range donc à la verticale, au bord droit, sur les dos des
   cartes d'Est (qui ne disent rien), entre les deux panneaux de droite. La
   main ne bouge pas : `_measureToolbar` garde la remontée qu'imposait la barre
   horizontale (TOOLBAR_LIFT_TEL), seule sa moitié basse est libérée. Au
   tarot, l'avatar d'Est se décale d'autant (`tarotPlaces`).
   Les feuilles Son / Dire / Disposition s'ancrent alors au bas de l'écran, à
   gauche de la barre. Sans `transform` sur la barre : cf. la note des
   popouts plus haut.
   ========================================================================== */
@media (max-height: 500px) and (orientation: landscape) {
    .game-toolbar {
        left: auto; right: calc(var(--safe-right, 0px) + 2px);
        top: 0; bottom: 0;
        align-items: center;
    }
    /* `.game-toolbar` en tête : le bloc « RESPONSIVE iPhone », plus bas dans
       la feuille, redéfinit la marge de `.toolbar-tools` */
    .game-toolbar .toolbar-tools {
        flex-direction: column; flex-wrap: nowrap;
        max-width: none;
        padding: 6px 3px;
    }
    .game-toolbar .toolbar-tools .sidebar-divider { width: 28px; height: 1px; margin: 3px 0; }
    .sidebar-popout {
        right: calc(var(--safe-right, 0px) + 48px);
        bottom: env(safe-area-inset-bottom, 0px);
        max-height: calc(100dvh - 12px);
    }
    /* Le badge d'enchère d'Est passe à GAUCHE de son avatar : à droite, il
       allait sous la barre (et se faisait déjà rogner par le bord) */
    .player-bid-badge.badge-est { left: auto !important; right: 60px; }
    /* L'astuce du plein écran s'ouvre à GAUCHE de son bouton */
    .fs-hint-bubble {
        bottom: auto; top: 50%; left: auto; right: calc(100% + 10px);
        transform: translateY(-50%);
        animation: none;
    }
    .fs-hint-bubble::after {
        top: 50%; left: 100%;
        transform: translateY(-50%);
        border-top-color: transparent; border-left-color: #fbbf24;
    }
}

/* --- Écrans tactiles : cibles au doigt ---
   `pointer: coarse` vise le doigt, pas la taille de l'écran : une tablette
   tactile en profite sans que la souris d'un portable soit pénalisée. */
@media (pointer: coarse) {
    .popout-chip   { min-height: 40px; padding: 6px 14px; }
    .popout-emoji  { min-width: 40px; min-height: 40px; }
    .popout-line   { min-height: 44px; }
    .popout-close  { width: 40px; height: 40px; top: 6px; right: 8px; }
    .popout-switch { --sw-w: 56px; --sw-h: 32px; --sw-k: 24px; }
    .popout-select { min-height: 42px; }
}

/* Salon d'attente : bandeau d'actions sous le corps du salon.
   Il remplace le `mt-6` que portaient les boutons quand ils vivaient dans la
   colonne de droite. */
.lobby-actions { margin-top: 1.5rem; }

/* CARTES JOUEUR SALON D'ATTENTE */
.lobby-player-card {
    position: relative;
    border-radius: 16px;
    border: 2px solid rgba(255,255,255,0.12);
    padding: 72px 8px 14px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    transition: border-color 0.3s, background 0.3s, opacity 0.3s;
    background: rgba(0,0,0,0.28);
    text-align: center;
    min-width: 0;
}
.lobby-seat-avatar {
    position: absolute;
    top: -58px;
    left: 50%;
    transform: translateX(-50%);
    width: 120px;
    height: 120px;
    border-radius: 16px;
    overflow: hidden;
    border: 3px solid rgba(255,255,255,0.18);
    box-shadow: 0 6px 20px rgba(0,0,0,0.65);
    background: #1a1c2e;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: border-color 0.3s, box-shadow 0.3s;
}
.lobby-seat-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center top;
}

/* Badge Joker — lobby (avatar 120px) — coin haut-gauche, centre du SVG aligné sur le coin */
.lobby-joker-badge {
    position: absolute;
    top: -62px;                 /* avatar à -58px ; badge 36px → centre sur coin haut-gauche + 10px vers le bas */
    left: calc(50% - 78px);     /* 50% - 60 (demi-avatar) - 18 (demi-badge 36px) */
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 12;
    pointer-events: none;
    transform: rotate(-20deg);
    filter: drop-shadow(0 1px 5px rgba(0,0,0,0.95)) drop-shadow(0 0 3px rgba(0,0,0,0.7));
}
.lobby-joker-badge svg,
.lobby-joker-badge img {
    width: 32px;
    height: auto;
}

/* Badge « prêt » — salon public. Symétrique du Joker, coin haut-DROIT de
   l'avatar : dans un salon public la partie ne part qu'à l'unanimité, il faut
   pouvoir lire d'un coup d'œil qui a validé et qui hésite encore. */
.lobby-pret-badge {
    position: absolute;
    top: -62px;
    left: calc(50% + 42px);     /* 50% + 60 (demi-avatar) - 18 (demi-badge) */
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    font-weight: 900;
    z-index: 12;
    pointer-events: none;
    border: 2px solid;
    box-shadow: 0 1px 6px rgba(0,0,0,0.8);
    transition: all 0.25s;
}
.lobby-pret-badge.pret-oui {
    background: rgba(34,197,94,0.92);
    border-color: #4ade80;
    color: #fff;
}
.lobby-pret-badge.pret-non {
    background: rgba(0,0,0,0.55);
    border-color: rgba(255,255,255,0.28);
    color: rgba(255,255,255,0.45);
}

/* Badge Joker — HUD jeu (avatar 175px) — coin haut-gauche, analogue au jeton donneur bas-droit */
.hud-joker-badge {
    position: absolute;
    top: calc(var(--joker-sz, 52px) / -2);
    left: calc(var(--joker-sz, 52px) / -2);
    width: var(--joker-sz, 52px);
    height: var(--joker-sz, 52px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 12;
    pointer-events: none;
    transform: rotate(-20deg);
    filter: drop-shadow(0 2px 7px rgba(0,0,0,0.95)) drop-shadow(0 0 4px rgba(0,0,0,0.7));
}
.hud-joker-badge svg,
.hud-joker-badge img {
    width: var(--joker-sz, 52px);
    height: auto;
}

/* ═══ Zones d'offrande de cadeaux (boisson / friandise) ═══
   Même taille que le joker. Boisson : bord gauche, milieu hauteur (sous le
   joker). Friandise : coin bas-droit de l'avatar. */
.gift-zone {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0,0,0,0.32);
    border: 1px solid rgba(255,255,255,0.28);
    cursor: pointer;
    opacity: 0.55;
    z-index: 13;
    /* .player-hud a pointer-events:none — on réactive le clic sur la zone elle-même
       pour que l'offrande marche sur TOUS les sièges (moi + bots inclus). */
    pointer-events: auto;
    user-select: none;
    line-height: 1;
    transition: opacity 0.15s, transform 0.15s, background 0.15s;
    filter: drop-shadow(0 1px 3px rgba(0,0,0,0.8));
}
.gift-zone:hover { opacity: 1; background: rgba(0,0,0,0.6); }

/* Pictos des zones : SVG monochromes en mask-image → couleur pilotée en CSS
   (blanc pur). Boisson = un verre ; Friandise = une part de gâteau. */
.gift-ico {
    width: 58%;
    height: 58%;
    background-color: #ffffff;
    pointer-events: none;
    -webkit-mask-repeat: no-repeat;   mask-repeat: no-repeat;
    -webkit-mask-position: center;    mask-position: center;
    -webkit-mask-size: contain;       mask-size: contain;
}
.gift-ico-boisson {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 3v6c0 2.97 2.16 5.43 5 5.91V19H8v2h8v-2h-3v-4.09c2.84-.48 5-2.94 5-5.91V3H6z'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 3v6c0 2.97 2.16 5.43 5 5.91V19H8v2h8v-2h-3v-4.09c2.84-.48 5-2.94 5-5.91V3H6z'/%3E%3C/svg%3E");
}
/* Part de gâteau triangulaire (+ cerise) posée dans une assiette */
.gift-ico-friandise {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='3' r='1.5'/%3E%3Cpath d='M12 5.6 5 16.6h14z'/%3E%3Cpath d='M2.2 16.6h19.6c0 1.9-4.4 3.1-9.8 3.1S2.2 18.5 2.2 16.6z'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='3' r='1.5'/%3E%3Cpath d='M12 5.6 5 16.6h14z'/%3E%3Cpath d='M2.2 16.6h19.6c0 1.9-4.4 3.1-9.8 3.1S2.2 18.5 2.2 16.6z'/%3E%3C/svg%3E");
}

/* Cadeau posé dans une zone : l'image remplit la pastille (au lieu de l'emoji),
   agrandie de 20 % (déborde légèrement, centrée). */
.gift-zone-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
    transform: scale(1.2);
}
/* Une zone qui contient un cadeau : pleine opacité, fond neutre, non cliquable
   (le cadeau se consomme). */
.gift-zone:has(.gift-zone-img) { opacity: 1; background: transparent; border-color: transparent; cursor: default; }
.gift-zone:has(.gift-zone-img):hover { transform: none; }

/* Cadeau en vol pendant l'offrande (part de l'offreur → arrive chez le
   destinataire → se pose dans la zone). */
.flying-gift {
    position: fixed;
    z-index: 500;
    object-fit: contain;
    pointer-events: none;
    filter: drop-shadow(0 8px 20px rgba(0,0,0,0.6));
    will-change: left, top, width, height, transform;
}
/* Offrande à soi-même : le cadeau ORBITE (spirale) sans se retourner. La
   2e rotation (négative) annule l'orientation → l'objet reste droit. */
.flying-gift.gift-selfloop { animation: gift-orbit 0.9s ease-in-out; }
@keyframes gift-orbit {
    0%   { transform: translate(-50%,-50%) rotate(0deg)   translateX(0)    rotate(0deg); }
    50%  { transform: translate(-50%,-50%) rotate(180deg) translateX(32px) rotate(-180deg); }
    100% { transform: translate(-50%,-50%) rotate(360deg) translateX(0)    rotate(-360deg); }
}

/* Lobby — zones dans .lobby-player-card (comme le joker), pour déborder sur le
   bord gauche de l'avatar (l'avatar lui-même a overflow:hidden). Coords carte,
   miroir bas du joker (joker : top:-62 ; left: calc(50% - 78px)).
   Friandise : coin bas-gauche ; Boisson : juste au-dessus. */
.gift-zone.gift-lobby { width: 36px; height: 36px; font-size: 18px; }
.gift-zone.gift-lobby.gift-friandise { left: calc(50% - 78px); top: 30px; }
.gift-zone.gift-lobby.gift-boisson    { left: calc(50% - 78px); top: -10px; }
.gift-zone.gift-lobby:hover { transform: scale(1.12); }

/* HUD jeu — zones empilées sur le bord GAUCHE, ancrage type joker (offsets
   fixes -taille/2, pas de %). Friandise : coin bas-gauche ; Boisson : juste
   au-dessus (même bord gauche). */
.gift-zone.gift-hud { width: var(--joker-sz, 52px); height: var(--joker-sz, 52px); font-size: calc(var(--joker-sz, 52px) * 0.46); }
.gift-zone.gift-hud.gift-friandise { left: calc(var(--joker-sz, 52px) / -2); bottom: calc(var(--joker-sz, 52px) / -2); }
.gift-zone.gift-hud.gift-boisson    { left: calc(var(--joker-sz, 52px) / -2); bottom: calc(var(--joker-sz, 52px) / 2 + 4px); }
.gift-zone.gift-hud:hover { transform: scale(1.12); }

/* ═══ Modale de choix d'un cadeau ═══ */
/* ── Règles du jeu, encadrées ──
   z-index 280 : au-dessus du sélecteur de jeu, qui reste ouvert dessous et
   qu'on retrouve en fermant. ATTENTION : le sélecteur ne s'en tient PAS au 220
   de sa classe `.gift-modal-overlay`, il le surcharge EN LIGNE à 270 — un 230
   ici laissait donc les règles dessous. Les deux seules choses qui doivent
   encore passer par-dessus sont les toasts (300). */
.regles-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.72);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 280;
    padding: 16px;
}
.regles-modal {
    display: flex;
    flex-direction: column;
    width: min(880px, 96vw);
    height: min(88vh, 940px);
    background: #0e0814;                      /* le fond des pages légales */
    border: 1px solid rgba(255,255,255,0.14);
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.75);
    overflow: hidden;                          /* l'iframe suit les arrondis */
}
.regles-modal-bar {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 12px 10px 16px;
    background: rgba(255,255,255,0.04);
    border-bottom: 1px solid rgba(255,255,255,0.10);
}
.regles-modal-titre {
    color: #fff;
    font-weight: 900;
    font-size: 0.95rem;
    line-height: 1.2;
}
.regles-modal-x {
    flex-shrink: 0;
    width: 30px; height: 30px;
    border-radius: 8px;
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.16);
    color: rgba(255,255,255,0.75);
    font-size: 0.85rem;
    font-weight: 900;
    cursor: pointer;
    transition: all .15s;
}
.regles-modal-x:hover { background: rgba(255,255,255,0.18); color: #fff; }
.regles-modal-frame {
    flex: 1;
    width: 100%;
    border: 0;
    display: block;
    background: #0e0814;
}

.gift-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.62);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 220;
    padding: 20px;
}
.gift-modal {
    background: linear-gradient(160deg, #1f2136, #14162a);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 18px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.7);
    padding: 16px 20px 14px;
    width: min(460px, 94vw);
    max-height: 90vh;
    overflow-y: auto;   /* filet de sécurité sur très petits écrans */
    text-align: center;
}
.gift-modal-title {
    color: #fff;
    font-weight: 900;
    font-size: 1rem;
    line-height: 1.3;
    margin-bottom: 10px;
}
.gift-modal-target { color: rgba(255,255,255,0.55); font-size: 0.8rem; font-weight: 700; }
.gift-modal-empty {
    color: rgba(255,255,255,0.55);
    font-size: 0.86rem;
    font-weight: 600;
    padding: 22px 8px;
    line-height: 1.5;
}
.gift-modal-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    padding-top: 7px;   /* place pour la pastille ★ qui déborde en haut */
}
.gift-card {
    background: rgba(255,255,255,0.05);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 12px;
    padding: 6px 4px 5px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    transition: transform 0.12s, background 0.12s, border-color 0.12s;
}
.gift-card:hover {
    transform: translateY(-3px);
    background: rgba(255,255,255,0.1);
    border-color: rgba(251,191,36,0.6);
}
.gift-card img { width: 100%; max-width: 64px; height: auto; object-fit: contain; }
.gift-card-name {
    color: rgba(255,255,255,0.8);
    font-weight: 700;
    font-size: 0.6rem;
    line-height: 1.15;
    text-align: center;
}
.gift-card-cost {
    color: #fbbf24;
    font-weight: 800;
    font-size: 0.68rem;
    white-space: nowrap;
}
.gift-modal-close {
    margin-top: 12px;
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.2);
    color: rgba(255,255,255,0.85);
    font-weight: 800;
    font-size: 0.82rem;
    border-radius: 10px;
    padding: 8px 26px;
    cursor: pointer;
    transition: background 0.15s;
}
.gift-modal-close:hover { background: rgba(255,255,255,0.16); }

/* ── Fenêtre de dotation du club ───────────────────────────────────────────
   Elle s'ouvre d'elle-même : elle doit se lire en un regard et se fermer sans
   réfléchir. D'où une seule chose grosse — le nombre — et tout le reste petit.
   Le fond tire vers l'or sans crier : c'est une bonne nouvelle, pas une
   alerte. */
.cp-dot {
    background:
        radial-gradient(120% 90% at 50% 0%, rgba(251,191,36,.16), transparent 62%),
        rgba(14,8,20,.96);
    border: 1px solid rgba(251,191,36,.42);
    box-shadow: 0 24px 60px rgba(0,0,0,.7), 0 0 70px rgba(251,191,36,.14);
}
.cp-dot-ecusson {
    width: 58px; height: 58px; display: block; margin: 2px auto 12px;
    filter: drop-shadow(0 4px 14px rgba(251,191,36,.45));
    animation: cpDotEcusson .7s cubic-bezier(.2,.8,.3,1) both;
}
@keyframes cpDotEcusson {
    from { transform: scale(.55) rotate(-16deg); opacity: 0; }
    to   { transform: none; opacity: 1; }
}
.cp-dot-titre {
    font-size: 1.02rem; font-weight: 900; color: #fbbf24;
    line-height: 1.25; margin-bottom: 10px;
}
/* Le nombre et son unité sur la même ligne de base : « 30 000 » domine, et
   « jetons » se tient à côté sans concourir. */
.cp-dot-somme {
    display: flex; align-items: baseline; justify-content: center; gap: 8px;
    margin: 2px 0 12px;
}
.cp-dot-nb {
    font-size: 2.9rem; font-weight: 900; color: #fff; letter-spacing: -.03em;
    line-height: 1; text-shadow: 0 0 26px rgba(251,191,36,.55);
}
.cp-dot-unite {
    font-size: .82rem; font-weight: 800; text-transform: uppercase;
    letter-spacing: .12em; color: rgba(251,191,36,.85);
}
.cp-dot-texte {
    font-size: .76rem; line-height: 1.55; color: rgba(255,255,255,.62);
    max-width: 32ch; margin: 0 auto;
}
.cp-dot-fin {
    margin-top: 13px; padding: 7px 10px; border-radius: 9px;
    background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.12);
    font-size: .68rem; font-weight: 700; color: rgba(255,255,255,.5);
}
.cp-dot-fin strong { color: rgba(255,255,255,.85); font-weight: 900; }

/* ── Les appels de l'onglet Jetons ─────────────────────────────────────────
   Ils se partagent la même place, à droite du solde, et jamais plus de deux à
   la fois. Même gabarit obligatoirement : côte à côte, une différence de
   hauteur ou de graisse se verrait aussitôt.
   L'or PLEIN pour l'achat, l'or CREUX pour l'adhésion. Les deux mènent à la
   boutique, mais l'achat est ce que le joueur venait chercher en ouvrant
   l'onglet ; l'adhésion est la proposition, elle se tient un pas en retrait. */
.jeton-cta {
    flex-shrink: 0; border: none; border-radius: 10px;
    padding: 9px 14px; font-family: inherit;
    font-weight: 900; text-transform: uppercase; letter-spacing: .03em;
    font-size: .66rem; line-height: 1.2; text-align: center; cursor: pointer;
    background: #fbbf24; color: #0e0814;
    box-shadow: 0 0 16px rgba(251,191,36,.5);
    transition: transform .1s, background .15s;
}
.jeton-cta:hover { transform: scale(1.05); }
.jeton-cta small { display: block; font-size: .52rem; font-weight: 900; opacity: .8; }
.jeton-cta-club {
    background: transparent; color: #fbbf24;
    border: 1.5px solid rgba(251,191,36,.6); box-shadow: none;
}
.jeton-cta-club:hover { background: rgba(251,191,36,.14); }
/* Le dépannage de la phase de test, en vert : ce n'est pas un achat, et rien
   ne serait plus trompeur que de lui donner l'or de la boutique. */
.jeton-cta-gratuit {
    background: #22c55e; color: #052e13;
    box-shadow: 0 0 16px rgba(34,197,94,.5);
}

/* Bouton d'adhésion au club — même gabarit que « Fermer », en or, et sur
   toute la largeur : c'est l'action de l'écran, pas une option de plus.
   Désactivé tant que le paiement n'existe pas ; il le DIT au lieu de
   disparaître, sinon le visiteur croirait qu'on lui cache le moyen d'adhérer. */
.gift-modal-cp {
    display: block; width: 100%; margin-top: 14px;
    background: linear-gradient(135deg, rgba(251,191,36,.22), rgba(251,191,36,.10));
    border: 1px solid rgba(251,191,36,.45);
    color: #fbbf24; font-weight: 900; font-size: .84rem;
    border-radius: 10px; padding: 10px 18px;
    cursor: pointer; transition: background .15s;
}
.gift-modal-cp:hover:not(:disabled) { background: rgba(251,191,36,.30); }
.gift-modal-cp:disabled { cursor: default; opacity: .62; }
.gift-modal-cp small {
    display: block; font-size: .68rem; font-weight: 700;
    color: rgba(255,255,255,.5); margin-top: 2px; letter-spacing: .02em;
}

/* ── Les deux idées pour aujourd'hui ─────────────────────────────────────
   Des cartes d'or ; celle de l'Arena du jour prend la couleur du jeu du jour
   (`--jeu-rgb`, posée par le serveur) et montre sa vignette au lieu d'un
   emoji : on reconnaît le jeu avant de lire. Les deux cartes gardent la
   même hauteur, l'emoji occupe la place de la vignette (88 px). */
.sugg-carte {
    flex: 1 1 300px; max-width: 340px; padding: 28px 22px; border-radius: 20px; text-align: center;
    background: linear-gradient(160deg, #fde047, #fbbf24); box-shadow: 0 20px 60px rgba(251,191,36,.25);
    display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.sugg-icone { height: 88px; display: flex; align-items: center; font-size: 3.4rem; line-height: 1; }
.sugg-titre { color: #1a1206; font-size: 1.15rem; font-weight: 900; line-height: 1.25; min-height: 2.5em; display: flex; align-items: center; }
.sugg-bouton {
    margin-top: 4px; padding: 12px 30px; border: none; border-radius: 12px; cursor: pointer;
    background: #1a1206; color: #fde047; font-size: .9rem; font-weight: 900; text-transform: uppercase; letter-spacing: .06em;
    transition: transform .1s;
}
.sugg-bouton:hover { transform: scale(1.05); }
.sugg-carte.arena {
    background: linear-gradient(160deg, rgb(var(--jeu-rgb)), rgba(var(--jeu-rgb), .55) 55%, #14162a);
    box-shadow: 0 20px 60px rgba(var(--jeu-rgb), .35), inset 0 0 0 1px rgba(255,255,255,.14);
}
.sugg-carte.arena .sugg-titre { color: #fff; text-shadow: 0 2px 6px rgba(0,0,0,.5); }
.sugg-carte.arena .sugg-bouton { background: #fbbf24; color: #1a1206; }
.sugg-carte.arena .vignette { filter: drop-shadow(0 6px 14px rgba(0,0,0,.45)); }

/* Un NOUVEAU challenge : le vert des challenges disponibles (le liseré
   `.chal-dispo` de l'onglet Challenges), pour qu'on le reconnaisse d'un écran
   à l'autre, une pastille « Nouveau » et la date de fermeture, qui dit
   qu'il ne restera pas. */
.sugg-carte { position: relative; }
.sugg-carte.nouveau-challenge {
    background: linear-gradient(160deg, #4ade80, #16a34a 55%, #0b2e1a);
    box-shadow: 0 20px 60px rgba(34,197,94,.35), inset 0 0 0 1px rgba(255,255,255,.18);
}
.sugg-carte.nouveau-challenge .sugg-titre { color: #fff; text-shadow: 0 2px 6px rgba(0,0,0,.45); }
.sugg-carte.nouveau-challenge .sugg-bouton { background: #fbbf24; color: #1a1206; }
.sugg-pastille {
    position: absolute; top: 14px; right: 14px;
    padding: 4px 10px; border-radius: 999px;
    background: #fbbf24; color: #1a1206;
    font-size: .7rem; font-weight: 900; text-transform: uppercase; letter-spacing: .1em;
    box-shadow: 0 4px 12px rgba(0,0,0,.3);
}
.sugg-sous-titre {
    margin-top: -6px; color: rgba(255,255,255,.85);
    font-size: .85rem; font-weight: 700; letter-spacing: .02em;
}

/* Les avantages de l'Illimité, en DEUX colonnes : six lignes empilées
   faisaient 650 px, plus que les 90 vh d'un portable — la fenêtre
   défilait, et « Passer en Illimité » se trouvait sous le pli. En deux
   colonnes et avec des marges serrées, le tout tient en 490 px, mesuré.
   Sous 540 px de large, une colonne : on retombe sur le filet de sécurité
   du défilement, mieux qu'un texte illisible. */
.cp-avantages {
    display: grid; grid-template-columns: 1fr 1fr; gap: 6px;
}
.cp-avantages > div {
    display: flex; gap: 8px; align-items: flex-start;
    padding: 6px 8px; border-radius: 8px; background: rgba(255,255,255,0.04);
}
@media (max-width: 540px) {
    .cp-avantages { grid-template-columns: 1fr; }
}

/* Cadeau préféré du destinataire : mis en avant dans la modale */
.gift-card { position: relative; }
.gift-card-pref { border-color: rgba(251,191,36,0.75); background: rgba(251,191,36,0.10); }
.gift-pref-badge {
    position: absolute;
    top: -7px;
    right: -7px;
    background: #fbbf24;
    color: #1f2136;
    font-weight: 900;
    font-size: 0.62rem;
    line-height: 1;
    padding: 3px 5px;
    border-radius: 999px;
    box-shadow: 0 2px 6px rgba(0,0,0,0.5);
    pointer-events: none;
}

/* ═══ Onglets Boissons / Friandises préférées (Mon compte) ═══ */
.pref-hint {
    color: rgba(255,255,255,0.5);
    font-size: 0.74rem;
    line-height: 1.5;
    margin-bottom: 10px;
}
.pref-empty {
    color: rgba(255,255,255,0.28);
    font-size: 0.78rem;
    font-style: italic;
    padding: 14px 4px;
}
.pref-selected { display: flex; flex-direction: column; gap: 6px; }
.pref-row {
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.1);
    border-radius: 9px;
    padding: 5px 8px;
}
.pref-rank {
    width: 20px; height: 20px;
    flex-shrink: 0;
    border-radius: 50%;
    background: #fbbf24;
    color: #1f2136;
    font-weight: 900;
    font-size: 0.66rem;
    display: flex; align-items: center; justify-content: center;
}
.pref-thumb { width: 34px; height: 34px; object-fit: contain; flex-shrink: 0; }
.pref-name  { flex: 1; color: #fff; font-size: 0.8rem; font-weight: 700; min-width: 0;
              overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pref-cost  { color: #fbbf24; font-size: 0.72rem; font-weight: 800; flex-shrink: 0; }
.pref-btn {
    width: 26px; height: 26px;
    flex-shrink: 0;
    border-radius: 7px;
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.15);
    color: rgba(255,255,255,0.8);
    font-size: 0.8rem;
    font-weight: 900;
    cursor: pointer;
    transition: background 0.15s, opacity 0.15s;
}
.pref-btn:hover:not(:disabled) { background: rgba(255,255,255,0.18); }
.pref-btn:disabled { opacity: 0.25; cursor: default; }
.pref-del { color: #f87171; border-color: rgba(248,113,113,0.35); }
.pref-del:hover { background: rgba(248,113,113,0.18); }

.pref-available {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
    gap: 8px;
}
.pref-card {
    background: rgba(255,255,255,0.05);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 10px;
    padding: 6px 4px 4px;
    cursor: pointer;
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    transition: transform 0.12s, background 0.12s, border-color 0.12s;
}
.pref-card:hover:not(.pref-card-disabled) {
    transform: translateY(-2px);
    background: rgba(255,255,255,0.1);
    border-color: rgba(251,191,36,0.6);
}
.pref-card img { width: 100%; max-width: 48px; height: auto; object-fit: contain; }
.pref-card-cost { color: #fbbf24; font-weight: 800; font-size: 0.66rem; }
.pref-card-disabled { opacity: 0.3; cursor: default; }

/* Bouton « Enregistrer » homogène pour tous les onglets de Mon compte */
.compte-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    margin-top: auto;
    padding-top: 12px;
    flex-shrink: 0;
}
.compte-save {
    background: rgba(250,204,21,0.18);
    border: 1.5px solid rgba(250,204,21,0.55);
    border-radius: 9px;
    padding: 9px 26px;
    color: #facc15;
    font-size: 0.8rem;
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: .06em;
    cursor: pointer;
    transition: background .15s, border-color .15s;
}
.compte-save:hover { background: rgba(250,204,21,0.3); border-color: rgba(250,204,21,0.75); }
.compte-ok { color: #4ade80; font-weight: 800; font-size: 0.8rem; }

/* 9 cadeaux sur 2 rangées (5 en haut, 4 en bas) : remplit la zone dispo, jamais de scroll.
   Les 2 rangées (flex:1) se partagent la hauteur → avatars agrandis. */
.pref-grid9 {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.pref-grid9-row {
    flex: 1;
    min-height: 0;
    display: flex;
    gap: 8px;
    justify-content: center;
    align-items: stretch;
}
.pref-card9 {
    position: relative;
    flex: 0 0 calc((100% - 32px) / 5);   /* largeur calée sur 5 cases par rangée */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-height: 0;
    background: rgba(255,255,255,0.05);
    border: 1.5px solid rgba(255,255,255,0.12);
    border-radius: 10px;
    padding: 6px 5px;
    cursor: pointer;
    overflow: hidden;
    transition: transform .12s, background .12s, border-color .12s;
}
.pref-card9:hover:not(.pref-card9-disabled) {
    transform: translateY(-2px);
    background: rgba(255,255,255,0.1);
}
.pref-card9 img { width: auto; max-width: 82%; max-height: 66%; object-fit: contain; }
.pref-card9-name {
    color: rgba(255,255,255,0.85);
    font-size: 0.64rem;
    font-weight: 700;
    text-align: center;
    line-height: 1.15;
    max-width: 100%;
    flex-shrink: 0;
}
.pref-card9-cost { color: #fbbf24; font-weight: 800; white-space: nowrap; }
/* Case sélectionnée : le nom s'inserre pour ne pas passer sous les flèches (à droite). */
.pref-card9-sel .pref-card9-name { padding: 0 22px; }
.pref-card9-sel {
    border-color: rgba(250,204,21,0.7);
    background: rgba(250,204,21,0.12);
}
.pref-card9-disabled { opacity: 0.35; cursor: default; }
.pref-card9-rank {
    position: absolute;
    top: 3px; left: 3px;
    width: 19px; height: 19px;
    border-radius: 50%;
    background: #facc15;
    color: #1a1206;
    font-size: 0.68rem;
    font-weight: 900;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 4px rgba(0,0,0,0.5);
    z-index: 2;
}
/* Flèches d'ordre sur les cases sélectionnées (surimpression, à droite) */
.pref-card9-order {
    position: absolute;
    top: 50%;
    right: 3px;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    gap: 3px;
    z-index: 2;
}
.pref-ord-btn {
    width: 22px; height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(255,255,255,0.25);
    background: rgba(0,0,0,0.55);
    border-radius: 6px;
    color: #fff;
    font-size: 0.75rem;
    line-height: 1;
    cursor: pointer;
    transition: background .12s;
}
.pref-ord-btn:hover:not(:disabled) { background: rgba(250,204,21,0.35); }
.pref-ord-btn:disabled { opacity: 0.25; cursor: default; }

.pref-actions { display: flex; align-items: center; gap: 12px; margin-top: 16px; padding-bottom: 4px; }
.pref-save {
    background: rgba(250,204,21,0.18);
    border: 1.5px solid rgba(250,204,21,0.55);
    color: #facc15;
    font-weight: 900;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    border-radius: 9px;
    padding: 8px 22px;
    cursor: pointer;
    transition: background 0.15s;
}
.pref-save:hover { background: rgba(250,204,21,0.3); }
.pref-ok { color: #4ade80; font-weight: 800; font-size: 0.78rem; }

.lobby-player-card.state-human-us   { border-color: rgba(59,130,246,0.9);  background: rgba(30,58,138,0.28); }
.lobby-player-card.state-human-us   .lobby-seat-avatar { border-color: #60a5fa; box-shadow: 0 0 18px rgba(96,165,250,0.45), 0 6px 20px rgba(0,0,0,0.65); }
.lobby-player-card.state-human-them { border-color: rgba(239,68,68,0.9);   background: rgba(127,29,29,0.28); }
.lobby-player-card.state-human-them .lobby-seat-avatar { border-color: #f87171; box-shadow: 0 0 18px rgba(248,113,113,0.45), 0 6px 20px rgba(0,0,0,0.65); }
.lobby-player-card.state-bot  { border-color: rgba(168,85,247,0.65); border-style: dashed; background: rgba(88,28,135,0.22); }
.lobby-player-card.state-bot  .lobby-seat-avatar { border-color: rgba(192,132,252,0.85); border-style: solid; box-shadow: 0 0 14px rgba(168,85,247,0.35), 0 6px 20px rgba(0,0,0,0.65); }
.lobby-player-card.state-empty { border-color: rgba(255,255,255,0.1); border-style: dashed; opacity: 0.45; }

/* BULLE DE DIALOGUE LOBBY */
.bubble-lobby {
    position: absolute;
    bottom: calc(100% + 66px);
    left: 50%;
    transform: translateX(-50%);
    background: #fff;
    color: #1a1a1a;
    padding: 7px 13px;
    border-radius: 10px;
    border: 2.5px solid #000;
    box-shadow: 3px 3px 0 rgba(0,0,0,0.3);
    font-family: 'Arial Black', 'Verdana', sans-serif;
    font-weight: 900;
    font-size: 0.8rem;
    text-align: center;
    /* Les phrases longues reviennent à la ligne au lieu de déborder/être coupées */
    white-space: normal;
    width: max-content;
    max-width: min(220px, 78vw);
    word-break: break-word;
    line-height: 1.25;
    z-index: 200;
    pointer-events: none;
    animation: pop-in 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;
}
.bubble-lobby::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border-width: 7px;
    border-style: solid;
    border-color: #000 transparent transparent transparent;
}

/* JETON DONNEUR (DEALER CHIP) */
.dealer-token {
    position: absolute;
    top: -15px;   /* Déborde un peu en haut */
    right: -15px; /* Déborde un peu à droite */
    width: 40px;
    height: 40px;
    z-index: 60;  /* Au-dessus de la carte joueur */
    filter: drop-shadow(2px 4px 6px rgba(0,0,0,0.5));
    animation: drop-chip 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

/* AVATAR SUR LE PLATEAU (coin opposé au jeton donneur) */
.player-avatar-token {
    position: absolute;
    bottom: -15px;
    left: -15px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, 0.25);
    z-index: 60;
    filter: drop-shadow(2px 4px 6px rgba(0,0,0,0.5));
    pointer-events: none;
}

/* Animation d'arrivée du jeton (simple fondu) */
@keyframes drop-chip {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* ==========================================================================
   HUD AVATARS — vignettes dans les 4 coins du plateau
   ========================================================================== */
/* [TEST] La réflexion des robots sur le plateau : une zone par siège, dans
   les bandes verticales où vivent les avatars — que l'on efface pendant ce
   temps (`.reflexions-on`). Sous les overlays de jeu (210) et les bulles,
   au-dessus des panneaux des coins (60). Texte à chasse fixe : ce sont les
   lignes du superviseur, alignées en colonnes. */
.reflexions-on .player-hud { display: none; }
.reflexion-zone {
    z-index: 105;
    display: flex;
    flex-direction: column;
    background: rgba(0, 0, 0, 0.74);
    border: 1px solid rgba(250, 204, 21, 0.35);
    border-radius: 8px;
    color: #e5e7eb;
    font-family: Consolas, 'Courier New', monospace;
    font-size: 10.5px;
    line-height: 1.3;
    overflow: hidden;
    pointer-events: auto;
}
.reflexion-tete {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 3px 7px;
    background: rgba(250, 204, 21, 0.14);
    color: #facc15;
    font-weight: 900;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .04em;
    white-space: nowrap;
    overflow: hidden;
}
.reflexion-enchere { color: #fff; font-weight: 800; text-transform: none; }
.reflexion-enchere img { height: 12px; display: inline-block; vertical-align: -2px; }
.reflexion-heure { margin-left: auto; color: rgba(255,255,255,0.4); font-weight: 400; }
/* Le corps défile ; chaque message est séparé du suivant, le dernier en tête. */
.reflexion-corps { flex: 1; overflow: auto; user-select: text; }
.reflexion-msg { padding: 4px 7px 6px; border-bottom: 1px solid rgba(250, 204, 21, 0.28); }
.reflexion-msg:first-child { background: rgba(250, 204, 21, 0.06); }
.reflexion-msg-tete {
    display: flex; gap: 8px; align-items: baseline;
    color: rgba(255,255,255,0.5); font-size: 9.5px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .04em;
}
.reflexion-evals { border-collapse: collapse; width: 100%; margin: 3px 0 2px; }
.reflexion-evals td { padding: 1px 3px; vertical-align: top; }
.ev-c { width: 16px; }
.ev-c img { height: 12px; width: 12px; display: block; margin-top: 1px; }
.ev-val { white-space: nowrap; color: #fff; font-weight: 800; }
.ev-tot { color: #facc15; font-weight: 800; }
.ev-conf { color: rgba(255,255,255,0.45); margin-right: 5px; }
.ev-plus { color: rgba(255,255,255,0.6); }
.ev-rejete { opacity: 0.35; }
.ev-elague { opacity: 0.65; }
.reflexion-texte {
    margin: 2px 0 0;
    padding: 0;
    white-space: pre-wrap;
    word-break: break-word;
    font: inherit;
}
.reflexion-decision { color: #facc15; font-weight: 800; margin-top: 3px; }
.reflexion-vide { padding: 8px; color: rgba(255,255,255,0.3); text-align: center; }

.player-hud {
    position: absolute;
    z-index: 110;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    pointer-events: none;
    transition: transform 0.25s ease;
}

.hud-avatar-outer {
    position: relative;
    display: inline-block;
}

.hud-avatar-wrap {
    width: var(--avatar-h, 175px);
    height: var(--avatar-h, 175px);
    border-radius: calc(var(--avatar-h, 175px) * 0.16);
    overflow: hidden;
    background: rgba(0, 0, 0, 0.55);
    border: 3px solid rgba(255, 255, 255, 0.15);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.65);
    transition: border-color 0.3s ease, box-shadow 0.3s ease, transform 0.25s ease;
}

.hud-avatar-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center top;
    display: block;
}

/* Contour pulsant pendant la réflexion — inset shadow = trait épaissi sans changer les dimensions */
.player-hud.hud-thinking .hud-avatar-wrap {
    animation: hud-thinking-pulse 1s ease-in-out infinite;
}

@keyframes hud-thinking-pulse {
    0%, 100% {
        box-shadow: inset 0 0 0 0px rgba(251,191,36,0.0),
                    0 0 22px rgba(251,191,36,0.4), 0 8px 32px rgba(0,0,0,0.65);
    }
    50% {
        box-shadow: inset 0 0 0 4px rgba(251,191,36,0.85),
                    0 0 44px rgba(251,191,36,0.85), 0 8px 32px rgba(0,0,0,0.65);
    }
}

/* Joueur déconnecté — contour rouge pulsant, grisé */
.player-hud.hud-disconnected .hud-avatar-wrap {
    animation: hud-disconnected-pulse 2s ease-in-out infinite;
    filter: grayscale(70%);
    opacity: 0.75;
}

@keyframes hud-disconnected-pulse {
    0%, 100% { box-shadow: inset 0 0 0 0px rgba(239,68,68,0.0), 0 8px 32px rgba(0,0,0,0.65); }
    50%       { box-shadow: inset 0 0 0 4px rgba(239,68,68,0.8), 0 0 24px rgba(239,68,68,0.5), 0 8px 32px rgba(0,0,0,0.65); }
}

/* Compte à rebours avant déconnexion : bordure rouge qui pulse vivement.
   Plus rapide et plus intense que hud-disconnected pour bien alerter. */
.player-hud.hud-afk .hud-avatar-wrap {
    border-color: rgba(239,68,68,0.9) !important;
    animation: hud-afk-pulse 0.8s ease-in-out infinite;
}
@keyframes hud-afk-pulse {
    0%, 100% { box-shadow: inset 0 0 0 2px rgba(239,68,68,0.55), 0 0 10px rgba(239,68,68,0.35), 0 8px 32px rgba(0,0,0,0.65); }
    50%      { box-shadow: inset 0 0 0 5px rgba(239,68,68,1),    0 0 34px rgba(239,68,68,0.9),  0 8px 32px rgba(0,0,0,0.65); }
}

.hud-disconnected-badge {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
    font-weight: 900;
    color: rgba(239,68,68,0.85);
    text-shadow: 0 1px 4px rgba(0,0,0,0.7);
    pointer-events: none;
}

/* Badge AFK — horloge, coin haut-droit, même taille que le jeton donneur */
.hud-afk-badge {
    position: absolute;
    top: -20px;
    right: -20px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: radial-gradient(circle at 50% 50%, #1a0d00 55%, #2d1800 100%);
    border: 2.5px solid #f59e0b;
    z-index: 10;
    box-shadow:
        0 0 10px rgba(245,158,11,0.55),
        0 3px 8px rgba(0,0,0,0.7),
        inset 0 0 6px rgba(245,158,11,0.12);
    pointer-events: none;
    animation: afk-glow 1s ease-in-out infinite;
    /* Marques des heures (12, 3, 6, 9) simulées par l'outline */
    outline: 1px solid transparent;
}

/* Aiguille des minutes — tourne en 10s (durée de AFK_GRACE_SECS) */
.hud-afk-badge::before {
    content: '';
    position: absolute;
    bottom: 50%;
    left: calc(50% - 1px);
    width: 2px;
    height: 12px;
    background: #f59e0b;
    border-radius: 1px 1px 0 0;
    transform-origin: bottom center;
    animation: afk-hand-min 10s linear infinite;
}

/* Chiffre centré — au-dessus des aiguilles */
.afk-badge-num {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fef08a;
    font-size: 0.82rem;
    font-weight: 900;
    text-shadow: 0 0 6px rgba(245,158,11,0.8), 0 1px 3px rgba(0,0,0,0.9);
    z-index: 1;
}

@keyframes afk-hand-min {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@keyframes afk-glow {
    0%, 100% { box-shadow: 0 0 8px rgba(245,158,11,0.4), 0 3px 8px rgba(0,0,0,0.7), inset 0 0 6px rgba(245,158,11,0.1); }
    50%       { box-shadow: 0 0 18px rgba(245,158,11,0.9), 0 3px 8px rgba(0,0,0,0.7), inset 0 0 6px rgba(245,158,11,0.2); }
}

/* Jeton donneur — centré sur le coin bas-droit de l'avatar */
.hud-dealer-chip {
    position: absolute;
    bottom: calc(var(--badge-sz, 40px) / -2);
    right: calc(var(--badge-sz, 40px) / -2);
    width: var(--badge-sz, 40px);
    height: var(--badge-sz, 40px);
    z-index: 10;
    filter: drop-shadow(0 3px 8px rgba(0,0,0,0.7));
    animation: drop-chip 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.hud-name {
    font-size: 14px;
    font-weight: 800;
    color: rgba(255, 255, 255, 0.9);
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.9);
    max-width: 210px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: center;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* Équipe NOUS — bordure bleue */
.player-hud.hud-us .hud-avatar-wrap {
    border-color: rgba(96, 165, 250, 0.65);
    box-shadow: 0 0 22px rgba(96, 165, 250, 0.3), 0 8px 32px rgba(0, 0, 0, 0.65);
}

/* Équipe EUX — bordure rouge */
.player-hud.hud-them .hud-avatar-wrap {
    border-color: rgba(248, 113, 113, 0.65);
    box-shadow: 0 0 22px rgba(248, 113, 113, 0.3), 0 8px 32px rgba(0, 0, 0, 0.65);
}

/* Tour actif — halo or, légère mise à l'échelle */
.player-hud.hud-active .hud-avatar-wrap {
    border-color: #fbbf24;
    box-shadow: 0 0 36px rgba(251, 191, 36, 0.7), 0 8px 32px rgba(0, 0, 0, 0.65);
    transform: scale(1.05);
}

.player-hud.hud-active .hud-name {
    color: #fbbf24;
    text-shadow: 0 0 8px rgba(251, 191, 36, 0.6);
}

/* ==========================================================================
   PANNEAU PROFIL JOUEUR — extension inline de l'avatar
   ========================================================================== */
.hud-avatar-outer.hud-human,
.hud-avatar-outer.hud-robot {
    cursor: pointer;
    pointer-events: all;
}
.hud-avatar-outer.hud-human:hover .hud-avatar-wrap,
.hud-avatar-outer.hud-robot:hover .hud-avatar-wrap {
    box-shadow: 0 0 0 2px rgba(96,165,250,0.7), 0 8px 32px rgba(0,0,0,0.65);
}

/* Extension jeu HUD — sort à droite de l'avatar */
.hud-friend-expand {
    position: absolute;
    top: 0;
    left: 100%;
    width: 0;
    height: var(--avatar-h, 175px);
    overflow: hidden;
    transition: width 0.28s cubic-bezier(0.4, 0, 0.2, 1);
    z-index: 200;
    border-radius: 0 calc(var(--avatar-h, 175px) * 0.16) calc(var(--avatar-h, 175px) * 0.16) 0;
}
.hud-friend-expand.panel-open {
    width: var(--avatar-h, 175px);
}
/* Expansion vers la gauche (avatar côté droit de l'écran) */
.hud-friend-expand.expand-left {
    left: auto;
    right: 100%;
    border-radius: calc(var(--avatar-h, 175px) * 0.16) 0 0 calc(var(--avatar-h, 175px) * 0.16);
}
.hud-friend-expand.expand-left .friend-expand-inner {
    border-left: 1px solid rgba(96,165,250,0.25);
    border-right: none;
    border-radius: calc(var(--avatar-h, 175px)*0.16) 0 0 calc(var(--avatar-h, 175px)*0.16);
}

/* Extension lobby — sort à droite de l'avatar (sibling dans lobby-player-card) */
.lobby-friend-expand {
    position: absolute;
    top: -72px;
    left: calc(50% + 60px);
    width: 0;
    height: 148px;
    overflow: hidden;
    transition: width 0.28s cubic-bezier(0.4, 0, 0.2, 1);
    z-index: 201;
    border-radius: 0 12px 12px 0;
}
.lobby-friend-expand.panel-open {
    width: 128px;
}

/* Contenu commun du panneau */
.friend-expand-inner {
    position: relative;
    background: linear-gradient(135deg, rgba(12,20,40,0.97), rgba(25,38,58,0.97));
    border-top: 1px solid rgba(96,165,250,0.25);
    border-right: 1px solid rgba(96,165,250,0.25);
    border-bottom: 1px solid rgba(96,165,250,0.25);
    height: 100%;
    box-sizing: border-box;
    padding: 8px 7px;
    display: flex;
    flex-direction: column;
    gap: 3px;
    overflow: hidden;
    color: white;
}
/* Croix de fermeture (coin haut-droit du panneau) */
.fp-close {
    position: absolute;
    top: 2px;
    right: 3px;
    width: 16px;
    height: 16px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(255,255,255,0.08);
    color: rgba(255,255,255,0.55);
    font-size: 0.62rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2;
    transition: background .15s, color .15s;
}
.fp-close:hover {
    background: rgba(239,68,68,0.85);
    color: #fff;
}
/* Ligne de pseudo (1er div du panneau) insérée symétriquement pour ne pas passer sous la croix */
.friend-expand-inner > div:first-of-type {
    padding-left: 14px;
    padding-right: 14px;
}
.hud-friend-expand .friend-expand-inner {
    width: var(--avatar-h, 175px);
    border-radius: 0 calc(var(--avatar-h, 175px) * 0.16) calc(var(--avatar-h, 175px) * 0.16) 0;
}
.lobby-friend-expand .friend-expand-inner {
    width: 128px;
    border-radius: 0 10px 10px 0;
    padding: 8px 7px;
}

/* Boutons dans le panneau */
.fp-btn {
    border: none; border-radius: 7px; padding: 9px 6px;
    font-size: 0.72rem; font-weight: 900; cursor: pointer;
    text-transform: uppercase; letter-spacing: .05em; width: 100%;
    transition: opacity .15s, transform .1s; pointer-events: all;
    line-height: 1;
}
.fp-btn:hover { opacity: 0.88; transform: scale(1.03); }
.fp-btn:active { transform: scale(0.97); }
.fp-btn.fp-add    { background: rgba(59,130,246,0.9);  color: white; box-shadow: 0 2px 8px rgba(59,130,246,0.4); }
.fp-btn.fp-accept { background: rgba(34,197,94,0.9);   color: white; box-shadow: 0 2px 8px rgba(34,197,94,0.4); }
.fp-btn.fp-refuse { background: rgba(239,68,68,0.65);  color: white; }
.fp-btn.fp-remove { background: rgba(107,114,128,0.3); color: rgba(255,255,255,0.5); }

/* ==========================================================================
   POKER 5 CARTES
   ========================================================================== */
.poker-card-wrap {
    width: 72px; height: 106px;
    perspective: 700px;
    flex-shrink: 0;
}
.poker-card-inner {
    position: relative;
    width: 100%; height: 100%;
    transform-style: preserve-3d;
    transition: transform 0.55s cubic-bezier(0.4,0,0.2,1);
}
.poker-card-inner.flipped {
    transform: rotateY(180deg);
}
.poker-card-face,
.poker-card-back {
    position: absolute;
    inset: 0;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    border-radius: 8px;
    overflow: hidden;
    border: 1.5px solid rgba(255,255,255,0.12);
    box-shadow: 0 4px 16px rgba(0,0,0,0.5);
    background: white;
}
.poker-card-face {
    transform: rotateY(180deg);
}
.poker-card-back img,
.poker-card-face img {
    width: 100%; height: 100%;
    object-fit: contain;
    display: block;
}
.poker-card-wrap.win .poker-card-face {
    border-color: #ffd700;
    box-shadow: 0 0 14px 4px rgba(255,215,0,0.55), 0 4px 16px rgba(0,0,0,0.5);
}

/* ==========================================================================
   MODAL LISTE DES AMIS
   ========================================================================== */
.friends-modal-overlay {
    position: fixed; inset:0; z-index:500;
    background: rgba(0,0,0,0.6);
    display:flex; align-items:center; justify-content:center;
}
.friends-modal {
    background: linear-gradient(145deg, rgba(15,23,42,0.99), rgba(30,41,59,0.99));
    border:1px solid rgba(96,165,250,0.2);
    border-radius:18px;
    width: min(480px, 96vw);
    max-height: 75vh;
    display:flex; flex-direction:column;
    box-shadow: 0 24px 64px rgba(0,0,0,0.8);
    overflow:hidden;
}
.friends-modal-header {
    padding:16px 20px 12px;
    border-bottom:1px solid rgba(255,255,255,0.07);
    display:flex; align-items:center; justify-content:space-between;
    flex-shrink:0;
}
.friends-modal-tabs {
    display:flex; gap:6px; padding:10px 16px 0;
    flex-shrink:0;
}
.friends-modal-tab {
    padding:6px 14px; border-radius:8px 8px 0 0;
    font-size:0.72rem; font-weight:800; text-transform:uppercase; letter-spacing:.05em;
    cursor:pointer; border:1px solid transparent; border-bottom:none;
    background:transparent; color:rgba(255,255,255,0.35); transition:all .15s;
}
.friends-modal-tab.active {
    background:rgba(96,165,250,0.12);
    border-color:rgba(96,165,250,0.2);
    color:#60a5fa;
}
.friends-modal-body {
    flex:1; overflow-y:auto; padding:12px 16px 16px;
}
.friend-row {
    display:flex; align-items:flex-start; gap:12px;
    padding:10px; border-radius:10px;
    background:rgba(255,255,255,0.03); margin-bottom:6px;
    border:1px solid rgba(255,255,255,0.05);
    transition:background .15s;
}
.friend-row:hover { background:rgba(255,255,255,0.06); }
.friend-row-avatar {
    width:128px; height:128px; border-radius:12px;
    overflow:hidden; flex-shrink:0;
    border:1px solid rgba(255,255,255,0.1);
}
.friend-row-avatar img { width:100%;height:100%;object-fit:cover;object-position:center top;display:block; }
.online-dot {
    width:8px; height:8px; border-radius:50%;
    background:#4ade80; box-shadow:0 0 5px rgba(74,222,128,0.6);
}
.offline-dot {
    width:8px; height:8px; border-radius:50%;
    background:rgba(255,255,255,0.2);
}

/* ==========================================================================
   BULLES D'ANNONCES SPÉCIALES (COINCHE / SURCOINCHE)
   Version "Pro & Sobre"
   ========================================================================== */

/* --- BULLES ÉQUIPE NOUS (bleu) et ÉQUIPE EUX (rouge) --- */
.speech-bubble.bubble-team-us {
    border-color: #60a5fa;
    box-shadow: 4px 4px 0px rgba(96, 165, 250, 0.4);
}
.speech-bubble.bubble-team-us::after  { border-color: #60a5fa transparent transparent transparent; }
.speech-bubble.bubble-bottom.bubble-team-us::after { border-color: transparent transparent #60a5fa transparent; }
.speech-bubble.bubble-left.bubble-team-us::after   { border-color: transparent #60a5fa transparent transparent; }
.speech-bubble.bubble-right.bubble-team-us::after  { border-color: transparent transparent transparent #60a5fa; }

.speech-bubble.bubble-team-them {
    border-color: #f87171;
    box-shadow: 4px 4px 0px rgba(248, 113, 113, 0.4);
}
.speech-bubble.bubble-team-them::after  { border-color: #f87171 transparent transparent transparent; }
.speech-bubble.bubble-bottom.bubble-team-them::after { border-color: transparent transparent #f87171 transparent; }
.speech-bubble.bubble-left.bubble-team-them::after   { border-color: transparent #f87171 transparent transparent; }
.speech-bubble.bubble-right.bubble-team-them::after  { border-color: transparent transparent transparent #f87171; }

/* Base commune pour les bulles spéciales */
.speech-bubble.bubble-coinche,
.speech-bubble.bubble-surcoinche {
    font-family: 'Roboto', sans-serif; /* Police standard du jeu */
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: 1px;
    padding: 8px 16px;
    min-width: auto; /* On laisse le texte décider de la largeur */
    box-shadow: 0 4px 10px rgba(0,0,0,0.5); /* Ombre portée élégante */
    transform-origin: center center;
    /* On utilise l'animation d'entrée standard "pop" définie plus haut dans le CSS, 
       mais on force une taille un peu plus grande */
    transform: scale(1.1); 
}

/* --- STYLE COINCHE (Rouge Casino) --- */
.bubble-coinche {
    /* Dégradé Rouge profond, plus classe que le rouge pur */
    background: linear-gradient(180deg, #dc2626 0%, #991b1b 100%) !important; 
    color: white !important;
    border: 2px solid rgba(255,255,255,0.8) !important;
}

/* Petite flèche Rouge pour la Coinche */
.bubble-coinche::after { border-color: #991b1b transparent transparent transparent !important; }
.bubble-bottom.bubble-coinche::after { border-color: transparent transparent #dc2626 transparent !important; }
.bubble-left.bubble-coinche::after { border-color: transparent #dc2626 transparent transparent !important; }
.bubble-right.bubble-coinche::after { border-color: transparent transparent transparent #dc2626 !important; }


/* --- STYLE SURCOINCHE (Violet Royal & Or) --- */
.bubble-surcoinche {
    /* Dégradé Violet sombre */
    background: linear-gradient(180deg, #7c3aed 0%, #4c1d95 100%) !important; 
    color: #fcd34d !important; /* Texte Doré */
    border: 2px solid #fcd34d !important; /* Bordure Dorée */
}

/* Petite flèche Violette pour la Surcoinche */
.bubble-surcoinche::after { border-color: #4c1d95 transparent transparent transparent !important; }
.bubble-bottom.bubble-surcoinche::after { border-color: transparent transparent #7c3aed transparent !important; }
.bubble-left.bubble-surcoinche::after { border-color: transparent #7c3aed transparent transparent !important; }
.bubble-right.bubble-surcoinche::after { border-color: transparent transparent transparent #7c3aed !important; }


.think-bubble {
    position: absolute;
    background: rgba(30, 41, 59, 0.95); /* Fond sombre bleuté */
    border: 2px dashed #8b5cf6; /* Bordure violette pour la réflexion */
    border-radius: 16px;
    padding: 6px 10px;
    color: #c4b5fd;
    font-size: 11px;
    font-weight: 700;
    text-align: center;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);
    z-index: 100;
    white-space: nowrap;
    pointer-events: none;
}

/* Petits cercles pour l'effet "nuage de pensée" */
.think-bubble::before, .think-bubble::after {
    content: '';
    position: absolute;
    background: rgba(30, 41, 59, 0.95);
    border: 2px dashed #8b5cf6;
    border-radius: 50%;
}

.think-bubble::before { width: 8px; height: 8px; }
.think-bubble::after { width: 4px; height: 4px; }

/* Orientations et positionnement des cercles selon le joueur */
.think-bubble.bottom-pos {
    bottom: 115%; left: 50%; transform: translateX(-50%);
}
.think-bubble.bottom-pos::before { bottom: -10px; left: 50%; transform: translateX(-50%); }
.think-bubble.bottom-pos::after { bottom: -16px; left: 50%; transform: translateX(-50%); }

/* Joueur à DROITE de l'écran (J1) : La bulle s'affiche à sa GAUCHE */
.think-bubble.right-pos {
    right: 115%; top: 50%; transform: translateY(-50%);
}
.think-bubble.right-pos::before { right: -10px; top: 50%; transform: translateY(-50%); }
.think-bubble.right-pos::after { right: -16px; top: 50%; transform: translateY(-50%); }

.think-bubble.top-pos {
    top: 115%; left: 50%; transform: translateX(-50%);
}
.think-bubble.top-pos::before { top: -10px; left: 50%; transform: translateX(-50%); }
.think-bubble.top-pos::after { top: -16px; left: 50%; transform: translateX(-50%); }

/* Joueur à GAUCHE de l'écran (J3) : La bulle s'affiche à sa DROITE */
.think-bubble.left-pos {
    left: 115%; top: 50%; transform: translateY(-50%);
}
.think-bubble.left-pos::before { left: -10px; top: 50%; transform: translateY(-50%); }
.think-bubble.left-pos::after { left: -16px; top: 50%; transform: translateY(-50%); }

/* Transition douce */
.fade-think-enter-active, .fade-think-leave-active {
    transition: opacity 0.3s ease;
}
.fade-think-enter-from, .fade-think-leave-to {
    opacity: 0;
}

/* Swap Lobby */

.btn-swap {
    width: 2.5rem;       /* w-10 */
    height: 2.5rem;      /* h-10 */
    border-radius: 50%;  /* rounded-full */
    
    background-color: #374151; /* bg-gray-700 */
    border: 2px solid rgba(234, 179, 8, 0.5); /* border-yellow-500/50 */
    color: white;
    
    display: flex;
    align-items: center;
    justify-content: center;
    
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); /* shadow-xl */
    
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    transform: scale(1);
    cursor: pointer;
}

.btn-swap:hover {
    background-color: #ca8a04; /* hover:bg-yellow-600 */
    border-color: white;       /* hover:border-white */
    transform: scale(1.1) rotate(180deg); /* Animation Zoom + Rotation */
}


/* ==========================================================================
   HUB MENU_USER — carte Mon Espace + hauteur fixe (toutes configs)
   ========================================================================== */
/* LA MÊME HAUTEUR QUE LES AUTRES ONGLETS — 360 px, ni plus ni moins. Le hub
   n'avait qu'un plancher : plus haut que Challenges ou Statistiques, il
   faisait changer la taille de la fenêtre (et son facteur d'agrandissement,
   calculé sur la hauteur) à chaque passage d'onglet. Les deux rangées se
   partagent la hauteur, la première un peu plus large. */
.hub-tab { height: 360px; max-height: 360px; display: flex; flex-direction: column; overflow: hidden; }
.hub-tab > .hub-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.hub-body > .hub-left { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.hub-left > div:first-child { flex: 1.2; min-height: 0; }
.hub-bottom-row { flex: 1; min-height: 0; }
.hub-mon-espace-card { display: flex; flex-direction: column; }
.hub-mon-espace-grid { flex: 1; align-content: stretch; }

/* LES TUILES : une seule recette, une couleur par tuile (`--t`, en r,g,b).
   Dégradé franc, bord teinté, éclat au survol dans la même couleur — les
   fonds à 8 % sur bord à 20 % faisaient des tuiles éteintes, bronze, violet
   ou gris, tristes à mourir. La couleur vit ICI et non dans la page : changer
   la palette est une ligne par tuile. */
.tuile {
    --hub-glow: rgba(var(--t), .45);
    background: linear-gradient(160deg, rgba(var(--t), .30), rgba(var(--t), .10));
    border: 1.5px solid rgba(var(--t), .50);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.10);
}
button.tuile:hover, div.tuile:hover {
    background: linear-gradient(160deg, rgba(var(--t), .46), rgba(var(--t), .20));
    border-color: rgba(var(--t), .85);
}
/* JOUER : l'or de la marque tirait au marron une fois fondu dans le fond
   sombre. La tuile principale prend le couple de la marque — l'or qui glisse
   vers le rouge du cœur —, plus dense que les autres : c'est la porte
   d'entrée, elle doit se voir la première. */
.tuile-jouer {
    --hub-glow: rgba(251,191,36,.55);
    background: linear-gradient(150deg, rgba(251,191,36,.62) 0%, rgba(245,158,11,.50) 45%, rgba(239,75,94,.48) 100%);
    border-color: rgba(253,224,71,.75);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 6px 18px rgba(0,0,0,.35);
}
button.tuile-jouer:hover {
    background: linear-gradient(150deg, rgba(251,191,36,.80) 0%, rgba(245,158,11,.66) 45%, rgba(239,75,94,.62) 100%);
    border-color: rgba(253,224,71,1);
}
.hub-mon-espace-card {
    background: rgba(255,255,255,0.03);
    border: 1.5px solid rgba(255,255,255,0.09);
    border-radius: 12px;
    padding: 9px 10px;
    
}
/* NOTE : .hub-body, .hub-left, .hub-right n'ont PAS de style de base.
   Ce sont des divs block normaux → Bloc Jouer + Mon Espace s'empilent verticalement.
   La réorganisation en grille n'est appliquée que sur iPhone via @media ci-dessous. */

/* Libellés courts des boutons de niveau (STD/INT/EXP) — visibles seulement sur iPhone */
.lvl-short { display: none; }

/* ==========================================================================
   CLASSES GÉNÉRIQUES — Formulaires & Inputs (réutilisables partout)
   ========================================================================== */

.form {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.form-group {
    display: flex;
    flex-direction: column;
}

.form-label {
    color: rgba(226, 232, 240, 0.92);
    font-weight: 700;
    font-size: 1rem;
    /* Capitales espacées : élégant mais nettement plus lent à lire, et le public
       du jeu a 70-80 ans. La forme des mots redevient reconnaissable en casse
       normale, ce qui compte plus ici que le style. */
    letter-spacing: 0.02em;
    margin-bottom: 0.25rem;
}

/* ── Messages sous les champs ─────────────────────────────────────────────
   Ils remplacent les bandeaux de 2 secondes : un message d'erreur doit rester
   affiché jusqu'à correction, et se trouver à côté de ce qu'il désigne. */
.form-error,
.form-ok,
.form-hint {
    font-size: 0.95rem;
    line-height: 1.45;
    margin-top: 6px;
    margin-left: 2px;
}
.form-error { color: #fca5a5; font-weight: 600; }
.form-ok    { color: #86efac; font-weight: 600; }
.form-hint  { color: rgba(255, 255, 255, 0.72); }

.form-actions {
    display: flex;
    gap: 1rem;
    margin: 0.5rem 0;
}

/* « Pseudo oublié ? » est le filet de sécurité de qui arrive sur un terminal
   neuf : il doit se voir. 0.875rem en bleu moyen sur fond sombre passait sous
   le seuil de contraste et sous le seuil de lisibilité d'un œil de 75 ans. */
.form-link {
    align-self: center;
    background: transparent;
    border: none;
    color: #93c5fd;
    font-size: 1.05rem;
    text-decoration: underline;
    cursor: pointer;
    transition: color 0.15s;
    padding: 0.55rem 0.25rem;
}

.form-link:hover {
    color: #93c5fd;
}

.confirmation {
    text-align: center;
    padding: 16px 0 8px;
}

.confirmation-icon {
    font-size: 3rem;
    margin-bottom: 14px;
}

.confirmation-title {
    font-size: 1.1rem;
    font-weight: 900;
    color: #fff;
    margin-bottom: 10px;
}

.confirmation-text {
    color: rgba(255, 255, 255, 0.6);
    font-size: 0.9rem;
    line-height: 1.7;
    margin-bottom: 8px;
}

.confirmation-email {
    color: #eef210;
}

.confirmation-hint {
    color: rgba(255, 255, 255, 0.4);
    font-size: 0.82rem;
    margin-bottom: 24px;
}

/* ==========================================================================
   SCREENS MODERNES — Look aligné landing page
   ========================================================================== */

/* Fond : tapis multicolor + overlay sombre (identique hero landing) */
.screen-login,
.screen-create-account,
.screen-menu-user,
.screen-lobby,
.screen-rematch {
    background:
        linear-gradient(to bottom right, rgba(14,8,20,.72) 0%, rgba(14,8,20,.50) 50%, rgba(14,8,20,.72) 100%),
        url('/tapis/multicolor.svg?nom=') center/cover no-repeat;
}

/* Carte LOGIN */
.screen-login .modal-box {
    width: 90%;
    max-width: 420px;
    margin: 0 auto;
    padding: 2rem 2.2rem 1.6rem;
    background: rgba(20, 11, 31, 0.88);
    border: 1px solid rgba(251, 191, 36, 0.18);
    border-radius: 20px;
    backdrop-filter: blur(24px) saturate(1.5);
    -webkit-backdrop-filter: blur(24px) saturate(1.5);
    box-shadow:
        0 0 0 1px rgba(255,255,255,.04),
        0 24px 64px rgba(0,0,0,0.55),
        0 0 100px rgba(251,191,36,.05);
}

/* Carte CREATE_ACCOUNT — plus large, scrollable */
.screen-create-account .modal-box {
    width: 90%;
    max-width: 520px;
    max-height: 90dvh;
    overflow-y: auto;
    margin: 0 auto;
    padding: 2rem 2.2rem 1.6rem;
    background: rgba(20, 11, 31, 0.88);
    border: 1px solid rgba(251, 191, 36, 0.18);
    border-radius: 20px;
    backdrop-filter: blur(24px) saturate(1.5);
    -webkit-backdrop-filter: blur(24px) saturate(1.5);
    box-shadow:
        0 0 0 1px rgba(255,255,255,.04),
        0 24px 64px rgba(0,0,0,0.55),
        0 0 100px rgba(251,191,36,.05);
}

/* Titre : gradient or, police système, sans text-shadow */
.screen-login .modal-title,
.screen-create-account .modal-title {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-size: 1.6rem;
    font-weight: 900;
    letter-spacing: -0.02em;
    background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 50%, #fde68a 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    text-shadow: none;
    margin-bottom: 1.5rem;
}

/* Labels : discrets */
.screen-login .form-label,
.screen-create-account .form-label {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: .1em;
    color: rgba(241,245,249,.45);
    margin-bottom: 0.3rem;
}

/* Inputs : glass léger */
.screen-login .input-text,
.screen-create-account .input-text {
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.11);
    border-radius: 10px;
    font-size: 1rem;
}
.screen-login .input-text:focus,
.screen-create-account .input-text:focus {
    background: rgba(255,255,255,.08);
    border-color: rgba(251,191,36,.45);
    box-shadow: 0 0 0 3px rgba(251,191,36,.1);
}

/* Bouton principal */
.screen-login .btn-action,
.screen-create-account .btn-action {
    background: #fbbf24;
    color: #0e0814;
    font-weight: 800;
    font-size: 0.95rem;
    letter-spacing: .06em;
    border-radius: 10px;
    border: none;
    border-bottom: none;
    padding: 13px 28px;
    box-shadow: 0 4px 18px rgba(251,191,36,.32);
    transition: all .2s ease;
}
.screen-login .btn-action:hover,
.screen-create-account .btn-action:hover {
    background: #fde68a;
    transform: translateY(-2px);
    box-shadow: 0 8px 28px rgba(251,191,36,.5);
}
.screen-login .btn-action:active,
.screen-create-account .btn-action:active { transform: translateY(0); border-bottom: none; }

/* Bouton secondaire : outline */
.screen-login .btn-secondary,
.screen-create-account .btn-secondary {
    background: transparent;
    color: #f1f5f9;
    font-weight: 700;
    font-size: 0.95rem;
    letter-spacing: .04em;
    border-radius: 10px;
    border: 1.5px solid rgba(255,255,255,.22);
    border-bottom: 1.5px solid rgba(255,255,255,.22);
    padding: 13px 28px;
    box-shadow: none;
    transition: all .2s ease;
}
.screen-login .btn-secondary:hover,
.screen-create-account .btn-secondary:hover {
    border-color: rgba(255,255,255,.5);
    background: rgba(255,255,255,.06);
    transform: translateY(-2px);
    box-shadow: none;
}
.screen-login .btn-secondary:active,
.screen-create-account .btn-secondary:active { transform: translateY(0); }

/* Liens */
.screen-login .form-link,
.screen-create-account .form-link {
    color: rgba(241,245,249,.45);
    font-size: 0.8rem;
    text-decoration: none;
}
.screen-login .form-link:hover,
.screen-create-account .form-link:hover {
    color: #fbbf24;
    text-decoration: none;
}


/* Carte LOBBY / REMATCH — large, glassmorphisme, scrollbar fine */
.screen-lobby .modal-box,
/* « Rejouer » et « Quitter » restent au bas de la fenêtre de fin de partie.
   La boîte récapitule le score, les équipes et l'Elo : dès que la hauteur
   manque — un iPhone SE en portrait suffit, le paysage plus encore — les
   boutons se retrouvaient tout en bas d'un contenu qui défile, hors de vue.
   La fenêtre paraissait alors bloquée.
   Sans média query : `sticky` ne produit aucun effet tant que le contenu tient,
   et le bandeau qui détache les boutons n'apparaît qu'avec la classe
   `peut-defiler`, posée par app.js quand le débordement est réel. */
.fin-partie-actions {
    position: sticky;
    bottom: 0;
    z-index: 2;
}
.modal-box.peut-defiler .fin-partie-actions {
    margin-top: 8px;
    padding-top: 6px;
    background: linear-gradient(to bottom, rgba(14,8,20,0), rgba(14,8,20,.97) 35%);
}
/* Le voile générique de défilement ferait doublon et passerait par-dessus. */
.screen-rematch .modal-box.peut-defiler::after { display: none; }

.screen-rematch .modal-box {
    width: 90%;
    max-width: 940px;
    max-height: 92dvh;
    overflow-y: auto;
    margin: 0 auto;
    padding: 1.4rem 1.6rem 1.4rem;
    text-align: center;
    background: rgba(14, 8, 20, 0.92);
    border: 1px solid rgba(251, 191, 36, 0.14);
    border-radius: 20px;
    backdrop-filter: blur(28px) saturate(1.4);
    -webkit-backdrop-filter: blur(28px) saturate(1.4);
    box-shadow:
        0 0 0 1px rgba(255,255,255,.03),
        0 32px 80px rgba(0,0,0,0.65),
        0 0 120px rgba(251,191,36,.04);
    scrollbar-width: thin;
    scrollbar-color: rgba(251,191,36,.25) transparent;
}
.screen-lobby .modal-box::-webkit-scrollbar,
.screen-rematch .modal-box::-webkit-scrollbar { width: 4px; }
.screen-lobby .modal-box::-webkit-scrollbar-track,
.screen-rematch .modal-box::-webkit-scrollbar-track { background: transparent; }
.screen-lobby .modal-box::-webkit-scrollbar-thumb,
.screen-rematch .modal-box::-webkit-scrollbar-thumb {
    background: rgba(251,191,36,.25);
    border-radius: 999px;
}
.screen-lobby .modal-box::-webkit-scrollbar-thumb:hover,
.screen-rematch .modal-box::-webkit-scrollbar-thumb:hover { background: rgba(251,191,36,.5); }

/* Titre lobby / rematch : gradient or, police système */
.screen-lobby .modal-title,
.screen-rematch .modal-title {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-size: 1.4rem;
    font-weight: 900;
    letter-spacing: -0.01em;
    background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 50%, #fde68a 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    text-shadow: none;
}

/* Carte MENU_USER — large, glassmorphisme */
.screen-menu-user .modal-box {
    width: 90%;
    max-width: 900px;
    max-height: 92dvh;
    overflow-y: auto;
    margin: 0 auto;
    padding: 1.4rem 1.6rem 1.4rem;
    text-align: left;
    background: rgba(14, 8, 20, 0.92);
    border: 1px solid rgba(251, 191, 36, 0.14);
    border-radius: 20px;
    backdrop-filter: blur(28px) saturate(1.4);
    -webkit-backdrop-filter: blur(28px) saturate(1.4);
    box-shadow:
        0 0 0 1px rgba(255,255,255,.03),
        0 32px 80px rgba(0,0,0,0.65),
        0 0 120px rgba(251,191,36,.04);
}

/* === CREATE_ACCOUNT — écran court (iPhone en paysage) ===
   Sur ce format, c'est la HAUTEUR qui manque, jamais la largeur : un iPhone
   couché offre 844 px de large pour 390 de haut. Or la fenêtre y était bridée
   à 450 px et le formulaire replié sur une seule colonne — ce qui doublait sa
   hauteur, précisément là où elle est la ressource rare. Le formulaire
   demandait alors 1017 px de défilement pour 334 px visibles.
   La fenêtre s'élargit donc et garde ses deux colonnes. */
@media (max-height: 450px) {
    .screen-create-account .modal-box {
        width: calc(100% - 16px);
        max-width: 720px;
        max-height: 95dvh;
        overflow-y: auto;
        padding: 1rem;
        margin: auto;
    }
}

/* === ACCUEIL DE L'ESSAI — écran court (téléphone en paysage) ===
   Même constat que l'inscription : sur une seule colonne, l'accueil faisait
   469 px pour 334 visibles, et « JOUER → » — l'action pour laquelle le
   visiteur est venu de la landing — tombait sous le bord. Deux colonnes : le
   prénom, le bouton et les liens à gauche, les quatre visages à droite.
   À la fin de l'essai, « CRÉER MON COMPTE » passait sous le voile « ▾ » et
   paraissait éteint : il reste collé au bas de la fenêtre. */
@media (max-height: 450px) {
    #modal-essai-accueil { width: calc(100% - 16px); max-width: 760px; }
    #modal-essai-accueil .form {
        display: grid; grid-template-columns: 1fr 1fr; column-gap: 20px; align-items: center;
    }
    #modal-essai-accueil .form > .form-group:first-child { grid-column: 1; grid-row: 1; }
    #modal-essai-accueil .form > .form-group:nth-child(2) { grid-column: 2; grid-row: 1 / span 3; margin: 0; }
    #modal-essai-accueil .form > .btn-action { grid-column: 1; grid-row: 2; }
    #modal-essai-accueil .form > .essai-liens { grid-column: 1; grid-row: 3; }
    #modal-essai-accueil .essai-visage { width: 72px; height: 72px; }
    #modal-essai-accueil .confirmation .btn-action { position: sticky; bottom: 8px; z-index: 3; }
}

/* === BADGE OBTENU — écran court (iPhone en paysage) ===
   La fenêtre mesurait 534 px de haut pour 390 disponibles sur un iPhone 14
   couché : elle défilait, et le bouton « Fermer » se trouvait sous la ligne de
   flottaison — sur un écran de félicitations, dont la moitié du propos est
   l'image du badge, c'est raté deux fois.
   Le poste le plus lourd était l'image, 256 px à elle seule, soit près de la
   moitié du total ; viennent ensuite les marges et les écarts, généreux au
   repos. Tout est resserré, l'image ramenée à 104 px : 266 px au total, ce qui
   tient sur un iPhone SE couché, le plus petit format visé.
   `!important` est nécessaire : le popup porte ses styles en ligne. */
@media (max-height: 450px) {
    .badge-overlay .badge-box {
        padding: 12px 20px !important;
        gap: 6px !important;
        max-width: 340px !important;
        border-radius: 16px !important;
    }
    .badge-overlay .badge-image {
        width: 104px !important;
        height: 104px !important;
    }
    /* Le halo suit l'image, sinon il rayonne autour d'un cercle deux fois
       plus grand que celle-ci. */
    .badge-overlay .badge-halo { inset: -12px !important; }
    .badge-overlay .badge-entete > div:first-child { font-size: 0.52rem !important; margin-bottom: 2px !important; }
    .badge-overlay .badge-entete > div:last-child  { font-size: 0.72rem !important; }
    .badge-overlay .badge-separateur { width: 50px !important; }
    .badge-overlay .badge-description { font-size: 1rem !important; }
    .badge-overlay .badge-date { font-size: 0.58rem !important; }
    /* Les étoiles décoratives encombrent une fenêtre deux fois plus petite,
       et l'une d'elles passait derrière le bouton de fermeture. */
    .badge-overlay .badge-box > span { display: none !important; }
    .badge-overlay .badge-fermer {
        margin-top: 2px !important;
        padding: 6px 20px !important;
        font-size: 0.68rem !important;
    }
}

/* Le repli sur une colonne se décide sur la LARGEUR, seul cas où deux colonnes
   ne tiennent pas — un téléphone tenu droit, où la fenêtre fait 370 px. */
@media (max-width: 560px) {
    .form-row {
        grid-template-columns: 1fr;
        gap: 16px 20px;
    }
}


/* ==========================================================================
   RESPONSIVE iPhone — sidebar compacte, éléments réduits
   ========================================================================== */
@media (max-height: 450px) {
    /* Le toolbar est téléporté hors de #app (Teleport Vue) : position:fixed
       est relatif au viewport, aucun contre-scale nécessaire.
       zoom:1 annule le zoom desktop → tailles tactiles en px réels ;
       la safe-area basse (barre home paysage) est déjà gérée par le `bottom`. */
    .toolbar-inner {
        gap: 4px;
    }
    .toolbar-tools {
        padding: 3px 6px;   /* même resserrement qu'en grand format */
        gap: 3px;
    }
    /* NOTE : les fenêtres Son / Dire / Disposition étaient ajustées ici. Elles
       ont désormais leur propre bloc (« FENÊTRES DE LA BARRE D'OUTILS »), qui
       les passe en feuille ancrée en bas dès que le petit côté descend sous
       500 px — ce media query, lui, ne regardait que la hauteur et laissait
       donc le téléphone en portrait de côté. */
    /* 34px : taille tactile minimale confortable (zoom:1, px réels) */
    .sidebar-btn {
        width: 34px;
        height: 34px;
    }
    .sidebar-btn svg, .sidebar-btn img {
        width: 18px !important;
        height: 18px !important;
    }

    /* NOTE : --card-w / --card-h / --hand-w sont pilotées par app.js
       (gameLayout : min(H,W)/3.4 sur téléphone) — ne pas les surcharger ici,
       les valeurs inline sur :root gagneraient de toute façon.
       Les mini-cartes du dernier pli (.mini-card-img) gardent leur taille de
       base : le zoom plancher (0,62) du .ui-panel suffit à les rendre
       lisibles. */

    .hud-name {
        font-size: 11px;
        max-width: 140px;
    }
    .player-bid-badge {
        left: 60px !important;
    }


    /* ── Fenêtres plus hautes que l'écran ──
       Le centrage flex de .modal-overlay coupait le haut ET le bas sans
       pouvoir y accéder. margin:auto centre quand ça tient, sinon la
       fenêtre s'aligne en haut et l'overlay devient scrollable. */
    .modal-overlay {
        align-items: flex-start;
        overflow-y: auto;
    }
    /* Le hub utilisateur, lui, tient désormais dans l'écran : collé en haut, il
       laissait 45 px de vide sous lui. `safe center` le centre tant qu'il tient
       et bascule tout seul en haut s'il venait à déborder — le comportement que
       ce media query cherche, sans le défaut du centrage nu, dont le haut
       devient inatteignable. La ligne `center` seule sert de repli aux
       navigateurs qui ignorent le mot-clé. */
    .modal-overlay.screen-menu-user {
        align-items: center;
        align-items: safe center;
    }
    /* MAIS les écrans qui empilent la marque AU-DESSUS de la fenêtre sont en
       `flex-direction: column` (cf. `.modal-overlay.screen-login` plus haut).
       Dans ce sens, `align-items` gouverne l'axe HORIZONTAL : le flex-start
       ci-dessus ne les alignait pas en haut, il les collait à gauche — la
       marque « CoinchePassion » se retrouvait à 119 px du bord au lieu d'être
       centrée à 422 sur un iPhone en paysage. La fenêtre, large de 95 %,
       masquait le problème ; la marque, étroite, le rendait flagrant.
       En colonne, c'est `justify-content` qui aligne vers le haut. */
    .modal-overlay.screen-login,
    .modal-overlay.screen-create-account {
        align-items: center;
        /* `safe center` centre le groupe tant qu'il tient, et bascule tout seul
           en haut dès qu'il déborde — ce qui est exactement l'intention de ce
           media query, sans le défaut du centrage nu (haut coupé et
           inatteignable quand ça dépasse). La ligne `center` seule sert de
           repli aux navigateurs qui ignorent le mot-clé. */
        justify-content: center;
        justify-content: safe center;
    }
    /* La marque et la fenêtre forment UN bloc : le `margin: auto` générique
       ci-dessous, en colonne, laissait la fenêtre absorber tout l'espace libre
       et se décrocher de la marque de 130 px. On ne garde ici que le centrage
       horizontal. */
    .modal-overlay.screen-login .modal-box,
    .modal-overlay.screen-create-account .modal-box {
        margin: 0 auto;
    }

    /* ── Modals scrollables ── */
    .modal-box {
        margin: auto;
        max-height: 95dvh;
        overflow-y: auto;
        padding: 1rem;
        border-width: 2px;
    }

    /* ── Récap de fin de manche : tenir dans l'écran (iPhone paysage) ── */
    /* Le zoom réduit aussi le max-height : on le divise par le zoom pour que le
       plafond corresponde à la vraie hauteur écran (sinon scroll prématuré alors
       qu'il reste de la place). La boîte peut ainsi occuper ~98 % de l'écran. */
    /* Zoom FIXE de 0,8, et non `--panel-zoom` : à son plancher de 0,62, les
       libellés tombaient à 6-8 px et « Continuer » à 25 px de haut, pour une
       fenêtre qui n'occupait que 300 des 390 px. La hauteur se regagne en
       masquant « Début de partie » (redit par les panneaux de coin) et en
       mettant « Total manche » et « Total partie » côte à côte. */
    .recap-box {
        zoom: 0.8;
        max-height: calc(98dvh / 0.8);
        overflow-y: auto;
        padding: 0.7rem 1rem;
        pointer-events: auto;
    }
    .recap-banner       { padding: 0.45rem 0.8rem; }
    .recap-banner-title { font-size: 1rem; }
    .recap-contract-slot{ min-height: 28px; }
    .recap-contract-pill{ font-size: 0.92rem; padding: 2px 9px; }
    .recap-col          { padding: 0.4rem 0.7rem; }
    .recap-line         { font-size: 0.9rem; padding: 1px 0; }
    .recap-line.prev    { display: none; }
    .recap-cols + .recap-cols .recap-col {
        display: grid; grid-template-columns: 1fr 1fr; column-gap: 8px; align-items: end;
    }
    .recap-cols + .recap-cols .recap-col > div:not(.recap-line) { grid-column: 1 / -1; }
    .recap-line.gain, .recap-line.total { flex-direction: column; align-items: center; }
    .recap-line.gain  .recap-line-val { font-size: 1.45rem; }
    .recap-line.total .recap-line-val { font-size: 1.6rem; }
    .recap-foot         { padding: 0.5rem 0.8rem 0.6rem; }
    /* « Continuer » : ses styles sont en ligne */
    .recap-foot-row > button { padding: 14px 22px !important; font-size: 1rem !important; }

    /* ── Titres ── */
    .modal-title {
        font-size: 1.2rem !important;
        margin-bottom: 0.5rem !important;
    }

    /* ── Inputs ── */
    .input-text {
        padding: 7px 10px;
        font-size: 0.9rem;
        margin-bottom: 8px;
    }
    .input-text-sm {
        padding: 5px 8px;
        font-size: 0.82rem;
        margin-bottom: 5px;
    }

    /* ── Screen LOGIN ── */
    .screen-login .modal-box {
        width: calc(100% - 16px);
        max-width: 450px;
        max-height: 95dvh;
        overflow-y: auto;
        padding: 1rem;
        margin: auto;
    }

    .login-label {
        font-size: 0.7rem;
        margin-bottom: 0.2rem;
    }

    .login-input {
        padding: 0.6rem 0.8rem;
        font-size: 0.85rem;
        margin-bottom: 0.6rem;
    }

    .login-actions {
        gap: 0.6rem;
        margin: 0.3rem 0;
    }

    .login-btn {
        padding: 0.6rem 0.8rem;
        font-size: 0.8rem;
    }

    .login-link {
        font-size: 0.75rem;
        padding: 0.4rem 0;
    }

    /* ── Boutons formulaire ── */
    .btn-action,
    .btn-secondary {
        padding: 7px 16px;
        font-size: 0.9rem;
        border-bottom-width: 2px;
    }

    /* ── LOBBY : 4 joueurs côte à côte ──
       La grille garde ses 7 pistes (siège, séparateur, siège…) mais les
       3 colonnes intermédiaires sont écrasées à 0 (boutons d'échange cachés),
       donc tout tient sur UNE ligne. Les étiquettes NOUS/EUX (span 3)
       restent centrées sur leur paire de sièges. */
    .lobby-grid {
        grid-template-columns: 1fr 0 1fr 0 1fr 0 1fr !important;
        gap: 6px !important;
        margin-top: 0 !important;
    }
    .lobby-grid.mt-16 { margin-top: 28px !important; } /* place pour les avatars */
    .btn-swap { display: none; }

    /* ── LOBBY : avatars compacts ──
       Encore resserrés depuis le passage en une seule colonne : la grille des
       joueurs est le plus gros poste de hauteur, et c'est elle qui décide si
       « Parler / Son » passe au-dessus du bandeau d'actions ou dessous. */
    /* Les avatars étaient tombés à 58 px : on ne distinguait plus un visage
       d'un autre, et le salon perdait ce qui en fait l'intérêt — voir avec qui
       l'on va jouer. Ce n'est pourtant pas la hauteur qui manquait : une carte
       occupe 142 px, avatar débordant compris, pour 359 utiles en paysage.
       À 88 px l'avatar redevient lisible, la carte monte à ~172 px, et il reste
       de quoi loger le titre, la ligne Parler/Son et le bandeau d'actions.
       Le portrait garde ses 120 px, il n'a jamais eu ce problème. */
    .lobby-seat-avatar {
        width: 88px;
        height: 88px;
        top: -42px;
        border-radius: 13px;
    }
    .lobby-player-card {
        padding: 50px 6px 6px !important;
    }
    /* Les décorations suivent le rayon de l'avatar : leur décalage se lisait
       « demi-largeur + 9 px », soit 53 px pour 88 au lieu de 38 pour 58. */
    .lobby-joker-badge {
        top: -44px;
        left: calc(50% - 53px);
        width: 24px;
        height: 24px;
    }
    .gift-zone.gift-lobby { width: 22px; height: 22px; font-size: 12px; }
    .gift-zone.gift-lobby.gift-friandise { left: calc(50% - 53px); top: 6px; right: auto; bottom: auto; }
    .gift-zone.gift-lobby.gift-boisson    { left: calc(50% - 53px); top: -20px; right: auto; bottom: auto; }

    /* ── LOBBY : une seule colonne, comme partout ailleurs ──
       Le salon passait en deux colonnes sur ce format, pour économiser de la
       hauteur. Mais les quatre joueurs, qui se rangent en ligne, se retrouvaient
       comprimés dans 55 % de la largeur, tandis que la colonne de droite en
       consommait 45 % pour y loger deux boutons. Un iPhone couché offre 844 px :
       la largeur n'est pas ce qui manque.
       Empilé, tout tient — et si l'hôte déploie ses options, le bandeau
       d'actions reste collé en bas de toute façon. */
    .lobby-body { display: block; }
    .lobby-left, .lobby-right { width: auto; }
    .lobby-right { padding-top: 0; }
    /* Parler et Son : une ligne compacte sous les joueurs. */
    .lobby-right .flex.justify-center.gap-3 {
        flex-wrap: nowrap;
        margin-top: 6px !important;
        margin-bottom: 0;
    }
    .lobby-right .flex.justify-center.gap-3 button { padding: 4px 12px !important; }

    /* En-tête resserré : le titre et sa légende sont dimensionnés en style en
       ligne, d'où les !important. Ensemble ils rendent une trentaine de pixels,
       ce qui suffit à faire passer « Parler / Son » au-dessus du bandeau
       d'actions plutôt que dessous. */
    .screen-lobby .modal-title {
        font-size: 1.2rem !important;
        margin-bottom: 2px !important;
    }
    .screen-lobby .modal-box > div[style*="marginBottom"],
    .screen-lobby .modal-box > div[style*="margin-bottom"] { margin-bottom: .3rem !important; }

    /* Le salon respire moins : 1,4 rem de marge haute et basse, c'est 45 px
       pris sur les 357 disponibles. */
    .screen-lobby .modal-box,
    .screen-rematch .modal-box { padding: .7rem 1.1rem; }

    /* ── FIN DE PARTIE : tout doit tenir dans 359 px ──
       La marge haute du tableau réservait 68 px au débordement des avatars.
       Ceux du salon sont passés à 88 px avec un débordement de 42 : la réserve
       était devenue trop large de 26 px. Le reste vient des espacements et des
       compteurs, dont la taille n'apporte rien sur un écran court. */
    .screen-rematch .modal-title { font-size: 1.25rem !important; margin-bottom: .25rem !important; }
    .fin-partie-tables {
        margin-top: 46px !important;
        gap: 14px !important;
    }
    .fin-partie-camp { gap: 8px !important; }
    .fin-partie-compteurs { gap: 5px !important; }
    .fin-partie-compteur { padding: 5px 11px !important; min-width: 62px !important; }
    .fin-partie-compteur-nb { font-size: 1.35rem !important; }

    /* Les actions passent sous les deux colonnes, et y RESTENT visibles :
       le salon change de hauteur selon le nombre de joueurs et les options de
       l'hôte, si bien qu'un simple placement en bas les envoyait hors de vue
       dès que le contenu dépassait. Collées au bas de la fenêtre, « Jouer » et
       « Quitter » sont toujours sous la main, quoi qu'il y ait au-dessus. */
    .lobby-actions {
        position: sticky;
        bottom: 0;
        z-index: 2;
        margin-top: 8px;
        padding-top: 6px;
        background: linear-gradient(to bottom, rgba(14,8,20,0), rgba(14,8,20,.97) 35%);
    }
    .lobby-actions .py-3 { padding-top: .45rem; padding-bottom: .45rem; }
    .lobby-actions .text-xl { font-size: 1rem; }
    .lobby-actions .gap-4 { gap: .6rem; }
    /* Le voile générique de défilement ferait doublon avec ce bandeau, et
       passerait par-dessus les boutons. */
    .screen-lobby .modal-box.peut-defiler::after { display: none; }

    /* ── LOBBY : zone hôte compacte ── */
    .lobby-host-zone {
        margin-top: 0 !important;
        gap: 0.5rem !important;
    }
    .lobby-score-presets { display: none; }
    .lobby-host-zone .w-11 { width: 2rem; }
    .lobby-host-zone .h-12 { height: 2rem; }
    .lobby-host-zone .text-2xl { font-size: 1.1rem; }
    .lobby-host-zone .py-3 { padding-top: 0.4rem; padding-bottom: 0.4rem; }
    .lobby-host-zone .text-white { font-size: 0.85rem; }

    /* ── MENU_USER : carte profil compacte ──
       Objectif : aucun défilement vertical. Couché, l'iPhone n'offre que
       359 px de fenêtre pour 418 px de contenu — 61 px de trop. Le rembourrage
       de la fenêtre en prenait 45 à lui seul, l'en-tête 138. */
    .screen-menu-user .modal-box { padding: 5px 14px !important; }
    .menu-user-header {
        padding: 5px 10px !important;
        gap: 6px !important;
        margin-bottom: 5px !important;
    }
    .menu-user-avatar-wrap {
        width: 74px !important;
        height: 74px !important;
        border-radius: 12px !important;
    }
    /* Le cadre des badges portait sa taille en ligne : 120 px carrés, devenus
       le plus haut élément de l'en-tête une fois l'avatar réduit. Ciblé par son
       `data-coach`, plus stable qu'une classe utilitaire. */
    .menu-user-header [data-coach="badge"],
    .menu-user-header [data-coach="badge"] img { width: 96px !important; }
    .hub-tab { min-height: 0 !important; height: auto !important; max-height: none !important; display: block !important; }

    /* ── HORS DE L'ACCUEIL : un en-tête d'une ligne, des onglets à la hauteur
       de l'écran (25/10/2026) ──
       L'en-tête prenait 150 px sur 375, et chaque onglet gardait ses 360 px
       de bureau : « ▶ Jouer » du défi, les rangs 4 à 10, les tableaux des
       jetons étaient sous la ligne de flottaison, dans un défilement imbriqué.
       Hors de l'accueil, l'en-tête ne garde que ce qui sert de repère — le
       visage, le nom, les badges, le Joker et la colonne des boutons, mise
       à plat —, et l'onglet prend toute la hauteur qui reste (la fenêtre
       devient une colonne, l'onglet son élément souple). */
    .screen-menu-user .modal-box.hors-accueil {
        display: flex; flex-direction: column;
        height: calc(100dvh - 8px); max-height: calc(100dvh - 8px);
    }
    /* `overflow: visible` : un onglet coupé à sa hauteur (Top 10, Défis)
       cachait ses rangs 4 à 10 et ses compteurs ; débordant, c'est la fenêtre
       qui défile, avec son signe ▾ */
    .screen-menu-user .modal-box.hors-accueil > div[style*="360px"] {
        flex: 1 1 0; height: auto !important; min-height: 0 !important; max-height: none !important;
        overflow: visible !important;
    }
    .hors-accueil .menu-user-header { flex-shrink: 0; padding-top: 12px !important; padding-bottom: 4px !important; }
    .hors-accueil .menu-user-avatar-wrap { width: 44px !important; height: 44px !important; border-width: 2px !important; border-radius: 9px !important; }
    .hors-accueil .menu-user-header .min-w-0 > div + div { display: none; }          /* compteurs */
    .hors-accueil .menu-user-header [data-coach="badge"],
    .hors-accueil .menu-user-header [data-coach="badge"] img { width: 50px !important; }
    .hors-accueil .menu-user-header [data-coach="badge"] > div:first-of-type > div:first-child { display: none; }
    .hors-accueil .menu-user-header [data-coach="badge"] > div:first-of-type > div + div { font-size: .62rem !important; }
    .hors-accueil .menu-user-header [data-coach="classement"] { display: none !important; }
    .hors-accueil .menu-user-header [data-coach="amicale"] { display: none !important; }
    .hors-accueil .menu-user-joker { flex-direction: row !important; padding-top: 0 !important; padding-bottom: 0 !important; }
    .hors-accueil .menu-user-joker img { width: 28px !important; }
    .hors-accueil .menu-user-joker > div:nth-of-type(2) { display: none; }            /* « Débutant »… */
    .hors-accueil .menu-user-header > div:last-child { flex-direction: row !important; align-items: center !important; gap: 6px !important; }
    .hors-accueil .menu-user-header > div:last-child > button:first-child { margin-bottom: 0 !important; }
    /* Badges : la barre de filtres défile au doigt au lieu d'être coupée, et
       l'image (256 px) se loge dans la hauteur qui reste — sa place dans le
       carrousel, elle, ne change pas (le pas de 276 px est calculé) */
    .badges-filtres { overflow-x: auto; scrollbar-width: none; }
    .badges-filtres::-webkit-scrollbar { display: none; }
    .badge-piste { height: 100%; justify-content: center; }
    .badge-piste > img { height: auto !important; max-height: calc(100% - 30px); }
    /* Au doigt, il n'y a pas de survol : la description se lit d'emblée */
    .badge-desc { opacity: 1 !important; }

    /* ── HUB D'UN TÉLÉPHONE EN PAYSAGE : deux rangées (25/10/2026) ──
       ┌────────────────────────────────┬───────────┐
       │ JOUER                          │ Salon     │
       │                                │ privé     │
       ├────────────────┬───────────────┴───────────┤
       │ Défis │ Chall. │ Stats Param. Appr. … Arena │
       └────────────────┴───────────────────────────┘
       Sous l'en-tête, il reste ~215 px : c'est la hauteur qui manque, pas
       la largeur. Une grille sur une seule rangée était prévue ici, mais
       elle ne s'est jamais appliquée — `.hub-tab > .hub-body` (deux classes,
       règle de base) battait `.hub-body` — et ses cinq pictos de « Mon
       espace », empilés, l'auraient rendue plus haute que l'écran. La
       grille porte donc le sélecteur de la règle de base.
       `display: contents` sur les conteneurs intermédiaires fait de leurs
       enfants des items directs de la grille : les quatre cartes s'ordonnent
       alors librement, sans rien changer au HTML. */
    .hub-tab > .hub-body {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 170px;
        grid-template-areas: "publics publics prive" "defier espace espace";
        gap: 8px;
        align-items: stretch;
    }
    /* Deux niveaux à traverser : `.hub-left` enveloppe un conteneur flex qui
       porte les salons publics et le salon privé. Rendre le seul parent
       transparent aurait fait de ce conteneur un item de grille sans zone
       assignée — il serait parti dans une colonne implicite. */
    .hub-left        { display: contents !important; }
    .hub-left > div  { display: contents !important; }
    .hub-publics     { grid-area: publics; }
    .hub-prive       { grid-area: prive; }
    .hub-bottom-row  { display: contents !important; }
    .hub-defier-card { grid-area: defier; }
    .hub-mon-espace-card { grid-area: espace; margin-top: 0 !important; }
    .hub-publics, .hub-prive, .hub-defier-card, .hub-mon-espace-card { padding: 6px 8px !important; }

    /* ── Titres des blocs masqués (gain de hauteur) :
       "Jouer avec toute la communauté", "Jouer entre amis", "Défier" ── */
    .hub-left .text-yellow-500\/50,
    .hub-defier-card > div:first-child { display: none !important; }
    /* « Changer de niveau ou de format » : un lien de 17 px de haut */
    .hub-publics > button + button { padding: 8px 12px !important; margin-top: 2px !important; }
    /* La première rangée tient en ~100 px, sinon la seconde sort de l'écran :
       JOUER sans son grand picto, le salon privé sur une ligne de liens */
    .hub-publics .hub-btn .hub-picto-grand { display: none; }   /* bat `.hub-btn .hub-ico`, plus bas */
    .hub-prive > button { padding: 6px !important; gap: 3px !important; }
    .hub-prive > button > div:nth-of-type(1) { font-size: .9rem !important; }
    .hub-prive > button > div:last-child { font-size: .6rem !important; gap: 4px !important; flex-wrap: nowrap !important; }

    /* ── Défier : les deux boutons côte à côte ── */
    .hub-defier-grid {
        grid-template-columns: 1fr 1fr !important;
        gap: 6px !important;
        height: 100%;
        align-content: stretch;
    }
    .hub-defier-grid > button { padding: 6px 8px !important; gap: 6px !important; min-height: 44px; }
    .hub-defier-grid .hub-ico { font-size: 1.3rem !important; }
    .hub-defier-grid .hub-picto { width: 1.3rem !important; height: 1.3rem !important; }
    /* Le bloc texte du bouton « Défis » porte un width:100% en ligne, qui dans
       une colonne étroite réclamait plus que la place disponible et poussait
       l'indicateur hors du bouton. `min-width:0` lui rend sa souplesse. */
    .hub-defier-grid > button > div { min-width: 0; flex: 1; }
    /* Le prix en jetons quitte ces deux boutons : « Quotidien », le badge et
       l'indicateur de la journée ne tiennent pas de front. Le coût reste
       affiché dans l'écran Défis, au moment où il se décide. */
    /* Vue réécrit la couleur en ligne : `#d4af7a` devient `rgb(212, 175, 122)`,
       et le premier sélecteur ne trouvait rien */
    .hub-defier-grid span[style*="#d4af7a"],
    .hub-defier-grid span[style*="212, 175, 122"] { display: none !important; }
    .hub-defier-grid > button > div div:first-child { font-size: .74rem !important; letter-spacing: .02em !important; }
    /* Sans leur picto : « CHALLENGES » se coupait dans ~115 px */
    .hub-defier-grid .hub-btn .hub-picto { display: none; }

    /* ── Joker ELO compact ── */
    .menu-user-joker img { width: 40px !important; }
    .menu-user-joker .text-3xl { font-size: 1.1rem !important; }
    .menu-user-joker { padding-left: 8px !important; padding-right: 8px !important; }

    /* ── Mon espace : une rangée de pictos, chacun avec son NOM (un picto
       seul ne se devine pas), sans le sous-titre ── */
    .hub-mon-espace-card > div:first-child { display: none; }   /* titre "Mon espace" */
    .hub-mon-espace-grid {
        grid-template-columns: none !important;
        grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
        gap: 5px !important;
        flex: 1;
        align-content: stretch;
    }
    .hub-mon-espace-grid > button {
        flex-direction: column !important;
        padding: 5px 2px !important;
        border-radius: 8px !important;
        gap: 2px !important;
        justify-content: center !important;
        min-height: 44px;
    }
    .hub-mon-espace-grid .hub-picto { width: 1.3rem !important; height: 1.3rem !important; }
    .hub-mon-espace-grid > button > div { text-align: center !important; min-width: 0; max-width: 100%; }
    .hub-mon-espace-grid > button > div > div:first-child {
        font-size: .56rem !important; letter-spacing: 0 !important;
        white-space: normal !important; line-height: 1.05;
    }
    .hub-mon-espace-grid > button > div > div + div { display: none !important; }  /* sous-titres */
}


/* ==========================================================================
   DYNAMISATION — couche ambiante & micro-animations (écrans hors plateau)
   Même langage visuel que la landing page : aurores, enseignes flottantes,
   shimmer doré, reflets sur les boutons.
   ========================================================================== */

/* --- Couche ambiante : composant <ambient-fx>, PREMIER enfant d'un écran.
       Peinte au-dessus du fond tapis de l'écran, sous la fenêtre modale qui
       la suit dans le DOM (la .modal-box est position:relative). --- */
.ambient-fx-in {
    position: absolute; inset: 0;
    overflow: hidden;
    pointer-events: none;
}

.ambient-aurora {
    position: absolute;
    border-radius: 50%;
    filter: blur(90px);
    mix-blend-mode: screen;
    will-change: transform;
}
.ambient-aurora-1 {
    width: 560px; height: 560px;
    background: radial-gradient(circle, rgba(124,58,237,.5), transparent 65%);
    top: -140px; left: -120px;
    animation: ambDrift1 22s ease-in-out infinite alternate;
}
.ambient-aurora-2 {
    width: 500px; height: 500px;
    background: radial-gradient(circle, rgba(251,191,36,.38), transparent 65%);
    bottom: -120px; right: -100px;
    animation: ambDrift2 26s ease-in-out infinite alternate;
}
.ambient-aurora-3 {
    width: 420px; height: 420px;
    background: radial-gradient(circle, rgba(255,68,102,.3), transparent 65%);
    top: 30%; left: 45%;
    animation: ambDrift3 19s ease-in-out infinite alternate;
}
@keyframes ambDrift1 { to { transform: translate(140px, 90px)   scale(1.18); } }
@keyframes ambDrift2 { to { transform: translate(-120px, -70px) scale(1.12); } }
@keyframes ambDrift3 { to { transform: translate(-90px, 110px)  scale(0.9);  } }

.ambient-pt {
    position: absolute; bottom: -50px;
    line-height: 1;
    animation: ambRise linear infinite;
    will-change: transform;
    user-select: none;
    text-shadow: 0 0 10px currentColor, 0 0 26px currentColor;
}
@keyframes ambRise {
    to { transform: translateY(-115vh) rotate(320deg); }
}

/* --- Apparition des fenêtres modales (montée + fondu) --- */
.modal-box {
    animation: boxRise .5s cubic-bezier(.16,1,.3,1);
}
@keyframes boxRise {
    from { opacity: 0; transform: translateY(22px) scale(.98); }
    to   { opacity: 1; transform: none; }
}

/* --- Titres : shimmer doré (même effet que la landing) --- */
.modal-title {
    background: linear-gradient(110deg, #fbbf24 20%, #fff7d6 38%, #f59e0b 52%, #fde68a 70%, #fbbf24 85%);
    background-size: 220% auto;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: goldShineTitle 4.5s linear infinite;
}
@keyframes goldShineTitle {
    to { background-position: -220% center; }
}

/* --- Boutons d'action : reflet balayant au survol --- */
.btn-action {
    position: relative;
    overflow: hidden;
}
.btn-action::after {
    content: '';
    position: absolute; top: 0; left: -85%;
    width: 55%; height: 100%;
    background: linear-gradient(105deg, transparent, rgba(255,255,255,.45), transparent);
    transform: skewX(-20deg);
    transition: left .55s ease;
    pointer-events: none;
}
.btn-action:hover::after { left: 135%; }

/* --- Joker du login : flottement + halo pulsant --- */
.login-joker {
    animation: jokerFloat 3.5s ease-in-out infinite;
}
@keyframes jokerFloat {
    0%, 100% { transform: translateY(0);    filter: drop-shadow(0 0 10px rgba(251,191,36,.35)); }
    50%      { transform: translateY(-6px); filter: drop-shadow(0 0 22px rgba(251,191,36,.65)); }
}

/* --- Lobby : cartes joueurs réactives --- */
.lobby-player-card {
    transition: transform .2s ease, box-shadow .2s ease;
}
.lobby-player-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 10px 28px rgba(0,0,0,.45);
}

/* --- Hub (Menu utilisateur) : boutons réactifs + halo avatar --- */
.hub-lvl-grid > button,
.hub-defier-grid > button,
.hub-mon-espace-grid > button {
    transition: transform .18s ease, box-shadow .18s ease, background .18s ease;
}
.hub-lvl-grid > button:hover,
.hub-defier-grid > button:hover,
.hub-mon-espace-grid > button:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 22px rgba(0,0,0,.4);
}
.menu-user-avatar-wrap {
    animation: avatarGlow 3.5s ease-in-out infinite;
}

/* --- Boutons du hub : relief, reflet balayant, éclat coloré (tailles inchangées :
       uniquement pseudo-éléments absolus, transform et box-shadow) --- */
.hub-btn {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}
/* Relief interne : lumière en haut, assombrissement en bas */
.hub-btn::before {
    content: '';
    position: absolute; inset: 0;
    border-radius: inherit;
    background: linear-gradient(180deg, rgba(255,255,255,.10), transparent 42%, rgba(0,0,0,.18));
    pointer-events: none;
    z-index: -1;
}
/* Reflet balayant au survol */
.hub-btn::after {
    content: '';
    position: absolute; top: 0; left: -90%;
    width: 55%; height: 100%;
    background: linear-gradient(105deg, transparent, rgba(255,255,255,.22), transparent);
    transform: skewX(-20deg);
    transition: left .5s ease;
    pointer-events: none;
}
.hub-btn:hover::after { left: 140%; }
/* Soulèvement + éclat coloré (couleur par bouton via --hub-glow) */
button.hub-btn, div.hub-btn {
    transition: transform .18s ease, box-shadow .18s ease, background .15s, border-color .15s;
}
button.hub-btn:hover, div.hub-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 22px rgba(0,0,0,.45), 0 0 20px var(--hub-glow, rgba(251,191,36,.2));
}
button.hub-btn:active {
    transform: translateY(0) scale(.97);
    box-shadow: 0 3px 10px rgba(0,0,0,.4);
}
/* Icône qui « pop » au survol */
.hub-btn .hub-ico {
    display: inline-block;
    transition: transform .22s cubic-bezier(.2,1.4,.4,1);
}
/* Les pictos du hub : une famille (static/icons/hub.svg), un trait, une
   couleur — le blanc, légèrement voilé, comme les titres des tuiles. Les
   emojis changeaient de dessin d'une tuile à l'autre et de plateforme à
   l'autre. La taille se règle ici et non dans le SVG. */
.hub-picto {
    width: 2rem; height: 2rem; flex-shrink: 0;
    color: rgba(255,255,255,0.92);
    filter: drop-shadow(0 2px 4px rgba(0,0,0,.45));
}
.hub-picto-grand { width: 2.1rem; height: 2.1rem; }
.hub-btn:hover .hub-ico { transform: scale(1.25) rotate(-6deg); }
@media (prefers-reduced-motion: reduce) {
    .hub-btn::after { display: none; }
    button.hub-btn:hover, div.hub-btn:hover { transform: none; }
}

/* Défi du jour disponible : cible qui pulse avec halo (incitation à jouer) */
.defi-dispo {
    display: inline-block;
    animation: defiPulse 1.4s ease-in-out infinite;
    filter: drop-shadow(0 0 6px rgba(96,165,250,.9));
}
@keyframes defiPulse {
    0%, 100% { transform: scale(1)    rotate(0deg); filter: drop-shadow(0 0 4px rgba(96,165,250,.6)); }
    50%      { transform: scale(1.35) rotate(-8deg); filter: drop-shadow(0 0 14px rgba(96,165,250,1)); }
}
@media (prefers-reduced-motion: reduce) {
    .defi-dispo { animation: none; }
}
@keyframes avatarGlow {
    0%, 100% { box-shadow: 0 0 14px rgba(250,204,21,.25); }
    50%      { box-shadow: 0 0 28px rgba(250,204,21,.55); }
}

/* Bouton « Retour » du hub : bien en évidence quand on est dans un sous-onglet */
.hub-btn-retour {
    background: #fbbf24;
    border: 1px solid #fde68a;
    color: #0e0814;
    transition: background .15s, box-shadow .15s;
    animation: hubBackPulse 1.7s ease-in-out infinite;
}
.hub-btn-retour:hover {
    background: #fde68a;
    box-shadow: 0 0 16px rgba(251,191,36,.75);
    animation: none;
}
@keyframes hubBackPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(251,191,36,.55); }
    50%      { box-shadow: 0 0 14px 2px rgba(251,191,36,.6); }
}
@media (prefers-reduced-motion: reduce) {
    .hub-btn-retour { animation: none !important; }
}

/* --- Jeux de jetons : habillage casino --- */
.casino-box {
    background:
        radial-gradient(ellipse at 50% -10%, rgba(212,175,122,.13), transparent 55%),
        radial-gradient(ellipse at 50% 115%, rgba(124,58,237,.15), transparent 60%),
        rgba(12,12,26,.97) !important;
    border: 1.5px solid rgba(212,175,122,.55) !important;
    box-shadow:
        0 24px 70px rgba(0,0,0,.85),
        0 0 60px rgba(212,175,122,.16),
        inset 0 0 40px rgba(212,175,122,.05) !important;
}
.casino-title {
    display: flex; align-items: center; gap: 10px;
    color: #d4af7a;
    font-family: Georgia, 'Times New Roman', serif;
    font-size: 1.05rem; font-weight: bold;
    letter-spacing: .09em; text-transform: uppercase;
    text-shadow: 0 0 18px rgba(212,175,122,.45);
    white-space: nowrap;
}
.casino-title::before,
.casino-title::after {
    content: '✦';
    color: rgba(212,175,122,.6);
    font-size: .8rem;
    animation: casinoStar 2.2s ease-in-out infinite;
}
.casino-title::after { animation-delay: 1.1s; }
@keyframes casinoStar {
    0%, 100% { opacity: .35; transform: scale(.85); }
    50%      { opacity: 1;   transform: scale(1.2); }
}
/* Guirlande d'ampoules (chenillard) sous le titre */
.casino-lights {
    width: 100%; height: 6px;
    border-radius: 999px;
    background: repeating-linear-gradient(90deg,
        rgba(212,175,122,.95) 0 6px,
        rgba(212,175,122,.12) 6px 18px);
    animation: casinoLights 1.1s linear infinite;
    box-shadow: 0 0 12px rgba(212,175,122,.35);
    flex-shrink: 0;
}
@keyframes casinoLights { to { background-position: 18px 0; } }

/* Bouton d'action principal : or massif + reflet balayant */
.casino-btn {
    flex: 1;
    background: linear-gradient(135deg, #b8860b, #e8c98a 55%, #b8860b);
    border: none; border-radius: 8px;
    padding: 10px;
    color: #14091f;
    font-weight: 900; text-transform: uppercase; letter-spacing: .06em;
    font-size: .72rem;
    cursor: pointer;
    position: relative; overflow: hidden;
    box-shadow: 0 4px 16px rgba(212,175,122,.3);
    transition: transform .12s ease, box-shadow .15s ease;
}
.casino-btn:hover { transform: translateY(-1px); box-shadow: 0 6px 24px rgba(212,175,122,.5); }
.casino-btn::after {
    content: '';
    position: absolute; top: 0; left: -80%;
    width: 50%; height: 100%;
    background: linear-gradient(105deg, transparent, rgba(255,255,255,.55), transparent);
    transform: skewX(-20deg);
    animation: t10Sheen 2.8s ease-in-out infinite;
    pointer-events: none;
}
.casino-btn-wait {
    flex: 1;
    background: rgba(212,175,122,.07);
    border: 1.5px solid rgba(212,175,122,.2);
    border-radius: 8px;
    padding: 10px;
    color: rgba(212,175,122,.4);
    font-weight: 900; text-transform: uppercase;
    font-size: .72rem;
    cursor: not-allowed;
}
/* Compteur de tentatives : pastille dorée */
.casino-tries {
    font-size: .66rem;
    color: rgba(212,175,122,.7);
    background: rgba(212,175,122,.07);
    border: 1px solid rgba(212,175,122,.22);
    border-radius: 999px;
    padding: 3px 14px;
    letter-spacing: .04em;
}
/* Gain : pop d'apparition + halo vert pulsant */
.casino-gain {
    display: inline-block;
    animation: casinoGainPop .55s cubic-bezier(.2,1.6,.4,1),
               casinoGainGlow 1.6s ease-in-out .55s infinite;
}
@keyframes casinoGainPop {
    0%   { transform: scale(.3); opacity: 0; }
    70%  { transform: scale(1.18); }
    100% { transform: scale(1); opacity: 1; }
}
@keyframes casinoGainGlow {
    0%, 100% { text-shadow: 0 0 18px rgba(74,222,128,.5); }
    50%      { text-shadow: 0 0 36px rgba(74,222,128,1); }
}
/* Pop simple (résultat poker) */
.casino-pop { animation: casinoGainPop .55s cubic-bezier(.2,1.6,.4,1); }

/* Roue : anneau d'ampoules tournant + respiration lumineuse */
.casino-roue-ring {
    border: 4px dotted rgba(212,175,122,.85) !important;
    animation: casinoRing 14s linear infinite, casinoBoardGlow 2.4s ease-in-out infinite;
}
@keyframes casinoRing { to { transform: rotate(360deg); } }
/* Halo respirant (boîtier manchot, plateau pyramide) */
.casino-board-glow { animation: casinoBoardGlow 2.6s ease-in-out infinite; }
@keyframes casinoBoardGlow {
    0%, 100% { box-shadow: 0 0 22px rgba(212,175,122,.15); }
    50%      { box-shadow: 0 0 44px rgba(212,175,122,.38); }
}
/* Manchot : fenêtre centrale pulsante */
.casino-slot-window { animation: casinoSlotWin 1.6s ease-in-out infinite; }
@keyframes casinoSlotWin {
    0%, 100% { background: rgba(212,175,122,.04); }
    50%      { background: rgba(212,175,122,.12); }
}

/* --- Top 10 : podium spectaculaire --- */
.t10-pod {
    position: relative;
    display: flex; flex-direction: column; align-items: center;
    width: 128px;
}
.t10-av {
    position: relative;
    border-radius: 50%;
    overflow: hidden;
    background: #1a1c2e;
    box-shadow: 0 6px 18px rgba(0,0,0,.5);
    flex-shrink: 0;
}
.t10-av img, .t10-av svg {
    width: 100%; height: 100%;
    object-fit: cover; object-position: center top;
    display: block;
}
.t10-crown {
    font-size: 1.5rem; line-height: 1;
    margin-bottom: 3px;
    animation: t10Crown 2.4s ease-in-out infinite;
    text-shadow: 0 0 14px rgba(251,191,36,.85);
}
@keyframes t10Crown {
    0%, 100% { transform: translateY(0) rotate(-5deg); }
    50%      { transform: translateY(-5px) rotate(5deg); }
}
.t10-name {
    max-width: 100%;
    margin-top: 5px;
    color: #fff; font-size: 0.72rem; font-weight: 800;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t10-elo {
    display: flex; align-items: center; gap: 4px;
    color: rgba(250,204,21,.85); font-size: 0.66rem; font-weight: 900;
}
/* Marches du podium (reflet balayant) */
.t10-ped {
    width: 100%;
    margin-top: 6px;
    border-radius: 9px 9px 4px 4px;
    display: flex; align-items: center; justify-content: center;
    position: relative; overflow: hidden;
    box-shadow: inset 0 2px 8px rgba(255,255,255,.22), 0 6px 16px rgba(0,0,0,.45);
}
.t10-ped::after {
    content: '';
    position: absolute; top: 0; left: -80%;
    width: 50%; height: 100%;
    background: linear-gradient(105deg, transparent, rgba(255,255,255,.5), transparent);
    transform: skewX(-20deg);
    animation: t10Sheen 3.4s ease-in-out infinite;
}
@keyframes t10Sheen {
    0%        { left: -80%; }
    45%, 100% { left: 130%; }
}
.t10-ped-or     { height: 54px; background: linear-gradient(160deg, #FFD700, #B8860B); font-size: 1.6rem;  }
.t10-ped-argent { height: 38px; background: linear-gradient(160deg, #e5e7eb, #9ca3af); font-size: 1.3rem;  }
.t10-ped-bronze { height: 28px; background: linear-gradient(160deg, #CD7F32, #8B4513); font-size: 1.15rem; }

/* Mise en avant du joueur : halo doré pulsant + ruban VOUS */
.t10-me .t10-av { animation: t10MeGlow 1.8s ease-in-out infinite; }
@keyframes t10MeGlow {
    0%, 100% { box-shadow: 0 0 0 3px rgba(250,204,21,.95), 0 0 20px rgba(250,204,21,.45), 0 6px 18px rgba(0,0,0,.5); }
    50%      { box-shadow: 0 0 0 3px rgba(250,204,21,.95), 0 0 42px rgba(250,204,21,.95), 0 6px 18px rgba(0,0,0,.5); }
}
.t10-vous {
    position: absolute; bottom: 0; left: 50%;
    transform: translateX(-50%);
    background: #facc15; color: #0e0814;
    font-size: 0.5rem; font-weight: 900; letter-spacing: .08em;
    padding: 1px 8px; border-radius: 999px 999px 0 0;
    box-shadow: 0 -2px 8px rgba(0,0,0,.35);
}

/* Rangs 4 à 10 : cartes compactes */
.t10-mini {
    display: flex; flex-direction: column; align-items: center;
    gap: 3px; padding: 8px 4px 6px;
    border-radius: 10px;
    background: linear-gradient(180deg, rgba(250,204,21,.07), rgba(250,204,21,.02));
    border: 1px solid rgba(250,204,21,.14);
    min-width: 0;
    transition: transform .15s ease;
}
.t10-mini-rank {
    font-size: 0.58rem; font-weight: 900;
    color: rgba(250,204,21,.75);
    background: rgba(250,204,21,.1);
    border: 1px solid rgba(250,204,21,.3);
    border-radius: 999px; padding: 0 7px;
}
.t10-mini-av {
    width: 40px; height: 40px;
    border-radius: 50%; overflow: hidden;
    border: 1.5px solid rgba(255,255,255,.18);
    background: #1a1c2e;
    flex-shrink: 0;
}
.t10-mini-av img, .t10-mini-av svg { width: 100%; height: 100%; object-fit: cover; object-position: center top; display: block; }
.t10-mini-name {
    max-width: 100%;
    color: rgba(255,255,255,.85); font-size: 0.6rem; font-weight: 700;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.t10-mini-elo { color: rgba(250,204,21,.65); font-size: 0.56rem; font-weight: 900; }
/* Le joueur dans les rangs 4-10 : carte surélevée + halo pulsant */
.t10-me-mini {
    border-color: rgba(250,204,21,.85);
    background: linear-gradient(180deg, rgba(250,204,21,.2), rgba(250,204,21,.06));
    transform: translateY(-4px);
    animation: t10MeCard 1.8s ease-in-out infinite;
}
@keyframes t10MeCard {
    0%, 100% { box-shadow: 0 0 10px rgba(250,204,21,.25); }
    50%      { box-shadow: 0 0 26px rgba(250,204,21,.65); }
}


/* --- Fiche robot (clic sur avatar d'un bot, lobby ou plateau) --- */
.robot-fiche-overlay {
    position: fixed; inset: 0; z-index: 260;
    display: flex; align-items: center; justify-content: center;
    background: rgba(5, 3, 10, 0.78);
    backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
    padding: 20px;
}
.robot-fiche-box {
    position: relative;
    width: 100%; max-width: 620px;
    max-height: 90vh; overflow-y: auto;
    background: linear-gradient(160deg, #1e293b 0%, #0f172a 100%);
    border: 1px solid rgba(251,191,36,0.3);
    border-radius: 16px;
    box-shadow: 0 24px 70px rgba(0,0,0,0.8), 0 0 60px rgba(251,191,36,0.1);
    color: #e2e8f0;
}
/* Version carte d'identité : bandeau titre + liseré */
.robot-fiche-id { padding: 0; overflow: hidden; }
.robot-fiche-idbar {
    background: linear-gradient(90deg, rgba(251,191,36,0.22), rgba(251,191,36,0.05));
    border-bottom: 1px solid rgba(251,191,36,0.3);
    color: #fbbf24; font-size: 0.62rem; font-weight: 900;
    text-transform: uppercase; letter-spacing: .18em;
    padding: 8px 22px;
}
.robot-fiche-id .robot-fiche-head,
.robot-fiche-id .robot-fiche-body { padding-left: 22px; padding-right: 22px; }
.robot-fiche-close {
    position: absolute; top: 8px; right: 14px; z-index: 2;
    background: none; border: none; cursor: pointer;
    color: rgba(255,255,255,0.45); font-size: 18px; line-height: 1;
}
.robot-fiche-close:hover { color: #fff; }
.robot-fiche-head {
    display: flex; align-items: center; gap: 14px;
    padding-top: 16px; padding-bottom: 14px; margin-bottom: 14px;
    border-bottom: 1px solid rgba(255,255,255,0.1);
}
.robot-fiche-avatar {
    width: 88px; height: 88px; flex-shrink: 0;
    border-radius: 12px; overflow: hidden;
    border: 2px solid rgba(251,191,36,0.4);
    background: rgba(0,0,0,0.4);
}
.robot-fiche-avatar img { width: 100%; height: 100%; object-fit: cover; object-position: center top; display: block; }
.robot-fiche-name { font-size: 1.3rem; font-weight: 900; color: #fbbf24; line-height: 1.1; }
.robot-fiche-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.robot-fiche-tag {
    font-size: 0.6rem; font-weight: 800; text-transform: uppercase; letter-spacing: .05em;
    color: rgba(226,232,240,0.85); background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.14); border-radius: 999px; padding: 2px 8px;
}
.robot-fiche-tag-lvl   { color: #93c5fd; background: rgba(59,130,246,0.15); border-color: rgba(59,130,246,0.35); }
/* Niveau du robot : les trois couleurs des boutons de salon du hub — Standard
   jaune, Intermédiaire bleu, Expert rouge. Un robot hors de ces trois niveaux
   (« A ») garde le bleu neutre de .robot-fiche-tag-lvl. */
.rf-lvl-S { color: #eef210; background: rgba(238,242,16,0.13); border-color: rgba(238,242,16,0.35); }
.rf-lvl-I { color: #4d97f8; background: rgba(9,113,241,0.16);  border-color: rgba(9,113,241,0.45); }
.rf-lvl-E { color: #ff4d4d; background: rgba(252,7,7,0.15);    border-color: rgba(252,7,7,0.42); }
.robot-fiche-tag-child { color: #6ee7b7; background: rgba(16,185,129,0.15); border-color: rgba(16,185,129,0.35); }
.robot-fiche-joker { display: flex; align-items: center; gap: 7px; margin-top: 9px; }
.robot-fiche-joker img { width: 30px; height: 30px; object-fit: contain; flex-shrink: 0; }
.robot-fiche-joker-txt {
    display: flex; flex-direction: column; line-height: 1.15;
    font-size: 0.68rem; font-weight: 700; color: rgba(226,232,240,0.85);
}
.robot-fiche-joker-txt b { font-size: 0.62rem; font-weight: 800; color: #fbbf24; }
.robot-fiche-gouts { display: flex; flex-wrap: wrap; gap: 8px; }
.robot-fiche-gout  { display: flex; flex-direction: column; align-items: center; gap: 2px; width: 50px; }
.robot-fiche-gout img  { width: 38px; height: 38px; object-fit: contain; }
.robot-fiche-gout span { font-size: 0.55rem; color: rgba(226,232,240,0.75); text-align: center; line-height: 1.1; }
.robot-fiche-body { display: flex; flex-direction: column; padding-bottom: 20px; }
/* Chaque champ : libellé à gauche, valeur à droite, comme sur une pièce d'identité */
.robot-fiche-row {
    display: grid; grid-template-columns: 116px 1fr; gap: 10px; align-items: start;
    padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,0.06);
}
.robot-fiche-row:last-child { border-bottom: none; }
.robot-fiche-label {
    font-size: 0.6rem; font-weight: 900; text-transform: uppercase; letter-spacing: .06em;
    color: rgba(251,191,36,0.7); padding-top: 2px;
}
.robot-fiche-val  { font-size: 0.85rem; color: #e2e8f0; line-height: 1.4; }
.robot-fiche-presentation {
    font-size: 0.82rem; line-height: 1.5; color: rgba(226,232,240,0.9);
    font-style: italic; margin: 0;
}

/* --- Modale « jetons insuffisants » : version spectaculaire --- */
.jeton-modal-overlay {
    background-color: rgba(5, 3, 10, 0.88) !important;   /* fond du dessous bien masqué */
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    /* En COLONNE, comme les écrans de connexion : la plaque « CoinchePassion »
       se pose alors AU-DESSUS de la boîte, en frère et non en enfant. C'est ce
       qui donne aux fenêtres de jetons la même tête qu'au reste du site.
       Sans enseigne (le guide d'installation iOS), une colonne à un seul
       enfant reste centrée — la règle est donc sans effet là-bas. */
    flex-direction: column;
}
.jeton-modal-box {
    border: 1.5px solid rgba(251,191,36,.5) !important;
    box-shadow:
        0 0 0 1px rgba(255,255,255,.04),
        0 24px 70px rgba(0,0,0,.85),
        0 0 90px rgba(251,191,36,.18) !important;
}

/* --- Accessibilité : mouvement réduit --- */
@media (prefers-reduced-motion: reduce) {
    .ambient-fx-in { display: none; }
    .t10-crown, .t10-ped::after, .t10-me .t10-av, .t10-me-mini { animation: none !important; }
    .casino-title::before, .casino-title::after, .casino-lights, .casino-btn::after,
    .casino-gain, .casino-pop, .casino-roue-ring, .casino-board-glow, .casino-slot-window { animation: none !important; }
    .modal-box,
    .modal-title,
    .login-joker,
    .menu-user-avatar-wrap {
        animation: none !important;
    }
    .btn-action::after { display: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   ÉCRANS D'AUTHENTIFICATION — densité compacte
   Connexion / Inscription / Choix du pseudo (Google). Ces écrans empilent
   beaucoup de champs : sans ça, l'inscription déborde de l'écran et scrolle.
   Portée strictement limitée à ces 3 écrans — le reste du jeu est inchangé.
   ═══════════════════════════════════════════════════════════════════════════ */
.screen-login .modal-box,
.screen-create-account .modal-box {
    padding: 1.15rem 1.35rem;
    max-height: 92vh;          /* garde-fou petits écrans : scrolle au lieu d'être coupé */
    overflow-y: auto;
}
.screen-login .modal-box::-webkit-scrollbar,
.screen-create-account .modal-box::-webkit-scrollbar { width: 6px; }
.screen-login .modal-box::-webkit-scrollbar-thumb,
.screen-create-account .modal-box::-webkit-scrollbar-thumb {
    background: rgba(251,191,36,.25); border-radius: 3px;
}

/* Champs plus denses */
.screen-login .form,
.screen-create-account .form { gap: 0.6rem; }

.screen-login .form-row,
.screen-create-account .form-row { gap: 12px; }

.screen-login .form-label,
.screen-create-account .form-label {
    font-size: 0.82rem;
    letter-spacing: 0.08em;
    margin-bottom: 0.15rem;
}
.screen-login .input-text,
.screen-create-account .input-text {
    padding: 0.55rem 0.85rem;
    font-size: 0.98rem;
}
.screen-login .form-actions,
.screen-create-account .form-actions { margin: 0.35rem 0 0; }

/* En-tête (joker + titre) resserré */
.screen-login .login-joker,
.screen-create-account .login-joker,
.screen-create-account .modal-box > img { width: 42px !important; height: 42px !important; margin: 2px auto 6px !important; }

.screen-login .modal-title,
.screen-create-account .modal-title { font-size: 1.45rem; margin-bottom: 0.5rem; }

/* Le bouton est hors flux : on aligne juste sa position sur le padding réduit
   de ces écrans, il ne consomme aucune hauteur. */
.screen-login .back-to-home,
.screen-create-account .back-to-home {
    top: 0.8rem; left: 0.8rem;
    font-size: 0.8rem;
    padding: 5px 10px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   MINI-JEUX — agrandissement sur grand écran
   Les 4 boîtes (Roue, Avatar Manchot, Pyramide, Poker) ont des dimensions en
   pixels fixes (320 → 580 px de large, ~520 px de haut au plus) : sur un grand
   écran elles paraissent minuscules. Leur contenu étant en SVG avec viewBox,
   un `scale` est VECTORIEL — donc net, sans réécrire les mises en page internes.
   Chaque palier exige une hauteur suffisante : `transform` n'affecte pas la mise
   en page, une boîte trop grande serait coupée sans barre de défilement.
   ═══════════════════════════════════════════════════════════════════════════ */
.casino-box {
    transform: scale(var(--casino-scale, 1));
    transform-origin: center center;
    transition: transform .18s ease;
}
/* --casino-scale est désormais calculé par app.js (_ajusterCasino) plutôt que
   posé par paliers. Les paliers ne savaient qu'AGRANDIR — de ×1,15 à ×1,70 —
   et laissaient les jeux à leur taille pleine sur téléphone, où le plinko
   dépassait de 306 px en hauteur et débordait en largeur une fois l'appareil
   tenu droit. La mesure retient la plus contraignante des deux dimensions
   disponibles, ce qui couvre l'agrandissement comme la réduction, et s'adapte
   à chaque jeu — ils ne font ni la même largeur ni la même hauteur. */

/* ══ LISTE DES CHALLENGES (hub joueur) ═══════════════════════════════════════
   Deux cartes par ligne, quatre visibles sans défilement dans les 360 px de
   l'onglet. La contrainte a guidé le dessin : tout ce qui était empilé —
   compteur d'essais, échéance, score, boutons — tient sur des lignes courtes,
   et la carte se lit de haut en bas sans chercher.

   Les trois actions (Infos, Classement, Participer) partagent une seule classe
   et se partagent la largeur à parts égales : elles avaient des tailles et des
   paddings tous différents, ce qui donnait une rangée de boutons bancale. */
.chal-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 9px;
}
@media (max-width: 620px) { .chal-grid { grid-template-columns: 1fr; } }

.chal-card {
    display: flex; flex-direction: column; gap: 5px;
    padding: 9px 10px 8px;
    border-radius: 12px;
    border: 1px solid rgba(255,255,255,0.10);
    background: rgba(0,0,0,0.30);
    /* Filet de couleur à gauche : l'état du challenge se lit avant le texte. */
    border-left-width: 3px;
    transition: border-color .15s, background .15s, transform .12s;
}
.chal-card:hover { transform: translateY(-1px); background: rgba(255,255,255,0.04); }
.chal-card.chal-encours { border-color: rgba(250,204,21,0.30); border-left-color: #facc15; }
.chal-card.chal-dispo   { border-color: rgba(34,197,94,0.30);  border-left-color: #22c55e; }
.chal-card.chal-fini    { border-color: rgba(255,255,255,0.10); border-left-color: rgba(255,255,255,0.22); }
.chal-card.chal-clos    { border-color: rgba(180,83,9,0.30);   border-left-color: #b45309; }

.chal-head { display: flex; align-items: flex-start; gap: 6px; }
.chal-titre {
    flex: 1; min-width: 0;
    font-size: 0.86rem; font-weight: 900; color: #fff; line-height: 1.15;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chal-card.chal-fini .chal-titre { color: rgba(255,255,255,0.72); }

/* Pastille d'essais restants : le chiffre prime, le mot l'explique. */
.chal-essais {
    flex-shrink: 0; text-align: center; line-height: 1;
    padding: 3px 6px; border-radius: 7px;
    border: 1px solid rgba(255,255,255,0.12); background: rgba(255,255,255,0.05);
    color: rgba(255,255,255,0.55);
}
.chal-essais b { display: block; font-size: 0.82rem; font-weight: 900; }
.chal-essais span { font-size: 0.5rem; font-weight: 900; text-transform: uppercase; letter-spacing: .04em; opacity: .8; }
.chal-essais.chal-dernier { color: #fdba74; border-color: rgba(249,115,22,0.35); background: rgba(124,45,18,0.25); }

/* ── Ce que le challenge rapporte ──────────────────────────────────────────
   Même plaque que le compteur de jetons du hub — fond plein vert, le nombre
   au-dessus, « JETONS » en capitales dessous. C'est la même monnaie : elle
   doit se reconnaître d'un écran à l'autre sans qu'on ait à lire.
   La géométrie, elle, est celle de `.chal-essais` qui la jouxte : deux
   plaques côte à côte de tailles différentes se verraient aussitôt. */
.chal-gain {
    flex-shrink: 0; text-align: center; line-height: 1;
    padding: 3px 7px; border-radius: 7px;
    background: #22c55e; color: #052e13;
    box-shadow: 0 0 10px rgba(34,197,94,.35);
}
.chal-gain b { display: block; font-size: 0.82rem; font-weight: 900; }
.chal-gain span {
    font-size: 0.5rem; font-weight: 900; text-transform: uppercase;
    letter-spacing: .1em; opacity: .8;
}
/* Un challenge deja clos ne rapporte plus rien : la plaque s'eteint plutot
   que de disparaitre, sinon la carte changerait de forme selon son etat. */
.chal-gain.chal-gain-clos {
    background: rgba(255,255,255,.06); color: rgba(255,255,255,.4);
    box-shadow: none;
}
/* ── Ce que le challenge rapporte au CLASSEMENT ────────────────────────────
   Même géométrie que la plaque de jetons, à côté de laquelle elle se pose :
   deux récompenses, deux plaques jumelles. Mais le fond reste sobre et le
   joker porte seul la couleur — deux aplats vifs côte à côte se seraient
   disputé le regard, et c'est le nombre qu'on vient lire.
   Le joker multicolore, et non celui d'un niveau : la récompense ne dépend
   pas du Joker que le joueur possède. */
.chal-pts {
    flex-shrink: 0; text-align: center; line-height: 1;
    padding: 3px 7px; border-radius: 7px;
    border: 1px solid rgba(250,204,21,.30);
    background: rgba(250,204,21,.08);
    color: #fcd34d;
}
.chal-pts b {
    display: flex; align-items: center; justify-content: center; gap: 3px;
    font-size: 0.82rem; font-weight: 900;
}
.chal-pts img { width: 13px; height: 13px; flex-shrink: 0; }
.chal-pts span {
    display: block; margin-top: 2px;
    font-size: 0.5rem; font-weight: 900; text-transform: uppercase;
    letter-spacing: .1em; opacity: .8;
}
/* Clôturé : la plaque s'éteint, comme sa jumelle, plutôt que de disparaître. */
.chal-pts.chal-pts-clos {
    border-color: rgba(255,255,255,.10); background: rgba(255,255,255,.04);
    color: rgba(255,255,255,.4);
}
.chal-pts.chal-pts-clos img { filter: grayscale(1); opacity: .5; }

/* Colonne du classement : meme vert, mais en texte — une plaque par ligne
   ferait un mur de pastilles. */
.rank-gain { color: #4ade80; font-weight: 900; font-variant-numeric: tabular-nums; }
.rank-gain.rank-gain-nul { color: rgba(255,255,255,.25); font-weight: 700; }

.chal-meta { font-size: 0.62rem; color: rgba(255,255,255,0.42); line-height: 1.3; }
.chal-score { font-size: 0.65rem; font-weight: 900; color: #fcd34d; }
.chal-score .chal-rang { margin-left: 6px; font-weight: 700; color: rgba(255,255,255,0.35); }

.chal-echeance {
    align-self: flex-start;
    font-size: 0.56rem; font-weight: 900;
    padding: 2px 6px; border-radius: 999px; border: 1px solid;
}

/* Barre d'avancement d'une tentative en cours */
.chal-jauge { height: 5px; border-radius: 999px; background: rgba(255,255,255,0.10); overflow: hidden; }
.chal-jauge > div { height: 100%; border-radius: 999px; background: #facc15; transition: width .3s; }

/* Rangée d'actions : collée en bas pour que deux cartes voisines s'alignent. */
.chal-actions { display: flex; gap: 5px; margin-top: auto; padding-top: 3px; }
.chal-btn {
    flex: 1 1 0; min-width: 0; height: 27px;
    display: inline-flex; align-items: center; justify-content: center; gap: 3px;
    border-radius: 8px; border: 1px solid transparent;
    font-size: 0.6rem; font-weight: 900; text-transform: uppercase; letter-spacing: .03em;
    white-space: nowrap; cursor: pointer; transition: background .15s, color .15s, border-color .15s;
}
.chal-btn-ghost {
    background: rgba(255,255,255,0.05); border-color: rgba(255,255,255,0.10); color: rgba(255,255,255,0.55);
}
.chal-btn-ghost:hover { background: rgba(255,255,255,0.13); color: #fff; }
.chal-btn-rank {
    background: rgba(202,138,4,0.16); border-color: rgba(202,138,4,0.30); color: #fcd34d;
}
.chal-btn-rank:hover { background: rgba(202,138,4,0.32); color: #fef3c7; }
.chal-btn-go   { background: #16a34a; color: #fff; }
.chal-btn-go:hover { background: #22c55e; }
.chal-btn-suite { background: #ca8a04; color: #fff; }
.chal-btn-suite:hover { background: #eab308; }

/* Titre de groupe : « 3 CHALLENGES DISPONIBLES » */
.chal-groupe { display: flex; align-items: center; gap: 7px; margin: 0 0 7px; }
.chal-groupe .chal-puce { width: 7px; height: 7px; border-radius: 999px; flex-shrink: 0; }
.chal-groupe .chal-libelle {
    font-size: 0.62rem; font-weight: 900; text-transform: uppercase; letter-spacing: .12em;
}
.chal-groupe .chal-trait { flex: 1; height: 1px; background: rgba(255,255,255,0.08); }



/* ── Saisie assistée du prénom (écran de découverte) ────────────────────────
   Un emplacement de HAUTEUR FIXE partagé par l'indication et les propositions.
   Sans lui, l'apparition des pastilles pousserait le bouton « Jouer » vers le
   bas pendant la frappe — et sur une fenêtre déjà juste, ferait surgir une
   barre de défilement. Trois pastilles tiennent sur une ligne. */
.prenom-slot {
    min-height: 34px;
    display: flex; align-items: center;
    margin-top: 6px;
}
.prenom-slot .form-hint { margin-top: 0; }
.prenom-suggestions { display: flex; gap: 6px; flex-wrap: nowrap; overflow: hidden; }
.prenom-sugg {
    height: 32px; padding: 0 13px;
    border-radius: 999px;
    border: 1.5px solid rgba(251, 191, 36, 0.35);
    background: rgba(251, 191, 36, 0.10);
    color: #fbbf24;
    font-size: 0.95rem; font-weight: 800;
    white-space: nowrap; cursor: pointer;
    transition: background .15s, border-color .15s, transform .1s;
}
.prenom-sugg:hover  { background: rgba(251, 191, 36, 0.22); border-color: rgba(251, 191, 36, 0.6); }
.prenom-sugg:active { transform: scale(0.97); }


/* ── Bouton d'effacement dans un champ de saisie ────────────────────────────
   40 px de côté : on l'atteint sans viser. Le champ réserve la place à droite
   en permanence — élargir son remplissage à l'apparition du bouton ferait
   sauter le texte sous les doigts. */
.champ-efface { position: relative; }
.champ-efface .input-text { padding-right: 46px; }
.btn-efface {
    position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
    /* Au-dessus de son champ, sans jamais atteindre la couche des boutons
       flottants (agrandissement, z-index 1000) qui couvrent toute la page. */
    z-index: 3;
    width: 40px; height: 40px;
    display: flex; align-items: center; justify-content: center;
    background: none; border: none; padding: 0;
    color: rgba(148, 163, 184, 0.75);
    font-size: 1.15rem; line-height: 1; cursor: pointer;
    border-radius: 999px;
    transition: color .15s, background .15s;
}
.btn-efface:hover  { color: #fff; background: rgba(255, 255, 255, 0.09); }
.btn-efface:active { background: rgba(255, 255, 255, 0.16); }


/* Les deux échappées de l'écran de découverte, sur une ligne sous le bouton.
   Elles se touchent au doigt (44 px de haut) sans peser visuellement : ce sont
   des sorties, pas l'action principale. */
.essai-liens {
    display: flex; align-items: center; justify-content: center;
    gap: 4px; flex-wrap: wrap;
}
.essai-liens .form-link { padding: 10px 12px; min-height: 44px; }
.essai-liens-sep { color: rgba(255,255,255,.22); font-weight: 700; }
/* Les deux autres jeux : une note de bas d'écran, plus légère encore que les
   sorties ci-dessus. Elle ne doit pas concurrencer « CRÉER MON COMPTE », qui
   reste l'issue de ce parcours — elle ouvre juste une porte à côté. */
.essai-autres-jeux { margin-top: -2px; font-size: 0.82rem; }
.essai-autres-jeux > span:first-child { color: rgba(255,255,255,.38); font-weight: 700; }
.essai-autres-jeux .form-link { padding: 8px 8px; min-height: 36px; font-size: 0.82rem; }


/* ── Sous-onglet « Compte » du hub ──────────────────────────────────────────
   Contrainte : 360 px de haut, barre d'onglets comprise, et AUCUN défilement.
   Un réglage qu'il faut aller chercher en faisant défiler n'est pas trouvé.
   D'où deux colonnes, les deux nouveaux mots de passe côte à côte, et un
   espacement resserré. Une seule colonne sous 720 px, où deux formulaires
   accolés deviendraient illisibles — là, défiler redevient légitime. */
/* TROIS COLONNES, À LA LARGEUR DE LEUR CONTENU et non en parts égales.
   Un mot de passe fait dix caractères, une adresse en fait quarante : leur
   donner la même place étirait l'une et serrait l'autre. La troisième colonne
   a remplacé une bande pleine largeur qui poussait le compte Google hors de la
   fenêtre — l'onglet se mettait alors à défiler pour trois champs. */
.compte-colonnes {
    display: grid;
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 0.85fr) minmax(0, 1.3fr);
    gap: 10px;
    align-items: stretch;
}
/* Un bouton secondaire à côté de `btn-action`, à la même hauteur : « Annuler »
   ne doit pas ressembler à « Envoyer », ni décaler la ligne. */
/* Un groupe qui remplit sa carte, pour que le bouton qu'il contient retrouve
   le bas — `margin-top: auto` ne pousse que dans un flex, et un `<div>`
   intermediaire lui coupait l'effet. */
.compte-pile { display: flex; flex-direction: column; flex: 1; }

/* Google, réduit à sa plus simple expression : il vit maintenant DANS la carte
   adresse, où il n'a plus la largeur de la fenêtre mais celle d'une colonne.
   `margin-top: auto` le colle au bas de la carte — c'est un renseignement, pas
   une saisie : il se lit en dernier. */
.compte-google-mini {
    margin-top: auto; padding-top: 8px;
    border-top: 1px solid rgba(255, 255, 255, 0.10);
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.compte-google-mini .text-sm  { font-size: 0.78rem !important; }
.compte-google-mini .text-xs  { font-size: 0.7rem !important; line-height: 1.35; }
.compte-google-mini button { font-size: 0.66rem !important; padding: 5px 9px !important; }

.btn-plat-compte {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 9px;
    color: rgba(255, 255, 255, 0.6);
    font-weight: 900; font-size: 0.72rem;
    letter-spacing: .04em; padding: 9px 6px; cursor: pointer;
}
.btn-plat-compte:hover { color: #fff; border-color: rgba(255, 255, 255, 0.28); }
.compte-duo {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
}
/* Une colonne sur un écran ÉTROIT ET HAUT seulement : un iPhone SE couché
   (667 × 375) passait sous les 720 px et empilait les deux colonnes, sur un
   écran où c'est la hauteur qui manque (25/10/2026). */
@media (max-width: 720px) and (min-height: 501px) {
    .compte-colonnes { grid-template-columns: 1fr; }
    .compte-duo      { grid-template-columns: 1fr; }
}

.compte-carte {
    display: flex; flex-direction: column;
    background: rgba(0, 0, 0, 0.20);
    border: 1px solid rgba(251, 191, 36, 0.15);
    border-radius: 12px;
    padding: 9px 12px 10px;
}
.compte-carte-titre {
    display: flex; align-items: center; gap: 7px;
    color: #fff; font-weight: 900; font-size: 0.92rem;
    margin-bottom: 7px;
}
.compte-carte-titre span { font-size: 1.15rem; }

/* Resserrement mesuré : le formulaire d'inscription occupe un écran entier,
   celui-ci partage 300 px avec son voisin. Les champs restent à 36 px de haut —
   en dessous, on ne les touche plus, on les vise. */
.compte-carte .form-group { margin-bottom: 7px; }
.compte-carte .input-text { padding: 0.5rem 0.75rem; font-size: 0.98rem; }
.compte-carte .form-label { font-size: 0.8rem; margin-bottom: 2px; }
.compte-carte .form-hint  { font-size: 0.78rem; margin-top: 2px; line-height: 1.3; }
.compte-carte .btn-action { margin-top: auto; padding: 0.6rem; font-size: 0.82rem; }
.compte-carte .prenom-slot { min-height: 28px; margin-top: 2px; }
.compte-carte .prenom-sugg { height: 26px; font-size: 0.84rem; padding: 0 9px; }
.compte-carte .password-toggle { width: 34px; height: 34px; }
.compte-carte .password-input-wrapper .input-text { padding-right: 38px; }

/* Ligne « Compte Google » du sous-onglet : une bascule, pas une saisie. Elle
   se contente du minimum pour laisser les 360 px de l'onglet aux formulaires.
   Le texte peut courir sur deux lignes quand le compte n'a pas de mot de passe :
   l'interligne resserré évite qu'il pousse le tout au défilement. */
.compte-google { border-top: 1px solid rgba(255,255,255,0.08); padding-top: 7px; }
.compte-google .text-sm { font-size: 0.84rem !important; }
.compte-google .text-xs { font-size: 0.74rem !important; line-height: 1.3 !important; }
.compte-google span[style*="font-size:1.5rem"] { font-size: 1.1rem !important; }

/* ── Fin de partie publique : trois sorties, une hiérarchie ─────────────────
   Les options changent selon qui est à table, mais leur PLACE ne change pas :
   action principale à gauche, « Quitter » à droite, toujours. C'est cette
   stabilité qui empêche l'écran de paraître différent à chaque partie.
   Une seule dominante par écran — trois boutons de même poids, c'est un
   carrefour, et à 75 ans un carrefour se paie en hésitation. */
.fin-partie-btn {
    flex: 1;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    font-weight: 900;
    letter-spacing: .05em;
    padding: 12px 14px;
    border-radius: 12px;
    cursor: pointer;
    transition: all .15s;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* La dominante est plus large ET plus contrastée : deux signaux valent mieux
   qu'un pour une main qui vise vite. */
.fin-partie-principal {
    flex: 1.7;
    font-size: 0.95rem;
    background: rgba(34,197,94,0.15);
    border: 1px solid rgba(34,197,94,0.35);
    color: #4ade80;
    box-shadow: 0 4px 20px rgba(34,197,94,.15);
}
.fin-partie-principal:hover {
    background: rgba(34,197,94,0.25);
    border-color: rgba(34,197,94,0.6);
    transform: translateY(-1px);
}
/* Quitter reste lisible mais ne se dispute jamais le regard. */
.fin-partie-quitter {
    flex: 0.8;
    font-size: 0.82rem;
    background: transparent;
    border: 1px solid rgba(239,68,68,0.28);
    color: rgba(248,113,113,0.8);
}
.fin-partie-quitter:hover {
    background: rgba(239,68,68,0.14);
    border-color: rgba(239,68,68,0.5);
    color: #f87171;
}

/* Surtitre du bouton « rejouer avec X » : le prénom garde la ligne pour lui,
   sinon il se ferait tronquer — et un prénom tronqué ne désigne plus personne. */
.fin-partie-sur {
    display: block;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: .12em;
    opacity: .7;
    margin-bottom: 2px;
}

/* ── Fin de partie : la table réduite à ceux qui décident ───────────────────
   Un camp à gauche, un camp à droite, et entre les deux le compte des parties
   quand — et seulement quand — la table survit à la partie. */
.fin-partie-tables {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 30px;
    flex-wrap: wrap;
    /* L'avatar déborde de 58 px au-dessus de sa carte : sans cette marge, il
       passerait sous les scores. */
    margin-top: 68px;
}
.fin-partie-camp { display: flex; gap: 14px; }

/* Largeur FIXE. Sans elle la carte se réduit à son texte — souvent moins que
   les 120 px de l'avatar, qui déborde alors sur celui d'à côté. La grille
   d'origine tenait ses colonnes en 1fr ; ici les cartes flottent, et il faut
   le dire explicitement. */
.fin-partie-camp .lobby-player-card {
    width: 150px;
    flex: 0 0 150px;
}
.fin-partie-compteurs { display: flex; flex-direction: column; gap: 8px; }
.fin-partie-compteur {
    border-radius: 14px;
    padding: 8px 16px;
    text-align: center;
    min-width: 76px;
}
.fin-partie-compteur-nous {
    background: rgba(37,99,235,0.15);
    border: 2px solid rgba(59,130,246,0.4);
}
.fin-partie-compteur-eux {
    background: rgba(185,28,28,0.15);
    border: 2px solid rgba(239,68,68,0.4);
}
.fin-partie-compteur-nb { color: #fff; font-size: 1.9rem; font-weight: 900; line-height: 1; }
.fin-partie-compteur-lb {
    font-size: 0.55rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .08em; margin-top: 3px;
}
.fin-partie-compteur-nous .fin-partie-compteur-lb { color: rgba(96,165,250,0.7); }
.fin-partie-compteur-eux  .fin-partie-compteur-lb { color: rgba(248,113,113,0.7); }

/* Deux états seulement sous chaque carte : il a répondu, ou on l'attend. Le
   « non » n'existe plus — celui qui s'en va disparaît de l'écran. */
.fin-partie-pastille {
    font-weight: 900; padding: 2px 8px; border-radius: 10px;
    /* Les états sont écrits en toutes lettres — « ··· » ne dit rien à personne —
       donc la pastille doit les contenir sans déborder de sa carte. */
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 0.56rem;
    letter-spacing: .03em;
}
.fin-partie-oui {
    background: rgba(34,197,94,0.2); color: #4ade80; border: 1px solid #22c55e;
}
.fin-partie-attente {
    background: rgba(234,179,8,0.12); color: #fbbf24; border: 1px solid rgba(234,179,8,0.35);
}
/* Ma propre carte tant que je n'ai pas répondu : ce n'est pas une attente, c'est
   une invitation. */
.fin-partie-avous {
    background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.75);
    border: 1px solid rgba(255,255,255,0.25);
}

/* Le décompte n'apparaît que dans les vingt dernières secondes. Discret : c'est
   une information, pas une sommation. */
.fin-partie-decompte {
    margin-top: 6px;
    font-size: 0.8rem;
    font-weight: 900;
    letter-spacing: .08em;
    color: rgba(251,191,36,0.85);
}

/* Annonces à égalité : la fenêtre s'ouvre quand même, mais elle n'a rien à
   détailler — ni points, ni cartes. Un bloc unique, calme, qui dit pourquoi. */
.recap-annulation {
    display: flex;
    align-items: center;
    gap: 16px;
    background: rgba(251, 191, 36, 0.08);
    border: 1px solid rgba(251, 191, 36, 0.3);
    border-radius: 12px;
    padding: 18px 20px;
    margin-bottom: 16px;
    text-align: left;
}
.recap-annulation-icone { font-size: 2rem; line-height: 1; flex-shrink: 0; }
.recap-annulation-texte {
    color: rgba(255, 255, 255, 0.85);
    font-size: 0.95rem;
    line-height: 1.5;
}
.recap-annulation-texte strong { color: #fbbf24; font-weight: 900; }


/* ── Points du pli en vol ──────────────────────────────────────────────────
   Le score ne bouge plus à la pose de la dernière carte : la pastille part du
   pli, suit les cartes vers le paquet du gagnant, et le chiffre ne change qu'à
   son atterrissage. C'est elle qui RELIE le pli au score.
   La couleur dit le camp, comme les bulles de dialogue. */
.flying-points {
    position: absolute;
    z-index: 260;                 /* au-dessus des cartes volantes (250) */
    pointer-events: none;
    font-weight: 900;
    font-size: 1.5rem;
    letter-spacing: -.02em;
    padding: 2px 10px;
    border-radius: 999px;
    white-space: nowrap;
    text-shadow: 0 2px 6px rgba(0,0,0,.75);
    transition: left .85s cubic-bezier(.22,.61,.36,1),
                top .85s cubic-bezier(.22,.61,.36,1),
                opacity .85s ease-in,
                transform .85s cubic-bezier(.22,.61,.36,1);
}
.flying-points.fp-nous {
    color: #dbeafe;
    background: rgba(37,99,235,.82);
    box-shadow: 0 0 16px rgba(59,130,246,.55);
}
.flying-points.fp-eux {
    color: #fee2e2;
    background: rgba(185,28,28,.82);
    box-shadow: 0 0 16px rgba(239,68,68,.55);
}
@media (prefers-reduced-motion: reduce) {
    .flying-points { transition-duration: .01s; }
}


/* ── Le score qui encaisse enfle un instant ────────────────────────────────
   Joue à l'ATTERRISSAGE des points du pli, pas à la pose de la dernière carte :
   le grossissement et le changement de chiffre sont le même événement.

   `display:inline-block` est indispensable — `transform` reste sans effet sur
   un inline, et le chiffre ne bougerait pas d'un pixel.

   `transform-origin: right` parce que les valeurs sont alignées à droite dans
   le panneau : sans cela, le nombre déborderait sur son libellé en grossissant. */
.panel-score-value { display: inline-block; transform-origin: right center; }

@keyframes score-enfle {
    0%   { transform: scale(1);    }
    28%  { transform: scale(1.55); }
    100% { transform: scale(1);    }
}
.score-enfle { animation: score-enfle .65s cubic-bezier(.34,1.56,.64,1); }

@media (prefers-reduced-motion: reduce) {
    .score-enfle { animation: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   TUTORIEL
   z-index : au-dessus des overlays de jeu (210) et des popouts de la barre
   d'outils (215), en dessous des modales de challenge (265+) et des toasts
   (300). Une leçon commente le plateau : elle doit passer devant lui, mais
   jamais devant un message qui réclame une décision.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Surbrillance d'une cible désignée par le script (carte, main, pli). */
.tuto-cible {
    outline: 3px solid rgba(56, 189, 248, 0.95);
    outline-offset: 2px;
    border-radius: 6px;
    box-shadow: 0 0 18px 4px rgba(56, 189, 248, 0.55);
    animation: tuto-pulse 1.5s ease-in-out infinite;
    z-index: 220;
}
@keyframes tuto-pulse {
    0%, 100% { box-shadow: 0 0 14px 3px rgba(56, 189, 248, 0.45); }
    50%      { box-shadow: 0 0 26px 8px rgba(56, 189, 248, 0.80); }
}
@media (prefers-reduced-motion: reduce) {
    .tuto-cible { animation: none; }
}

/* Bandeau de progression, en haut au centre. */
.tuto-bandeau {
    position: fixed; top: 8px; left: 50%; transform: translateX(-50%);
    z-index: 220; display: flex; align-items: center; gap: 12px;
    padding: 5px 8px 5px 14px; border-radius: 999px;
    background: rgba(8, 20, 34, 0.88);
    border: 1.5px solid rgba(56, 189, 248, 0.35);
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(6px);
}
.tuto-bandeau-titre { color: #e0f2fe; font-weight: 900; font-size: 0.8rem; letter-spacing: .02em; }
.tuto-bandeau-etape {
    color: #7dd3fc; font-weight: 900; font-size: 0.68rem;
    background: rgba(56, 189, 248, 0.14); border-radius: 999px; padding: 2px 8px;
}
.tuto-bandeau-quit {
    color: rgba(226, 232, 240, 0.75); font-weight: 800; font-size: 0.68rem;
    background: rgba(255, 255, 255, 0.07); border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 999px; padding: 3px 11px; cursor: pointer;
}
.tuto-bandeau-quit:hover { background: rgba(239, 68, 68, 0.22); border-color: rgba(239, 68, 68, 0.45); color: #fecaca; }

/* Encart du narrateur : posé juste AU-DESSUS du panneau « NOUS », et aligné
   sur son bord gauche.
   Le commentaire suit très souvent les points marqués — il faut donc lire le
   texte et le score d'un seul coup d'œil, sans traverser l'écran. L'encart
   masque un peu de tapis et l'avatar Ouest : c'est assumé, une leçon dure
   quelques minutes et ce qu'elle explique prime sur ce qu'elle cache.
   Le calcul : `.ui-panel` fait 128px de haut et porte `zoom: --panel-zoom`,
   sa hauteur réelle est donc le produit des deux. `--safe-left` est utilisé
   tel quel, SANS division par le zoom — contrairement au panneau, cet encart
   n'est pas zoomé, sa coordonnée est déjà en pixels d'écran.
   `#app` ne porte aucun transform (cf. app.js), `fixed` se réfère donc bien au
   même repère que le panneau. */
.tuto-encart {
    position: fixed; z-index: 220;
    left:   var(--safe-left, 0px);
    bottom: calc(128px * var(--panel-zoom, 1) + 10px);
    width: min(380px, 55vw);
    max-height: 42vh; overflow-y: auto;
    padding: 13px 15px 12px;
    border-radius: 14px;
    background: linear-gradient(160deg, rgba(8, 22, 38, 0.95), rgba(6, 14, 26, 0.95));
    border: 1.5px solid rgba(56, 189, 248, 0.32);
    box-shadow: 0 10px 34px rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(7px);
}
.tuto-encart-texte { color: #e8f4fd; font-size: 0.87rem; line-height: 1.55; font-weight: 600; }
.tuto-encart-btn {
    margin-top: 11px; width: 100%; padding: 7px 0;
    border-radius: 9px; cursor: pointer;
    background: rgba(56, 189, 248, 0.9); color: #05202f;
    font-weight: 900; font-size: 0.78rem; letter-spacing: .05em; text-transform: uppercase;
    border: none;
}
.tuto-encart-btn:hover { background: #7dd3fc; }
.tuto-encart-hint {
    margin-top: 9px; color: rgba(125, 211, 252, 0.75);
    font-size: 0.7rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
}

/* Fin de leçon et catalogue : même fond assombri. */
.tuto-fin-fond {
    position: fixed; inset: 0; z-index: 285;
    background: rgba(4, 8, 16, 0.82);
    display: flex; align-items: center; justify-content: center; padding: 22px;
    backdrop-filter: blur(3px);
}
.tuto-fin-carte {
    width: min(420px, 92vw); padding: 26px 24px 22px; text-align: center;
    border-radius: 18px;
    background: linear-gradient(160deg, rgba(12, 30, 50, 0.98), rgba(7, 16, 30, 0.98));
    border: 1.5px solid rgba(56, 189, 248, 0.32);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
}
.tuto-fin-titre { margin-top: 10px; color: #e0f2fe; font-weight: 900; font-size: 1.1rem; }
.tuto-fin-msg   { margin-top: 8px; color: rgba(224, 242, 254, 0.72); font-size: 0.86rem; line-height: 1.55; }
.tuto-fin-btn {
    margin-top: 20px; padding: 9px 30px; border: none; border-radius: 10px; cursor: pointer;
    background: rgba(56, 189, 248, 0.92); color: #05202f;
    font-weight: 900; font-size: 0.82rem; letter-spacing: .05em; text-transform: uppercase;
}
.tuto-fin-btn:hover { background: #7dd3fc; }

/* Catalogue */
.tuto-cat-carte {
    width: min(560px, 94vw); max-height: 82vh; display: flex; flex-direction: column;
    border-radius: 18px; overflow: hidden;
    background: linear-gradient(160deg, rgba(12, 30, 50, 0.98), rgba(7, 16, 30, 0.98));
    border: 1.5px solid rgba(56, 189, 248, 0.3);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
}
.tuto-cat-entete {
    display: flex; align-items: flex-start; justify-content: space-between;
    padding: 18px 20px 14px; border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
.tuto-cat-titre  { color: #e0f2fe; font-weight: 900; font-size: 1.05rem; letter-spacing: .02em; }
.tuto-cat-sous   { color: rgba(224, 242, 254, 0.55); font-size: 0.75rem; margin-top: 3px; }
.tuto-cat-fermer {
    background: rgba(255, 255, 255, 0.07); border: 1px solid rgba(255, 255, 255, 0.14);
    color: rgba(226, 232, 240, 0.8); border-radius: 8px; width: 28px; height: 28px;
    cursor: pointer; font-size: 0.8rem; flex-shrink: 0;
}
.tuto-cat-fermer:hover { background: rgba(239, 68, 68, 0.2); color: #fecaca; }
.tuto-cat-corps  { padding: 14px 18px 18px; overflow-y: auto; }
.tuto-cat-vide   { padding: 34px 20px; text-align: center; color: rgba(224, 242, 254, 0.5); font-size: 0.85rem; }
.tuto-cat-bloc   { margin-bottom: 18px; }
.tuto-cat-bloc-titre  { color: #7dd3fc; font-weight: 900; font-size: 0.7rem; text-transform: uppercase; letter-spacing: .1em; }
.tuto-cat-bloc-resume { color: rgba(224, 242, 254, 0.5); font-size: 0.75rem; margin: 3px 0 9px; }
.tuto-cat-lecon {
    width: 100%; display: flex; align-items: center; gap: 10px;
    padding: 9px 12px; margin-bottom: 6px; border-radius: 10px; cursor: pointer; text-align: left;
    background: rgba(56, 189, 248, 0.08); border: 1.5px solid rgba(56, 189, 248, 0.16);
}
.tuto-cat-lecon:hover { background: rgba(56, 189, 248, 0.2); border-color: rgba(56, 189, 248, 0.42); }
.tuto-cat-lecon-off   { opacity: .38; cursor: not-allowed; background: rgba(255, 255, 255, 0.03); border-color: rgba(255, 255, 255, 0.08); }
.tuto-cat-lecon-off:hover { background: rgba(255, 255, 255, 0.03); border-color: rgba(255, 255, 255, 0.08); }
.tuto-cat-num {
    flex-shrink: 0; width: 21px; height: 21px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: rgba(56, 189, 248, 0.22); color: #bae6fd; font-weight: 900; font-size: 0.66rem;
}
.tuto-cat-nom    { flex: 1; color: #e8f4fd; font-weight: 700; font-size: 0.83rem; }
.tuto-cat-avenir { color: rgba(226, 232, 240, 0.45); font-size: 0.62rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; }
.tuto-cat-go     { color: #7dd3fc; font-size: 0.7rem; }

/* Fenêtre d'enchères neutralisée pendant une leçon de tutoriel : visible —
   c'est elle qu'on explique — mais inerte. `pointer-events` sur le conteneur
   suffit et couvre TOUS les boutons qu'il contient, y compris ceux ajoutés
   plus tard : désactiver chaque bouton un par un aurait laissé passer le
   prochain qu'on ajoute. */
.bid-overlay-verrouille { pointer-events: none; opacity: .55; filter: saturate(.6); }

/* Écran de fin de leçon : le titre de la leçon suivante, sous son bouton. */
.tuto-fin-suite {
    margin-top: 7px; color: rgba(125, 211, 252, 0.8);
    font-size: 0.72rem; font-weight: 700;
}
/* Action secondaire (« Revenir au hub ») : présente mais discrète — enchaîner
   est le geste attendu, quitter reste possible sans être proposé à égalité. */
.tuto-fin-btn2 {
    margin-top: 14px; padding: 6px 20px; cursor: pointer;
    background: transparent; border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 9px; color: rgba(226, 232, 240, 0.7);
    font-weight: 800; font-size: 0.72rem; letter-spacing: .04em;
}
.tuto-fin-btn2:hover { background: rgba(255, 255, 255, 0.07); color: #e2e8f0; }

/* Téléphone en paysage : l'écran ne fait que ~390px de haut, et l'encart
   adossé au panneau en mangerait près de la moitié. On le resserre plutôt que
   de le déplacer — sa position près du score reste ce qui compte. */
/* Au TAROT, la main de Sud s'étend sur toute la largeur du bas de l'écran,
   deux rangées de cartes : l'encart y couvrirait celles qu'on lui demande de
   jouer. Il monte donc en haut à gauche, sous le panneau de la manche, sur
   l'éventail d'Ouest — des dos, rien qu'on ait à lire. */
.tuto-encart.tuto-encart-haut {
    bottom: auto;
    top: calc(128px * var(--panel-zoom, 1) + 10px);
    max-height: 38vh;
}

@media (max-height: 480px) {
    .tuto-encart       { width: min(320px, 48vw); max-height: 36vh; padding: 9px 11px; }
    .tuto-encart.tuto-encart-haut { max-height: 30vh; }
    .tuto-encart-texte { font-size: 0.78rem; line-height: 1.42; }
    .tuto-encart-btn   { margin-top: 8px; padding: 5px 0; font-size: 0.72rem; }
}

/* Fenêtres de jeu pendant un tutoriel : lisibles, mais leurs boutons sont
   inertes. C'est le SCRIPT qui déclare, valide et referme — un clic du
   spectateur ferait diverger la table de ce que la leçon raconte, et les
   décomptes automatiques sont eux aussi neutralisés (cf. app.js).
   `pointer-events` porte sur les seuls éléments interactifs : le contenu reste
   sélectionnable et la fenêtre garde son aspect normal, sans voile ni grisé
   qui suggéreraient une panne. */
.tuto-fenetre-figee button,
.tuto-fenetre-figee .announcement-btn,
.tuto-fenetre-figee [role="button"] { pointer-events: none; opacity: .5; }
/* Les barres de décompte n'ont plus rien à décompter : les masquer évite
   d'afficher une jauge figée, qu'on lirait comme un blocage. */
.tuto-fenetre-figee .countdown-bar,
.tuto-fenetre-figee .recap-timer { visibility: hidden; }

/* Écran d'attente d'une démonstration : il couvre le temps mort entre le clic
   sur la landing et la première carte. Réutilise l'animation `spin` déjà
   définie plus haut plutôt que d'en ajouter une seconde. */
.demo-chargement {
    position: fixed; inset: 0; z-index: 400;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
    background: radial-gradient(circle at 50% 40%, #0d2136, #060d18 70%);
    text-align: center; padding: 24px;
}
.demo-chargement-roue {
    width: 46px; height: 46px; border-radius: 50%;
    border: 3px solid rgba(56, 189, 248, 0.18);
    border-top-color: rgba(56, 189, 248, 0.9);
    animation: spin 0.9s linear infinite;
}
.demo-chargement-titre { color: #e0f2fe; font-weight: 900; font-size: 1.05rem; letter-spacing: .02em; }
.demo-chargement-sous  { color: rgba(224, 242, 254, 0.55); font-size: 0.82rem; }
@media (prefers-reduced-motion: reduce) {
    .demo-chargement-roue { animation-duration: 3s; }
}

/* ═══════════════════════════════════════════════════════════════════════
   CARTE D'ANNONCE AVANCEE DANS LA MAIN  (essai, comptes de test)
   L'avancee elle-meme est geometrique et se fait dans `getFanStyle` : elle
   passe par `top`, donc par le style EN LIGNE. Ici on ne pose que la lueur,
   via `filter` -- toucher a `transform` ecraserait la rotation de l'eventail.
   ═══════════════════════════════════════════════════════════════════════ */
.card-img.carte-annoncee {
    filter: drop-shadow(0 0 5px rgba(251, 191, 36, 0.95))
            drop-shadow(0 0 13px rgba(251, 191, 36, 0.5));
    transition: filter 0.3s ease;
}

/* --- Pendant la presentation, la main passe AU-DESSUS des avatars ---
   `.hand-container` n'a pas de z-index : il vaut donc `auto`, et le HUD des
   joueurs (z-index 110) recouvrait les cartes avancees. Et comme les mains 1,
   2 et 3 portent un `transform: rotate(...)`, elles creent leur PROPRE
   contexte d'empilement : le z-index des cartes y est enferme et ne pouvait
   pas s'en echapper -- c'est le conteneur qu'il faut lever, pas la carte.
   150 : au-dessus des avatars, sous la fenetre de recapitulatif (210). */
.hand-container.main-annoncante { z-index: 150; }

/* --- Pastille de valeur d'annonce (20 / 50 / 100 / 150 / 200) ---
   L'HOTE fait la largeur d'une carte et ne sert qu'a centrer la pastille
   au-dessus d'elle ; c'est lui qui porte la contre-rotation du siege. La
   PASTILLE, ronde, vit dedans : sa taille ne depend donc pas du nombre de
   chiffres, « 20 » et « 200 » font le meme disque. */
.pastille-hote {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}
.pastille-annonce {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width:  var(--past-d, 34px);
    height: var(--past-d, 34px);
    border-radius: 50%;
    font-size: var(--past-texte, 14px);
    font-weight: 900;
    line-height: 1;
    letter-spacing: -0.03em;
    color: #fff;
    /* Fond PLEIN et sombre, surmonte d'un reflet qui s'eteint avant la moitie :
       c'est ce qui fait un jeton plutot qu'un rond, sans rien couter au texte.
       Un degrade radial partant du clair mettait le centre -- donc le chiffre --
       a 2,2:1 contre le blanc, la ou il en faut 4,5. Ici le texte repose sur la
       couleur pleine, a 6,5:1. */
    background: linear-gradient(180deg, rgba(255,255,255,0.38), rgba(255,255,255,0) 52%),
                var(--past-c2);
    border: 2px solid rgba(255, 255, 255, 0.92);
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.55),
                inset 0 1px 0 rgba(255, 255, 255, 0.5);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
    animation: pastille-entree 0.5s cubic-bezier(.34, 1.56, .64, 1) var(--past-delai, 0s) backwards;
}
/* Halo : un anneau qui s'ecarte et s'efface. Il attire l'oeil sur la valeur
   sans bouger la pastille elle-meme, dont l'aplomb doit rester lisible. */
.pastille-annonce::after {
    content: '';
    position: absolute;
    inset: -2px;
    border-radius: 50%;
    border: 2px solid var(--past-c1);
    animation: pastille-halo 2.1s ease-out var(--past-delai, 0s) infinite;
}
/* Les couleurs d'equipe du jeu : bleu pour nous, rouge pour eux -- les memes
   que les bulles de dialogue et les scores. */
.pastille-us   { --past-c1: #7cb3f8; --past-c2: #1d4ed8; }
.pastille-them { --past-c1: #fb9a9a; --past-c2: #b91c1c; }

@keyframes pastille-entree {
    0%   { opacity: 0; transform: scale(0.2) translateY(10px); }
    60%  { opacity: 1; transform: scale(1.18) translateY(0); }
    100% { opacity: 1; transform: scale(1); }
}
@keyframes pastille-halo {
    0%   { transform: scale(1);    opacity: 0.7; }
    70%  { transform: scale(1.75); opacity: 0; }
    100% { transform: scale(1.75); opacity: 0; }
}

/* --- Presentation des annonces : AUCUN voile ---
   C'est le seul de nos trois overlays dont l'essentiel est DERRIERE lui : les
   cartes avancees dans les quatre mains, avec leur pastille de valeur.
   Assombrir le tapis y reviendrait a masquer ce qu'on demande justement de
   regarder. Le bilan de manche et la modale de synchronisation gardent leur
   voile a 40 % : rien, derriere eux, n'est a lire.
   La boite, elle, a son propre fond opaque (.announcement-box) et ne depend
   pas du voile pour rester lisible. `pointer-events` reste a `auto` : pendant
   la presentation, le tapis se regarde mais ne se joue pas. */
.announcement-overlay.sans-voile { background-color: transparent; }
/* Téléphone en paysage : la boîte des annonces validées, haute de 185 px et
   centrée, venait couvrir le haut des cartes que Nord montre, et leur pastille
   de valeur — ce qu'elle annonce justement. Plus compacte (~140 px) et
   descendue de 24 px, elle les dégage ; son bouton garde sa taille. */
@media (max-height: 500px) and (orientation: landscape) {
    .announcement-overlay.sans-voile { padding-top: 24px; }
    .announcement-overlay.sans-voile .announcement-box { padding: 10px 14px; }
    .announcement-overlay.sans-voile .announcement-title { margin-bottom: 8px; padding-bottom: 4px; }
    .announcement-overlay.sans-voile .announcement-box > .mb-4 { margin-bottom: 8px; }
}

/* ── Rattrapage des defis passes (onglet Defis) ────────────────────────
   Le calendrier ne dit pas de lui-meme qu'il est devenu cliquable. Cette
   ligne, dans le dore du club, l'annonce juste au-dessus du bouton Jouer.
   Elle emprunte la pastille CP a `.hub-cp-appel` : c'est la meme promesse,
   elle doit se reconnaitre au premier coup d'oeil. */
.defi-rattrapage {
    display: flex; align-items: center; gap: 7px;
    margin-bottom: 8px; padding: 7px 9px; border-radius: 8px;
    background: rgba(251,191,36,.10);
    border: 1px solid rgba(251,191,36,.32);
    color: rgba(253,230,138,.92);
    font-size: 0.6rem; font-weight: 700; line-height: 1.35;
}
.defi-rattrapage-cp {
    flex-shrink: 0; padding: 2px 6px; border-radius: 5px;
    background: rgba(251,191,36,.20);
    border: 1px solid rgba(251,191,36,.5);
    color: #fbbf24;
    font-size: 0.52rem; font-weight: 900; letter-spacing: .1em;
}

/* La vignette d'un compte de GESTION dans « Qui joue ? ». Il n'a pas de visage
   et ne mene pas a une table : sans cette mention, il passerait pour un joueur
   dont l'avatar n'a pas charge. */
.cp-gestion {
    display: block; margin-top: 2px;
    font-size: 0.52rem; font-weight: 900; letter-spacing: .08em;
    text-transform: uppercase; color: #fbbf24; opacity: .85;
}

/* ══ Salon privé : la modale doit se DÉTACHER ══
   Elle s'ouvre par-dessus le hub, qui est noir comme elle : bordure ambrée
   sur fond sombre sur fond sombre, on ne voyait plus où commençait la
   fenêtre. Elle prend donc la couleur du salon privé — le violet qu'on
   retrouve sur le liseré du tapis choisi et sur le bouton « Créer ». Le
   voile est aussi plus dense et FLOUTE ce qu'il y a derrière : c'est le
   flou, plus que la bordure, qui dit « ceci est au premier plan ». */
.modale-salon {
    position: fixed;
    z-index: 9999;
    background-color: rgba(4, 2, 10, 0.82);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    /* Elle est désormais calée sur la FENÊTRE et non plus sur le hub : sur un
       écran bas, elle peut donc dépasser. `overflow-y` seul ne suffirait pas —
       avec `align-items:center` le haut deviendrait inatteignable. C'est le
       `margin:auto` de l'enfant qui centre tant qu'il y a la place et rend les
       deux bords accessibles dès qu'il n'y en a plus. */
    overflow-y: auto;
    padding: 20px 0;
}
.modale-salon > .modal-box {
    margin: auto;
    position: relative;        /* ancre le filet ::before ci-dessous */
    background: rgba(26, 14, 46, 0.98);
    border: 1px solid rgba(167, 139, 250, 0.55);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.7),
                0 24px 60px rgba(0, 0, 0, 0.75),
                0 0 42px rgba(124, 58, 237, 0.30);
}
/* Un filet violet en tête de fenêtre, et le titre à l'unisson : deux repères
   valent mieux qu'un quand la bordure seule peut passer inaperçue. */
.modale-salon > .modal-box::before {
    content: '';
    position: absolute;
    top: 0; left: 14%; right: 14%;
    height: 2px;
    border-radius: 0 0 2px 2px;
    background: linear-gradient(90deg, transparent, #a78bfa, transparent);
}
.modale-salon .modal-title { color: #c4b5fd; }

/* ==========================================================================
   TAROT — le plateau (étape 1)
   ==========================================================================
   Une table de tarot garde les avatars de la coinche (`player-hud`), à leur
   place, et masque le reste de son plateau : mains en éventail,
   paquets, complément, et les quatre panneaux de coin — « Nous / Eux » n'a
   pas de sens quand chacun joue pour soi. La classe est posée sur <body> par
   app.js, le temps que l'écran de jeu montre une table de tarot. */
body.plateau-tarot .hand-container,
body.plateau-tarot .dealer-pos,
body.plateau-tarot .supplement-overlay { display: none !important; }

/* Une carte : dessin (500 × 915) ou mini (500 × 667), coins arrondis ici —
   les fichiers ont des coins carrés remplis de la couleur du bord. */
.tarot-carte {
    position: absolute; display: block; background: #fff;
    border-radius: 7% / 4.2%;
    box-shadow: 0 2px 6px rgba(0,0,0,.5);
    user-select: none; -webkit-user-select: none; -webkit-user-drag: none;
}
.tarot-carte.en-main { pointer-events: auto; transition: transform .15s ease, filter .15s ease; }
.tarot-carte.en-main.jouable { cursor: pointer; }
.tarot-carte.en-main.jouable:hover { transform: translateY(-9%); }
.tarot-carte.en-main.grise { filter: brightness(.55) saturate(.6); }
/* La carte qui vient de partir : son trou reste jusqu'à l'atterrissage */
.tarot-carte.en-main.en-vol { visibility: hidden; }
/* L'ÉCART DE SUD (28/09/2026) : les cartes vont de la main aux six places du
   chien et en reviennent — mêmes éléments, ils GLISSENT (`left`, `top`) ; la
   main se resserre de même. Les places vides : un contour en pointillé. */
.tarot-carte.en-main.ecart { transition: left .3s ease, top .3s ease, transform .15s ease, filter .15s ease; }
.tarot-carte.en-main.au-chien { box-shadow: 0 0 0 2px rgba(255,255,255,.85), 0 6px 14px rgba(0,0,0,.55); }
.tarot-ecart-place {
    position: absolute; z-index: 40; pointer-events: none; box-sizing: border-box;
    border: 2px dashed rgba(255,255,255,.5); border-radius: 7% / 4.2%; background: rgba(0,0,0,.15);
}
/* Sous les places : où j'en suis, le chelem, VALIDER — centrée sur `left` */
.tarot-ecart-barre {
    position: absolute; z-index: 205; transform: translateX(-50%); pointer-events: auto;
    display: flex; align-items: center; gap: 8px; white-space: nowrap;
    padding: 6px 8px 6px 12px; border-radius: 12px;
    background: rgba(14, 8, 20, .9); border: 1px solid rgba(251,191,36,.22); color: #fff;
    box-shadow: 0 8px 24px rgba(0,0,0,.55);
}
.tarot-ecart-etat { font-weight: 800; font-size: .85rem; color: #fdba74; font-variant-numeric: tabular-nums; }
.tarot-ecart-etat.ok { color: #4ade80; }
.tarot-ecart-regle { color: rgba(255,255,255,.6); font-weight: 600; }
/* Le compte à rebours des trente secondes ; les dix dernières pressent. Assez
   large pour « 30 s » : à 2,6em, la barre entière rétrécissait sous dix secondes */
.tarot-ecart-temps {
    min-width: 3.2em; text-align: center; font-weight: 900; font-size: .85rem; font-variant-numeric: tabular-nums;
    padding: 2px 6px; border-radius: 999px; background: rgba(255,255,255,.1); color: #fff;
}
.tarot-ecart-temps.presse { background: #ea580c; animation: tarotPresse 1s ease-in-out infinite; }
@keyframes tarotPresse { 50% { transform: scale(1.12); } }
@media (prefers-reduced-motion: reduce) { .tarot-ecart-temps.presse { animation: none; } }
.tarot-ecart-barre .tarot-chelem { flex: 0 0 auto; align-self: stretch; padding: 0 12px; font-size: .8rem; }
.tarot-ecart-barre .btn-take { flex: 0 0 auto; padding: 8px 18px; }
/* L'écart d'un autre : qui la table attend, et la jauge de son temps. Centrée
   sur son point (`tarotLayout.attenteEcart`), d'une largeur qui ne bouge pas :
   le nom ne change pas pendant l'écart, la jauge et le compteur sont fixes */
.tarot-attente {
    position: absolute; z-index: 205; transform: translate(-50%, -50%); pointer-events: none;
    display: flex; flex-direction: column; align-items: stretch; gap: 6px; box-sizing: border-box;
    min-width: 15em; padding: 8px 14px 9px; border-radius: 12px;
    background: rgba(14, 8, 20, .9); border: 1px solid rgba(251,191,36,.22); color: #fff;
    box-shadow: 0 8px 24px rgba(0,0,0,.55);
    font-size: .85rem; text-align: center; white-space: nowrap;
}
.tarot-attente-titre { font-weight: 700; color: rgba(255,255,255,.85); }
.tarot-attente-titre b { color: #fbbf24; font-weight: 900; }
.tarot-attente-temps { display: flex; align-items: center; gap: 8px; }
.tarot-attente-jauge { flex: 1; height: 4px; border-radius: 2px; background: rgba(255,255,255,.12); overflow: hidden; }
.tarot-attente-jauge div { height: 100%; background: linear-gradient(90deg, #f59e0b, #fbbf24); transition: width .25s linear; }
.tarot-attente-temps span { flex: 0 0 2.6em; text-align: right; font-weight: 800; font-size: .8rem; font-variant-numeric: tabular-nums; color: rgba(255,255,255,.7); }
.tarot-attente-temps.presse .tarot-attente-jauge div { background: #ea580c; }
.tarot-attente-temps.presse span { color: #fb923c; }
@media (prefers-reduced-motion: reduce) { .tarot-attente-jauge div { transition: none; } }
@media (max-height: 500px) {
    .tarot-attente { gap: 4px; min-width: 12em; padding: 4px 9px 5px; border-radius: 9px; font-size: .68rem; }
    .tarot-attente-temps { gap: 6px; }
    .tarot-attente-temps span { font-size: .66rem; }
    .tarot-attente-jauge { height: 3px; }
    .tarot-ecart-barre { gap: 5px; padding: 3px 4px 3px 8px; border-radius: 9px; }
    .tarot-ecart-etat { font-size: .68rem; }
    .tarot-ecart-temps { font-size: .68rem; padding: 1px 4px; }
    .tarot-ecart-regle { display: none; }   /* pas la place : le refus du serveur la redira */
    .tarot-ecart-barre .tarot-chelem { padding: 0 7px; font-size: .66rem; gap: 3px; border-width: 1.5px; }
    /* VALIDER faisait ~20 px de haut et la case Chelem 12, sous un compte à
       rebours de trente secondes : la taille d'un doigt (cf. `ecartBarre`) */
    .tarot-ecart-barre .tarot-chelem input { width: 18px; height: 18px; }
    .tarot-ecart-barre .btn-take { padding: 11px 14px; font-size: .75rem; }
}

/* Le tas du chien : six dos décalés, comme les paquets de la coinche */
.tarot-chien-tas { position: absolute; z-index: 44; pointer-events: none; }
.tarot-chien-tas img {
    position: absolute; inset: 0; width: 100%; height: 100%; display: block;
    border-radius: 7% / 4.2%; box-shadow: 1px 1px 3px rgba(0,0,0,.45);
}
.tarot-chien-carte { pointer-events: none; animation: tarotChienParait .35s ease-out; }
@keyframes tarotChienParait { from { opacity: 0; transform: scale(.85); } to { opacity: 1; transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .tarot-chien-carte { animation: none; } }
/* LE CHIEN SE RETOURNE (29/09/2026, `devoilerChienTarot`) : la rangée
   attend, cachée, sous les cartes animées. Chacune glisse (`left`, `top`)
   du tas à sa place, puis pivote : le dos et la face sont dos à dos
   (`backface-visibility`), la face tournée d'un demi-tour au départ. Levée
   (`leve`), la carte monte et grossit un peu le temps du geste ; la
   dernière frémit avant de se retourner. */
.tarot-chien-carte.en-attente { visibility: hidden; }
.tarot-chien-suspens {
    position: absolute; pointer-events: none;
    transition: left .42s cubic-bezier(.3, .9, .3, 1), top .42s cubic-bezier(.3, .9, .3, 1);
}
.tarot-chien-suspens.fremit { animation: tarotChienFremit .11s ease-in-out infinite alternate; }
@keyframes tarotChienFremit { from { transform: rotate(-1.6deg); } to { transform: rotate(1.6deg); } }
.tarot-chien-pivot {
    --lev: 0%; --sc: 1; --ry: 0deg;
    position: absolute; inset: 0; transform-style: preserve-3d;
    transform: perspective(900px) translateY(var(--lev)) scale(var(--sc)) rotateY(var(--ry));
    transition: transform .34s cubic-bezier(.35, .1, .25, 1);
}
.tarot-chien-pivot.leve { --lev: -9%; --sc: 1.07; }
.tarot-chien-pivot.retournee { --ry: 180deg; }
.tarot-chien-pivot.lente { transition-duration: .55s; }
.tarot-chien-pivot img {
    position: absolute; inset: 0; width: 100%; height: 100%; display: block;
    border-radius: 7% / 4.2%; background: #fff; box-shadow: 0 2px 6px rgba(0,0,0,.5);
    backface-visibility: hidden; -webkit-backface-visibility: hidden;
}
.tarot-chien-pivot.leve img { box-shadow: 0 10px 22px rgba(0,0,0,.55); }
.tarot-chien-face { transform: rotateY(180deg); }
/* LE « VU » : sous le chien retourné ou l'écart de fin de donne, la fenêtre
   des annonces de la coinche en bandeau — ce qu'on regarde, une pastille par
   joueur (✓ quand il a vu), Continuer et le temps qui reste, la barre qui se
   vide. Centrée sur `left` (`tarotLayout.barreVu`). */
.tarot-vu-barre {
    position: absolute; z-index: 205; transform: translateX(-50%); pointer-events: auto;
    display: flex; flex-direction: column; gap: 5px; white-space: nowrap;
    padding: 6px 8px 5px 12px; border-radius: 12px;
    background: rgba(14, 8, 20, .9); border: 1px solid rgba(251,191,36,.22); color: #fff;
    box-shadow: 0 8px 24px rgba(0,0,0,.55);
}
.tarot-vu-ligne { display: flex; align-items: center; gap: 10px; }
.tarot-vu-titre { font-weight: 900; font-size: .9rem; color: var(--gold, #fbbf24); }
.tarot-vu-titre b { color: #fff; font-weight: 800; }
.tarot-vu-pastilles { display: flex; gap: 5px; }
.tarot-vu-pastilles i {
    font-style: normal; width: 22px; height: 22px; border-radius: 50%; border: 2px solid rgba(255,255,255,.2);
    display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 900;
    background: rgba(255,255,255,.05); color: rgba(255,255,255,.35); transition: all .3s;
}
.tarot-vu-pastilles i.ok { border-color: #22c55e; background: rgba(34,197,94,.2); color: #22c55e; }
.tarot-vu-btn {
    font: inherit; font-weight: 800; font-size: .85rem; padding: 7px 14px; border-radius: 8px; border: 0; cursor: pointer;
    background: #2563eb; color: #fff; box-shadow: 0 2px 8px rgba(37,99,235,.4); display: flex; align-items: baseline; gap: 6px;
}
.tarot-vu-btn small { opacity: .65; font-weight: 400; min-width: 2.2em; text-align: center; font-variant-numeric: tabular-nums; }
.tarot-vu-btn:disabled { background: rgba(255,255,255,.08); color: rgba(255,255,255,.45); box-shadow: none; cursor: default; }
.tarot-vu-temps { height: 3px; border-radius: 2px; background: rgba(255,255,255,.1); overflow: hidden; }
.tarot-vu-temps div { height: 100%; background: linear-gradient(90deg, #3b82f6, #60a5fa); transition: width .25s linear; }
@media (max-height: 500px) {
    .tarot-vu-barre { gap: 3px; padding: 3px 4px 3px 8px; border-radius: 9px; }
    .tarot-vu-ligne { gap: 6px; }
    .tarot-vu-titre { font-size: .7rem; }
    .tarot-vu-pastilles i { width: 16px; height: 16px; font-size: 9px; border-width: 1.5px; }
    .tarot-vu-btn { font-size: .68rem; padding: 4px 9px; }
}

/* Les enchères et l'écart : une fenêtre au centre du tapis */
.tarot-panneau {
    /* Placée par `tarotLayout.centre` : bord gauche, milieu en hauteur, largeur */
    position: absolute; z-index: 205; transform: translateY(-50%); pointer-events: auto; box-sizing: border-box;
    display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center;
    padding: 14px 18px; border-radius: 14px;
    background: linear-gradient(145deg, rgba(14,16,34,.94), rgba(23,27,53,.94));
    border: 1.5px solid rgba(255,255,255,.14); color: #fff; box-shadow: 0 10px 40px rgba(0,0,0,.6);
}
.tarot-panneau-titre { font-weight: 900; font-size: 1.05rem; color: var(--gold, #fbbf24); }
/* Téléphone en paysage : une fenêtre compacte (~90 px), qui tient entre
   l'avatar de Nord et la main */
@media (max-height: 500px) {
    .tarot-panneau { padding: 7px 10px; gap: 4px; border-radius: 10px; }
    .tarot-panneau-titre { font-size: .85rem; }
}

/* LES COULEURS DES CONTRATS (28/09/2026) : une gamme du plus tranquille au
   plus risqué, qui suit le multiplicateur — vert ×1, jaune ×2, orange ×4,
   rose ×6. NI BLEU NI ROUGE : ce sont les couleurs des camps (le mien, les
   autres) sur les tas et les points qui volent ; une Garde bleue ou une Garde
   contre rouge se lisaient comme « attaque » ou « défense ». Le violet reste
   au chelem. Le jaune, trop clair pour un texte blanc, prend un texte sombre
   (`--ct-texte`). Posées par `data-contrat` sur les tuiles de la fenêtre,
   l'étiquette du tas de l'attaque et le panneau de la manche. */
[data-contrat="Petite"]       { --ct-a: #22c55e; --ct-b: #15803d; --ct-halo: rgba(34,197,94,.75); }
[data-contrat="Garde"]        { --ct-a: #fde047; --ct-b: #eab308; --ct-halo: rgba(250,204,21,.75);
                                --ct-texte: #2b1d00; --ct-ombre: 0 1px 0 rgba(255,255,255,.35); }
[data-contrat="Garde sans"]   { --ct-a: #fb923c; --ct-b: #c2410c; --ct-halo: rgba(249,115,22,.8); }
[data-contrat="Garde contre"] { --ct-a: #f472b6; --ct-b: #be185d; --ct-halo: rgba(236,72,153,.8); }

/* LA FENÊTRE DU CONTRAT : l'habit de celle de la coinche (`.bid-box`) — fond
   sombre, liseré doré, PASSE et VALIDE — sans son `zoom` : elle est placée en
   pixels par `tarotLayout.centre`, et doit y tenir. Chaque prise est une
   tuile de sa couleur ; le multiplicateur est ce qui se lit d'abord : c'est
   lui qui fait le prix de la donne. La case du chelem prend la place du
   bouton COINCHE et la couleur du bouton CAPOT, l'autre annonce de tous les
   plis. */
.tarot-panneau.tarot-contrat {
    gap: 10px; padding: 14px; border-radius: 16px;
    background: rgba(14, 8, 20, .93);
    border: 1px solid rgba(251,191,36,.22);
    box-shadow: 0 0 0 1px rgba(255,255,255,.03), 0 20px 60px rgba(0,0,0,.7), 0 0 60px rgba(251,191,36,.06);
    backdrop-filter: blur(20px) saturate(1.5); -webkit-backdrop-filter: blur(20px) saturate(1.5);
    animation: tarotContratEntre .3s ease-out;
}
/* Le `slideUpFade` de la coinche remplacerait le translateY(-50%) qui centre
   la fenêtre sur sa place : celui-ci le garde */
@keyframes tarotContratEntre {
    from { opacity: 0; transform: translateY(calc(-50% + 16px)); }
    to   { opacity: 1; transform: translateY(-50%); }
}
.tarot-contrats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; width: 100%; }
.tarot-contrat-btn {
    font: inherit; min-width: 0; cursor: pointer;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
    padding: 8px 4px; border-radius: 12px;
    background: linear-gradient(160deg, var(--ct-a), var(--ct-b));
    border: 1.5px solid rgba(255,255,255,.35); color: var(--ct-texte, #fff);
    text-shadow: var(--ct-ombre, 0 1px 2px rgba(0,0,0,.4));
    box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 3px 8px rgba(0,0,0,.35);
    transition: all .15s;
}
.tarot-contrat-nom { font-size: .78rem; font-weight: 800; line-height: 1.1; text-wrap: balance; }
.tarot-contrat-mult { font-size: 1.5rem; font-weight: 900; line-height: 1; font-variant-numeric: tabular-nums; }
.tarot-contrat-btn:hover:not(:disabled) { filter: brightness(1.12); transform: translateY(-2px); }
.tarot-contrat-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
/* Sélection : un liseré blanc épais et le halo de SA couleur ; le liseré
   s'épaissit vers l'intérieur (padding réduit d'autant), la tuile ne change
   pas de taille. Les autres pâlissent : le choix saute aux yeux. */
.tarot-contrat-btn.selected {
    border-width: 4px; border-color: #fff; padding: 5.5px 1.5px;
    transform: translateY(-4px) scale(1.06);
    box-shadow: 0 0 0 3px var(--ct-halo), 0 0 26px var(--ct-halo), 0 8px 18px rgba(0,0,0,.55);
}
.tarot-contrats:has(.selected) .tarot-contrat-btn:not(.selected):not(:disabled) { filter: saturate(.5) brightness(.8); }
.tarot-contrat-btn:disabled { opacity: .25; filter: grayscale(1); cursor: not-allowed; transform: none; box-shadow: none; }
.tarot-contrat-actions { width: 100%; }
.tarot-chelem {
    flex: 1; display: flex; align-items: center; justify-content: center; gap: 6px;
    font-weight: 900; font-size: .88rem; text-transform: uppercase; letter-spacing: .05em;
    border-radius: 10px; cursor: pointer; user-select: none;
    background: #374151; border: 2px solid #6b7280; color: #9ca3af;
    transition: all .2s ease;
}
.tarot-chelem input { width: 16px; height: 16px; margin: 0; accent-color: #a855f7; cursor: pointer; }
.tarot-chelem.coche { background: #9333ea; border-color: #c084fc; color: #fff; box-shadow: 0 4px 14px rgba(168,85,247,.45); }
.tarot-chelem.eteint { opacity: .35; cursor: not-allowed; }
.tarot-chelem:focus-within { outline: 2px solid #fbbf24; outline-offset: 2px; }
/* Téléphone en paysage : la fenêtre tient dans ~90 px, entre l'avatar de Nord
   et la main (cf. `tarotLayout.centre`). Le titre s'efface — le cartouche du
   coin le dit déjà : « à vous de parler ». */
@media (max-height: 500px) {
    .tarot-panneau.tarot-contrat { gap: 4px; padding: 5px 7px; border-radius: 12px; }
    .tarot-contrat .tarot-panneau-titre { display: none; }
    .tarot-contrats { gap: 5px; }
    .tarot-contrat-btn { gap: 0; padding: 2px; border-radius: 9px; }
    .tarot-contrat-btn.selected { border-width: 3px; padding: .5px; transform: translateY(-2px) scale(1.04); }
    .tarot-contrat-nom { font-size: .62rem; }
    .tarot-contrat-mult { font-size: .95rem; }
    /* PASSE et VALIDE à ~32 px plutôt que 22 : la fenêtre gagne dix pixels
       (`panDemi` de `tarotLayout`) */
    .tarot-contrat-actions .btn-pass, .tarot-contrat-actions .btn-take { padding: 9px 0; font-size: .75rem; }
    .tarot-chelem { gap: 4px; font-size: .72rem; border-width: 1.5px; }
    .tarot-chelem input { width: 16px; height: 16px; }
}
.tarot-carte.sur-tapis { pointer-events: none; }
.tarot-carte.gagnante { box-shadow: 0 0 0 3px var(--gold, #fbbf24), 0 4px 14px rgba(0,0,0,.6); }

/* Les mains de Nord, Est et Ouest : l'éventail de la coinche, serré. Le
   conteneur est placé et tourné par `gameLayout.hands`, chaque dos par
   `fanTarot` (left, top, --rot), comme les `.card-img` de la coinche. */
.tarot-eventail { position: absolute; pointer-events: none; z-index: 30; }
.tarot-dos-eventail {
    position: absolute; display: block;
    border-radius: 7% / 4.2%;
    box-shadow: -3px 3px 6px rgba(0,0,0,.4);
    transform: rotate(var(--rot)); transform-origin: center center;
}
/* Une main visible : la carte qui vole vers le pli laisse son trou */
.tarot-dos-eventail.en-vol { visibility: hidden; }

/* LES PANNEAUX DE COIN DU TAROT : le gabarit `.ui-panel` de la coinche
   (200 × 128, bandeau de 48, corps de 80). Le contrat dans sa couleur, en
   pastille ; pendant les enchères, la meilleure enchère dite, en pâle. */
.tarot-coin-contrat { display: flex; flex-direction: column; align-items: center; gap: 4px; max-width: 100%; }
.tarot-coin-contrat.provisoire { opacity: .6; }
.tarot-coin-contrat-nom {
    font-size: 17px; font-weight: 900; line-height: 1.15; white-space: nowrap;
    padding: 2px 10px; border-radius: 999px; border: 1px solid rgba(0,0,0,.25);
    color: var(--ct-texte, #fff); background: linear-gradient(160deg, var(--ct-a), var(--ct-b));
    text-shadow: var(--ct-ombre, 0 1px 2px rgba(0,0,0,.4));
}
.tarot-coin-preneur { display: flex; align-items: center; gap: 5px; max-width: 100%; }
.tarot-coin-preneur-nom {
    min-width: 0; font-size: 14px; font-weight: 800; color: #1a1008;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Le dernier pli : les minis du tarot (500 × 667), la gagnante cerclée */
.tarot-coin-mini { height: 44px; }
.tarot-coin-mini.gagnante { box-shadow: 0 0 0 2px #1a1008, 0 2px 4px rgba(0,0,0,.5); }
/* Le classement : quatre lignes dans les 80 px du corps */
.tarot-classement-ligne {
    display: grid; grid-template-columns: 12px 1fr auto; align-items: baseline; gap: 6px;
    font-size: 13px; line-height: 1.25;
}
.tarot-classement-ligne + .tarot-classement-ligne { border-top: 1px solid rgba(0,0,0,.1); }
.tarot-classement-rang { font-weight: 900; color: rgba(0,0,0,.45); }
.tarot-classement-nom { min-width: 0; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tarot-classement-score { font-weight: 900; font-variant-numeric: tabular-nums; }
.tarot-classement-ligne.moi .tarot-classement-nom,
.tarot-classement-ligne.moi .tarot-classement-score { color: #1e3a8a; }

/* Les deux tas : l'attaque et la défense. Le liseré dit le camp — bleu le
   mien, rouge l'autre, comme les points qui s'envolent (`fp-nous`, `fp-eux`). */
.tarot-tas { position: absolute; z-index: 45; pointer-events: none; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.tarot-tas-dos { position: relative; width: 100%; }
.tarot-tas-dos img {
    display: block; width: 100%; height: 100%; border-radius: 7% / 4.2%;
    box-shadow: 2px 2px 0 rgba(0,0,0,.35), 4px 4px 0 rgba(0,0,0,.2), 0 3px 8px rgba(0,0,0,.5);
}
.tarot-tas.nous .tarot-tas-dos img { outline: 2px solid rgba(59,130,246,.9); }
.tarot-tas.eux  .tarot-tas-dos img { outline: 2px solid rgba(239,68,68,.9); }
.tarot-tas-pts {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    font-weight: 900; color: #fff; font-size: 1.1rem; font-variant-numeric: tabular-nums;
    text-shadow: 0 1px 3px #000, 0 0 10px #000, 0 0 4px #000;
    transition: transform .25s ease;
}
.tarot-tas.pulse .tarot-tas-pts { transform: scale(1.45); }
/* LE CONTRAT, AU-DESSUS de la carte de l'attaque : une pastille de sa
   couleur, le chelem dessous dans le violet du bouton ; les points restent au
   centre de la carte. Hors du flux (`bottom: 100%`) : le tas garde la forme
   de sa carte, là où volent les plis. Les tailles (12 px, 10 px sur
   téléphone) sont celles que `tarotLayout` réserve pour placer le tas. */
.tarot-tas-contrat {
    position: absolute; bottom: calc(100% + 3px); left: 50%; transform: translateX(-50%); z-index: 1;
    display: flex; flex-direction: column; align-items: center; gap: 2px; white-space: nowrap;
}
.tarot-tas-contrat-nom {
    font-size: 12px; font-weight: 900; line-height: 1.15; padding: 2px 7px; border-radius: 999px;
    color: var(--ct-texte, #fff); background: linear-gradient(160deg, var(--ct-a), var(--ct-b));
    border: 1px solid rgba(255,255,255,.55); text-shadow: var(--ct-ombre, 0 1px 2px rgba(0,0,0,.4));
    box-shadow: 0 2px 6px rgba(0,0,0,.55);
}
.tarot-tas-chelem {
    font-size: 10px; font-weight: 900; line-height: 1.15; padding: 1px 6px; border-radius: 999px;
    text-transform: uppercase; letter-spacing: .04em;
    color: #fff; background: #9333ea; border: 1px solid #c084fc; box-shadow: 0 2px 6px rgba(0,0,0,.5);
}
/* Elle pend du côté opposé à l'avatar (`tarotLayout.tasAligne`) */
.tarot-tas.etiq-g .tarot-tas-contrat { left: auto; right: 0; transform: none; align-items: flex-end; }
.tarot-tas.etiq-d .tarot-tas-contrat { left: 0; transform: none; align-items: flex-start; }
/* Faute de hauteur, le chelem se met à côté du contrat */
.tarot-tas.etiq-ligne .tarot-tas-contrat { flex-direction: row; align-items: center; gap: 4px; }
@media (max-height: 500px) {
    .tarot-tas-contrat-nom { font-size: 10px; padding: 1px 5px; }
    .tarot-tas-chelem { font-size: 8.5px; padding: 0 4px; }
}
.tarot-tas-nom {
    font-size: 11px; font-weight: 800; color: #fff; white-space: nowrap;
    padding: 0 7px; border-radius: 999px; background: rgba(0,0,0,.45);
}
.tarot-tas.nous .tarot-tas-nom { background: rgba(37,99,235,.75); }
.tarot-tas.eux  .tarot-tas-nom { background: rgba(185,28,28,.75); }
/* LA FIN DE MANCHE : la `recap-box` de la coinche, plus ce que le tarot a
   en propre — le contrat dans sa couleur et son écart, le calcul de la
   marque, une ligne par joueur (le tarot se joue chacun pour soi). */
.tarot-recap { max-width: 460px; }
.tarot-recap-contrat {
    display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 8px;
    padding: 9px 12px 4px;
}
.tarot-recap-preneur { font-weight: 800; font-size: .9rem; }
.tarot-recap-ecart { font-weight: 900; font-size: .85rem; }
.tarot-recap-ecart.ok { color: #6ee7b7; }
.tarot-recap-ecart.fail { color: #fca5a5; }
.tarot-recap-chelem { display: flex; justify-content: center; align-items: center; gap: 6px; font-size: .78rem; font-weight: 800; padding-bottom: 4px; }
.tarot-recap-chelem.ok { color: #d8b4fe; }
.tarot-recap-chelem.fail { color: #fca5a5; }
.tarot-recap .recap-cols { margin-top: 6px; }
.tarot-recap-marque {
    text-align: center; font-size: .78rem; color: rgba(255,255,255,.6); font-variant-numeric: tabular-nums;
    padding: 7px 12px 2px;
}
.tarot-recap-scores { width: calc(100% - 24px); margin: 4px 12px 8px; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.tarot-recap-scores th {
    font-size: .6rem; font-weight: 900; text-transform: uppercase; letter-spacing: .1em;
    color: rgba(255,255,255,.4); text-align: right; padding: 2px 6px;
}
.tarot-recap-scores td { padding: 4px 6px; border-top: 1px solid rgba(255,255,255,.07); text-align: right; font-size: .85rem; font-weight: 800; }
.tarot-recap-scores td:first-child { text-align: left; }
.tarot-recap-scores td.plus { color: #6ee7b7; }
.tarot-recap-scores td.moins { color: #fca5a5; }
.tarot-recap-scores td.total { font-weight: 900; font-size: .95rem; }
.tarot-recap-scores tr.moi td:first-child, .tarot-recap-scores tr.moi td.total { color: #60a5fa; }
.tarot-recap-rang { display: inline-block; width: 1.3em; color: rgba(255,255,255,.4); font-weight: 900; }
.tarot-recap-tag {
    margin-left: 6px; padding: 0 5px; border-radius: 999px; font-size: .6rem; font-weight: 900;
    text-transform: uppercase; letter-spacing: .06em; background: rgba(255,255,255,.12); color: rgba(255,255,255,.7);
}
.tarot-recap-pied { padding: 8px 12px 10px; display: flex; flex-direction: column; gap: 8px; }
.tarot-recap-poignees { display: flex; justify-content: center; flex-wrap: wrap; gap: 4px 12px; font-size: .78rem; font-weight: 800; color: #fcd34d; padding-top: 6px; }

/* LA POIGNÉE — la proposition, là où ma carte va se poser (centrée sur son
   point, `tarotLayout.poigneeBarre`) ; les atouts montrés, levés dans la main ;
   la poignée présentée, en fenêtre, jusqu'au « vu » de chacun. */
.tarot-poignee-barre {
    position: absolute; z-index: 206; transform: translate(-50%, -50%); pointer-events: auto;
    display: flex; align-items: center; gap: 8px; white-space: nowrap;
    padding: 6px 8px 6px 12px; border-radius: 12px;
    background: rgba(14, 8, 20, .92); border: 1px solid rgba(251,191,36,.3); color: #fff;
    box-shadow: 0 8px 24px rgba(0,0,0,.55);
}
.tarot-poignee-barre .tarot-vu-btn { text-transform: capitalize; }
.tarot-poignee-barre .btn-take, .tarot-poignee-barre .btn-pass { flex: 0 0 auto; padding: 7px 14px; }
.tarot-poignee-titre { font-weight: 900; font-size: .9rem; color: var(--gold, #fbbf24); }
.tarot-poignee-aide { font-size: .72rem; color: rgba(255,255,255,.5); }
.tarot-poignee-compte { font-weight: 800; font-size: .85rem; color: #fdba74; font-variant-numeric: tabular-nums; }
.tarot-poignee-compte.ok { color: #4ade80; }
.tarot-carte.en-main.en-poignee {
    transform: translateY(-14%);
    box-shadow: 0 0 0 3px var(--gold, #fbbf24), 0 6px 14px rgba(0,0,0,.55);
}
.tarot-poignee-vue { max-width: 440px; }
/* Deux rangées égales (5 + 5, 7 + 6, 8 + 7) : le nombre de colonnes vient du gabarit */
.tarot-poignee-cartes { display: grid; justify-content: center; gap: 5px; padding: 12px 14px 4px; }
.tarot-poignee-carte { width: 38px; height: 51px; border-radius: 4px; background: #fff; box-shadow: 0 2px 5px rgba(0,0,0,.5); }
/* Les vraies cartes (hors téléphone), proportions du dessin (500 × 915) :
   deux rangées qui se chevauchent comme la main de Sud — 45 % de chaque carte
   visible en largeur, la rangée du bas couvrant le bas de celle du haut —,
   l'index en haut à gauche lisible partout. 15 atouts (8 + 7) : 305 px. */
.tarot-poignee-dessins { display: flex; flex-direction: column; align-items: center; padding: 14px 14px 4px; }
.tarot-poignee-rang { display: flex; }
.tarot-poignee-rang + .tarot-poignee-rang { margin-top: -74px; }
.tarot-poignee-dessin { width: 74px; height: 135px; border-radius: 6px; background: #fff; box-shadow: 0 2px 6px rgba(0,0,0,.55); }
.tarot-poignee-dessin + .tarot-poignee-dessin { margin-left: -41px; }
.tarot-poignee-prime { text-align: center; font-size: .78rem; color: rgba(255,255,255,.6); padding: 6px 12px 8px; }
@media (max-height: 500px) {
    .tarot-poignee-barre { gap: 5px; padding: 3px 5px 3px 8px; border-radius: 9px; }
    .tarot-poignee-titre { font-size: .7rem; }
    .tarot-poignee-aide { display: none; }
    .tarot-poignee-compte { font-size: .68rem; }
    /* ~20 px de haut auparavant : la taille d'un doigt */
    .tarot-poignee-barre .btn-take, .tarot-poignee-barre .btn-pass { padding: 11px 12px; font-size: .72rem; }
}
.tarot-recap-pied-ligne { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

/* LA FIN DE PARTIE : le classement, les trois premiers aux couleurs du
   podium ; mes points en bleu, comme partout */
.tarot-fin { max-width: 380px; }
.tarot-fin-classement { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px 4px; }
.tarot-fin-ligne {
    display: grid; grid-template-columns: 34px 1fr auto; align-items: center; gap: 10px;
    padding: 7px 10px; border-radius: 10px; background: rgba(255,255,255,.05);
}
.tarot-fin-rang {
    width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    font-weight: 900; font-size: .95rem; background: rgba(255,255,255,.1); color: rgba(255,255,255,.7);
}
.tarot-fin-ligne.rang-1 .tarot-fin-rang { background: linear-gradient(160deg, #fde68a, #d97706); color: #3b2300; }
.tarot-fin-ligne.rang-2 .tarot-fin-rang { background: linear-gradient(160deg, #f1f5f9, #94a3b8); color: #1e293b; }
.tarot-fin-ligne.rang-3 .tarot-fin-rang { background: linear-gradient(160deg, #fdba74, #9a3412); color: #fff; }
.tarot-fin-ligne.rang-1 { background: rgba(251,191,36,.12); }
.tarot-fin-nom { font-weight: 800; font-size: .95rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tarot-fin-score { font-weight: 900; font-size: 1.1rem; font-variant-numeric: tabular-nums; }
.tarot-fin-ligne.moi .tarot-fin-nom, .tarot-fin-ligne.moi .tarot-fin-score { color: #60a5fa; }
/* Ce que ma place m'a rapporté (le tarot paie à la place, 21/10/2026) */
.tarot-fin-jetons { display: block; margin-top: 1px; color: #86efac; font-size: .72rem; font-weight: 800; }
.tarot-fin-actions { padding: 12px 14px 14px; }

/* TÉLÉPHONE EN PAYSAGE : la fin de manche et la fin de partie du tarot (25/10/2026).
   Au zoom de plancher (0,62) des fenêtres de la coinche, « Plis », « Bouts » et
   « Il fallait » tombaient à 7,7 px, l'en-tête du tableau à 6, et « Voir le
   classement » à 16 px de haut. Plus grandes, elles ne tiennent qu'en DEUX
   colonnes : les camps et la marque à gauche, le tableau des joueurs à droite,
   le verdict et le pied sur toute la largeur. Le classement de fin de partie,
   court, passe à l'échelle 1. Le bouton du « vu » prend la taille d'un doigt,
   dans ces fenêtres comme au chien et à l'écart. */
@media (max-height: 500px) and (orientation: landscape) {
    .recap-box.tarot-recap {
        zoom: 0.85;
        width: calc(94vw / 0.85); max-width: calc(94vw / 0.85);
        max-height: calc(98dvh / 0.85);
        display: grid; grid-template-columns: 1fr 1fr; column-gap: 10px;
        grid-template-areas: "ban ban" "con con" "che che" "cols sco" "poi sco" "mar sco" "pied pied";
        grid-template-rows: auto auto auto auto auto 1fr auto;
        padding: 0;
    }
    .tarot-recap > .recap-banner { grid-area: ban; }
    .tarot-recap > .tarot-recap-contrat { grid-area: con; }
    .tarot-recap > .tarot-recap-chelem { grid-area: che; }
    .tarot-recap > .recap-cols { grid-area: cols; margin: 4px 0 0 8px; }
    .tarot-recap > .tarot-recap-poignees { grid-area: poi; }
    .tarot-recap > .tarot-recap-marque { grid-area: mar; }
    .tarot-recap > .tarot-recap-scores { grid-area: sco; width: calc(100% - 8px); margin: 4px 8px 4px 0; align-self: start; }
    .tarot-recap > .tarot-recap-pied { grid-area: pied; }
    .recap-box.tarot-fin, .recap-box.tarot-poignee-vue {
        zoom: 1;
        max-height: 98dvh;
    }
    .tarot-fin .tarot-fin-classement { padding-top: 8px; gap: 4px; }
    .tarot-vu-btn { min-height: 38px; }
    .recap-box .tarot-vu-btn { min-height: 46px; font-size: .9rem; }
}

/* TÉLÉPHONE EN PAYSAGE : LES FENÊTRES TIENNENT DANS L'ÉCRAN (25/10/2026).
   Sur 375 px de haut, plusieurs fenêtres dépassaient l'écran sans le dire :
   « Pause Challenge » (420 px, ses deux boutons coupés), « Choisir sa partie »
   (FERMER et JOUER sous le pli), « Choisir un jeu », le visage réservé (586
   px), l'Illimité (545), le configurateur d'avatar, la boutique. Chacune est
   bornée à l'écran et ramassée ; quand la place manque vraiment, elle passe
   en deux colonnes plutôt que de défiler. */
@media (max-height: 500px) and (orientation: landscape) {
    /* Pause Challenge : les mêmes blocs, des marges de téléphone */
    .ch-between-box { max-height: calc(100dvh - 12px); overflow-y: auto; }
    .ch-between-box > div:nth-child(1) { padding-top: 8px; padding-bottom: 8px; }
    .ch-between-box > div:nth-child(2) { padding-top: 10px; padding-bottom: 6px; }
    .ch-between-box > div:nth-child(3) { margin-bottom: 8px; }
    .ch-between-box > div:nth-child(3) > div { padding-top: 6px; padding-bottom: 6px; }
    .ch-between-box > div:nth-child(4) { margin-bottom: 10px; padding-top: 6px; padding-bottom: 6px; }
    .ch-between-box > div:nth-child(5) { padding-bottom: 10px; }
    .ch-between-box > div:nth-child(5) > button { min-height: 44px; }

    .gift-modal-overlay { padding: 6px; }
    .gift-modal { max-height: calc(100dvh - 12px); }

    /* Choisir sa partie : les niveaux à gauche, le format et JOUER à droite */
    .choix-partie-box {
        width: 94vw !important; max-width: 720px;
        display: grid; grid-template-columns: 1.25fr 1fr; column-gap: 14px;
        grid-template-areas: "titre titre" "lab1 lab2" "niv fmt" "niv pied";
        grid-template-rows: auto auto auto 1fr;
    }
    .choix-partie-box > :nth-child(1) { grid-area: titre; margin-bottom: 4px; }
    .choix-partie-box > :nth-child(2) { grid-area: lab1; margin-top: 0 !important; }
    .choix-partie-box > :nth-child(3) { grid-area: niv; }
    .choix-partie-box > :nth-child(4) { grid-area: lab2; margin-top: 0 !important; }
    .choix-partie-box > :nth-child(5) { grid-area: fmt; grid-template-columns: 1fr !important; }
    .choix-partie-box > .gift-modal-pied { grid-area: pied; align-self: end; margin-top: 10px !important; }
    .choix-partie-box > .gift-modal-pied > button { min-height: 44px; }

    /* Choisir un jeu : des lignes plus basses, Fermer toujours visible */
    .jeu-modal-box > div:not(.gift-modal-title) > div { padding-top: 5px !important; padding-bottom: 5px !important; }
    .jeu-modal-box img { width: 34px !important; }
    .jeu-modal-box > .gift-modal-close {
        display: block; margin: 10px auto 0; min-height: 40px;
        position: sticky; bottom: 0; z-index: 2; background: #272a3b;
    }

    /* Un visage réservé : le visage, le titre et les boutons à gauche, ce
       qu'ouvre l'Illimité à droite */
    .cp-refus-box {
        width: min(640px, 96vw) !important;
        display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); column-gap: 16px;
        grid-template-areas: "img av" "titre av" "cp av" "fermer av";
        align-items: start;
    }
    .cp-refus-box > .cp-refus-image { grid-area: img; width: 110px !important; height: 110px !important; margin: 0 auto 8px !important; }
    .cp-refus-box > .gift-modal-title { grid-area: titre; margin-bottom: 0; }
    .cp-refus-box > .cp-refus-avantages { grid-area: av; margin-top: 0 !important; align-self: center; }
    .cp-refus-box > .gift-modal-cp { grid-area: cp; margin-top: 8px; }
    .cp-refus-box > .gift-modal-close { grid-area: fermer; justify-self: center; margin-top: 8px; }

    /* L'Illimité : chaque avantage sur une ligne, son détail tu */
    .cp-modal-box .cp-avantage-detail { display: none; }
    .cp-modal-box .cp-avantages { gap: 4px; }
    .cp-modal-box .cp-avantages > div { padding: 4px 8px; align-items: center; }

    /* Le configurateur d'avatar : Valider et Annuler collés au bas, des
       pastilles de teinte et un « C » à la taille d'un doigt */
    .avatar-config-box { max-height: calc(100dvh - 12px) !important; width: 96vw !important; padding: 10px 14px 0 !important; }
    .avatar-config-box > div:first-child { margin-bottom: 8px; padding-bottom: 6px; }
    .avatar-config-box .w-6.h-6 { width: 30px; height: 30px; }
    .avatar-config-pied {
        position: sticky; bottom: 0; z-index: 2;
        background: #111827; padding-top: 8px !important; padding-bottom: 10px;
    }
    .avatar-config-pied > button { min-height: 40px; }
    .avatar-config-c { width: 36px !important; height: 36px !important; }

    /* Boutique et jetons : la plaque de la marque prenait 54 px sur 375 */
    .jeton-modal-overlay > .modal-brand { display: none; }

    /* Les idées du jour : avec trois cartes, « Plus tard » sortait de l'écran */
    .sugg-fond { overflow-y: auto; align-items: center !important; align-items: safe center !important; padding: 8px !important; }
}

/* TÉLÉPHONE EN PAYSAGE : LES BOUTONS FIXES (25/10/2026).
   « Aide », fixé en bas à droite, se posait sur VALIDER de l'inscription et
   sur QUITTER du salon : en haut à droite, à côté du plein écran, il ne
   couvre plus aucune action. Le plein écran passe de 28 × 24 px à la taille
   d'un doigt. La puce « Installer l'application » se réduit à son icône,
   sa croix de 22 px à 30. L'encoche d'un iPhone (`--safe-*`) est respectée. */
@media (max-height: 500px) and (orientation: landscape) {
    .fullscreen-btn { top: 0; right: var(--safe-right, 0px); padding: 8px 10px; }
    .aide-fixe {
        top: 4px !important; bottom: auto !important;
        right: calc(8px + var(--safe-right, 0px)) !important; min-height: 36px;
    }
    body:has(.fullscreen-btn) .aide-fixe { right: calc(48px + var(--safe-right, 0px)) !important; }
    .pwa-puce { bottom: 6px !important; left: calc(6px + var(--safe-left, 0px)) !important; }
    .pwa-puce-texte { display: none; }
    .pwa-puce-btn { width: 40px; height: 40px; padding: 0 !important; justify-content: center; font-size: 18px !important; }
    .pwa-puce-fermer { width: 30px !important; height: 30px !important; }
}
/* iPhone : Safari agrandit la page dès qu'on touche un champ écrit sous 16 px
   (la recherche d'amis en 12, `.input-text` en 14,4…), et ne la rend pas. */
@media (pointer: coarse) and (max-height: 500px), (pointer: coarse) and (max-width: 500px) {
    input:not([type=checkbox]):not([type=radio]):not([type=range]), select, textarea { font-size: 16px !important; }
}

/* TÉLÉPHONE EN PAYSAGE : DES CIBLES À LA TAILLE D'UN DOIGT (25/10/2026).
   Jetons, AIDE, ACCUEIL et QUITTER du hub font 78 × 26 px, « Changer › » et
   « Rejoindre › » 20 px de haut, « Fermer » des fenêtres 34 : leur zone de
   toucher déborde de 6 px tout autour, sans que rien ne bouge à l'écran.
   Les compteurs de l'en-tête (PARTIES, VICTOIRES…) passaient à 7,7 px, et
   les liens secondaires de la connexion à 45 % d'opacité. */
@media (max-height: 500px) and (orientation: landscape) {
    .menu-user-header > div:last-child > button,
    .hub-jeu-btn, .hub-cp-appel, .gift-modal-close,
    .aide-fermer, .tuto-cat-fermer { position: relative; }
    .menu-user-header > div:last-child button::after,
    .hub-jeu-btn::after, .hub-cp-appel::after, .gift-modal-close::after {
        content: ''; position: absolute; inset: -6px;
    }
    /* Les ✕ de l'aide (23 px) et des leçons (28) */
    .aide-fermer::after, .tuto-cat-fermer::after { content: ''; position: absolute; inset: -9px; }
    .menu-user-header .min-w-0 [style*="0.48rem"] { font-size: .6rem !important; }
    .screen-login .form-link, .screen-create-account .form-link { color: rgba(241,245,249,.72); }
}

/* TÉLÉPHONE EN PORTRAIT : « ← Accueil » au-dessus du titre (25/10/2026).
   Posé à la hauteur du titre, il chevauchait « FAISONS UNE PARTIE » sur
   390 px de large. Il reprend sa place dans le flux, au-dessus, à gauche. */
@media (max-width: 500px) and (orientation: portrait) {
    .back-to-home,
    .screen-login .back-to-home,
    .screen-create-account .back-to-home {
        position: static; display: flex; width: fit-content;
        margin: -4px 0 6px; padding: 6px 8px 6px 0;
    }
}

/* SALON SUR UN TÉLÉPHONE EN PAYSAGE (25/10/2026).
   - Le badge « prêt » était calé pour un avatar de 120 px : à 88, il sortait
     de l'avatar et se posait sur les titres NOUS et EUX. Il se loge dans son
     coin haut droit.
   - Le bandeau collant des actions (dégradé, statut, départ automatique)
     recouvre le bas du salon : ses parties transparentes laissent passer le
     doigt vers PARLER et SON, dessous ; ses lignes se resserrent.
   - Les zones cadeau du salon font 22 px : leur zone de toucher déborde. */
@media (max-height: 450px) {
    .lobby-pret-badge { top: -44px; left: calc(50% + 18px); width: 28px; height: 28px; font-size: 14px; }
    .lobby-actions { pointer-events: none; }
    .lobby-actions button { pointer-events: auto; }
    .lobby-actions > div.flex-col { gap: 4px; }
    .lobby-actions .text-sm { font-size: .72rem; }
    .gift-zone.gift-lobby::after { content: ''; position: absolute; inset: -5px; border-radius: 50%; }
}
