/* ════════════════════════════════════════════════════════════════
   🎴 COLLECT — l'écran de jeu

   Une table, et tout le monde autour. Toi toujours en bas, à cheval
   sur le bord ; les autres répartis sur l'arc du haut, à l'angle que
   leur nombre commande.

   ⚠️ Tout ce qui doit toucher la table est ENFANT de la table, et se
   place en pourcentage de SA boîte — pas de celle de l'écran. C'est
   la seule façon pour que les sièges restent collés au feutre quelle
   que soit la taille de la fenêtre : un pourcentage d'écran ne suit
   pas une ellipse dont la hauteur vient d'un « aspect-ratio ».

   Le triangle des classes reste en haut à gauche : mesuré, un joueur
   qui ne le comprend pas réussit 1 % de ses vols, contre 86 % pour
   celui qui choisit sa classe.
   ════════════════════════════════════════════════════════════════ */

/* ⚠️ Les couleurs de classe vivent sur « :root » et non sur « .col ».
   Elles y étaient, et « .col-prise » — la carte volée, qui s'affiche en grand —
   est en « position: fixed » HORS de « .col » : les variables n'existaient donc
   pas pour elle, et sa pastille retombait sur la couleur du texte au lieu du
   corail, du violet ou du turquoise de sa classe. C'est la deuxième fois que ce
   décalage mord ici, après « --carte ». Tout ce qui peut sortir du plateau doit
   lire ses couleurs plus haut que le plateau.
   « --carte » reste sur « .col » : c'est une unité de mise en page du feutre,
   elle n'a pas de sens ailleurs. */
:root {
    --assaut: #ff7a5c;
    --mirage: #a78bfa;
    --oracle: #4fd1c5;
    --col-or: #ffd24a;
}

/* ⚠️ iOS ouvre son menu « Partager / Enregistrer l'image / Copier » sur TOUT
   appui long posé sur une image — et l'aperçu d'une carte se déclenche
   justement à l'appui long. Les deux se superposaient : on regardait sa carte
   à travers une feuille de partage.
   « -webkit-touch-callout: none » est la seule façon de le désarmer, et il faut
   qu'il porte sur l'image elle-même, c'est elle que le menu vise. « user-select »
   va avec : sans lui, un appui long sur un pseudo fait sortir les poignées de
   sélection de texte. Rien, dans ce mode, ne se copie ni ne se partage. */
.col, .col * {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}

.col {
    --carte: 4.6rem;

    position: fixed;
    inset: 0;
    z-index: 3;
    display: flex;
    flex-direction: column;
    padding: 0.7rem 0.7rem 0.6rem;
    overflow: hidden;
}

/* ── La barre du haut ─────────────────────────────────────────── */
.col-haut {
    flex: 0 0 auto;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.6rem;
}

/* ── Les règles, sous un parchemin ──
   Le triangle des classes vivait ici. Il montrait un cycle qui n'existe plus —
   les classes ne se battent plus entre elles, elles décident du prix d'un vol —
   et surtout il n'expliquait qu'une règle sur cinq, à un joueur qui débarque en
   cours de partie et n'en connaît aucune. */
/* ── Le bouton des règles ──
   Il bat tant qu'on ne l'a pas remarqué. L'onde vit sur un pseudo-élément :
   on n'anime ainsi que « transform » et « opacity », que le compositeur sait
   faire sans repeindre — un « box-shadow » animé aurait redessiné le bouton à
   chaque image, en boucle, pendant toute une manche. */
.col-regles-bouton.appelle {
    color: var(--col-or);
    border-color: rgba(255, 210, 74, 0.55);
    background: rgba(255, 210, 74, 0.09);
    animation: colReglesBat 1.5s ease-out infinite;
}
/* DEUX ondes, décalées. Une seule, régulière, se confondait avec le fond animé
   du feutre ; le décalage donne le coup de tambour. Le second cercle vit sur
   « ::before », libre sur ce bouton, et reste hors du flux malgré la grille. */
.col-regles-bouton.appelle::after,
.col-regles-bouton.appelle::before {
    content: '';
    position: absolute;
    inset: -0.2rem;
    border: 0.09rem solid var(--col-or);
    border-radius: 0.85rem;
    opacity: 0;
    pointer-events: none;
    animation: colReglesOnde 1.5s ease-out infinite;
}
.col-regles-bouton.appelle::before { animation-delay: 0.24s; }

/* Deux battements rapprochés, puis un temps mort qui occupe plus de la moitié
   du cycle. C'est le silence qui rend le coup suivant visible : une pulsation
   régulière, elle, devient un fond et cesse d'être remarquée — ce qui était
   exactement le défaut de l'ancienne, un aller-retour lent de 7 %. */
@keyframes colReglesBat {
    0%   { transform: scale(1)    rotate(0deg); }
    9%   { transform: scale(1.18) rotate(-6deg); }
    18%  { transform: scale(1.02) rotate(4deg); }
    27%  { transform: scale(1.13) rotate(-3deg); }
    40%  { transform: scale(1)    rotate(0deg); }
    100% { transform: scale(1)    rotate(0deg); }
}
@keyframes colReglesOnde {
    0%   { opacity: 0.85; transform: scale(0.86); }
    65%  { opacity: 0;    transform: scale(1.7); }
    100% { opacity: 0;    transform: scale(1.7); }
}

/* ── Le fil des actions ──────────────────────────────────────────
   En haut à droite, et assez pâle pour se lire du coin de l'œil sans
   disputer le feutre : il raconte, il ne réclame pas.
   ⚠️ « pointer-events: none » sur le fil entier — il couvre le coin haut
   droit, où vit aussi la pioche sur certaines tailles, et une colonne de
   texte n'a aucune raison d'intercepter un geste. Le bouton, lui, le
   reprend à son compte : c'est le seul morceau qui se touche. */
.col-fil {
    position: relative;
    flex: 0 0 auto;
    display: flex; flex-direction: column; align-items: flex-end;
    margin: 0.5rem 0.4rem 0 0;
    pointer-events: none;
}
/* ⚠️ HORS DU FLUX, et c'est là tout l'intérêt. Le fil vit dans « col-haut »,
   premier enfant d'une colonne flex : une ligne de plus l'agrandit, « col-scene »
   rétrécit d'autant, et TOUTE LA TABLE glisse vers le bas.
   Cela sautait aux yeux au doigt, où le fil s'ouvre d'un coup — mais le défaut
   valait aussi sur grand écran, en douceur : la table dérivait à mesure que les
   six premières lignes s'écrivaient, quelques pixels par action, sans que rien
   n'explique pourquoi.
   Sorti du flux, le fil ne pèse plus rien : il se pose PAR-DESSUS le coin, et
   « col-haut » garde la hauteur du seul bouton des règles. Le décalage du haut
   se règle donc ici, librement : plus rien n'en dépend. */
.col-fil-lignes {
    position: absolute;
    top: 1.1rem; right: 0;
    display: flex; flex-direction: column; align-items: flex-end;
    gap: 0.45rem;
    width: max-content;
    max-width: 42vw;
}
.col-fil-ligne {
    font-size: 0.88rem;
    line-height: 1.3;
    color: rgba(255, 255, 255, 0.34);
    text-align: right;
    white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis;
    max-width: 100%;
}
/* Le plus récent est en haut et se lit ; les précédents s'effacent sans
   disparaître. On garde ainsi le fil du tour sans que six lignes pèsent
   autant l'une que l'autre. */
.col-fil-ligne:nth-child(2) { color: rgba(255, 255, 255, 0.26); }
.col-fil-ligne:nth-child(3) { color: rgba(255, 255, 255, 0.20); }
.col-fil-ligne:nth-child(4) { color: rgba(255, 255, 255, 0.15); }
.col-fil-ligne:nth-child(5) { color: rgba(255, 255, 255, 0.11); }
.col-fil-ligne:nth-child(6) { color: rgba(255, 255, 255, 0.08); }

/* Une ligne neuve descend d'un cran et pousse les autres. Seuls « transform »
   et « opacity » bougent : la colonne se redessine à chaque action, et une
   hauteur animée ferait recalculer la mise en page du plateau entier. */
.col-fil-t-enter-active,
.col-fil-t-leave-active { transition: opacity 0.28s ease, transform 0.28s ease; }
.col-fil-t-enter-from { opacity: 0; transform: translateY(-0.5rem); }
.col-fil-t-leave-to   { opacity: 0; transform: translateY(0.4rem); }
.col-fil-t-leave-active { position: absolute; }
.col-fil-t-move { transition: transform 0.28s ease; }

/* Ordinateur : rien à déplier, le fil est là. */
.col-fil-bouton { display: none; }

.col-regles-bouton {
    position: relative;
    flex: 0 0 auto;
    width: 2.6rem; height: 2.6rem;
    display: grid; place-items: center;
    margin: 0.5rem 0 0 0.4rem;
    border: 0.06rem solid rgba(255, 255, 255, 0.12);
    border-radius: 0.7rem;
    background: rgba(255, 255, 255, 0.04);
    color: rgba(255, 255, 255, 0.4);
    cursor: pointer;
    transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}
.col-regles-bouton svg {
    width: 1.35rem; height: 1.35rem;
    fill: none; stroke: currentColor; stroke-width: 1.6;
    stroke-linecap: round; stroke-linejoin: round;
}
.col-regles-bouton:hover,
.col-regles-bouton.ouvert {
    color: var(--col-or);
    border-color: rgba(255, 210, 74, 0.5);
    background: rgba(255, 210, 74, 0.08);
}

/* Posé sur le feutre et non en plein écran : on lit sans quitter la partie des
   yeux, et un clic n'importe où referme. */
/* ── Les règles ──
   Au milieu de l'écran, sobre, et sans rien d'autre à regarder. Posé dans le
   coin, le panneau se lisait du coin de l'œil et ne s'imprimait pas ; et il
   disait tout, si bien qu'on n'en retenait rien. Une phrase par action. */
.col-regles-voile {
    position: fixed;
    inset: 0;
    z-index: 47;
    display: grid;
    place-items: center;
    padding: 1.2rem;
    background: rgba(6, 7, 10, 0.72);
    backdrop-filter: blur(0.25rem);
    cursor: pointer;
    animation: colVoileEntre 0.18s ease both;
}
@keyframes colVoileEntre { from { opacity: 0; } to { opacity: 1; } }

.col-regles {
    position: relative;
    width: min(27rem, 100%);
    max-height: 88vh;
    overflow: hidden auto;
    background: #0b0d11;
    border: 0.06rem solid rgba(255, 255, 255, 0.08);
    border-radius: 0.9rem;
    box-shadow: 0 1.6rem 3.4rem rgba(0, 0, 0, 0.75);
    cursor: default;
    animation: colReglesEntre 0.24s cubic-bezier(0.25, 0.9, 0.3, 1) both;
}

/* ── Le bandeau ──
   L'objectif y tient seul, sur un fond qui s'éteint vers le bas et un filet
   doré. Deux registres au lieu d'un empilement de titres : on sait du premier
   coup d'œil ce qu'on cherche, avant de savoir comment. */
.col-regles-bandeau {
    padding: 1.05rem 1.5rem 0.95rem;
    background: linear-gradient(180deg, rgba(255, 210, 74, 0.09), transparent);
    border-bottom: 0.06rem solid rgba(255, 210, 74, 0.18);
}
.col-regles-bandeau h4 {
    margin: 0 0 0.3rem;
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.5rem;
    letter-spacing: 0.05em;
    color: var(--col-or);
}
.col-regles-bandeau p { margin: 0; font-size: 0.82rem; color: rgba(255, 255, 255, 0.74); }
.col-regles-bandeau p b { color: #fff; }

/* Le tableau. Le premier écart est plus large que les autres : le bandeau et
   la première action se touchaient, et les deux registres n'en faisaient plus
   qu'un. */
.col-regles-corps { padding: 0.6rem 0 0.9rem; }

/* Un pied de modale, plus discret que les regles : c est un geste, pas une
   regle du jeu. Il se separe du tableau par un filet. */
.col-regles-astuce {
    margin: 0;
    padding: 0.7rem 1.5rem 1rem;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
    font-size: 0.68rem;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.4);
}

.col-regles-astuce b { color: rgba(255, 255, 255, 0.72); font-weight: 600; }

.col-regles-cap {
    padding: 1rem 1.5rem 0.5rem;
    font-size: 0.56rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.3);
}

/* ⚠️ Une GRILLE, et jamais un « display: flex » sur la ligne elle-même. La
   première version faisait cela : chaque « b » de la phrase devenait alors un
   élément flex à part entière, et la ligne « Voler », qui en portait quatre, se
   repliait en colonne d'un mot par ligne. Ici le nom et la phrase sont deux
   cellules, et la phrase reste un bloc de texte ordinaire. */
.col-regles-rang {
    display: grid;
    grid-template-columns: 5.6rem 1fr;
    gap: 0.9rem;
    padding: 0.55rem 1.5rem;
    align-items: baseline;
}

/* Une ligne sur deux à peine éclaircie : l'œil suit la sienne sans qu'il
   faille tracer un filet entre chacune. */
.col-regles-rang:nth-of-type(odd) { background: rgba(255, 255, 255, 0.022); }

.col-regles-rang b {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-family: 'Space Grotesk', sans-serif;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: currentColor;
}
/* Un bâtonnet plutôt qu'une pastille : il tient dans la hauteur d'une ligne
   sans avoir à être calé sur elle. */
.col-regles-rang b::before {
    content: '';
    width: 0.22rem;
    height: 0.9rem;
    border-radius: 999px;
    background: currentColor;
    box-shadow: 0 0 0.5rem currentColor;
}

.col-regles-rang span {
    font-size: 0.78rem;
    line-height: 1.45;
    color: rgba(255, 255, 255, 0.56);
}

.col-regles-rang.r-pioche  { color: #9db8d8; }
.col-regles-rang.r-echange { color: #9db8d8; }
.col-regles-rang.r-set     { color: var(--col-or); }
.col-regles-rang.r-scan    { color: var(--oracle); }
.col-regles-rang.r-vol     { color: var(--assaut); }

/* Sur téléphone, le nom passe au-dessus de sa phrase : deux colonnes dans la
   largeur d'un pouce laissaient à la phrase de quoi tenir trois mots. */
@media (max-width: 520px) {
    .col-regles-bandeau { padding: 0.9rem 1.1rem 0.8rem; }
    .col-regles-bandeau h4 { font-size: 1.3rem; }
    .col-regles-cap { padding: 0.85rem 1.1rem 0.45rem; }
    .col-regles-rang { grid-template-columns: 1fr; gap: 0.15rem; padding: 0.5rem 1.1rem; }
}

/* ── Le même parchemin, en plus grand sur écran ──
   Les valeurs de base servent le téléphone, où la place est comptée. Sur un
   écran elles laissaient un panneau étriqué au milieu d'un grand vide. Le
   seuil est celui du bloc ci-dessus, à un pixel près : ce qui est réglé au
   doigt reste intact, par construction. */
@media (min-width: 521px) {
    .col-regles { width: min(34rem, 100%); }

    .col-regles-bandeau { padding: 1.5rem 2.1rem 1.35rem; }
    .col-regles-bandeau h4 { margin-bottom: 0.45rem; font-size: 1.85rem; }
    .col-regles-bandeau p { font-size: 0.95rem; }

    .col-regles-corps { padding: 0.85rem 0 1.3rem; }
    .col-regles-cap { padding: 1.35rem 2.1rem 0.7rem; font-size: 0.62rem; }

    .col-regles-rang {
        grid-template-columns: 6.6rem 1fr;
        gap: 1.1rem;
        padding: 0.78rem 2.1rem;
    }
    .col-regles-rang b { font-size: 0.82rem; }
    .col-regles-rang b::before { width: 0.26rem; height: 1.05rem; }
    .col-regles-rang span { font-size: 0.9rem; }

    .col-regles-x {
        top: 0.95rem; right: 1.05rem;
        width: 2.1rem; height: 2.1rem;
        font-size: 1.35rem;
    }
}
@keyframes colReglesEntre {
    from { opacity: 0; transform: translateY(0.6rem) scale(0.98); }
    to   { opacity: 1; transform: none; }
}

.col-regles-x {
    position: absolute;
    top: 0.7rem; right: 0.8rem;
    width: 1.8rem; height: 1.8rem;
    padding: 0;
    display: grid; place-items: center;
    font-size: 1.2rem; line-height: 1;
    color: rgba(255, 255, 255, 0.35);
    background: none; border: 0;
    border-radius: 50%;
    cursor: pointer;
    transition: color 0.2s ease, background 0.2s ease;
}
.col-regles-x:hover { color: #fff; background: rgba(255, 255, 255, 0.07); }


.col-scene { position: relative; flex: 1 1 auto; min-height: 0; }

.col-table {
    position: absolute;
    left: 50%; top: 44%;
    transform: translate(-50%, -50%);
    width: min(93%, 65rem);
    aspect-ratio: 16 / 8.4;
    border-radius: 50%;
    background:
        radial-gradient(60% 60% at 50% 28%, rgba(255, 255, 255, 0.055), transparent 70%),
        linear-gradient(170deg, #17352b, #0d1f19);
    box-shadow:
        0 0 0 0.55rem rgba(74, 51, 23, 0.9),
        0 0 0 0.68rem rgba(255, 210, 74, 0.14),
        0 1.6rem 3.5rem rgba(0, 0, 0, 0.55),
        inset 0 0 4rem rgba(0, 0, 0, 0.45);
}

/* ── Le marché, au centre du feutre ───────────────────────────── */
.col-marche {
    position: absolute;
    left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    display: flex; align-items: center;
    z-index: 4;
}
/* « relative » : les cartes qui s'en vont passent en absolu le temps de
   sortir, sinon les autres attendraient leur disparition pour se décaler. */
.col-cartes { position: relative; display: flex; gap: 0.3rem; align-items: center; }
/* Le marché est commun donc lointain ; ta main est à toi et sous le pouce.
   Les deux ne méritent pas la même taille. */
.col-marche .col-carte { width: calc(var(--carte) * 0.9); }
/* ⚠️ « touch-action: none » est ce qui rend possible, au doigt, TOUT geste
   qui dure : le glissement d'une carte comme l'appui long qui ouvre l'aperçu.
   Sans lui, le navigateur garde le geste pour lui au cas où ce serait un
   défilement — il envoie un « pointercancel » et cesse d'émettre des
   « pointermove ». « preventDefault » sur le « pointerdown » n'y suffit pas :
   la décision est déjà prise quand il s'exécute.
   Il n'était posé que sur MA main, d'où un aperçu qui marchait là et nulle
   part ailleurs : au marché et sur les cartes scannées, le moindre frémissement
   du pouce annulait le pointeur et refermait tout.
   Rien à craindre pour le défilement : le plateau est en « position: fixed »
   et « overflow: hidden », il n'y a rien à faire défiler. Les cartes seulement,
   et non « .col » entier : la modale des règles, elle, doit pouvoir défiler. */
.col-carte, .col-dos { touch-action: none; }
.col-moi .col-carte { width: calc(var(--carte) * 1.14); }

/* Il n'est pas du marché : la marge l'en détache pour qu'on ne le prenne
   pas pour une sixième carte à échanger. La rangée reste centrée d'un bloc. */
.col-emplacement {
    margin-left: 1.4rem;
    width: calc(var(--carte) * 0.9);
    aspect-ratio: 225 / 350;
    border: 0.09rem dashed rgba(255, 210, 74, 0.32);
    border-radius: 0.45rem;
    display: grid; place-items: center;
    color: rgba(255, 210, 74, 0.3);
    font-size: 1rem;
}

/* ── La pioche, dans le coin bas droit de l'écran ─────────────── */
/* Un paquet, pas une carte : trois dos décalés. On lit « pile » et non
   « carte jouable », donc on n'essaie plus de la retourner. */
.col-pioche {
    position: absolute;
    right: 3.4rem; bottom: 3rem;
    width: calc(var(--carte) * 1.5);
    aspect-ratio: 225 / 350;
    z-index: 9;
}
/* Plus de marge de visée invisible : le paquet ne reçoit plus de glissement,
   il se clique. Elle n'agrandissait donc plus que la zone cliquable, et une
   zone cliquable qui déborde de trois centimètres attrape des clics qu'on ne
   lui destinait pas. */
/* Un sol sous le paquet, en permanence. Le fond de l'écran est noir et le dos
   des cartes presque : sans cette lueur froide, la pile flottait dans le vide
   et l'on ne voyait plus qu'elle avait une épaisseur. Elle devient dorée quand
   c'est notre tour — voir « .vivante » plus bas. */
.col-pioche::before {
    content: '';
    position: absolute; inset: -20%;
    border-radius: 50%;
    background: radial-gradient(closest-side, rgba(130, 160, 210, 0.16), transparent 74%);
    pointer-events: none;
    z-index: -1;
    transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.col-pioche span {
    position: absolute; inset: 0;
    border-radius: 0.55rem;
    /* Le liseré clair est l'ARÊTE de la carte : c'est lui, et non l'ombre, qui
       donne l'épaisseur sur un fond noir. */
    border: 0.09rem solid rgba(255, 255, 255, 0.22);
    background: repeating-linear-gradient(135deg, #26323f 0 7px, #1b232e 7px 14px);
    transition: transform 0.38s cubic-bezier(0.22, 0.68, 0.25, 1),
                box-shadow 0.38s ease, border-color 0.38s ease, color 0.38s ease;
}
/* Un décalage franc, et chaque épaisseur un peu plus sombre : sans ça on
   voyait une carte avec une ombre, pas une pile. */
.col-pioche span:nth-child(1) { transform: translate(0.85rem, 0.85rem); filter: brightness(0.62); }
.col-pioche span:nth-child(2) { transform: translate(0.42rem, 0.42rem); filter: brightness(0.82); }
.col-pioche span:nth-child(3) {
    display: grid; place-items: center;
    font-family: 'Bebas Neue', sans-serif; font-size: 1.15rem; letter-spacing: 0.08em;
    color: rgba(255, 255, 255, 0.42);
    box-shadow: 0 0.5rem 1.2rem rgba(0, 0, 0, 0.75), 0 0 0 0.04rem rgba(255, 255, 255, 0.06);
}

/* ── Un siège, posé sur le bord du feutre ─────────────────────── */
.col-siege {
    position: absolute;
    transform: translate(-50%, -50%);
    display: flex; flex-direction: column; align-items: center;
    gap: 0.2rem;
    z-index: 6;
}
.col-siege.choisissable .col-eventail { cursor: pointer; }

/* L'éventail : des dos de cartes, autant que la main en contient, tenus
   en main plutôt qu'alignés au cordeau. Le nombre se lit sans le compter. */
.col-eventail {
    display: flex; align-items: flex-end;
    padding-left: calc(var(--carte) * 0.4);
    /* La perspective vit sur l'éventail et non sur chaque carte : posée sur
       chacune, chaque carte aurait son propre point de fuite et le retournement
       se ferait droit — l'éventail entier doit tourner vers le même œil. */
    perspective: 900px;
}
/* Chaque carte adverse est une carte à DEUX faces, pas un rectangle sombre :
   c'est ce qui permet au scan de la retourner sur place au lieu d'ouvrir une
   fenêtre par-dessus la table. */
.col-dos {
    position: relative;
    width: calc(var(--carte) * 0.66);
    aspect-ratio: 225 / 350;
    margin-left: calc(var(--carte) * -0.4);
    transform-style: preserve-3d;
    transform-origin: 50% 120%;
    /* L'inclinaison doit vivre ICI et pas seulement dans l'animation d'entrée :
       sans cette règle, les dos se redressaient d'un coup à la fin de la
       distribution, quand la classe « entree » disparaissait avec elle. */
    transform: translateX(var(--dx, 0rem)) translateY(var(--dy, 0rem))
               rotate(var(--rot, 0deg)) rotateY(var(--flip, 0deg)) scale(var(--ech, 1));
    /* Deux propriétés animées, et deux seulement : « transform » pour le
       demi-tour et l'inclinaison, « opacity » pour l'effacement quand on survole
       le siège. La largeur et les marges refaisaient la mise en page à chaque
       image, pour les cinq cartes, pendant que cinq demi-tours tournaient :
       c'était la saccade. Ces deux-là, le compositeur les fait sans repeindre.

       ⚠️ Elles tiennent dans UNE SEULE déclaration, et ce n'est pas un détail
       de style. Une seconde règle « .col-dos { transition: opacity … } » posée
       plus bas écrase celle-ci — le raccourci remplace tout, il ne s'ajoute
       pas — et le retournement du scan redevient instantané. C'est exactement
       ce qui est arrivé en ajoutant l'effacement au survol. */
    transition: transform 0.6s cubic-bezier(0.32, 0.72, 0.24, 1),
                opacity 0.18s ease;
}
.col-dos > span {
    position: absolute; inset: 0;
    border-radius: 0.3rem;
    overflow: hidden;
    backface-visibility: hidden;
    border: 0.06rem solid rgba(255, 255, 255, 0.14);
    box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.5);
    transition: border-color 0.25s ease;
}
.col-dos-verso { background: repeating-linear-gradient(135deg, #1d2733 0 5px, #161d27 5px 10px); }
.col-dos-recto { transform: rotateY(180deg); background: #14131a; }
.col-dos-recto img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Le pion de classe, en petit : c'est LA chose à retenir d'un scan, et la
   seule qui décidera de ce qu'on peut lui prendre. */
.col-dos-recto .col-pion {
    position: absolute; top: 0.12rem; right: 0.12rem;
    width: 0.85rem; height: 0.85rem;
    display: grid; place-items: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.75);
}
.col-dos-recto .col-pion svg { width: 0.6rem; height: 0.6rem; }

/* ── Le scan : l'éventail se retourne et s'écarte ── */
.col-dos.retournee { --flip: 180deg; }
.col-eventail.scanne .col-dos {
    --ech: 1.35;
    z-index: 26;
    /* Prévenir le navigateur : il promeut les cinq cartes sur leur propre
       calque avant que ça bouge, plutôt qu'à la première image. */
    will-change: transform;
}
.col-eventail.scanne .col-dos:hover { --ech: 1.5; z-index: 27; }
.col-eventail.scanne { z-index: 25; }
/* ── Le temps qu'il reste, SOUS celui qui joue ──
   Il vivait dans le coin de l'écran : il fallait faire l'aller-retour entre
   deux bouts de la table pour savoir à qui il restait combien. Sous le siège,
   les deux informations sont au même endroit et se lisent d'un coup.

   La barre est une animation linéaire dont on règle la durée ET un retard
   NÉGATIF : elle reprend donc en cours de route, ce qui la rend juste après un
   rafraîchissement — et rien n'est repeint quatre fois par seconde comme le
   ferait un compteur en JavaScript. */
.col-jauge {
    display: block;
    width: 4.5rem; height: 0.22rem;
    margin: 0.32rem 0 0;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.6);
    overflow: hidden;
}
.col-jauge i {
    display: block; height: 100%;
    transform-origin: left;
    background: linear-gradient(90deg, var(--col-or), #ff9d3d);
    animation-name: colJaugeFond;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
}
.col-jauge.urgence i { background: linear-gradient(90deg, #ff6b4a, #ff3b30); }
@keyframes colJaugeFond { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* ── « Ta main est lue » ──
   Sobre, et sous son propre nom : se faire scanner n'appelle pas une alarme,
   mais on doit le savoir SUR LE MOMENT — c'est là qu'on apprend que son bluff
   ne tient plus, et non après s'être fait voler. */
/* Un œil POSÉ SUR la main, large et translucide. Une pastille en périphérie
   demandait qu'on la lise ; un œil sur ses propres cartes se comprend sans un
   mot, et il ne cache rien puisqu'on voit au travers. */
.col-oeil {
    position: absolute; left: 50%; top: 31%;
    transform: translate(-50%, -50%);
    width: calc(var(--carte) * 2.4);
    pointer-events: none;
    z-index: 14;
    animation: colOeilBat 2.4s ease-in-out infinite;
}
.col-oeil svg {
    display: block; width: 100%; height: auto;
    fill: rgba(20, 8, 4, 0.28);
    stroke: rgba(255, 190, 150, 0.85);
    stroke-width: 1.1;
    stroke-linecap: round; stroke-linejoin: round;
    filter: drop-shadow(0 0 0.6rem rgba(255, 120, 70, 0.55));
}
@keyframes colOeilBat {
    0%, 100% { opacity: 0.55; transform: translate(-50%, -50%) scale(0.97); }
    50%      { opacity: 1;    transform: translate(-50%, -50%) scale(1.03); }
}

/* ── L'écho d'un geste adverse ──
   Une main adverse est un paquet de dos : quand un joueur pioche ou échange,
   rien n'y bougeait, et l'on n'apprenait qu'il avait joué qu'en voyant le
   siège suivant s'allumer. Une carte qui glisse par la droite suffit à dire
   « il vient de faire quelque chose » sans rien révéler de plus. */
.col-echo {
    position: fixed;
    z-index: 30;
    margin: -1.5rem 0 0 -1rem;
    border-radius: 0.28rem;
    overflow: hidden;
    border: 0.06rem solid rgba(255, 255, 255, 0.2);
    box-shadow: 0 0.4rem 0.9rem rgba(0, 0, 0, 0.6);
    pointer-events: none;
    animation: colEcho 0.85s cubic-bezier(0.28, 0.75, 0.3, 1) forwards;
}
.col-echo.dos { background: repeating-linear-gradient(135deg, #26323f 0 5px, #1b232e 5px 10px); }
.col-echo img { width: 100%; height: 100%; object-fit: cover; display: block; }
@keyframes colEcho {
    0%   { opacity: 0; transform: translate(7rem, -0.9rem) rotate(16deg) scale(0.92); }
    22%  { opacity: 1; }
    82%  { opacity: 1; }
    100% { opacity: 0; transform: translate(0, 0) rotate(0deg) scale(0.72); }
}
/* À qui le tour : une lueur qui respire autour de l'éventail. Sobre parce
   qu'elle ne fait que pulser — pas de couleur criarde, pas de mouvement du
   siège lui-même, qui ferait sauter la table à chaque changement de main. */
.col-siege.tour .col-dos-verso { border-color: rgba(255, 210, 74, 0.55); }
.col-siege.tour .col-eventail,
.col-moi.tour .col-main {
    position: relative;
}
.col-siege.tour .col-eventail::before,
.col-moi.tour .col-main::before {
    content: '';
    position: absolute; inset: -0.6rem -0.4rem -0.9rem;
    border-radius: 1rem;
    background: radial-gradient(60% 60% at 50% 60%, rgba(255, 210, 74, 0.3), transparent 72%);
    animation: colLueur 2.1s ease-in-out infinite;
    pointer-events: none;
    z-index: -1;
}
@keyframes colLueur {
    0%, 100% { opacity: 0.35; transform: scale(0.96); }
    50%      { opacity: 1;    transform: scale(1.04); }
}
.col-siege.tour .col-nom, .col-moi.tour .col-nom {
    box-shadow: 0 0 0.7rem rgba(255, 210, 74, 0.35);
}
.col-siege.choisissable .col-dos-verso { border-color: rgba(255, 255, 255, 0.45); }

.col-etoiles {
    position: relative;
    display: flex; gap: 0.2rem;
    padding: 0.22rem 0.5rem;
    background: rgba(0, 0, 0, 0.62);
    border: 0.06rem solid rgba(255, 255, 255, 0.1);
    border-radius: 999px;
}
/* Des ÉTOILES, et non des ronds. L'emplacement où l'on pose porte déjà une
   étoile : le point qu'on y gagne doit en être une aussi, sinon rien ne relie
   ce qu'on fait à ce qu'on marque. Un « clip-path » plutôt qu'un caractère —
   une étoile typographique change de dessin d'une police à l'autre, et la
   nôtre doit être exactement celle de l'emplacement. */
.col-etoiles i {
    width: 0.72rem; height: 0.72rem;
    background: rgba(255, 255, 255, 0.3);
    clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%,
                       50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
    transition: background 0.25s ease, filter 0.25s ease;
}
.col-etoiles i.pleine {
    background: var(--col-or);
    filter: drop-shadow(0 0 0.3rem rgba(255, 210, 74, 0.85));
}

/* ⚠️ Un peu plus grandes SUR ORDINATEUR seulement. Sur téléphone, l'objectif
   est déjà collé à l'éventail et au chrono : les grossir là-bas reprendrait de
   la place à ce qui compte, les cartes. Le seuil est le même que celui du
   passe mobile plus bas (780 px), pour qu'il n'y ait qu'une frontière à
   déplacer si elle bouge un jour. */
@media (min-width: 781px) {
    .col-etoiles { gap: 0.26rem; padding: 0.26rem 0.62rem; }
    .col-etoiles i { width: 0.92rem; height: 0.92rem; }
}

/* ── Le point qui vient d'être marqué ──
   Deux ou trois fois par partie, et c'est TOUT ce qu'on cherche : la pastille
   se dilate, un anneau s'en échappe, et les points allumés blanchissent. Sans
   ça, la seule trace d'une victoire d'étape était un rond qui changeait de
   couleur en silence, au bas de l'écran, pendant que les éclats de verre
   accaparaient le regard ailleurs. */
.col-etoiles.gagne {
    animation: colPointBoite 0.75s cubic-bezier(0.24, 1.4, 0.4, 1);
    border-color: rgba(255, 210, 74, 0.85);
}
.col-etoiles.gagne::after {
    content: '';
    position: absolute; inset: -0.3rem;
    border-radius: 999px;
    border: 0.12rem solid var(--col-or);
    animation: colPointOnde 0.75s ease-out forwards;
    pointer-events: none;
}
.col-etoiles.gagne i.pleine { animation: colPointPlein 0.75s ease-out; }
.col-etoiles.gagne i.pleine:nth-child(2) { animation-delay: 0.05s; }
.col-etoiles.gagne i.pleine:nth-child(3) { animation-delay: 0.1s; }
@keyframes colPointBoite {
    0%   { transform: scale(1); }
    35%  { transform: scale(1.32); }
    100% { transform: scale(1); }
}
@keyframes colPointOnde {
    0%   { opacity: 1; transform: scale(0.85); }
    100% { opacity: 0; transform: scale(2.4); }
}
@keyframes colPointPlein {
    0%, 100% { box-shadow: 0 0 0.35rem rgba(255, 210, 74, 0.75); filter: brightness(1); }
    30%      { box-shadow: 0 0 1.1rem rgba(255, 240, 190, 1);    filter: brightness(2.4); }
}
/* L'étoile qui quitte l'emplacement pour aller se ranger sous le joueur.
   Elle naît grande au milieu du feutre, là où le regard est déjà, et rétrécit
   en chemin : c'est le trajet qui dit « ce set-là devient ce point-ci ». */
.col-etoile-vol {
    position: fixed;
    z-index: 64;
    width: 2.6rem; height: 2.6rem;
    margin: -1.3rem 0 0 -1.3rem;
    background: linear-gradient(160deg, #fff3cf, var(--col-or) 45%, #ff9d3d);
    clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%,
                       50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
    filter: drop-shadow(0 0 0.7rem rgba(255, 200, 80, 0.95));
    pointer-events: none;
    animation: colEtoileVol 0.78s cubic-bezier(0.36, 0, 0.2, 1) forwards;
}
@keyframes colEtoileVol {
    0%   { opacity: 0; transform: translate(0, 0) scale(0.2) rotate(-50deg); }
    16%  { opacity: 1; transform: translate(0, 0) scale(1.3) rotate(6deg); }
    30%  { opacity: 1; transform: translate(0, 0) scale(1)   rotate(0deg); }
    100% { opacity: 1; transform: translate(var(--dx), var(--dy)) scale(0.26) rotate(200deg); }
}

/* Les étincelles, semées autour de la pastille */
.col-etincelle {
    position: fixed;
    z-index: 63;
    width: 0.32rem; height: 0.32rem;
    border-radius: 50%;
    background: radial-gradient(circle, #fff6d8, var(--col-or) 55%, rgba(255, 138, 61, 0));
    pointer-events: none;
    animation: colEtincelle 0.8s cubic-bezier(0.15, 0.7, 0.3, 1) forwards;
}
@keyframes colEtincelle {
    0%   { opacity: 1; transform: translate(0, 0) scale(1.2); }
    100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(0.3); }
}

.col-nom {
    max-width: 7rem;
    padding: 0.13rem 0.55rem;
    font-size: 0.64rem; font-weight: 600;
    color: rgba(255, 255, 255, 0.72);
    background: rgba(0, 0, 0, 0.68);
    border-radius: 0.35rem;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.col-siege.tour .col-nom { color: var(--col-or); }

/* Trois points qui roulent sous le siège de celui dont c'est le tour. On sait
   alors qu'on attend quelqu'un, et non que l'écran s'est figé — c'est la
   première chose qu'on se demande quand rien ne bouge pendant dix secondes.
   Jamais sous le sien : on n'attend pas après soi-même. */
.col-reflechit {
    /* En haut a droite du siege, hors du flux : sous le nom, la colonne
       s allongeait a chaque changement de main et le siege sautait. */
    position: absolute;
    top: -0.35rem; right: -3.9rem;
    display: flex; gap: 0.2rem;
    padding: 0.25rem 0.4rem;
    background: rgba(0, 0, 0, 0.6);
    border-radius: 999px;
    align-items: center;
}
/* Trois cartes minuscules qui se retournent l'une après l'autre. Le signal
   parle le langage du jeu et non celui d'un chargeur de page : on lit « il
   regarde ses cartes », pas « ça charge ». */
.col-reflechit i {
    width: 0.42rem; height: 0.62rem;
    border-radius: 0.1rem;
    background: var(--col-or);
    opacity: 0.25;
    animation: colPense 1.6s ease-in-out infinite;
}
.col-reflechit i:nth-child(2) { animation-delay: 0.2s; }
.col-reflechit i:nth-child(3) { animation-delay: 0.4s; }
@keyframes colPense {
    0%, 60%, 100% { opacity: 0.22; transform: rotateY(0deg); }
    30%           { opacity: 1;    transform: rotateY(180deg) scaleX(1.1); }
}

/* ── Toi, à cheval sur le bord du bas ─────────────────────────── */
.col-moi {
    position: absolute;
    left: 50%; top: 100%;
    transform: translate(-50%, -46%);
    display: flex; flex-direction: column; align-items: center;
    z-index: 8;
}
.col-main {
    display: flex; align-items: flex-end;
    padding-left: calc(var(--carte) * 0.22);
}
.col-main .col-carte { margin-left: calc(var(--carte) * -0.22); transform-origin: 50% 130%; }
/* L'objectif descend sous l'éventail au lieu de le chevaucher. Il mordait sur
   le bas des cartes : à zéro point, deux ronds gris sur un portrait ne se
   distinguaient pas du dessin. Les ronds vides sont aussi un peu moins
   discrets — c'est justement quand on n'a rien marqué qu'il faut voir
   combien il en reste à marquer. */
/* Hors tour, la main baisse d'un ton. Rien n'y est cliquable, et une main
   aussi vive que pendant son tour laissait croire qu'on pouvait encore jouer —
   on tirait une carte, il ne se passait rien, et le refus ne s'affiche plus. */
.col-moi .col-main .col-carte {
    transition: transform 0.18s ease, border-color 0.18s ease,
                box-shadow 0.18s ease, filter 0.35s ease;
}
.col-moi:not(.tour) .col-main .col-carte { filter: saturate(0.45) brightness(0.62); }
.col-moi:not(.tour) .col-main .col-carte:hover { filter: saturate(0.75) brightness(0.85); }

.col-moi .col-etoiles { margin-top: 0.45rem; z-index: 2; }
/* La jauge se pose entre deux textes : elle a besoin d'air des deux côtés,
   sans quoi elle se lit comme le soulignement du nom. */
.col-moi .col-jauge { margin: 0.5rem 0 0.45rem; }
.col-siege .col-jauge { width: 3.6rem; margin: 0.45rem 0 0.4rem; }
/* ⚠️ « :not(.pleine) » n'est pas décoratif. Sans lui cette règle, à
   spécificité égale mais placée plus bas, écrasait l'or de « .pleine » — et
   les points gagnés restaient gris. */
.col-moi .col-etoiles i:not(.pleine) { background: rgba(255, 255, 255, 0.34); }
.col-moi .col-nom { margin-top: 0.15rem; color: var(--col-or); }

/* ── La carte ─────────────────────────────────────────────────── */
.col-carte {
    position: relative;
    flex: 0 0 auto;
    width: var(--carte);
    aspect-ratio: 225 / 350;
    padding: 0;
    background: #14131a;
    border: 0.09rem solid rgba(255, 255, 255, 0.14);
    border-radius: 0.42rem;
    cursor: pointer;
    box-shadow: 0 0.3rem 0.7rem rgba(0, 0, 0, 0.5);
    transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
}
.col-carte img {
    width: 100%; height: 100%; object-fit: cover; display: block;
    border-radius: 0.34rem;
}
.col-carte.classe-assaut { border-color: var(--assaut); }
.col-carte.classe-mirage { border-color: var(--mirage); }
.col-carte.classe-oracle { border-color: var(--oracle); }

/* La classe déborde du coin haut droit : elle se lit alors même quand les
   cartes se chevauchent en éventail, ce qui n'était pas le cas dans le coin. */
.col-pion {
    position: absolute; top: -0.32rem; right: -0.32rem;
    width: 1.15rem; height: 1.15rem;
    display: grid; place-items: center;
    background: #0b0b0f;
    border: 0.11rem solid currentColor;
    border-radius: 50%;
    box-shadow: 0 0.15rem 0.4rem rgba(0, 0, 0, 0.65);
    z-index: 3;
}
.col-pion svg { width: 0.62rem; height: 0.62rem; display: block; }
.pion-assaut { color: var(--assaut); }
.pion-mirage { color: var(--mirage); }
.pion-oracle { color: var(--oracle); }

/* La carte garde son inclinaison et monte tout droit. L'ordre compte : le
   « translateY » est écrit AVANT le « rotate », donc il s'applique après —
   dans l'axe de l'écran et non dans celui de la carte penchée, qui la ferait
   partir de biais. */
.col-carte { transform: translateY(var(--lift, 0rem)) translateY(var(--dy, 0rem)) rotate(var(--rot, 0deg)); }
.col-carte:hover { --lift: -0.65rem; z-index: 20; }
.col-carte.choisie { --lift: -1rem; border-color: var(--col-or); box-shadow: 0 0.7rem 1.4rem rgba(255, 210, 74, 0.32); z-index: 21; }
.col-carte.choisissable { box-shadow: 0 0 0 0.11rem rgba(255, 210, 74, 0.4), 0 0.3rem 0.7rem rgba(0, 0, 0, 0.5); }
.col-carte.eteinte { opacity: 0.3; }

/* Une carte dont on tient déjà de quoi avancer. C'était un trait doré au bas
   de la carte : un deuxième cadre par-dessus celui de la classe, qu'on
   confondait avec lui et qui ne bougeait jamais.

   C'est maintenant la « lueur ténébreuse » du prototype D : une brume dorée
   SOUS la carte, plus dense au bas, qui monte et redescend. Aucun trait, aucun
   cadre — une présence plutôt qu'un signal, qui tient à cinq exemplaires
   allumés en même temps sans que la table se mette à clignoter. */
/* Un néon qui COURT autour de la carte. Un dégradé conique tourne derrière,
   et un masque n'en laisse voir que le contour : la lumière fait le tour du
   cadre sans que rien ne se déplace. Les deux essais précédents — le liseré au
   bas, puis la brume — étaient immobiles, et c'est precisement ce qui les
   rendait invisibles au milieu de cinq cartes.

   « @property » est indispensable : sans lui, une variable d'angle n'est qu'un
   texte et ne s'interpole pas. Un navigateur qui l'ignore garde le halo fixe —
   dégradé honnête, la carte reste signalée, elle ne bouge simplement plus. */
@property --colTour {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}
/* La couche du dessous : plus large, floue, et qui tourne À L'ENVERS et plus
   vite. Une seule course était nette mais mince — de loin on ne voyait qu'un
   filet. Deux courses en sens contraire se croisent quatre fois par tour, et
   c'est ce battement-là qu'on remarque du coin de l'œil. */
/* La couche du dessous TOURNE, au lieu de se repeindre. Un dégradé conique
   dont on anime l'angle est refait à chaque image, et le flou avec — sur neuf
   cartes allumées à la fois, c'était le poste le plus lourd de l'écran et cela
   se sentait jusque dans la distribution. Ici l'élément est un CARRÉ (pour que
   la rotation ne découvre jamais de coin) que le navigateur peint une fois et
   se contente ensuite de faire pivoter : rien à recalculer. */
/* Un carré qui tourne se voit tourner : ses coins sortaient de derrière la
   carte, quatre fois par tour. On le rend circulaire ET on l'estompe par un
   masque radial — ce qui tourne n'a alors plus de bord du tout, et il ne reste
   qu'une lumière qui fait le tour. La forme reste un carré parfait sous le
   masque, sinon la rotation ferait battre la largeur. */
.col-carte.paire::before {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    height: 128%; aspect-ratio: 1;
    border-radius: 50%;
    background: conic-gradient(
        rgba(255, 138, 61, 0)   0deg,
        rgba(255, 190, 60, 0.7) 55deg,
        #ffd24a                 90deg,
        rgba(255, 138, 61, 0)   150deg,
        rgba(255, 138, 61, 0)   200deg,
        rgba(255, 210, 74, 0.5) 250deg,
        rgba(255, 138, 61, 0)   320deg);
    -webkit-mask: radial-gradient(closest-side, #000 34%, rgba(0, 0, 0, 0.55) 62%, transparent 100%);
            mask: radial-gradient(closest-side, #000 34%, rgba(0, 0, 0, 0.55) 62%, transparent 100%);
    filter: blur(0.35rem);
    opacity: 0.85;
    animation: colTourneInverse 1.4s linear infinite;
    pointer-events: none;
    z-index: -1;
    will-change: transform;
}
@keyframes colTourneInverse {
    from { transform: translate(-50%, -50%) rotate(0deg); }
    to   { transform: translate(-50%, -50%) rotate(-360deg); }
}

.col-carte.paire::after {
    content: '';
    position: absolute; inset: -0.28rem;
    border-radius: 0.68rem;
    padding: 0.26rem;
    background: conic-gradient(from var(--colTour),
        rgba(255, 210, 74, 0)   0deg,
        rgba(255, 210, 74, 0)   38deg,
        rgba(255, 210, 74, 0.9) 82deg,
        #fff0c0                 108deg,
        #ff9d3d                 138deg,
        rgba(255, 138, 61, 0)   196deg,
        rgba(255, 210, 74, 0)   360deg);
    /* Le masque évide le centre : il ne reste que l'anneau. Deux calques
       identiques, l'un limité à la boîte de contenu, soustraits l'un de
       l'autre — c'est le seul moyen d'obtenir un contour arrondi net. */
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
            mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask-composite: exclude;
    /* Plus d'ombre portée ici : un filtre recalculé à chaque image, sur une
       source qui change à chaque image. La lueur vient de la couche du dessous,
       qui elle ne fait que tourner. */
    animation: colTourne 1.6s linear infinite;
    pointer-events: none;
}
@keyframes colTourne { to { --colTour: 360deg; } }


/* ── La carte regardée de près ────────────────────────────────── */
.col-loupe {
    position: absolute;
    left: 1.2rem; top: 50%;
    transform: translateY(-50%);
    width: min(15.5rem, 27vw);
    background: #0e0e13;
    border-radius: 0.9rem;
    box-shadow: 0 1rem 2.4rem rgba(0, 0, 0, 0.6);
    z-index: 14;
    pointer-events: none;
    animation: colLoupe 0.18s ease both;
}
@keyframes colLoupe {
    from { opacity: 0; transform: translateY(-50%) translateX(-0.6rem); }
    to   { opacity: 1; transform: translateY(-50%) translateX(0); }
}
.col-loupe-vue { position: relative; border-radius: 0.9rem; overflow: visible; }
.col-loupe-vue img { width: 100%; display: block; border-radius: 0.9rem; }
/* Le fondu monte haut et se ferme sur le fond de la carte : le nom se pose
   SUR l'image, dans sa partie basse, au lieu d'être relégué dans un bandeau
   qui la couperait en deux. */
.col-loupe-vue::after {
    content: '';
    position: absolute; inset: 38% 0 0 0;
    background: linear-gradient(180deg, transparent, rgba(10, 10, 14, 0.72) 42%, #0a0a0e 82%);
    border-radius: 0 0 0.9rem 0.9rem;
}
.col-loupe-texte {
    position: absolute; inset: auto 0 0 0;
    padding: 0 1rem 3rem;
    z-index: 2;
}
.col-loupe-nom {
    display: block;
    font-size: 1.5rem; font-weight: 700; line-height: 1.05;
    letter-spacing: -0.015em;
}
.col-loupe-serie {
    display: block;
    margin-top: 0.62rem;
    font-size: 0.74rem; font-weight: 700;
    letter-spacing: 0.16em; text-transform: uppercase;
    color: var(--col-or);
}
/* Le filet et son losange : la signature de la v1. Le trait s'éteint aux
   deux bouts, ce qui l'empêche de faire une deuxième ligne de texte. */
.col-loupe-barre {
    display: block;
    position: relative;
    height: 0.06rem;
    margin-top: 0.85rem;
    background: linear-gradient(90deg, transparent, rgba(255, 210, 74, 0.5), transparent);
}
.col-loupe-barre::after {
    content: '';
    position: absolute; left: 50%; top: 50%;
    width: 0.3rem; height: 0.3rem;
    margin: -0.15rem 0 0 -0.15rem;
    background: var(--col-or);
    transform: rotate(45deg);
}
.col-loupe .col-pion {
    top: -0.55rem; right: -0.55rem;
    width: 2.1rem; height: 2.1rem;
    border-width: 0.15rem;
}
.col-loupe .col-pion svg { width: 1.05rem; height: 1.05rem; }

/* ── La consigne et les actions ───────────────────────────────── */
/* ⚠️ HAUTEUR FIXE, et non « min-height ». C'est là qu'était le vrai défaut :
   un message assez long pour passer à DEUX lignes agrandissait la barre, et
   tout le plateau remontait de quelques pixels — à chaque apparition, puis
   redescendait. « Un set est prêt — glisse une carte sur l'emplacement
   étoilé » faisait 368 px et passait à la ligne dès qu'on jouait sur un écran
   étroit.
   Une hauteur figée le rend impossible quoi qu'on écrive ici un jour, et
   « nowrap » avec elle : un texte trop long se coupe proprement plutôt que de
   déborder. Le rembourrage du bas la décolle du bord de l'écran, où elle se
   lisait comme une légende de page. */
.col-consigne {
    flex: 0 0 auto;
    height: 2.25rem;
    padding: 0.35rem 0.2rem 0.7rem;
    text-align: center;
    font-size: 0.74rem; line-height: 1.35;
    color: rgba(255, 255, 255, 0.55);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.col-consigne b { color: var(--col-or); }
.col-consigne.ko { color: #ff8b98; }

/* ════════ On joue sur la table, plus dans une barre ════════
   Plus de boutons : chaque action se fait à l'endroit qui la désigne. On
   glisse une carte sur la pioche pour piocher, sur une carte du marché pour
   l'échanger, sur l'emplacement pour poser. Les adversaires montrent leurs
   deux icônes au survol.

   Ce qui rend la chose lisible, c'est que les cibles s'annoncent SEULES
   quand c'est ton tour : la pioche respire, l'emplacement pulse dès qu'un set
   est prêt. On n'a jamais à deviner ce qui est cliquable. */

/* La pioche appelle quand on peut piocher — en BRILLANT, sans se déplacer.
   Elle se soulevait toute seule : on la voyait bouger sans l'avoir touchée, et
   le soulèvement ne voulait donc plus rien dire quand on la survolait enfin.
   Le mouvement est réservé au survol ; l'appel, lui, est une lumière.

   Conséquence technique, et c'est elle qui rend le survol fluide : la pulsation
   ne touche PLUS à « transform ». Une animation qui écrit une propriété la
   confisque — le survol reprenait la main d'un coup, sans transition possible.
   Séparées, chacune fait son travail. */
.col-pioche { cursor: default; }
.col-pioche.vivante { cursor: pointer; }
.col-pioche.vivante span:nth-child(3) { animation: colRespire 1.9s ease-in-out infinite; }
/* Le sol froid vire à l'or et se met à battre */
.col-pioche.vivante::before {
    background: radial-gradient(closest-side, rgba(255, 210, 74, 0.3), transparent 72%);
    animation: colHalo 1.9s ease-in-out infinite;
}
@keyframes colHalo {
    0%, 100% { opacity: 0.35; transform: scale(0.9); }
    50%      { opacity: 1;    transform: scale(1.06); }
}
/* Au survol, la carte du dessus commence à partir : elle se décolle de la pile
   et s'incline, comme une main qui la saisit. On voit alors que c'est CELLE-LÀ
   qu'on va prendre, et non la pile entière. */
.col-pioche.vivante:hover span:nth-child(3) {
    animation: none;
    transform: translate(-0.35rem, -1.15rem) rotate(-6deg);
    border-color: rgba(255, 210, 74, 0.75);
    box-shadow: 0 1.1rem 2rem rgba(0, 0, 0, 0.6), 0 0 1.8rem rgba(255, 210, 74, 0.45);
    color: rgba(255, 210, 74, 0.85);
}
.col-pioche.vivante:hover span:nth-child(2) { transform: translate(0.42rem, 0.42rem) rotate(1.5deg); }
.col-pioche.vivante:hover::before { animation: none; opacity: 1; transform: scale(1.12); }
/* Le retour au repos doit être aussi doux que la montée : sans transition sur
   « ::before », le halo se rétractait d'un coup quand on sortait du paquet. */
.col-pioche::before { transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.2, 0.8, 0.2, 1); }

/* La pastille « +1 » a été retirée : elle posait un carré de plus dans un coin
   déjà chargé, alors que le halo et le soulèvement disent la même chose sans
   rien ajouter à l'écran. */
/* Main pleine : le paquet s'éteint. C'est son tour, mais pas ce geste-là —
   autant que ça se lise sans avoir à cliquer pour l'apprendre. */
.col-pioche.morte { opacity: 0.34; filter: saturate(0.2); }
.col-pioche.morte span:nth-child(3) { animation: none; }
/* Aucune trace de « transform » ici, volontairement : voir plus haut. */
@keyframes colRespire {
    0%, 100% { border-color: rgba(255, 255, 255, 0.14);
               color: rgba(255, 255, 255, 0.32);
               box-shadow: 0 0.5rem 1.2rem rgba(0, 0, 0, 0.5); }
    50%      { border-color: rgba(255, 210, 74, 0.85);
               color: rgba(255, 210, 74, 0.8);
               box-shadow: 0 0.6rem 1.4rem rgba(0, 0, 0, 0.55),
                           0 0 0 0.12rem rgba(255, 210, 74, 0.35),
                           0 0 2.2rem rgba(255, 210, 74, 0.55); }
}

/* Une cible sous le doigt : elle se soulève et s'entoure d'or */
.col-cible {
    outline: 0.14rem solid var(--col-or);
    outline-offset: 0.14rem;
    transform: translateY(-0.5rem) scale(1.04) !important;
    z-index: 30;
}
.col-pioche.col-cible, .col-emplacement.col-cible { transform: scale(1.06) !important; }

/* L'emplacement pulse dès qu'un set est prêt : c'est le seul moment où il sert */
.col-emplacement.prete {
    border-color: var(--col-or);
    color: var(--col-or);
    animation: colPulse 1.5s ease-in-out infinite;
}
@keyframes colPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 210, 74, 0.35); }
    50%      { box-shadow: 0 0 0 0.5rem rgba(255, 210, 74, 0); }
}
/* Et les cartes qui le composent se signalent dans la main */
.col-carte.dans-le-set { outline: 0.11rem solid rgba(255, 210, 74, 0.75); outline-offset: 0.1rem; }

/* ════════ Poser un set : la fusion ════════
   Quand on traîne une carte, ses sœurs de la même série s'aimantent vers elle
   et brillent — on voit le set se rassembler avant même d'avoir lâché. Et
   l'emplacement, lui, aspire : un anneau se resserre vers son centre.

   C'est ce que la barre de boutons ne pouvait pas dire. « Poser » était un mot
   ; ici, le geste montre ce qu'il assemble. */
.col-carte.aimante {
    --lift: -0.55rem;
    border-color: var(--col-or);
    box-shadow: 0 0 0.9rem rgba(255, 210, 74, 0.55), 0 0.4rem 0.9rem rgba(0, 0, 0, 0.5);
    animation: colAimant 0.9s ease-in-out infinite;
    z-index: 15;
}
@keyframes colAimant {
    0%, 100% { filter: brightness(1); }
    50%      { filter: brightness(1.28); }
}
/* Un souffle doré part de la carte traînée vers celles qui la complètent */
.col-carte.aimante::before {
    content: '';
    position: absolute; inset: -0.5rem;
    border-radius: 0.7rem;
    background: radial-gradient(50% 50% at 50% 50%, rgba(255, 210, 74, 0.32), transparent 72%);
    animation: colAimantHalo 0.9s ease-in-out infinite;
    pointer-events: none;
    z-index: -1;
}
@keyframes colAimantHalo {
    0%, 100% { opacity: 0.4; transform: scale(0.92); }
    50%      { opacity: 1;   transform: scale(1.1); }
}

/* L'emplacement aspire quand la carte passe dessus */
.col-emplacement.avale {
    border-style: solid;
    border-color: var(--col-or);
    background: radial-gradient(60% 60% at 50% 50%, rgba(255, 210, 74, 0.22), transparent 72%);
}
.col-emplacement.avale::before {
    content: '';
    position: absolute; inset: -0.9rem;
    border-radius: 50%;
    border: 0.12rem solid rgba(255, 210, 74, 0.7);
    animation: colAvale 0.85s cubic-bezier(0.3, 0, 0.2, 1) infinite;
    pointer-events: none;
}
@keyframes colAvale {
    0%   { transform: scale(1.35); opacity: 0; }
    35%  { opacity: 0.9; }
    100% { transform: scale(0.55); opacity: 0; }
}
.col-emplacement { position: relative; }

/* ════════ L'échange : deux cartes qui se croisent ════════
   Le « transition-group » sait faire entrer et sortir, mais pas montrer qu'une
   carte PREND la place de l'autre. Sans ce croisement, on voyait deux
   changements sans lien : une carte apparaissait dans la main, une autre au
   marché, et rien ne disait qu'elles avaient été troquées.

   Les deux fantômes sont posés sur les vraies positions relevées au moment du
   lâcher, et volent l'un vers l'autre. Ils passent l'un devant l'autre — celui
   qui va vers la main dessus, parce que c'est celui qu'on suit du regard. */
.col-croise {
    position: fixed;
    z-index: 55;
    border-radius: 0.42rem;
    overflow: hidden;
    pointer-events: none;
    box-shadow: 0 0.8rem 1.6rem rgba(0, 0, 0, 0.6);
    transition: transform 0.26s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.26s ease;
}
.col-croise img { width: 100%; height: 100%; object-fit: cover; display: block; }
.col-croise.vers-main { z-index: 56; }
/* Un fantome qu on brise en vol : les eclats prennent le relais, lui s efface */
.col-croise.brisee { opacity: 0; transition: opacity 0.1s ease; }

/* ════════ La carte piochée, en vol ════════
   Elle part du paquet DOS VISIBLE et se retourne en chemin. C'est ce qui relie
   le geste à son résultat : sans ce vol, la carte apparaissait d'un coup dans
   l'éventail, et rien ne disait d'où elle sortait.

   Les deux faces sont posées dos à dos avec « backface-visibility: hidden » :
   à mi-parcours, l'une s'efface exactement quand l'autre paraît. */
.col-vol {
    position: fixed;
    z-index: 60;
    pointer-events: none;
    transform-style: preserve-3d;
    transition: transform 0.58s cubic-bezier(0.22, 0.68, 0.25, 1);
}
.col-vol span {
    position: absolute; inset: 0;
    border-radius: 0.5rem;
    overflow: hidden;
    backface-visibility: hidden;
    border: 0.09rem solid rgba(255, 255, 255, 0.16);
    box-shadow: 0 0.8rem 1.6rem rgba(0, 0, 0, 0.6);
}
.col-vol-face img { width: 100%; height: 100%; object-fit: cover; display: block; }
.col-vol-dos {
    transform: rotateY(180deg);
    background: repeating-linear-gradient(135deg, #1d2733 0 7px, #161d27 7px 14px);
}
/* Sa place l'attend dans l'éventail, vide : sans ça la carte serait à deux
   endroits en même temps, et l'éventail sauterait à l'arrivée du fantôme. */
.col-carte.envol { opacity: 0; }

/* La table tressaille une demi-seconde quand un set éclate. Le décalage est
   minuscule — un demi-caractère — mais c'est ce qui fait qu'on SENT la casse
   au lieu de la regarder. Au-delà, ça devient un tremblement de terre et l'on
   perd des yeux ce qui reste sur le feutre.

   La translation de repos est reprise dans chaque étape : « .col-table » est
   centrée par « translate(-50%, -50%) », qu'une secousse écraserait. */
.col-table.secoue { animation: colSecousse 0.42s cubic-bezier(0.36, 0.07, 0.19, 0.97); }
@keyframes colSecousse {
    0%, 100% { transform: translate(-50%, -50%) rotate(0deg); }
    14%      { transform: translate(calc(-50% - 0.45rem), calc(-50% + 0.22rem)) rotate(-0.45deg); }
    32%      { transform: translate(calc(-50% + 0.5rem),  calc(-50% - 0.28rem)) rotate(0.5deg); }
    52%      { transform: translate(calc(-50% - 0.32rem), calc(-50% - 0.16rem)) rotate(-0.3deg); }
    74%      { transform: translate(calc(-50% + 0.18rem), calc(-50% + 0.12rem)) rotate(0.16deg); }
}

/* ════════ Poser un set : l'éclat de verre ════════
   Les trois cartes filent vers l'emplacement, blanchissent, puis se brisent en
   sept éclats qui partent en étoile. Chaque éclat porte un MORCEAU du portrait
   — un « clip-path » découpé en coin depuis le centre — et non une paillette
   dorée : on doit reconnaître la carte qui vole en morceaux, sinon le geste
   ressemble à un feu d'artifice décoratif.

   C'est le seul instant de gloire du mode : deux ou trois fois par partie. On
   peut donc se permettre huit cents millisecondes, là où la pioche n'en aurait
   pas droit à trois cents. */
.col-brise {
    position: fixed;
    z-index: 62;
    pointer-events: none;
    /* 0,17 s pour rejoindre l'emplacement, pas 0,3 : on sentait un temps mort
       entre la carte posée et la casse. */
    transition: transform 0.17s cubic-bezier(0.4, 0, 0.3, 1), filter 0.2s ease;
}
.col-brise i {
    position: absolute; inset: 0;
    display: block;
    background-size: 100% 100%;
    background-position: center;
    border-radius: 0.1rem;
}
/* Sept coins issus du centre : le patron d'un verre qui casse. Un découpage en
   grille régulière se lisait comme un damier, pas comme une cassure. */
.col-brise i:nth-child(1) { clip-path: polygon(0% 0%,   42% 0%,   50% 50%, 0% 38%);   --a: -135deg; }
.col-brise i:nth-child(2) { clip-path: polygon(42% 0%,  100% 0%,  100% 22%, 50% 50%); --a: -58deg; }
.col-brise i:nth-child(3) { clip-path: polygon(100% 22%, 100% 62%, 50% 50%);          --a: 2deg; }
.col-brise i:nth-child(4) { clip-path: polygon(100% 62%, 100% 100%, 62% 100%, 50% 50%); --a: 55deg; }
.col-brise i:nth-child(5) { clip-path: polygon(62% 100%, 22% 100%, 50% 50%);          --a: 95deg; }
.col-brise i:nth-child(6) { clip-path: polygon(22% 100%, 0% 100%, 0% 72%, 50% 50%);   --a: 138deg; }
.col-brise i:nth-child(7) { clip-path: polygon(0% 72%,  0% 38%,   50% 50%);           --a: 184deg; }

.col-brise.eclate { filter: brightness(2.6); }
.col-brise.eclate i { animation: colEclat 0.46s cubic-bezier(0.15, 0.7, 0.3, 1) forwards; }
.col-brise.eclate i:nth-child(even) { animation-duration: 0.52s; }
@keyframes colEclat {
    0%   { opacity: 1; transform: rotate(var(--a)) translateX(0) rotate(calc(-1 * var(--a))); }
    100% { opacity: 0;
           transform: rotate(var(--a)) translateX(9rem) rotate(calc(-1 * var(--a) + 40deg)) scale(0.55); }
}
/* Le souffle blanc au point d'impact, une fraction de seconde */
.col-souffle {
    position: fixed;
    z-index: 61;
    pointer-events: none;
    border-radius: 50%;
    background: radial-gradient(closest-side, rgba(255, 244, 210, 0.9), rgba(255, 200, 80, 0.35) 55%, transparent 75%);
    animation: colSouffle 0.55s ease-out forwards;
}
@keyframes colSouffle {
    0%   { opacity: 0;   transform: scale(0.25); }
    22%  { opacity: 1;   transform: scale(0.8); }
    100% { opacity: 0;   transform: scale(2.6); }
}

/* La carte qu'on traîne, sous le doigt */
.col-fantome {
    position: fixed;
    z-index: 60;
    width: calc(var(--carte) * 1.14);
    aspect-ratio: 225 / 350;
    border-radius: 0.42rem;
    overflow: hidden;
    pointer-events: none;
    transform: translate(-50%, -50%) rotate(-4deg);
    box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.6);
    opacity: 0.92;
}
.col-fantome img { width: 100%; height: 100%; object-fit: cover; display: block; }
.col-carte.partie { opacity: 0.25; }

/* Les deux gestes qu'on peut faire à un adversaire */
/* Posés dans l'éventail, donc centrés sur les CARTES. Dans la colonne du
   siège, « 50 % » tombait entre le nom et les étoiles, sous les cartes. */
.col-siege-actions {
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    display: flex; gap: 0.4rem;
    opacity: 0; pointer-events: none;
    transition: opacity 0.18s ease;
    z-index: 12;
}
.col-siege.jouable:hover .col-siege-actions,
.col-siege.ouvert .col-siege-actions { opacity: 1; pointer-events: auto; }
.col-siege-actions button {
    width: 2.3rem; height: 2.3rem;
    display: grid; place-items: center;
    color: #17140a;
    background: var(--col-or);
    border: 0; border-radius: 50%;
    cursor: pointer;
    box-shadow: 0 0.3rem 0.8rem rgba(0, 0, 0, 0.55);
    transition: transform 0.15s ease;
}
.col-siege-actions button:hover { transform: scale(1.12); }
.col-siege-actions svg { width: 1.15rem; height: 1.15rem; stroke: currentColor; fill: none; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
/* ⚠️ L opacite porte sur les DOS, pas sur l eventail. Les deux boutons vivent
   DANS l eventail : une opacite posee sur lui s appliquait a toute la branche,
   boutons compris, et ils sortaient a trente-cinq pour cent — illisibles au
   moment precis ou l on veut cliquer dessus. Une opacite d ancetre ne se defait
   pas depuis l enfant, pas plus qu un filtre. On efface donc ce qu il faut
   effacer, et rien de plus. */
.col-siege.jouable:hover .col-eventail .col-dos,
.col-siege.ouvert .col-eventail .col-dos { opacity: 0.35; }

/* ════════ Le marché tourne ════════
   Chaque défausse pousse une carte au marché et en renvoie la plus ancienne
   dans le paquet. Sans transition, la rangée se réécrivait d'un coup et l'on
   ne comprenait pas ce qui venait d'entrer ni ce qui était parti. */
/* ── Le tapis roulant : la fin d'un tour ──
   La carte de gauche s'en va, tout glisse d'un cran, une neuve entre par la
   droite. C'est ce glissement qui dit qu'il reste un tour de moins à chacune —
   la position d'une carte au marché EST son compte à rebours. */
.col-marche-t-enter-active,
.col-marche-t-leave-active { transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.25, 1), opacity 0.35s ease; }
.col-marche-t-enter-from { opacity: 0; transform: translateX(5.5rem); }
.col-marche-t-leave-to   { opacity: 0; transform: translateX(-5.5rem); }
.col-marche-t-leave-active { position: absolute; }
.col-marche-t-move { transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.25, 1); }

/* ── Sur place : un échange ──
   Rien ne glisse, la carte tombe et l'autre descend à sa place. Le mouvement
   est VERTICAL exprès : un troc qui ferait glisser toute la rangée se lirait
   comme une fin de tour, et l'on ne saurait plus lequel des deux on regarde. */
.col-marche-p-enter-active { transition: transform 0.42s cubic-bezier(0.2, 0.9, 0.25, 1), opacity 0.3s ease; }
.col-marche-p-leave-active { transition: transform 0.35s cubic-bezier(0.4, 0, 0.7, 0.3), opacity 0.3s ease; position: absolute; }
.col-marche-p-enter-from { opacity: 0; transform: translateY(-2.6rem) scale(0.9); }
.col-marche-p-leave-to   { opacity: 0; transform: translateY(2.2rem) scale(0.86) rotate(6deg); }
.col-marche-p-move { transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.25, 1); }

/* ════════ La carte piochée ════════
   Elle vient du paquet, en bas à droite, et se retourne en chemin. */
.col-main-t-enter-active,
.col-main-t-leave-active { transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.25, 1), opacity 0.4s ease; }
.col-main-t-enter-from { opacity: 0; transform: translate(13rem, 5rem) rotateY(95deg) scale(0.85); }
.col-main-t-leave-to   { opacity: 0; transform: translateY(-2.5rem) scale(0.9); }
.col-main-t-leave-active { position: absolute; }
.col-main-t-move { transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.25, 1); }
.col-main { position: relative; }

/* ════════ L'entrée en partie ════════
   La table s'ouvre, les mains tombent toutes ensemble, puis le marché
   glisse. Sans ce temps, on découvre une position déjà installée sans
   avoir vu d'où viennent les cartes — et l'on ne comprend pas que le
   marché est commun. */
.col.entree .col-table { animation: colTable 0.5s cubic-bezier(0.2, 0.9, 0.25, 1) both; }
.col.entree .col-siege { animation: colSiege 0.45s ease both; animation-delay: 0.35s; }
.col.entree .col-dos,
.col.entree .col-main .col-carte {
    animation: colDonne 0.42s cubic-bezier(0.2, 0.85, 0.3, 1) both;
    animation-delay: calc(0.5s + var(--i, 0) * 0.05s);
}
.col.entree .col-marche .col-carte {
    animation: colMarche 0.4s cubic-bezier(0.2, 0.85, 0.3, 1) both;
    /* Une seconde de plus après la donne : sans ce temps mort, le marché
       arrivait dans le même mouvement que les mains et l'on ne comprenait pas
       qu'il est commun. */
    animation-delay: calc(1.7s + var(--i, 0) * 0.08s);
}
.col.entree .col-emplacement,
.col.entree .col-pioche { animation: colFondu 0.4s ease both; animation-delay: 2.15s; }

@keyframes colTable {
    from { opacity: 0; transform: translate(-50%, -50%) scale(0.9); }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes colSiege {
    from { opacity: 0; }
    to   { opacity: 1; }
}
/* Les cartes viennent du centre de la table : c'est de là qu'on distribue */
@keyframes colDonne {
    from { opacity: 0; transform: translate(0, -14rem) scale(0.6); }
    to   { opacity: 1; transform: translateY(var(--dy, 0rem)) rotate(var(--rot, 0deg)); }
}
/* Pas de « scale » ici : c'est lui qui faisait tressauter la bordure à la
   dernière image. Une mise à l'échelle épaissit le trait pendant l'animation,
   et le navigateur repeint autrement quand elle se termine — d'où le
   micro-saut. Un simple glissement n'a pas ce défaut. */
@keyframes colMarche {
    from { opacity: 0; transform: translateX(-5rem); }
    to   { opacity: 1; transform: translateY(var(--dy, 0rem)) rotate(var(--rot, 0deg)); }
}
@keyframes colFondu { from { opacity: 0; } to { opacity: 1; } }

/* ── Les feuilles (vol, duel, scan) ───────────────────────────── */
.col-voile {
    position: fixed; inset: 0; z-index: 40;
    background: rgba(4, 4, 8, 0.8);
    display: flex; align-items: flex-end; justify-content: center;
}
.col-feuille {
    width: 100%; max-width: 32rem;
    padding: 1rem 1rem 1.3rem;
    background: linear-gradient(180deg, #16151d, #0c0c10);
    border-top: 0.09rem solid rgba(255, 210, 74, 0.5);
    border-radius: 1.1rem 1.1rem 0 0;
    max-height: 90vh; overflow-y: auto;
}
.col-feuille h3 {
    margin: 0 0 0.15rem;
    font-family: 'Bebas Neue', sans-serif; font-size: 1.2rem; letter-spacing: 0.07em;
    color: var(--col-or);
}
.col-feuille p.aide { margin: 0 0 0.8rem; font-size: 0.68rem; line-height: 1.45; color: rgba(255, 255, 255, 0.42); }
.col-etiquette {
    display: block;
    margin: 0.7rem 0 0.3rem;
    font-family: 'Bebas Neue', sans-serif;
    font-size: 0.68rem; letter-spacing: 0.16em;
    color: rgba(255, 255, 255, 0.28);
}
.col-rangee {
    display: flex; gap: 0.5rem;
    justify-content: safe center;
    overflow-x: auto;
    padding: 0.7rem 0 0.3rem;
}
.col-rangee::-webkit-scrollbar { display: none; }


.col-valider {
    width: 100%; margin-top: 1rem; padding: 0.75rem;
    font: inherit; font-weight: 700; font-size: 0.88rem;
    color: #17140a;
    background: linear-gradient(135deg, #ffe066, #ffb300);
    border: 0; border-radius: 0.65rem;
    cursor: pointer;
}
.col-valider:disabled { opacity: 0.35; cursor: default; }
.col-fermer {
    width: 100%; margin-top: 0.45rem; padding: 0.5rem;
    font: inherit; font-size: 0.7rem; color: rgba(255, 255, 255, 0.45);
    background: none; border: 0; cursor: pointer;
}


/* ── Le vainqueur ─────────────────────────────────────────────── */
/* ── Le classement de fin ──
   On y lisait les cartes du vainqueur en grand. Elles ne disaient rien : on
   venait de les voir se briser, et personne ne veut relire une main qu'il a
   perdue. Ce qu'on cherche à la fin d'une partie, c'est où l'on s'est classé. */
/* Pas de boîte : le classement est POSÉ sur l'écran noir, comme dans les
   autres modes. Un cadre, un fond et une ombre par-dessus un écran déjà vide
   ne délimitaient rien — ils ajoutaient une fenêtre là où il n'y a rien
   d'autre à regarder.

   Elle attend que l'écran ait fini de s'assombrir : une seconde. Sans ce
   temps, on passait de la table au résultat sans avoir vu le coup qui l'avait
   décidé. */
.col-fin-boite {
    width: min(27rem, 92vw);
    display: flex; flex-direction: column; align-items: center;
    gap: 1.2rem;
    opacity: 0;
    transform: translateY(0.8rem);
    transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.2, 0.9, 0.25, 1);
}
.col-fin-boite.vu { opacity: 1; transform: none; }

/* Un intitule discret, dans le registre des autres modes : petites capitales,
   tres espacees, presque eteint. Il nomme ce qu on regarde sans se disputer
   l attention avec la premiere ligne. */
.col-fin-titre {
    font-size: 0.62rem; font-weight: 700;
    letter-spacing: 0.22em; text-transform: uppercase;
    color: rgba(255, 255, 255, 0.32);
}

.col-fin-liste { width: 100%; list-style: none; margin: 0; padding: 0; }
/* Chaque place occupe sa hauteur dès le départ, mais attend son tour : le
   bloc garde donc la même taille du premier au dernier dévoilement. Un filet
   entre les lignes, et rien de plus — pas de cartouche. */
.col-fin-liste li {
    position: relative; overflow: hidden;
    display: flex; align-items: center; gap: 0.8rem;
    padding: 0.7rem 0.2rem;
    border-bottom: 0.06rem solid rgba(255, 255, 255, 0.05);
    opacity: 0;
    transform: translateY(0.55rem);
    transition: opacity 0.4s ease, transform 0.4s cubic-bezier(0.2, 0.9, 0.25, 1);
}
.col-fin-liste li.vu { opacity: 1; transform: none; }
/* Un trait de lumière balaie la ligne au moment où elle paraît */
.col-fin-sweep {
    position: absolute; inset: 0;
    pointer-events: none;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.11), transparent);
    opacity: 0;
}
.col-fin-liste li.vu .col-fin-sweep {
    animation: colFinSweep 0.85s cubic-bezier(0.3, 0.8, 0.2, 1) 0.1s both;
}
@keyframes colFinSweep {
    0%   { opacity: 0; transform: translateX(-100%); }
    30%  { opacity: 1; }
    100% { opacity: 0; transform: translateX(100%); }
}
.col-fin-liste li.premier.vu { animation: colFinChoc 0.7s cubic-bezier(0.2, 1.4, 0.35, 1) both; }
@keyframes colFinChoc {
    0%   { transform: scale(0.92); }
    60%  { transform: scale(1.04); }
    100% { transform: scale(1); }
}
/* Le vainqueur se distingue par la TAILLE et la couleur, pas par un cadre :
   c'est ce que font les autres modes, et un cadre doré autour d'une ligne
   posée sur du noir se lit comme un bouton. */
.col-fin-liste li.premier { padding: 0.95rem 0.2rem; }
.col-fin-liste .rang {
    width: 1.4rem;
    font-family: 'Bebas Neue', sans-serif; font-size: 1.1rem;
    color: rgba(255, 255, 255, 0.32);
}
.col-fin-liste li.premier .rang { font-size: 1.7rem; color: var(--col-or); }
.col-fin-liste .nom {
    flex: 1; min-width: 0;
    text-align: left; font-size: 0.85rem; font-weight: 600;
    color: rgba(255, 255, 255, 0.72);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.col-fin-liste li.premier .nom { font-size: 1.1rem; color: #fff; }
.col-fin-liste li.moi .nom { color: var(--col-or); }
.col-fin-liste .sets { display: flex; gap: 0.22rem; }
.col-fin-liste .sets i {
    width: 0.7rem; height: 0.7rem;
    background: rgba(255, 255, 255, 0.18);
    clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%,
                       50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}
.col-fin-liste .sets i.pleine { background: var(--col-or); }
.col-fin-liste li.premier .sets i { width: 0.95rem; height: 0.95rem; }
/* Le compte a cote des etoiles. Les deux disent la meme chose, et c est
   voulu : les etoiles se lisent d un coup d oeil sur une ligne, le chiffre se
   compare d une ligne a l autre. */
.col-fin-liste .compte {
    display: flex; align-items: baseline;
    min-width: 2.4rem; justify-content: flex-end;
    font-family: 'Bebas Neue', sans-serif;
}
.col-fin-liste .compte b { font-size: 1.25rem; color: rgba(255, 255, 255, 0.7); }
.col-fin-liste .compte i { font-style: normal; font-size: 0.72rem; color: rgba(255, 255, 255, 0.28); }
.col-fin-liste li.premier .compte b { font-size: 1.9rem; color: var(--col-or); }
.col-fin-liste li.premier .compte i { font-size: 0.85rem; }
.col-fin-actions {
    display: flex; gap: 0.6rem; justify-content: center;
    margin-top: 0.4rem;
    opacity: 0; pointer-events: none;
    transition: opacity 0.45s ease;
}
.col-fin-actions.vu { opacity: 1; pointer-events: auto; }

.col-fin {
    position: fixed; inset: 0; z-index: 45;
    animation: colFinVoile 0.9s ease both;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 0.4rem;
    background: radial-gradient(70% 55% at 50% 20%, #1a1710, #08080b 70%);
    text-align: center;
    padding: 2rem 1.2rem;
}
/* L ecran s assombrit d abord, seul : la boite ne vient qu apres. */
@keyframes colFinVoile { from { opacity: 0; } to { opacity: 1; } }


/* ════════ Le vol : on prend, on paie ════════
   Aucune fenêtre, aucun voile. La carte prise se retourne AU MILIEU DU FEUTRE,
   la table reste entière autour, et la main du voleur reste cliquable — c'est
   là qu'il va chercher de quoi payer. C'était le dernier geste du mode qui se
   faisait encore par-dessus la table au lieu de sur elle. */
.col-prise {
    position: fixed; left: 50%; top: 34%;
    transform: translate(-50%, -50%);
    z-index: 44;
    display: flex; flex-direction: column; align-items: center; gap: 0.7rem;
    pointer-events: none;
    /* Le demi-tour doit etre un vrai demi-tour, pas un ecrasement horizontal */
    perspective: 1200px;
    animation: colPriseEntre 0.45s cubic-bezier(0.25, 0.85, 0.3, 1) both;
}
/* Elle VIENT de la main de la cible : « --de-x » et « --de-y » sont posés à
   la volée, en écart par rapport au milieu du feutre. Sans ce trajet, la carte
   apparaissait au centre sans qu'on sache d'où — et c'est précisément d'où
   elle vient qui fait le sel du vol. */
@keyframes colPriseEntre {
    from { opacity: 0.35;
           transform: translate(-50%, -50%) translate(var(--de-x, 0), var(--de-y, 0)) scale(0.42); }
    to   { opacity: 1;
           transform: translate(-50%, -50%) translate(0, 0) scale(1); }
}
.col-prise-carte {
    position: relative;
    /* ⚠️ PAS « var(--carte) » : « .col-prise » est posée en « fixed » HORS de
       « .col », qui porte cette variable. Le calcul était donc invalide, la
       largeur tombait à zéro et la carte n'apparaissait jamais — on la voyait
       « disparaître » alors qu'elle n'avait jamais été dessinée. */
    width: min(13rem, 30vw);
    aspect-ratio: 225 / 350;
    border-radius: 0.6rem;
    /* La perspective vit ici : le retournement doit être un vrai demi-tour, pas
       un écrasement horizontal. */
    transform-style: preserve-3d;
    transform: rotateY(0deg);
    transition: transform 0.62s cubic-bezier(0.32, 0.72, 0.24, 1);
    /* ⚠️ AUCUN « filter » ici. Un filtre force « transform-style: flat » : le
       demi-tour ne se propageait donc plus aux deux faces, « backface-visibility »
       se calculait sur leur seule rotation propre, et le dos restait visible
       quoi qu il arrive. On voyait la carte tourner et ne jamais se montrer.
       L ombre est passee sur les faces, ou elle ne casse rien. */
}
.col-prise-carte.retournee { transform: rotateY(180deg); }
.col-prise-carte > span {
    position: absolute; inset: 0;
    border-radius: 0.55rem;
    backface-visibility: hidden;
    box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.7);
}
.col-prise-dos {
    border: 0.11rem solid rgba(255, 255, 255, 0.2);
    background: repeating-linear-gradient(135deg, #26323f 0 8px, #1b232e 8px 16px);
}

/* ⚠️ PAS d'« overflow: hidden » ici, et c'est tout l'enjeu : la pastille de
   classe déborde du coin, et un débordement caché la coupait net au bord de la
   carte — on en voyait une moitié.
   Il n'y en a pas besoin : un fond est de toute façon rogné par le rayon de
   bordure, et la seule chose qui dépassait vraiment était l'image, à qui l'on
   donne son propre rayon. La pastille ne peut pas vivre ailleurs qu'ici : mise
   sur la carte, elle tournerait avec elle et s'afficherait en miroir. */
.col-prise-face { transform: rotateY(180deg); background: #14131a; border: 0.11rem solid; }
.col-prise-carte.classe-assaut .col-prise-face { border-color: var(--assaut); }
.col-prise-carte.classe-mirage .col-prise-face { border-color: var(--mirage); }
.col-prise-carte.classe-oracle .col-prise-face { border-color: var(--oracle); }
.col-prise-face img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: inherit; }
/* Elle déborde du coin, comme sur les cartes de la main et du marché : posée
   dans l'image, elle passait pour un détail de l'illustration. Et plus grande
   qu'ailleurs — c'est cette classe-là qu'il faut retrouver dans sa main. */
.col-prise-face .col-pion {
    position: absolute; top: -0.85rem; right: -0.85rem;
    width: 2.9rem; height: 2.9rem;
    border-width: 0.22rem;
    /* Elle brûle : un halo propre par-dessus l'ombre portée, et le symbole qui
       rayonne au lieu d'être simplement coloré. */
    box-shadow:
        0 0.15rem 0.4rem rgba(0, 0, 0, 0.65),
        0 0 0.9rem currentColor,
        0 0 2.2rem -0.3rem currentColor;
    z-index: 6;
}
.col-prise-face .col-pion svg {
    width: 1.55rem; height: 1.55rem;
    filter: drop-shadow(0 0 0.35rem currentColor);
}

/* L'onde vit sur un pseudo-élément : on n'animera donc que « transform » et
   « opacity », que le compositeur sait faire sans repeindre. Animer le
   « box-shadow » de la pastille elle-même aurait redessiné à chaque image.
   Un enfant en position absolue n'est pas un élément de grille : il traverse
   le « place-items: center » de la pastille sans le déranger. */
.col-prise-face .col-pion::after {
    content: '';
    position: absolute;
    inset: -0.3rem;
    border: 0.14rem solid currentColor;
    border-radius: 50%;
    opacity: 0;
    pointer-events: none;
}

/* Carte retournée : c'est SA classe qui commande la défausse, et le joueur a
   sept secondes pour trouver la même dans sa main. Autant qu'elle se voie. */
.col-prise-carte.retournee .col-prise-face .col-pion {
    animation: colPionBat 1.3s ease-in-out infinite;
}
.col-prise-carte.retournee .col-prise-face .col-pion::after {
    animation: colPionOnde 1.3s ease-out infinite;
}

@keyframes colPionBat {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.1); }
}
@keyframes colPionOnde {
    0%   { opacity: 0.8; transform: scale(0.85); }
    70%  { opacity: 0;   transform: scale(1.55); }
    100% { opacity: 0;   transform: scale(1.55); }
}
.col-prise-mot {
    padding: 0.3rem 0.8rem;
    font-size: 0.78rem;
    color: rgba(255, 255, 255, 0.65);
    background: rgba(0, 0, 0, 0.7);
    border-radius: 999px;
}
.col-prise-mot b { color: var(--col-or); }

/* ── Pendant le vol, il ne reste que deux choses à regarder ──
   La carte retournée, et sa propre main où trouver la même classe. Tout le
   reste s'efface : le marché, les sièges adverses, la barre du haut, et le
   feutre lui-même.

   ⚠️ Chaque bloc est nommé un par un, et surtout PAS « .col » en entier : un
   filtre sur la racine créerait un bloc conteneur qui casserait le
   « position: fixed » de la carte volée. C'est le piège le plus fréquent de ce
   projet.

   ⚠️ Et le feutre n'est PAS filtré, alors qu'il l'était : « .col-moi » — la
   main du joueur — est un ENFANT de « .col-table ». Le filtre dévalait donc
   jusqu'aux cartes qu'il faut justement voir pour choisir sa défausse, et un
   « filter: none » posé sur l'enfant n'y changeait rien : un filtre d'ancêtre
   ne se défait pas, il s'applique au rendu de toute la branche.
   Le feutre s'assombrit donc par un voile pose sur SON FOND, en « z-index: -1 »
   — ce qui le place au-dessus de son propre dégradé et en dessous de ses
   enfants. Le « transform » de la table en fait un bloc d'empilement, donc le
   voile ne peut pas s'échapper. Et l'on n'animera que « opacity », que le
   compositeur sait faire sans repeindre l'ellipse à chaque image. */
.col.larcin .col-marche,
.col.larcin .col-haut,
.col.larcin .col-siege { filter: brightness(0.22) saturate(0.35); }

.col-marche, .col-haut, .col-siege { transition: filter 0.35s ease; }

.col-table::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: 50%;
    background: rgba(6, 7, 10, 0.78);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.35s ease;
}
.col.larcin .col-table::after { opacity: 1; }

/* ── L'éventail visé : on choisit une PLACE ──
   Les positions ne bougent pas d'un tour à l'autre : le hasard n'en est un que
   pour l'étourdi. Chaque dos bat à son tour pour dire qu'il est prenable. */
.col-eventail.vise { z-index: 24; }
.col-dos.prenable {
    cursor: pointer;
    animation: colPrenable 1.4s ease-in-out infinite;
}
.col-dos.prenable:nth-child(2) { animation-delay: 0.12s; }
.col-dos.prenable:nth-child(3) { animation-delay: 0.24s; }
.col-dos.prenable:nth-child(4) { animation-delay: 0.36s; }
.col-dos.prenable:nth-child(5) { animation-delay: 0.48s; }
.col-dos.prenable .col-dos-verso {
    border-color: rgba(255, 210, 74, 0.75);
    box-shadow: 0 0 0.9rem rgba(255, 210, 74, 0.45);
}
.col-dos.prenable:hover { --lift: -0.6rem; z-index: 30; }
.col-dos.prenable:hover .col-dos-verso {
    border-color: var(--col-or);
    box-shadow: 0 0 1.4rem rgba(255, 210, 74, 0.85);
}
@keyframes colPrenable {
    0%, 100% { filter: brightness(1); }
    50%      { filter: brightness(1.45); }
}

/* ── Ma main, quand je dois payer ──
   Seules les cartes acceptées battent. À dette d'une carte, c'est la classe
   qui trie ; à deux, tout passe — et l'on comprend la différence sans qu'on
   ait à l'écrire. */
.col-carte.exigee {
    cursor: pointer;
    animation: colExigee 1.3s ease-in-out infinite;
}
/* ⚠️ La pulsation prend LA COULEUR DE LA CLASSE, pas l'or du jeu.
   La carte volée s'affiche avec sa bordure de classe ; les cartes qu'on a le
   droit de lâcher sont exactement celles de cette classe. Les faire battre en
   doré coupait le seul lien qui explique la règle — on voyait une carte rouge
   au centre et des cartes dorées en bas, sans rapport visible entre les deux.
   Trois teintes, une par classe, reprises de « --assaut / --mirage / --oracle ». */
.col-carte.classe-assaut { --eclat: 255, 122, 92; }
.col-carte.classe-mirage { --eclat: 167, 139, 250; }
.col-carte.classe-oracle { --eclat: 79, 209, 197; }
@keyframes colExigee {
    0%, 100% { box-shadow: 0 0.3rem 0.7rem rgba(0, 0, 0, 0.5); }
    50%      { box-shadow: 0 0 0 0.14rem rgba(var(--eclat, 255, 210, 74), 0.9),
                           0 0 1.6rem rgba(var(--eclat, 255, 210, 74), 0.6); }
}
.col-carte.lachee { opacity: 0.35; filter: saturate(0.3); }
/* Vol réussi : seule la bonne classe est acceptée. Les autres s'éteignent au
   lieu de rester vives et de se faire cliquer pour rien — la couleur du pion
   est trop petite pour trancher à elle seule. */
.col-carte.horsdette { opacity: 0.32; filter: saturate(0.25) brightness(0.7); }

/* Un tressaillement bref avant que la carte n'éclate : c'est lui qui fait
   qu'on la voit partir plutôt qu'on ne la voit disparaître. */
/* Un seul aller-retour, et court : la carte n a que cent millisecondes a vivre
   avant d eclater, deux passes n auraient jamais le temps de se jouer. */
.col-carte.col-secoue { animation: colSecoueCarte 0.14s cubic-bezier(0.36, 0.07, 0.19, 0.97); }
@keyframes colSecoueCarte {
    0%, 100% { transform: translateY(var(--lift, 0rem)) translateY(var(--dy, 0rem)) rotate(var(--rot, 0deg)); }
    25%      { transform: translateY(var(--lift, 0rem)) translateY(var(--dy, 0rem)) rotate(var(--rot, 0deg)) translateX(-0.35rem); }
    75%      { transform: translateY(var(--lift, 0rem)) translateY(var(--dy, 0rem)) rotate(var(--rot, 0deg)) translateX(0.35rem); }
}

/* La main qui se referme, chez celui qu'on vole : le pendant de l'œil du scan.
   Il ne peut rien y faire, mais il doit le voir arriver. */
.col-pince svg { stroke: rgba(255, 170, 120, 0.9); fill: none; stroke-width: 1.2; }
.col-pince { animation-duration: 1.5s; }


/* ── Écrans étroits ───────────────────────────────────────────── */
@media (max-width: 780px) {
    .col { --carte: 3.5rem; }
    /* La carte prise reste lisible : c est le seul moment ou l on doit
       reconnaitre une classe a coup sur. */
    .col-prise-carte { width: min(9.5rem, 46vw); }
    /* La table se redresse : en 9:16, une ellipse large laisse deux grands
       vides sur les côtés et écrase les sièges du haut. */
    .col-table { width: min(96%, 30rem); aspect-ratio: 1 / 1.02; top: 42%; }
    .col-marche { gap: 0.18rem; }
    /* ⚠️ 1,9 rem et non 1 : le paquet DÉBORDE de sa boîte. Ses deux dos du
       dessous sont décalés de 0,85 rem vers la droite et vers le bas, si bien
       qu'à « right: 1rem » la carte la plus extérieure passait à 0,15 rem du
       bord de l'écran — elle avait l'air coupée. Le retrait doit couvrir le
       décalage avant de commencer à écarter. */
    .col-pioche { right: 1.9rem; bottom: 1.9rem; width: calc(var(--carte) * 1.15); }

    /* Le neon de serie coute cher : un degrade conique se rematricule a chaque
       image, et le halo qui l entoure est un filtre. Sur telephone, jusqu a neuf
       cartes allumees a la fois, cela chauffe pour rien — on garde la course, on
       lache le halo et on ralentit. */
    .col-carte.paire::after  { animation-duration: 2.6s; }
    .col-carte.paire::before { animation-duration: 2.2s; filter: blur(0.3rem); opacity: 0.6; }
    .col-nom { max-width: 4.8rem; font-size: 0.56rem; }
    /* ── La loupe, au doigt ──
       Sur grand ecran elle se pose a gauche, hors du chemin du curseur qui la
       maintient ouverte. Au doigt il n y a pas de chemin a menager : elle se
       serrait contre le bord, rognee a 8,5 rem, et recouvrait a moitie la main
       qu on venait de toucher.
       Elle devient donc un calque : le fond s assombrit, la carte parait au
       milieu, et toucher ailleurs la referme.
       ⚠️ « pointer-events » reste a « none », herite de la regle de base. C est
       ce qui fait marcher la fermeture : sur telephone, toucher un element
       ailleurs envoie un « mouseleave » a la carte survolee, et le doigt doit
       atteindre cet element. Un voile qui prend le clic mangerait le geste —
       il faudrait alors deux touchers pour defausser une carte au lieu d un.
       ⚠️ Pas de « backdrop-filter » : il se recalcule des que quelque chose
       bouge dessous, et il y a jusqu a neuf cartes en neon sur le plateau. Un
       aplat plus opaque coute zero. */
    .col-loupe {
        position: fixed;
        inset: 0;
        left: 0; top: 0;
        width: auto;
        display: grid;
        place-items: center;
        padding: 2rem 1.4rem;
        background: rgba(5, 6, 9, 0.82);
        border-radius: 0;
        box-shadow: none;
        transform: none;
        z-index: 50;
        animation: colLoupeVoile 0.16s ease both;
    }
    .col-loupe-vue {
        width: min(15rem, 62vw);
        box-shadow: 0 1.4rem 3rem rgba(0, 0, 0, 0.7);
        animation: colLoupeCarte 0.22s cubic-bezier(0.2, 0.9, 0.3, 1) both;
    }
    .col-loupe-nom { font-size: 1.15rem; }

    @keyframes colLoupeVoile {
        from { opacity: 0; }
        to   { opacity: 1; }
    }
    @keyframes colLoupeCarte {
        from { opacity: 0; transform: scale(0.9); }
        to   { opacity: 1; transform: none; }
    }
    .col-action { font-size: 0.57rem; padding: 0.5rem 0.1rem; }
    /* Le marché tenait toute la largeur, d'un bord à l'autre. Deux crans de
       moins et la rangée respire — c'est le marché qu'on rogne, pas la main :
       elle est sous le pouce, lui est lointain. */
    .col-marche .col-carte { width: calc(var(--carte) * 0.72); }
    .col-emplacement { width: calc(var(--carte) * 0.72); margin-left: 0.9rem; }

    /* ── Les éventails adverses ──
       Ils gardaient leur taille d'ordinateur. À trois rivaux ça passait ; à
       quatre, les sièges des bouts se touchaient presque et mordaient sur le
       marché. Le recouvrement suit la largeur (le retrait vaut toujours 0,6 ×
       la carte), sinon des cartes plus étroites se chevaucheraient davantage
       et l'éventail se refermerait sur lui-même. */
    .col-dos      { width: calc(var(--carte) * 0.52); margin-left: calc(var(--carte) * -0.31); }
    .col-eventail { padding-left: calc(var(--carte) * 0.31); }
    .col.serre .col-dos      { width: calc(var(--carte) * 0.44); margin-left: calc(var(--carte) * -0.26); }
    .col.serre .col-eventail { padding-left: calc(var(--carte) * 0.26); }

    /* ── Viser une carte, au pouce ──
       C'est le seul geste du mode où l'on doit toucher une carte PRÉCISE chez
       quelqu'un d'autre, et il est irréversible : le vol part au premier
       contact. Or les dos se chevauchent, et à quatre rivaux il ne restait que
       dix pixels de large visibles par carte — on visait la troisième et l'on
       prenait la deuxième.
       Pendant la visée, et pendant elle seule, ils grossissent et se
       recouvrent moins : le pas passe de 10 à 20 px. Cela ne coûte rien au
       reste du temps, et ne vaut QUE pour le voleur — « prenable » n'est posée
       que sur l'éventail qu'il est en train de viser, jamais sur les autres.
       ⚠️ Les deux sélecteurs sont nécessaires : « .col.serre .col-dos » pèse
       trois classes, « .col-dos.prenable » n'en pèse que deux et perdrait. */
    .col-dos.prenable,
    .col.serre .col-dos.prenable {
        width: calc(var(--carte) * 0.62);
        margin-left: calc(var(--carte) * -0.12);
    }
    /* ⚠️ Écarter seul ne suffisait pas : l'éventail du siège de gauche butait
       sur le bord de l'écran, à 6 px près, et l'on ne pouvait pas aller plus
       loin. Le siège visé glisse donc vers le milieu le temps qu'on choisisse
       — « --recentre » vaut ce qu'il faut, et zéro partout ailleurs.
       Il s'ajoute au « translate(-50%, -50%) » qui EXISTE DÉJÀ sur le siège :
       aucun nouveau bloc conteneur n'apparaît, le piège habituel est évité.
       Le siège entier bouge, pseudo compris — pendant une visée la table est
       arrêtée, et ce qui bouge est justement ce qu'on regarde. */
    .col-siege.vise { transform: translate(calc(-50% + var(--recentre, 0px)), -50%); }

    /* ── Le fil, au doigt ──
       Six lignes en permanence sur un écran de téléphone, ce serait un quart
       du feutre pris à la table. Il se replie donc derrière un bouton, posé à
       l'opposé du parchemin des règles — un coin pour ce qu'on consulte, un
       coin pour ce qui se raconte.
       Fermé par défaut : on vient jouer, pas lire. */
    /* Sous le bouton, et non par-dessus : c'est lui qu'on vient de toucher,
       le recouvrir donnerait l'impression de l'avoir perdu. Et serré : au doigt
       on n'y lit pas du coin de l'œil, on ouvre le fil pour le lire, et six
       lignes doivent tenir dans un coin sans manger le feutre. */
    .col-fil-lignes { top: 100%; margin-top: 0.4rem; max-width: 62vw; gap: 0.1rem; }
    .col-fil-bouton {
        display: grid; place-items: center;
        pointer-events: auto;
        width: 2.6rem; height: 2.6rem;
        border: 0.06rem solid rgba(255, 255, 255, 0.12);
        border-radius: 0.7rem;
        background: rgba(255, 255, 255, 0.04);
        color: rgba(255, 255, 255, 0.4);
        cursor: pointer;
        transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
    }
    .col-fil-bouton svg {
        width: 1.25rem; height: 1.25rem;
        fill: none; stroke: currentColor; stroke-width: 1.8;
        stroke-linecap: round; stroke-linejoin: round;
    }
    .col-fil-bouton.ouvert {
        color: var(--col-or);
        border-color: rgba(255, 210, 74, 0.4);
        background: rgba(255, 210, 74, 0.08);
    }
    .col-fil .col-fil-lignes { display: none; }
    .col-fil.ouvert .col-fil-lignes { display: flex; }
    /* Au doigt on ne les lit pas du coin de l'œil, on ouvre le fil pour les
       lire : elles restent serrées, six lignes devant tenir dans un coin
       d'écran sans manger le feutre. */
    .col-fil-ligne { font-size: 0.64rem; line-height: 1.45; }

    /* ── L'attente ──
       « right: -3.9rem » la posait à côté du siège : un décalage pensé pour une
       table d'ordinateur, où il y a de la place à droite. Sur téléphone elle
       partait hors de l'écran pour le siège de droite, et venait se poser sur
       le voisin pour les autres. Elle passe AU-DESSUS du siège, centrée sur
       lui : il y a toujours de la place là, quel que soit le nombre de joueurs. */
    .col-reflechit {
        top: auto; bottom: 100%; right: auto; left: 50%;
        margin-bottom: 0.25rem;
        transform: translateX(-50%);
    }
}

@media (min-width: 1500px) {
    .col { --carte: 5.6rem; }
}
