/* ---------- Jetons -------------------------------------------------- */
:root {
    --paper:        #EFE2CC;
    --paper-hi:     #FBF4E6;
    --paper-deep:   #E1D0B3;
    --ink:          #17120F;
    --ink-2:        #3B302A;
    --ink-mute:     #7C6B5D;
    --red:          #D93B2B;
    --red-deep:     #A5261A;
    --teal:         #17948B;
    --cyan:         #3FC2CE;
    --gold:         #E9A72C;

    --font-display: 'Bricolage Grotesque', 'Trebuchet MS', sans-serif;
    --font-ui:      'Inter', system-ui, -apple-system, sans-serif;
    --font-mono:    'DM Mono', ui-monospace, 'SF Mono', monospace;

    --radius:       14px;
    --radius-sm:    8px;
    --border:       2px solid var(--ink);
    --lift:         4px 4px 0 var(--ink);
    --lift-sm:      3px 3px 0 var(--ink);
    --sidebar-w:    268px;
    --card-w:       186px;
    --acard-w:      122px;
    --tier-min:     116px;
    --tier-label-w: 96px;
    --panel-pad:    22px;
    --ease:         cubic-bezier(.2, .8, .25, 1);
}

*, *::before, *::after { box-sizing: border-box; }

[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

/* Les rayons du décor dépassent volontairement : on les recadre ici. */
html, body { overflow-x: clip; max-width: 100%; }

body {
    margin: 0;
    min-height: 100vh;
    font-family: var(--font-ui);
    font-size: 15px;
    line-height: 1.55;
    color: var(--ink);
    background-color: var(--paper);
    background-image:
        radial-gradient(circle at 10% -12%, rgba(233,167,44,.13), transparent 38%),
        radial-gradient(circle at 98% 2%, rgba(63,194,206,.09), transparent 34%);
    background-attachment: fixed;
}

/* Grain d'impression sur toute la page */
body::after {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 999;
    opacity: .35;
    mix-blend-mode: multiply;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
}

a { color: inherit; }

button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible {
    outline: 3px solid var(--teal);
    outline-offset: 2px;
}

::selection { background: var(--gold); color: var(--ink); }

/* ---------- Typographie --------------------------------------------- */
h1, h2, h3 {
    font-family: var(--font-display);
    font-weight: 800;
    letter-spacing: -.02em;
    line-height: 1.05;
    margin: 0;
}

h1 { font-size: clamp(30px, 4vw, 46px); }
h2 { font-size: clamp(20px, 2.4vw, 26px); }
h3 { font-size: 17px; letter-spacing: -.01em; }

.lede {
    max-width: 62ch;
    color: var(--ink-2);
    margin: 10px 0 0;
}

.mono { font-family: var(--font-mono); font-size: 12px; letter-spacing: .02em; }

/* Aberration chromatique du logotype */
.wordmark {
    font-family: var(--font-display);
    font-weight: 800;
    letter-spacing: -.03em;
    text-shadow: 2px 0 rgba(217, 59, 43, .85), -2px 0 rgba(63, 194, 206, .8);
}

/* ---------- Boutons -------------------------------------------------- */
.btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    border: var(--border);
    border-radius: 999px;
    background: var(--paper-hi);
    color: var(--ink);
    box-shadow: var(--lift-sm);
    font-weight: 600;
    font-size: 14px;
    text-decoration: none;
    cursor: pointer;
    transition: transform .12s var(--ease), box-shadow .12s var(--ease), background .15s;
}

.btn:hover { transform: translate(-1px, -1px); box-shadow: 5px 5px 0 var(--ink); }
.btn:active { transform: translate(3px, 3px); box-shadow: 0 0 0 var(--ink); }

.btn--primary { background: var(--red); color: var(--paper-hi); }
.btn--ink     { background: var(--ink); color: var(--paper-hi); }
.btn--ghost   { background: transparent; box-shadow: none; }
.btn--ghost:hover { background: rgba(23,18,15,.07); box-shadow: none; transform: none; }
.btn--sm      { padding: 7px 13px; font-size: 13px; }
.btn--danger  { background: var(--paper-hi); color: var(--red-deep); }
.btn--danger:hover { background: var(--red); color: var(--paper-hi); }
.btn[disabled] { opacity: .5; pointer-events: none; }

/* ---------- Structure admin ------------------------------------------ */
.shell {
    display: flex;
    min-height: 100vh;
    position: relative;
}

/* La colonne d'encre suit toute la hauteur de la page, pas seulement l'écran. */
.shell::before {
    content: '';
    position: absolute;
    top: 0; bottom: 0; left: 0;
    width: var(--sidebar-w);
    background: var(--ink);
    pointer-events: none;
}

.sidebar {
    position: sticky;
    top: 0;
    align-self: flex-start;
    width: var(--sidebar-w);
    height: 100vh;
    flex: 0 0 var(--sidebar-w);
    display: flex;
    flex-direction: column;
    padding: 22px 18px;
    background: var(--ink);
    color: var(--paper);
    border-right: 3px solid var(--ink);
    z-index: 40;
}

.sidebar::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: .12;
    background: repeating-linear-gradient(
        180deg, rgba(255,255,255,.6) 0 1px, transparent 1px 4px
    );
}

.brand {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-bottom: 20px;
    margin-bottom: 18px;
    border-bottom: 1px dashed rgba(239,226,204,.28);
    text-decoration: none;
}

.brand img {
    width: 46px;
    height: 46px;
    border-radius: 10px;
    border: 2px solid var(--paper);
    object-fit: cover;
}

.brand b { display: block; font-family: var(--font-display); font-size: 19px; letter-spacing: -.02em; }
.brand span { display: block; font-size: 11.5px; color: rgba(239,226,204,.62); letter-spacing: .04em; }

.nav { display: flex; flex-direction: column; gap: 6px; position: relative; }

.nav a {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 11px 14px;
    border-radius: 10px;
    color: rgba(239,226,204,.82);
    text-decoration: none;
    font-weight: 500;
    border: 2px solid transparent;
    transition: background .16s, color .16s, transform .16s var(--ease);
}

.nav a:hover { background: rgba(239,226,204,.09); color: var(--paper-hi); transform: translateX(3px); }

.nav a.is-active {
    background: var(--red);
    border-color: var(--paper);
    color: var(--paper-hi);
    box-shadow: 3px 3px 0 rgba(239,226,204,.9);
}

.nav .is-soon {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 11px 14px;
    border-radius: 10px;
    color: rgba(239,226,204,.42);
    font-weight: 500;
    /* Pas de cercle barré : une entrée « bientôt » n'est pas une faute, elle
       n'existe simplement pas encore. */
    cursor: default;
}

.nav .is-soon em {
    margin-left: auto;
    font-style: normal;
    font-size: 10.5px;
    padding: 2px 7px;
    border: 1px solid rgba(239,226,204,.28);
    border-radius: 999px;
}

.nav svg { width: 19px; height: 19px; flex: none; }

/* ---------- Le pied de la barre latérale ----------------------------------
   Qui je suis, où aller, comment partir. Trois choses de nature différente,
   assez semblables pour former un pied et assez distinctes pour qu'on ne
   clique pas sur « déconnecter » en visant le site public.
   -------------------------------------------------------------------- */

.sidebar-foot {
    margin-top: auto;
    position: relative;
    display: grid;
    gap: 4px;
    padding-top: 16px;
    border-top: 1px dashed rgba(239, 226, 204, .22);
}

/* Le compte : sur deux lignes, le libellé au-dessus du nom. Sur une seule,
   « Connecté : noiz » se lisait comme une phrase, pas comme une identité. */
.session-chip {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
    padding: 8px 10px;
    border-radius: 10px;
    background: rgba(239, 226, 204, .06);
    color: var(--paper);
}

.session-chip small {
    display: block;
    font-size: 10.5px;
    line-height: 1.3;
    color: rgba(239, 226, 204, .5);
    text-transform: uppercase;
    letter-spacing: .06em;
}

.session-chip b { font-size: 13.5px; }

/* La pastille verte dit que la session tient toujours. */
.session-chip i {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--teal);
    box-shadow: 0 0 0 3px rgba(23, 148, 139, .28);
}

.foot-lien {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 8px 10px;
    border-radius: 10px;
    font-size: 13px;
    color: rgba(239, 226, 204, .72);
    text-decoration: none;
    transition: background .15s, color .15s;
}

.foot-lien:hover {
    background: rgba(239, 226, 204, .08);
    color: var(--paper);
}

.foot-lien svg { flex: 0 0 auto; opacity: .7; }
.foot-lien:hover svg { opacity: 1; }

/* La sortie vire au rouge au survol : c'est le seul geste du pied qu'on ne
   veut pas faire par mégarde. */
.foot-lien--sortie:hover {
    background: rgba(200, 62, 44, .16);
    color: #f0a89c;
}

.main { flex: 1; min-width: 0; padding: 34px clamp(18px, 3.4vw, 48px) 72px; position: relative; }

/* Rayons de soleil du logo, en filigrane derrière l'en-tête */
/* Soleil du logo : disque complet, centré, fixé derrière le contenu.
   Il était ancré par le bas, on n'en voyait donc que la moitié haute. */
.main::before, .pub-main::before {
    content: '';
    position: fixed;
    top: 50%;
    left: 50%;
    width: min(1180px, 150vmin);
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: -1;
    opacity: .09;
    background: repeating-conic-gradient(
        from 0deg at 50% 50%,
        var(--red) 0deg 6deg, transparent 6deg 12deg
    );
    -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 5%, transparent 60%);
            mask-image: radial-gradient(circle at 50% 50%, #000 5%, transparent 60%);
}

/* En régie, on recentre sur la zone de travail, colonne déduite. */
.main::before { left: calc(50% + var(--sidebar-w) / 2); }

.page-head {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    align-items: flex-end;
    justify-content: space-between;
    margin-bottom: 30px;
}

.page-head .actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---------- Cartes / panneaux ---------------------------------------- */
.panel {
    background: var(--paper-hi);
    border: var(--border);
    border-radius: var(--radius);
    box-shadow: var(--lift);
    padding: var(--panel-pad);
    position: relative;
}

/* Deux panneaux qui se suivent ont besoin d'air. Les pages qui les rangent
   dans une grille s'en remettent à son « gap » ; celles qui les empilent
   directement n'avaient rien, et les blocs se touchaient. La règle épargne
   les grilles, dont l'espacement est déjà réglé. */
:not(.grid) > .panel + .panel { margin-top: 18px; }

.grid { display: grid; gap: 18px; }
.grid--stats { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.grid--lists { grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); }
.grid--albums { grid-template-columns: repeat(auto-fill, minmax(184px, 1fr)); }

.stat { display: grid; gap: 2px; }
.stat b { font-family: var(--font-display); font-size: 40px; line-height: 1; }
.stat span { color: var(--ink-mute); font-size: 13px; }
.stat .bar { height: 6px; border-radius: 3px; background: var(--paper-deep); margin-top: 10px; overflow: hidden; }
.stat .bar i { display: block; height: 100%; background: var(--red); }

/* ---------- Écran cathodique (pochettes) ------------------------------ */
.crt {
    position: relative;
    aspect-ratio: 1;
    border: var(--border);
    border-radius: 22px / 26px;
    overflow: hidden;
    background: var(--ink-2);
    flex: none;
}

.crt img { width: 100%; height: 100%; object-fit: cover; display: block; }

.crt::after {
    content: '';
    position: absolute;
    inset: 0;
    background:
        repeating-linear-gradient(180deg, rgba(0,0,0,.22) 0 1px, transparent 1px 3px),
        radial-gradient(ellipse at 50% 50%, transparent 52%, rgba(0,0,0,.42) 100%);
    pointer-events: none;
}

.crt--sm { width: 78px; border-radius: 14px / 16px; }

/* ---------- Vignette de tier list ------------------------------------ */
.listcard {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 16px;
    background: var(--paper-hi);
    border: var(--border);
    border-radius: var(--radius);
    box-shadow: var(--lift);
    text-decoration: none;
    transition: transform .16s var(--ease), box-shadow .16s var(--ease);
}

.listcard:hover { transform: translate(-2px, -2px); box-shadow: 7px 7px 0 var(--ink); }
.listcard h3 { margin-bottom: 2px; }
.listcard .meta { color: var(--ink-mute); font-size: 13px; }
.listcard .foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: auto; }

.tag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: 999px;
    border: 1.5px solid var(--ink);
    font-size: 11.5px;
    font-weight: 600;
    background: var(--paper-deep);
}

.tag--live { background: var(--red); color: var(--paper-hi); border-color: var(--red-deep); }
.tag--draft { background: transparent; color: var(--ink-mute); border-color: var(--ink-mute); }

/* « en ordre » : le rouge de « tag--live » dit qu'il se passe quelque chose,
   pas que tout va bien. Il faut une couleur pour l'état sain. */
.tag--ok { background: var(--teal); color: var(--paper-hi); border-color: var(--teal); }

.tag--live i {
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--paper-hi);
    animation: pulse 1.8s infinite;
}

@keyframes pulse { 0%,100% { opacity: 1 } 50% { opacity: .25 } }

/* Barre de progression du classement */
.progress { height: 8px; border: 1.5px solid var(--ink); border-radius: 999px; background: var(--paper); overflow: hidden; display: flex; }
.progress i { display: block; height: 100%; }

/* ---------- Recherche d'album ---------------------------------------- */
.searchbar { position: relative; margin-bottom: 26px; }

.searchbar input {
    width: 100%;
    padding: 18px 20px 18px 54px;
    border: 3px solid var(--ink);
    border-radius: 999px;
    background: var(--paper-hi);
    box-shadow: var(--lift);
    font-size: 17px;
    font-weight: 500;
}

.searchbar input::placeholder { color: var(--ink-mute); font-weight: 400; }
.searchbar svg { position: absolute; left: 20px; top: 50%; transform: translateY(-50%); width: 22px; height: 22px; }

.searchbar .spinner {
    position: absolute; right: 20px; top: 50%; transform: translateY(-50%);
    width: 20px; height: 20px; border-radius: 50%;
    border: 3px solid var(--paper-deep); border-top-color: var(--red);
    animation: spin .7s linear infinite;
    display: none;
}

.searchbar.is-busy .spinner { display: block; }

@keyframes spin { to { transform: translateY(-50%) rotate(360deg) } }

.album {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 0;
    border: var(--border);
    border-radius: var(--radius);
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    cursor: pointer;
    text-align: left;
    overflow: hidden;
    transition: transform .16s var(--ease), box-shadow .16s var(--ease);
}

.album:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--ink); }
.album .crt { border: 0; border-bottom: var(--border); border-radius: 0; }
.album .body { padding: 0 13px 14px; display: grid; gap: 3px; }
.album strong { font-size: 14.5px; line-height: 1.25; }
.album small { color: var(--ink-mute); font-size: 12.5px; }
.album.is-loading { opacity: .55; pointer-events: none; }

/* ---------- Éditeur de tier list ------------------------------------- */
.editor-head {
    display: flex;
    gap: 18px;
    align-items: center;
    flex-wrap: wrap;
    padding: 15px 18px;
    border: var(--border);
    border-radius: var(--radius);
    background: var(--paper-hi);
    box-shadow: var(--lift);
    margin-bottom: 24px;
}

.editor-head .crt { width: 92px; }
.editor-head .info { flex: 1; min-width: 220px; }
.editor-head .info h1 { font-size: clamp(24px, 3vw, 34px); }
.editor-head .info .meta { color: var(--ink-mute); margin-top: 4px; }
.editor-head .side { display: grid; gap: 9px; justify-items: end; }

/* Interrupteur de publication */
.switch { display: inline-flex; align-items: center; gap: 11px; cursor: pointer; font-weight: 600; font-size: 14px; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }

.switch .track {
    width: 54px; height: 30px;
    border: var(--border); border-radius: 999px;
    background: var(--paper-deep);
    position: relative;
    transition: background .2s;
}

.switch .track::after {
    content: '';
    position: absolute; top: 3px; left: 3px;
    width: 20px; height: 20px; border-radius: 50%;
    background: var(--ink);
    transition: transform .22s var(--ease), background .2s;
}

.switch input:checked + .track { background: var(--teal); }
.switch input:checked + .track::after { transform: translateX(24px); background: var(--paper-hi); }
.switch input:focus-visible + .track { outline: 3px solid var(--teal); outline-offset: 3px; }

/* Bandes de rangs — mire de test */
.tiers { display: grid; gap: 12px; }

.tier {
    display: flex;
    align-items: stretch;
    border: var(--border);
    border-radius: var(--radius);
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    overflow: hidden;
    min-height: var(--tier-min);
}

.tier__label {
    flex: 0 0 var(--tier-label-w);
    display: grid;
    place-items: center;
    padding: 6px;
    border-right: var(--border);
    position: relative;
}

.tier__label input {
    width: 100%;
    border: 0;
    background: transparent;
    text-align: center;
    font-family: var(--font-display);
    font-size: 34px;
    font-weight: 800;
    line-height: 1.1;
    color: var(--ink);
    padding: 0;
    border-radius: 6px;
}

.tier__label input:focus { outline: 2px dashed var(--ink); outline-offset: 2px; }

.tier__tools {
    position: absolute;
    left: 50%;
    bottom: 4px;
    transform: translateX(-50%);
    display: flex;
    gap: 5px;
    opacity: 0;
    transition: opacity .16s;
}
.tier:hover .tier__tools, .tier__label:focus-within .tier__tools { opacity: 1; }

.tier__tools button {
    width: 24px; height: 24px;
    display: grid; place-items: center;
    border: 1.5px solid var(--ink);
    border-radius: 6px;
    background: rgba(255,255,255,.55);
    cursor: pointer;
    padding: 0;
}

.tier__tools button:hover { background: var(--ink); color: var(--paper-hi); }
.tier__tools svg { width: 13px; height: 13px; }

.tier__drop, .pool__drop {
    flex: 1;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(var(--card-w), 1fr));
    gap: 10px;
    align-content: start;
    padding: 12px;
    min-height: 92px;
    transition: background .15s;
}

/* Les pochettes gardent une taille fixe : un carré étiré serait laid. */
.tier--albums .tier__drop,
.board .pool__drop,
.pool--albums .pool__drop {
    grid-template-columns: repeat(auto-fill, var(--acard-w));
}

.tier__drop.is-over, .pool__drop.is-over { background: rgba(23,148,139,.13); }

.tier__drop:empty::after, .pool__drop:empty::after {
    content: attr(data-empty);
    align-self: center;
    color: var(--ink-mute);
    font-size: 13px;
    font-style: italic;
}

.tier__letter {
    display: block;
    width: 100%;
    padding: 0 3px;
    text-align: center;
    font-family: var(--font-display);
    font-weight: 800;
    line-height: 1.05;

    /* La taille est calculée d'après la longueur du nom, à l'affichage : un
       « Interlude » doit tenir dans la même case qu'un « S », sans que la
       largeur du rang change d'une ligne à l'autre. */
    font-size: 34px;
    overflow-wrap: anywhere;
}

/* Rangs du classement général : on y range des pochettes */
.tier--albums { min-height: 0; }
.tier--albums .tier__drop { min-height: 108px; }

/* Bloc « tableau » : un classement complet avec son en-tête */
.board {
    padding: 20px;
    border: var(--border);
    border-radius: var(--radius);
    background: rgba(251,244,230,.72);
    box-shadow: var(--lift);
}

.board__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.board .pool { margin-top: 20px; }
.board .pool__head h3 { font-family: var(--font-display); font-size: 16px; }

/* Réserve de titres */
.pool { margin-top: 18px; }

.pool__head {
    display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
    margin-bottom: 9px;
}

.pool__drop {
    border: 2px dashed var(--ink-mute);
    border-radius: var(--radius);
    background: rgba(251,244,230,.6);
    min-height: 56px;
}

/* ---------- Carte titre -----------------------------------------------
   Le titre respire sur deux lignes, la ligne du bas porte durée et écoute.
   Plus généreuse que la version d'une ligne, sans retrouver son ancien
   encombrement : la note ayant quitté la page, la place est disponible. */
.card {
    position: relative;
    width: auto;
    min-width: 0;
    padding: 10px 11px 9px;
    border: var(--border);
    border-radius: 11px;
    background: var(--paper-hi);
    box-shadow: 2px 2px 0 var(--ink);
    cursor: grab;
    touch-action: none;
    user-select: none;
    display: grid;
    gap: 6px;
    align-content: start;
    transition: transform .14s var(--ease), box-shadow .14s var(--ease);
}

.card:hover { transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--ink); }
.card:active { cursor: grabbing; }

.card__top { display: flex; align-items: flex-start; gap: 7px; min-width: 0; }

.card__num {
    flex: none;
    min-width: 22px; height: 22px;
    display: grid; place-items: center;
    padding: 0 5px;
    border-radius: 6px;
    background: var(--ink);
    color: var(--paper-hi);
    font-family: var(--font-mono);
    font-size: 11px;
}

.card__title {
    font-weight: 600;
    font-size: 13.5px;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-width: 0;
}

.card__foot { display: flex; align-items: center; justify-content: space-between; gap: 7px; }
.card__foot .mono { color: var(--ink-mute); font-size: 12px; }
.card__links { display: flex; gap: 5px; }

.card__links a {
    width: 25px; height: 25px;
    display: grid; place-items: center;
    border: 1.5px solid var(--ink);
    border-radius: 50%;
    background: var(--paper);
    transition: background .15s, color .15s, transform .15s;
}

.card__links a:hover { transform: scale(1.12); }
.card__links a.yt:hover { background: var(--red); color: var(--paper-hi); }
.card__links svg { width: 13px; height: 13px; }

/* Carte album : la pochette prime, le texte accompagne */
.acard {
    display: grid;
    align-content: start;
    width: var(--acard-w);
    padding: 6px 6px 8px;
    gap: 4px;
}

.acard .crt { position: relative; width: 100%; border-radius: 10px / 12px; }

.acard b {
    font-size: 12px;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.acard small {
    font-size: 11px;
    color: var(--ink-mute);
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.acard__open {
    position: absolute;
    top: 10px; right: 10px;
    width: 22px; height: 22px;
    display: grid; place-items: center;
    border: 1.5px solid var(--ink);
    border-radius: 50%;
    background: var(--paper-hi);
    opacity: 0;
    transition: opacity .15s, transform .15s;
    z-index: 3;
}

.acard:hover .acard__open, .acard:focus-within .acard__open { opacity: 1; }
.acard__open:hover { transform: scale(1.12); background: var(--gold); }

.slot--album { width: var(--acard-w); height: 152px; }

.card.is-dragging { opacity: .28; }

.card.is-ghost {
    position: fixed;
    z-index: 900;
    pointer-events: none;
    transform: rotate(-3deg) scale(1.05);
    box-shadow: 8px 10px 0 rgba(23,18,15,.35);
    cursor: grabbing;
}

.slot {
    width: auto;
    min-width: 0;
    height: 87px;
    border: 2px dashed var(--teal);
    border-radius: 11px;
    background: rgba(23,148,139,.1);
}

/* ---------- Barre du grand classement --------------------------------- */
.rankbar {
    display: flex;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
    padding: 16px 20px;
    margin-bottom: 20px;
    border: var(--border);
    border-radius: var(--radius);
    background: var(--paper-hi);
    color: inherit;
    box-shadow: var(--lift);
    text-decoration: none;
    position: relative;
    transition: transform .14s var(--ease), box-shadow .14s var(--ease), background .16s;
}

.rankbar:hover { transform: translate(-2px, -2px); box-shadow: 7px 7px 0 var(--ink); background: #fff; }
.rankbar:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); }

.rankbar__title { display: flex; align-items: center; gap: 14px; }
.rankbar__title > svg { color: var(--red); flex: none; }
.rankbar__title b { display: block; font-family: var(--font-display); font-size: 19px; }
.rankbar__title small { display: block; font-size: 12.5px; color: var(--ink-mute); }

.rankbar__stats {
    display: flex;
    gap: 24px;
    margin-left: auto;
    margin-right: 34px;
    font-size: 12.5px;
    color: var(--ink-mute);
}

.rankbar__stats b {
    display: block;
    font-family: var(--font-display);
    font-size: 26px;
    color: var(--ink);
    line-height: 1.1;
}

.rankbar__chevron {
    position: absolute;
    right: 20px;
    display: grid;
    place-items: center;
    color: var(--ink-mute);
    transition: transform .16s var(--ease), color .16s;
}

.rankbar:hover .rankbar__chevron { transform: translate(2px, -2px); color: var(--red); }

/* ---------- Pastille de note (en-tête) --------------------------------- */
.scorebtn {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 7px 13px 7px 8px;
    border: var(--border);
    border-radius: 999px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    cursor: pointer;
    text-align: left;
    transition: transform .14s var(--ease), box-shadow .14s var(--ease);
}

.scorebtn:hover { transform: translate(-1px, -1px); box-shadow: 5px 5px 0 var(--ink); background: #fff; }
.scorebtn:active { transform: translate(2px, 2px); box-shadow: 0 0 0 var(--ink); }

.scorebtn__value {
    display: grid;
    place-items: center;
    min-width: 46px;
    padding: 3px 9px;
    border: 2px solid var(--ink);
    border-radius: 999px;
    background: var(--paper-deep);
    font-family: var(--font-display);
    font-size: 21px;
    transition: background .2s, color .2s;
    font-weight: 800;
    line-height: 1.15;
}

.scorebtn.is-partial .scorebtn__value { background: var(--paper-deep); }

.scorebtn__label { font-size: 12px; font-weight: 600; line-height: 1.25; }
.scorebtn__label em { display: block; font-style: normal; font-weight: 500; color: var(--ink-mute); }

.scorebtn--static { cursor: default; box-shadow: var(--lift-sm); }
.scorebtn--static:hover { transform: none; box-shadow: var(--lift-sm); background: var(--paper-hi); }

/* Avis affiché sous le titre, côté public */
.avis {
    margin: 9px 0 0;
    padding: 8px 12px;
    border-left: 3px solid var(--red);
    background: rgba(225,208,179,.35);
    border-radius: 0 8px 8px 0;
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--ink-2);
    max-width: 68ch;
}

.avis svg { vertical-align: -2px; color: var(--red); }

/* ---------- Note et avis ---------------------------------------------- */
.verdict {
    display: grid;
    grid-template-columns: minmax(170px, 210px) 1fr;
    gap: 20px;
    margin-top: 14px;
}

.verdict__label {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--ink-2);
    text-transform: uppercase;
    letter-spacing: .06em;
}

.verdict__label em {
    font-style: normal;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 500;
    color: var(--ink-mute);
}

.verdict__value { display: flex; align-items: baseline; gap: 8px; margin: 4px 0 6px; }

.verdict__value input, .verdict__value b {
    width: 150px;
    padding: 2px 8px;
    border: 2px dashed transparent;
    border-radius: 10px;
    background: transparent;
    font-family: var(--font-display);
    font-size: 54px;
    font-weight: 800;
    line-height: 1;
    color: var(--red);
}

.verdict__value b { width: auto; border: 0; padding: 0; }
.verdict__value input:hover { border-color: var(--paper-deep); }
.verdict__value input:focus { border-color: var(--ink); outline: none; background: var(--paper); }
.verdict__value span { font-size: 16px; color: var(--ink-mute); font-weight: 600; }

.verdict__hint { font-size: 12.5px; color: var(--ink-mute); margin: 8px 0 0; max-width: 34ch; }

.verdict__review { display: grid; gap: 7px; align-content: start; }
.verdict__review label { display: flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
.verdict__review p { margin: 0; color: var(--ink-2); }

.verdict__review textarea {
    width: 100%;
    padding: 12px 14px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper);
    font-family: var(--font-ui);
    font-size: 14px;
    line-height: 1.45;
    min-height: 62px;
    resize: vertical;
}

.verdict__review textarea:focus { background: #fff; outline: none; box-shadow: var(--lift-sm); }

.verdict--static { grid-template-columns: minmax(150px, 200px) 1fr; background: rgba(251,244,230,.8); }

/* Pastille de note sur les vignettes */
.score-chip {
    display: inline-grid;
    place-items: center;
    min-width: 32px;
    padding: 1px 7px;
    margin-right: 6px;
    border: 1.5px solid var(--ink);
    border-radius: 999px;
    background: var(--gold);
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 800;
}

.acard__score {
    position: absolute;
    left: 6px; bottom: 6px;
    min-width: 30px;
    padding: 1px 6px;
    border: 1.5px solid var(--ink);
    border-radius: 999px;
    background: var(--gold);
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 800;
    z-index: 2;
}

/* ---------- Paramètres -------------------------------------------------- */
.settings { display: grid; gap: 20px; max-width: 760px; margin: 0 auto; }

.linked {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    padding: 12px 16px;
    margin-bottom: 14px;
    border: 1.5px solid var(--ink);
    border-radius: 12px;
    background: var(--paper);
}

.linked img { width: 46px; height: 46px; border-radius: 50%; border: 2px solid var(--ink); object-fit: cover; }
.linked > div { display: grid; gap: 1px; }
.linked b { font-size: 15px; }
.linked .mono { color: var(--ink-mute); }
.linked .btn { margin-left: auto; }

.devbox {
    margin-top: 18px;
    border: 1.5px dashed var(--ink-mute);
    border-radius: 12px;
    background: rgba(225,208,179,.28);
}

.devbox > summary {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 16px;
    cursor: pointer;
    font-weight: 600;
    font-size: 14px;
}

.devbox > summary span {
    font-size: 11px;
    font-weight: 500;
    padding: 2px 8px;
    border: 1px solid var(--ink-mute);
    border-radius: 999px;
    color: var(--ink-mute);
}

.devbox[open] > summary { border-bottom: 1.5px dashed var(--ink-mute); margin-bottom: 14px; }
.devbox > *:not(summary) { padding-left: 16px; padding-right: 16px; }
.devbox > form:last-child { padding-bottom: 16px; }

.copyline {
    padding: 9px 13px;
    border: 1.5px solid var(--ink);
    border-radius: 8px;
    background: var(--paper-hi);
    word-break: break-all;
    font-size: 12.5px;
}

.field .hint { font-weight: 400; color: var(--ink-mute); }

.alert--ok {
    border-color: var(--teal);
    background: rgba(31,158,146,.14);
    color: #0f6b63;
}
.settings .panel h2 { display: flex; align-items: center; gap: 10px; }
.settings .panel > .lede { margin-bottom: 16px; font-size: 14px; }
.settings .panel a { color: var(--red-deep); }

.stack { display: grid; gap: 12px; max-width: 420px; }
.stack h3 { margin-bottom: 2px; }
.stack .row { display: flex; gap: 10px; flex-wrap: wrap; }

.userlist { list-style: none; margin: 0 0 4px; padding: 0; display: grid; gap: 8px; }

.userlist li {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 10px 14px;
    border: 1.5px solid var(--paper-deep);
    border-radius: 10px;
    background: var(--paper);
}

.userlist__name { display: flex; align-items: center; gap: 9px; }
.userlist__actions { display: flex; gap: 8px; margin-left: auto; }

.notice { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.notice .lede { margin-top: 6px; }

/* ---------- Panneau de chaîne (tableau de bord) ------------------------ */
.channel { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.channel.is-live { border-color: var(--red-deep); box-shadow: 4px 4px 0 var(--red-deep); }

.channel__avatar {
    width: 76px; height: 76px;
    border-radius: 50%;
    border: var(--border);
    object-fit: cover;
    flex: none;
}

.channel__body { flex: 1; min-width: 200px; }
.channel__state { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.channel__body h2 { font-size: 20px; }
.channel__body .meta { color: var(--ink-mute); font-size: 13.5px; margin: 4px 0 0; }
.channel__tags { display: flex; gap: 6px; flex-wrap: wrap; margin: 10px 0 0; }
.channel__tags .tag { background: var(--paper); font-weight: 500; }

.channel__thumb {
    position: relative;
    flex: none;
    width: 208px;
    aspect-ratio: 16 / 9;
    border: var(--border);
    border-radius: 12px;
    overflow: hidden;
    box-shadow: var(--lift-sm);
    background: var(--ink);
}

.channel__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.channel__thumb span {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    color: var(--paper-hi);
    background: rgba(23,18,15,.3);
    transition: background .16s;
}

.channel__thumb:hover span { background: rgba(217,59,43,.5); }

/* ---------- Bandeau de direct (site public) ----------------------------
   Placé sous le menu : la marque reste la première chose vue, et le bandeau
   peut apparaître ou disparaître sans faire sauter l'en-tête. */
.livebar {
    background: var(--paper-deep);
    border-bottom: 2px solid var(--ink);
    overflow: hidden;
}

.livebar[data-state="live"] { background: var(--red); color: var(--paper-hi); }

.livebar__inner {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 9px clamp(14px, 4vw, 56px);
    min-height: 42px;
}

.livebar__badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex: none;
    padding: 3px 12px;
    border: 1.5px solid currentColor;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
}

.livebar__badge i { width: 8px; height: 8px; border-radius: 50%; background: currentColor; opacity: .5; }
.livebar[data-state="live"] .livebar__badge i { opacity: 1; animation: pulse 1.6s infinite; }

.livebar__marquee { flex: 1 1 auto; overflow: hidden; min-width: 0; }

.livebar__marquee span {
    display: inline-block;
    white-space: nowrap;
    font-size: 13.5px;
    font-weight: 600;
}

/* Le défilement n'est posé que si le titre déborde : le script ajoute cette
   classe après avoir mesuré. Un titre court restait animé pour rien. */
.livebar__marquee span.defile { animation: marquee 26s linear infinite; }

.livebar:hover .livebar__marquee span.defile { animation-play-state: paused; }

.livebar__meta {
    display: flex;
    align-items: center;
    gap: 16px;
    flex: none;
    margin-left: auto;
    font-size: 12.5px;
    opacity: .9;
}

.livebar__meta span { white-space: nowrap; }
.livebar__meta b { font-family: var(--font-display); font-size: 15px; }

.livebar__cta {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: none;
    padding: 5px 13px;
    border: 1.5px solid currentColor;
    border-radius: 999px;
    font-size: 12.5px;
    font-weight: 600;
    text-decoration: none;
    color: inherit;
    transition: background .15s;
}

.livebar__cta:hover { background: rgba(255,255,255,.22); }

@keyframes marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

/* ---------- Accueil public --------------------------------------------- */
.landing {
    display: grid;
    justify-items: center;
    text-align: center;
    gap: 18px;
    padding: 40px 0 20px;
    position: relative;
}

/*
 * Le cadre s'ajuste à l'écran qu'il entoure.
 *
 * En bloc, il prenait toute la largeur disponible et laissait une bande
 * rouge vide à droite de l'image — le logo paraissait décalé alors qu'il
 * était simplement noyé dans un cadre trop grand.
 */
.landing__tv {
    position: relative;
    width: fit-content;
    margin-inline: auto;
    padding: 16px 16px 26px;
    border: 3px solid var(--ink);
    border-radius: 28px;
    background: var(--red);
    box-shadow: 8px 8px 0 var(--ink);
}

.landing__screen { width: clamp(150px, 34vw, 210px); border-width: 3px; }

.landing__knob {
    position: absolute;
    bottom: 8px;
    width: 12px; height: 12px;
    border-radius: 50%;
    border: 2px solid var(--ink);
    background: var(--gold);
}

.landing__knob:nth-of-type(1) { left: 26%; }
.landing__knob:nth-of-type(2) { left: 40%; background: var(--paper-hi); }

.landing__name { font-size: clamp(34px, 7vw, 62px); margin-top: 6px; }
.landing__lede { text-align: center; }
.landing__actions { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; margin-top: 4px; }

.landing__counts {
    display: flex;
    gap: 34px;
    flex-wrap: wrap;
    justify-content: center;
    margin: 22px 0 0;
    padding: 16px 26px;
    border-top: 2px dashed var(--paper-deep);
    border-bottom: 2px dashed var(--paper-deep);
}

.landing__counts div { display: grid; gap: 2px; }
.landing__counts dt { order: 2; font-size: 12.5px; color: var(--ink-mute); }
.landing__counts dd { order: 1; margin: 0; font-family: var(--font-display); font-size: 34px; line-height: 1; }

.landing__more { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; margin-top: 8px; }

.landing__card {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 13px 20px;
    border: var(--border);
    border-radius: var(--radius);
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    text-decoration: none;
    transition: transform .14s var(--ease), box-shadow .14s var(--ease);
}

.landing__card:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--ink); }
.landing__card.is-soon { opacity: .55; box-shadow: none; border-style: dashed; }
.landing__card em { font-style: normal; font-size: 11px; padding: 2px 8px; border: 1px solid var(--ink-mute); border-radius: 999px; }

.landing__player {
    width: min(880px, 100%);
    margin-top: 26px;
    border: var(--border);
    border-radius: var(--radius);
    background: var(--paper-hi);
    box-shadow: var(--lift);
    overflow: hidden;
    text-align: left;
}

.landing__playerhead {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 12px 16px;
    border-bottom: var(--border);
}

.landing__playerhead b { flex: 1; min-width: 160px; font-size: 15px; }
.landing__playerhead .mono { color: var(--ink-mute); }

.landing__frame { position: relative; aspect-ratio: 16 / 9; background: var(--ink); }
.landing__frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ---------- Suggestions du chat ---------------------------------------- */
.sugg-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; margin-top: 24px; }
.sugg-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.sugg-list.is-muted { opacity: .62; }
.sugg-vide { color: var(--ink-mute); font-style: italic; font-size: 13.5px; }

.sugg {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 9px 11px;
    border: var(--border);
    border-radius: 11px;
    background: var(--paper-hi);
    box-shadow: 2px 2px 0 var(--ink);
}

/* Le bord gauche s'épaissit dès qu'une suggestion est retenue, mais garde
   la couleur d'encre des autres bords tant qu'elle n'est pas en lice : en
   « paper-deep », il se confondait avec le fond et la carte semblait ouverte
   sur la gauche. */
.sugg[data-status="kept"] { border-left-width: 5px; }

/* En lice pour le prochain tirage : nettement distinct des simples retenues. */
.sugg[data-picked="1"] {
    border-left-color: var(--teal);
    background: linear-gradient(90deg, rgba(31,158,146,.13), transparent 32%), var(--paper-hi);
}

.sugg[data-picked="1"] .sugg__text { color: var(--ink); }
.sugg[data-status="kept"][data-picked="0"] .sugg__text { color: var(--ink-2); }

.sugg-bar__counts .is-lice b { color: var(--teal); }

/* Une suggestion qui vient d'arriver se signale, puis rentre dans le rang. */
.sugg.is-new { animation: sugg-arrivee 2.4s var(--ease); }

@keyframes sugg-arrivee {
    0%   { transform: translateX(-14px); opacity: 0; box-shadow: 2px 2px 0 var(--red); }
    12%  { transform: none; opacity: 1; }
    12%, 60% { border-color: var(--red); box-shadow: 3px 3px 0 var(--red); }
    100% { border-color: var(--ink); box-shadow: 2px 2px 0 var(--ink); }
}
.sugg[data-status="discarded"] { box-shadow: none; border-style: dashed; }

.sugg__pick { flex: none; cursor: pointer; display: grid; place-items: center; }
.sugg__pick input { position: absolute; opacity: 0; width: 0; height: 0; }

.sugg__pick span {
    width: 20px; height: 20px;
    display: block;
    border: 2px solid var(--ink);
    border-radius: 6px;
    background: var(--paper);
    position: relative;
}

.sugg__pick input:checked + span { background: var(--teal); }

.sugg__pick input:checked + span::after {
    content: '';
    position: absolute;
    left: 5px; top: 1px;
    width: 5px; height: 10px;
    border: solid var(--paper-hi);
    border-width: 0 2.5px 2.5px 0;
    transform: rotate(45deg);
}

.sugg__pick input:focus-visible + span { outline: 3px solid var(--teal); outline-offset: 2px; }

.sugg__cover {
    flex: none;
    width: 42px; height: 42px;
    display: grid; place-items: center;
    border: 1.5px solid var(--ink);
    border-radius: 8px;
    background: var(--paper-deep);
    overflow: hidden;
    color: var(--ink-mute);
}

.sugg__cover img { width: 100%; height: 100%; object-fit: cover; }

.sugg__body { flex: 1; min-width: 0; display: grid; gap: 1px; }
.sugg__text { font-size: 13.5px; line-height: 1.25; }
.sugg__album { font-size: 12px; color: var(--teal); display: flex; align-items: center; gap: 5px; }
.sugg__album.is-empty { color: var(--ink-mute); font-style: italic; }
.sugg__meta { font-size: 11px; color: var(--ink-mute); }
.sugg__actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

.reception__form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

.reception__form select {
    padding: 8px 12px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper);
    font-size: 13.5px;
    max-width: 320px;
}

/* Recherche d'album dans une fenêtre : plus compacte que la page dédiée */
.searchbar--compact { margin-bottom: 14px; }
.searchbar--compact input { padding: 12px 16px 12px 46px; font-size: 15px; border-width: 2px; }
.searchbar--compact svg { left: 16px; width: 19px; height: 19px; }
.searchbar--compact .spinner { right: 16px; width: 17px; height: 17px; }

#recherche .grid--albums {
    grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
    max-height: 46vh;
    overflow-y: auto;
    padding: 2px;
}

#recherche .album .body { padding: 0 10px 11px; }
#recherche .album strong { font-size: 13px; }
.recherche__etat { color: var(--ink-mute); font-size: 13.5px; margin: 0 0 10px; }
#recherche-source b { font-weight: 700; }

/* Bandeau d'état, en tête de la page roulette */
.sugg-bar {
    display: flex;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
    padding: 11px 16px;
    margin-bottom: 22px;
    border: var(--border);
    border-radius: var(--radius);
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
}

.sugg-bar__state {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    text-align: left;
}

.sugg-bar__state i {
    width: 10px; height: 10px;
    flex: none;
    border-radius: 50%;
    background: var(--ink-mute);
}

.sugg-bar__state[data-active="1"] i { background: var(--red); animation: pulse 1.8s infinite; }
.sugg-bar__state b { display: block; font-size: 14px; }
.sugg-bar__state small { display: block; font-size: 12px; color: var(--ink-mute); }
.sugg-bar__state:hover b { text-decoration: underline; }

.sugg-bar__counts { display: flex; gap: 20px; margin-left: auto; font-size: 12px; color: var(--ink-mute); }
.sugg-bar__counts b { display: block; font-family: var(--font-display); font-size: 21px; color: var(--ink); line-height: 1.1; }

.reglages__bloc { padding: 16px 0; border-bottom: 1.5px dashed var(--paper-deep); }
.reglages__bloc:last-of-type { border-bottom: 0; }
.reglages__bloc h3 { display: flex; align-items: center; gap: 9px; margin-bottom: 5px; }
.reglages__bloc .lede { font-size: 13.5px; margin-bottom: 12px; }

/* ---------- Roulette : plateau de jeu télé ------------------------------ */
.wheel__box {
    position: relative;
    width: min(560px, 100%);
    padding: 18px;
    background: var(--paper-hi);
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    box-shadow: 8px 8px 0 var(--ink);
    overflow: hidden;
    animation: toast-in .22s var(--ease);
}

.wheel__confetti { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 6; }
.wheel__head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.wheel__head .mono { color: var(--ink-mute); margin-left: auto; }

/* Cadre complet pour la source OBS : même facture que les panneaux du site. */
.wheelcard {
    /* Ancré au centre de la source : le recentrage doit venir après la mise
       à l'échelle, sinon un cadre réduit se décale hors cadre. */
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(1);
    transform-origin: center center;
    display: grid;
    justify-items: center;
    gap: 12px;

    padding: 40px 30px 38px;
    border: 4px solid var(--ink);
    border-radius: 20px;
    background:
        radial-gradient(circle at 50% 0%, rgba(233,167,44,.16), transparent 55%),
        var(--paper-hi);
    box-shadow: 10px 10px 0 var(--ink);
}

/*
 * Dans l'incrustation, la carte s'efface.
 *
 * Elle découperait un rectangle opaque en plein direct, et sa marge
 * intérieure ferait réduire toute la scène par le script d'ajustement.
 */
.overlay-body .wheelcard {
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
}

.wheel__stage {
    position: relative;
    aspect-ratio: 1;
    max-width: 400px;
    margin: 26px auto 30px;
    isolation: isolate;
}

/*
 * Dans l'incrustation seulement, la roue prend la place.
 *
 * La console garde la sienne : c'est une page parmi d'autres, avec un menu
 * et des boutons autour. Le sélecteur est doublé pour l'emporter sur
 * « overlay__stage », qui fixe 520 px plus loin dans la feuille.
 */
.overlay-body .wheel__stage.wheel__stage {
    max-width: none;

    /* Le titre occupe le haut ; la roue se pose en dessous sans le
       chevaucher. */
    width: min(62vh, 92vw);
    margin: 0 auto;
}

/*
 * La roue reste au centre.
 *
 * La descendre pour dégager le titre la décalait visiblement ; c'est à la
 * roue de rétrécir un peu, pas de bouger — le centre est sa place.
 */

.wheel__disc, .wheel__ring {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.wheel__disc { z-index: 1; }
.wheel__ring { z-index: 2; }

/* La part gagnante s'illumine à l'arrêt. */
.wheel__disc .part { transition: filter .3s; }
.wheel__disc .part.is-won { animation: part-gagnante 1.5s var(--ease) 3; }

@keyframes part-gagnante {
    0%, 100% { filter: none; }
    50%      { filter: brightness(1.42) saturate(1.2); }
}

/* Ampoules du plateau : alternance lente au repos, rapide pendant le tirage. */

.wheel__pointer {
    position: absolute;
    top: -2.5%;
    left: 50%;
    z-index: 4;
    width: 0; height: 0;
    pointer-events: none;
    transform: translateX(-50%);
    transform-origin: 50% 10%;
    border-left: 9px solid transparent;
    border-right: 9px solid transparent;
    border-top: 26px solid var(--ink);
}

/* Le claquement du pointeur à chaque part qui défile. */
.wheel__pointer.is-tic { animation: pointeur-tic 110ms var(--ease); }

@keyframes pointeur-tic {
    0%   { transform: translateX(-50%) rotate(0deg); }
    40%  { transform: translateX(-50%) rotate(13deg); }
    100% { transform: translateX(-50%) rotate(0deg); }
}

/* Ampoules de la jante : alternance lente au repos, chenillard au tirage. */
.ampoule { opacity: .6; transition: opacity .25s; }
.wheel__stage.is-spinning .ampoule--a { animation: ampoule 300ms steps(1) infinite; }
.wheel__stage.is-spinning .ampoule--b { animation: ampoule 300ms steps(1) infinite reverse; }
.wheel__stage.is-won .ampoule { animation: ampoule 560ms steps(1) infinite alternate; }

@keyframes ampoule {
    0%   { opacity: 1; }
    50%  { opacity: .28; }
    100% { opacity: 1; }
}

/* Stries radiales, très en arrière-plan.
   Deux calques : l'enveloppe gère l'apparition, l'enfant tourne sans fin.
   Sur un seul élément, l'animation de rotation écrasait la mise à l'échelle,
   et l'effet d'ouverture ne se voyait pas. */
.stries {
    position: fixed;
    z-index: -2;
    pointer-events: none;

    /* Un carré, et non le rectangle de l'écran : un cercle inscrit dans un
       rectangle donne une ellipse aplatie, et le motif se voyait comme un
       ovale au moment où il s'ouvre. La diagonale de l'écran est couverte. */
    /*
     * Assez grand pour couvrir la diagonale, pas plus.
     *
     * À 240 vmax, le disque faisait plusieurs milliers de pixels : deux
     * couches floutées y coûtaient si cher que la transition d'ouverture
     * saccadait. Le double de la diagonale suffit à ce qu'aucun bord
     * n'entre dans le cadre.
     */
    /*
     * Juste la diagonale de l'écran.
     *
     * Un dégradé conique est recalculé à chaque image quand il tourne : sa
     * surface se paie directement en fluidité. À 150 vmax on peignait quatre
     * fois plus de pixels que le cadre n'en montre. 118 vmax couvre la
     * diagonale d'un 16/9 sans qu'aucun bord n'entre dans le champ.
     */
    top: 50%;
    left: 50%;
    width: 118vmax;
    height: 118vmax;
    margin: -59vmax 0 0 -59vmax;

    opacity: 0;
    transform: scale(.12);
    transition: opacity .7s var(--ease), transform 1.1s cubic-bezier(.16,.9,.24,1);

    /* Le navigateur prépare la couche à l'avance : sans cela, il la
       recompose à chaque image, flous compris. */
    will-change: transform, opacity;

    /* « overflow » ne suffit pas : l'enfant tourne en permanence, et un
       descendant transformé échappe au rognage arrondi du parent. Le
       découpage explicite, lui, s'applique quoi qu'il arrive. */
    border-radius: 50%;
    overflow: hidden;
    clip-path: circle(50% at 50% 50%);
}

/*
 * Une lueur, plus des rayons.
 *
 * Les faisceaux colorés couvraient tout l'écran : posés sur une incrustation
 * transparente, ils barraient le direct de traits verts et rouges. Une lueur
 * concentrique fait le même travail — attirer l'œil au centre — sans rien
 * masquer de ce qu'il y a derrière.
 */
/*
 * Des rayons de lumière, pas un disque peint.
 *
 * Le beige entre les couleurs remplissait tout : le motif était opaque et
 * cachait le direct. Vide, il laisse passer l'image, et chaque strie devient
 * un faisceau qu'on voit passer devant.
 */
/*
 * Les rayons du décor : une seule couche, sans filtre.
 *
 * Trois calques superposés, chacun flouté puis mis en rotation, faisaient
 * tomber l'affichage à douze images par seconde — l'ouverture saccadait. La
 * mesure est sans appel : la rotation d'un dégradé conique coûte cher, et un
 * « filter » par-dessus double la note.
 *
 * Tout est donc écrit dans le dégradé lui-même. Chaque rayon porte un cœur
 * clair, des flancs colorés et une extinction progressive : c'est le halo,
 * obtenu sans rien flouter. Les couleurs sont poussées à la main, puisqu'il
 * n'y a plus de « saturate » pour les relever.
 */
.stries i {
    display: block;
    position: absolute;
    inset: 0;

    /*
     * Les proportions d'origine : de larges bandes, pas des filaments.
     *
     * Chaque couleur occupe un tiers du pas — un cœur clair, un corps franc,
     * puis une extinction longue qui tient lieu de halo. Les bornes sont
     * doublées à chaque palier pour que le plat reste plat et que seule
     * l'extinction se dégrade.
     */
    background: repeating-conic-gradient(
        from 0deg at 50% 50%,

        /* Le rouge. */
        rgba(255, 176, 150, 1)      0deg,
        rgba(255, 176, 150, 1)   2.4deg,
        rgba(255,  60,  36, .95) 3.2deg,
        rgba(255,  60,  36, .95)   6deg,
        rgba(255,  60,  36, .35)   8deg,
        rgba(255,  60,  36, 0)    10deg,

        /* L'or. */
        rgba(255, 244, 176, 1)    10deg,
        rgba(255, 244, 176, 1)  12.4deg,
        rgba(255, 186,  26, .95) 13.2deg,
        rgba(255, 186,  26, .95)  16deg,
        rgba(255, 186,  26, .35)  18deg,
        rgba(255, 186,  26, 0)    20deg,

        /* Le vert. */
        rgba(190, 252, 220, 1)    20deg,
        rgba(190, 252, 220, 1)  22.4deg,
        rgba( 44, 224, 136, .92) 23.2deg,
        rgba( 44, 224, 136, .92)  26deg,
        rgba( 44, 224, 136, .35)  28deg,
        rgba( 44, 224, 136, 0)    30deg
    );

    /* Promue en couche d'affichage : le navigateur la fait tourner sans la
       repeindre. */
    will-change: transform;
    animation: stries-tourne 55s linear infinite;
}


@keyframes stries-tourne { to { transform: rotate(360deg); } }


@keyframes stries-tourne { to { transform: rotate(360deg); } }

/* Ouverture depuis le centre, fermeture en simple fondu. */
.stries.is-on {
    opacity: .92;
    transform: scale(1);
    transition: opacity .5s var(--ease), transform 1.1s cubic-bezier(.16,.9,.24,1);
}

.stries:not(.is-on) { transition: opacity .8s var(--ease), transform 0s linear .8s; }


@media (prefers-reduced-motion: reduce) {
    .stries i { animation: none; }
    .stries { transition: opacity .4s linear; transform: none; }
}

/* État des liens YouTube d'un album, dans l'en-tête de l'éditeur. */
.ytstate {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 11px;
    border: var(--border);
    border-radius: 999px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    font-family: var(--font-mono);
    font-size: 12px;
    cursor: pointer;
}

.ytstate:hover { transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--ink); }
.ytstate[data-etat="ok"] { background: var(--teal); color: var(--paper-hi); border-color: var(--ink); }
.ytstate[data-etat="partiel"] { background: var(--gold); }
.ytstate[data-etat="vide"] { color: var(--ink-mute); }

/* Bouton réduit à son icône, pour les actions secondaires. */
.btn--icon { padding: 9px 11px; }
.btn--icon svg { margin: 0; }

/* Interrupteur d'origine de la note, dans la fenêtre note et avis. */
.verdict__mode {
    display: inline-flex;
    margin-bottom: 12px;
    border: 2px solid var(--ink);
    border-radius: 999px;
    overflow: hidden;
    background: var(--paper);
}

.verdict__mode button {
    padding: 5px 15px;
    border: 0;
    background: none;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--ink);
    cursor: pointer;
}

.verdict__mode button.is-on { background: var(--ink); color: var(--paper-hi); }

/* Note calculée : lisible, mais visiblement verrouillée. */
.verdict__value input[readonly] {
    border-style: solid;
    background: var(--paper-deep);
    color: var(--ink-2);
    cursor: default;
}

/* Pastille de note : la valeur et un crayon, rien d'autre. */
.scorebtn__pen { display: grid; place-items: center; color: var(--ink-mute); }
.scorebtn:hover .scorebtn__pen { color: var(--ink); }

.scorebtn b {
    width: 7px; height: 7px;
    padding: 0;
    border-radius: 50%;
    background: var(--teal);
    align-self: flex-start;
    margin-left: -4px;
}

/* Explorateur YouTube, dans le cadre du lecteur. */
.player__explore {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px;
    background: var(--paper);
    overflow: hidden;
}

.player__quete { display: flex; gap: 8px; }

.player__quete input {
    flex: 1;
    padding: 9px 13px;
    border: 2px solid var(--ink);
    border-radius: 9px;
    background: var(--paper-hi);
    font-size: 14px;
}

.player__quete-etat { margin: 0; font-size: 12.5px; color: var(--ink-mute); }

.player__resultats {
    flex: 1;
    overflow-y: auto;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 8px;
    align-content: start;
}

.ytres {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper-hi);
    cursor: pointer;
    text-align: left;
}

.ytres:hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 var(--ink); }
.ytres img { width: 96px; height: 54px; object-fit: cover; border-radius: 6px; flex: none; }
.ytres span { min-width: 0; }
.ytres b { display: block; font-size: 12.5px; line-height: 1.25;
           display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ytres small { display: block; font-size: 11px; color: var(--ink-mute); }

/* Historique des tirages */
.histo { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 7px;
         max-height: 52vh; overflow-y: auto; }

.histo li {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 8px 11px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper-hi);
}

.histo .crt { width: 40px; flex: none; }
.histo__corps { flex: 1; min-width: 0; }
.histo__corps b { display: block; font-size: 13.5px; line-height: 1.2; }
.histo__corps small { display: block; font-size: 11.5px; color: var(--ink-mute); }

/* Panneau de correction de l'album, sous le lecteur. */
.player__fix {
    display: flex;
    align-items: flex-end;
    gap: 10px;
    flex-wrap: wrap;
    padding: 12px 18px 14px;
    border-top: var(--border);
    background: var(--paper);
}

.player__fix label { flex: 1; min-width: 300px; font-size: 12px; font-weight: 600; }
.player__fix em { font-style: normal; font-weight: 400; color: var(--ink-mute); }

.player__fix input {
    display: block;
    width: 100%;
    margin-top: 4px;
    padding: 7px 11px;
    border: 2px solid var(--ink);
    border-radius: 8px;
    background: var(--paper-hi);
    font-family: var(--font-mono);
    font-size: 12px;
}

/* Bascule audio d'album / clip officiel, dans le lecteur. */
.player__bascule {
    display: inline-flex;
    flex: none;
    border: 2px solid var(--ink);
    border-radius: 999px;
    overflow: hidden;
    background: var(--paper);
}

.player__bascule button {
    padding: 5px 14px;
    border: 0;
    background: none;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    color: var(--ink);
}

.player__bascule button.is-on { background: var(--ink); color: var(--paper-hi); }

/* Album retenu, posé au milieu de la roue à l'arrêt. */
.wheel__carte {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 8;

    /*
     * Une largeur fixe, pas une part de la roue.
     *
     * En pourcentage, la carte du résultat grandissait avec la roue : agrandir
     * l'une gonflait l'autre, et le texte devenait démesuré.
     */
    width: min(296px, 74vw);
    transform: translate(-50%, -50%);
    display: grid;
    justify-items: center;
    gap: 3px;
    padding: 18px 18px 20px;
    border: 3px solid var(--ink);
    border-radius: 14px;
    background: var(--paper-hi);
    box-shadow: 6px 7px 0 var(--ink);
    text-align: center;
    animation: carte-arrivee .55s cubic-bezier(.2,1.45,.4,1);
}

.wheel__carte .crt { width: 62%; max-width: 190px; margin-bottom: 12px; }

.wheel__carte b {
    font-family: var(--font-display);
    font-size: 19px;
    line-height: 1.15;
    text-shadow: 1.5px 0 rgba(217,59,43,.7), -1.5px 0 rgba(63,194,206,.6);
}

.wheel__carte small { font-size: 13px; color: var(--ink-2); line-height: 1.25; }

.wheel__carte span {
    margin-top: 6px;
    padding: 3px 11px;
    border: 1.5px solid var(--ink);
    border-radius: 999px;
    background: var(--gold);
    font-size: 11.5px;
    font-weight: 600;
}

@keyframes carte-arrivee {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(.7); }
    100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

.wheel__actions { display: flex; gap: 10px; justify-content: center; margin-top: 16px; flex-wrap: wrap; }

.wheel__result {
    text-align: center;
    margin-top: 18px;
    display: grid;
    gap: 4px;
    position: relative;
    z-index: 7;
    animation: victoire .6s cubic-bezier(.2,1.5,.4,1);
}

@keyframes victoire {
    0%   { opacity: 0; transform: translateY(16px) scale(.86); }
    60%  { opacity: 1; }
    100% { opacity: 1; transform: none; }
}

.wheel__label { font-size: 11.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-mute); }

.wheel__result b {
    font-family: var(--font-display);
    font-size: clamp(21px, 4vw, 30px);
    line-height: 1.15;
    text-shadow: 2px 0 rgba(217,59,43,.75), -2px 0 rgba(63,194,206,.7);
}

.wheel__result small { color: var(--ink-mute); font-size: 13px; }
.wheel__result .row { display: flex; gap: 10px; justify-content: center; margin-top: 12px; flex-wrap: wrap; }
.wheel__foot { display: grid; place-items: center; margin-top: 16px; }

@media (prefers-reduced-motion: reduce) {
    .wheel__stage.is-spinning 
}

@media (max-width: 900px) {
    .sugg-cols { grid-template-columns: 1fr; gap: 22px; }
}

@media (max-width: 680px) {
    .sugg-bar { gap: 12px; }
    .sugg-bar__counts { margin-left: 0; gap: 16px; }
    .sugg { flex-wrap: wrap; }
    .sugg__actions { width: 100%; justify-content: flex-start; }
    .reception__form select { max-width: none; width: 100%; }
}

/* ---------- Roulette pour le direct (source OBS) ------------------------
   Fond transparent par défaut : OBS compose la page sur la scène.
   Rien n'est affiché tant qu'aucun tirage n'a été lancé. */
.overlay-body {
    margin: 0;
    min-height: 100vh;
    background: transparent;
    display: grid;
    place-items: center;
    overflow: hidden;
}

/*
 * Un voile sombre pendant l'annonce.
 *
 * Les rayons ne sont plus flous : sur une image claire, leurs couleurs se
 * perdaient. Ce fond léger les fait ressortir sans cacher le direct — on
 * voit encore ce qu'il y a derrière.
 */
.overlay-body .stries::before {
    content: '';
    /* Fixé au cadre : il n'a pas à déborder, et un voile de cent vmax de
       côté coûtait à peindre pour rien. */
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    /* Uniforme : un dégradé faisait paraître les rayons plus faibles sur
       les bords, alors qu'ils y sont aussi vifs qu'au centre. */
    background: rgba(14, 10, 8, .42);
}

/* Sans fond, pas de grain : il n'a aucun sens sur une source transparente. */
.overlay-body::after { display: none; }

/* Avec fond, on reprend tout l'habillage de la régie : papier, lavis et grain. */
.overlay-body.has-paper {
    background-color: var(--paper);
    background-image:
        radial-gradient(circle at 10% -12%, rgba(233,167,44,.13), transparent 38%),
        radial-gradient(circle at 98% 2%, rgba(63,194,206,.09), transparent 34%);
}

.overlay-body.has-paper::after {
    display: block;
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 999;
    opacity: .35;
    mix-blend-mode: multiply;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
}

/* Le soleil du logo, comme derrière les pages de la régie. */
.overlay-body.has-paper::before {
    content: '';
    position: fixed;
    top: 50%; left: 50%;
    width: min(1180px, 150vmin);
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: -1;
    opacity: .09;
    background: repeating-conic-gradient(
        from 0deg at 50% 50%,
        var(--red) 0deg 6deg, transparent 6deg 12deg
    );
    -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 5%, transparent 60%);
            mask-image: radial-gradient(circle at 50% 50%, #000 5%, transparent 60%);
}

.overlay {
    display: grid;
    justify-items: center;
    gap: 20px;
    padding: 0;
    opacity: 0;
    transform: scale(.94);
    transition: opacity .5s var(--ease), transform .5s var(--ease);
    pointer-events: none;
}

.overlay.is-visible { opacity: 1; transform: scale(1); }

.overlay__stage {
    position: relative;
    width: min(62vh, 62vw, 520px);
    aspect-ratio: 1;
}

.overlay__confetti { position: absolute; inset: -40%; width: 180%; height: 180%; pointer-events: none; z-index: 4; }

.overlay__stage { max-width: none; width: 520px; margin-bottom: 26px; }
.overlay__disc { filter: drop-shadow(5px 7px 0 rgba(23,18,15,.5)); }
.overlay__pointer { border-left-width: 17px; border-right-width: 17px; border-top-width: 38px; }

.overlay__result {
    position: relative;
    z-index: 5;
    display: grid;
    justify-items: center;
    gap: 2px;
    padding: 12px 24px;
    width: 100%;
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    background: var(--paper-hi);
    box-shadow: 7px 7px 0 var(--ink);
    text-align: center;
    max-width: min(84vw, 620px);
    animation: toast-in .34s var(--ease);
}

.overlay__label {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.overlay__result b {
    font-family: var(--font-display);
    font-size: 30px;
    line-height: 1.12;
    text-shadow: 2px 0 rgba(217,59,43,.75), -2px 0 rgba(63,194,206,.7);
}

.overlay__result { animation: victoire .6s cubic-bezier(.2,1.5,.4,1); }

.overlay__result small { color: var(--ink-2); font-size: 14px; }

/* Adresse de la source, dans la régie */
.overlay-link { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 12px; }

.overlay-link input {
    flex: 1;
    min-width: 220px;
    padding: 7px 11px;
    border: var(--border);
    border-radius: 9px;
    background: var(--paper);
    font-family: var(--font-mono);
    font-size: 12px;
}

/* ---------- Plein écran ------------------------------------------------
   Tout ce qui relève de la régie disparaît : il ne reste que le classement,
   de quoi le montrer sans montrer les commandes. */
.is-fullscreen .sidebar,
.is-fullscreen .hors-plein,
.is-fullscreen .saver { display: none !important; }

.is-fullscreen .main { margin-left: 0; padding: 16px clamp(16px, 3vw, 46px) 28px; }

/* La colonne du menu doit disparaître de la grille, pas seulement son
   contenu : sinon il reste une bande sombre sur toute la hauteur. */
/* Le fond sombre de la colonne du menu est peint par un décor du conteneur,
   pas par le menu lui-même : le masquer ne suffisait pas. */
.is-fullscreen .shell::before { display: none; }

/* La barre du haut ne garde que le bouton de sortie, calé à droite. */
.is-fullscreen .main > .page-head:first-of-type { margin-bottom: 10px; justify-content: flex-end; }

/* Le bouton de sortie reste discret jusqu'au survol. */
.is-fullscreen #fullscreen { opacity: .25; transition: opacity .18s; }
.is-fullscreen #fullscreen:hover,
.is-fullscreen #fullscreen:focus-visible { opacity: 1; }

/* ---------- Notifications -------------------------------------------- */
.toasts { position: fixed; right: 20px; bottom: 20px; z-index: 950; display: grid; gap: 10px; justify-items: end; }

.toast {
    display: flex; align-items: center; gap: 9px;
    padding: 11px 17px;
    border: var(--border);
    border-radius: 999px;
    background: var(--ink);
    color: var(--paper-hi);
    box-shadow: var(--lift);
    font-size: 13.5px;
    font-weight: 500;
    animation: toast-in .28s var(--ease);
}

.toast--ok i { width: 8px; height: 8px; border-radius: 50%; background: var(--teal); }
.toast--err { background: var(--red); }
.toast.is-out { animation: toast-out .25s var(--ease) forwards; }

@keyframes toast-in  { from { opacity: 0; transform: translateY(12px) } }
@keyframes toast-out { to { opacity: 0; transform: translateY(8px) } }

/* Indicateur de sauvegarde */
.saver { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--ink-mute); }
.saver i { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-mute); transition: background .2s; }
.saver.is-saving i { background: var(--gold); animation: pulse 1s infinite; }
.saver.is-saved i { background: var(--teal); }

/* ---------- Fenêtre modale ------------------------------------------- */
.modal { position: fixed; inset: 0; z-index: 960; display: none; place-items: center; padding: 20px; }
.modal.player { padding: 16px; }

/* Une fenêtre large, pour montrer beaucoup de pochettes à la fois. */
.modal--large .modal__box { max-width: 900px; width: 100%; }
.modal__corps {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;

    /* Un peu d'air au bord du conteneur qui défile.
       Sans lui, un bouton collé au bord se fait rogner : son ombre, son
       liseré de survol et son cerclage de focus dépassent du cadre et sont
       coupés net. Le retrait négatif rend cet espace, pour que le contenu
       reste aligné sur le titre et le pied. */
    padding: 5px 6px;
    margin: 0 -6px;
}

/* Une liste ouverte dans la modale doit pouvoir en dépasser.
   C'est « .modal__box » qui la coupait, pas « .modal__corps » : son
   « overflow: auto » tronquait la liste au bord de la boîte. Le temps qu'elle
   est ouverte, la boîte laisse déborder ; elle retrouve son défilement dès
   qu'on referme. */
.modal__box:has(.sugg-viewer__liste:not([hidden])) { overflow: visible; }

/* Voile du lecteur : sombre, pour isoler la vidéo du reste.
   Sans flou : il coûte cher à calculer sur toute la surface de l'écran, et
   fait saccader l'ouverture sur les machines modestes. Un fond assez opaque
   isole tout aussi bien. */
.modal.player .modal__veil {
    background: rgba(18, 14, 11, .86);
    cursor: default;
}

/* Bouton de correction, réduit à son signe. */
.player__head .btn--icon {
    padding: 6px 11px;
    font-size: 16px;
    line-height: 1;
}

/* Le grain d'impression est peint par-dessus toute la page. Sur la roue, il
   multipliait les couleurs et les rendait plus sombres qu'à l'écran du live :
   on le suspend le temps du tirage, pour que les deux soient identiques. */
body.roulette-ouverte::after { display: none; }

/* La régie n'a pas besoin du fond de scène : il fatiguait l'œil et faussait
   la lecture des couleurs de la roue. */
.modal.wheel .modal__veil { z-index: 1; }
.modal.wheel .wheel__box { z-index: 2; }
.modal.is-open { display: grid; }
.modal__veil { position: absolute; inset: 0; background: rgba(23,18,15,.62); }

.modal__box {
    position: relative;
    width: min(430px, 100%);
    padding: 26px;
    background: var(--paper-hi);
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    box-shadow: 8px 8px 0 var(--ink);
    animation: toast-in .22s var(--ease);

    /* Une fenêtre plus haute que l'écran devient illisible : on la borne.
       L'ombre portée impose une marge à droite et en bas, sinon elle serait
       rognée.

       La boîte se partage en trois : le titre et le pied ne bougent pas,
       seul le corps défile. Elle défilait auparavant d'un bloc, et les
       boutons du bas sortaient de l'écran dès que le contenu était long —
       on ne pouvait alors ni valider ni fermer. */
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - 40px);
    max-height: calc(100dvh - 40px);
    overscroll-behavior: contain;
    margin: 0 10px 10px 0;
}

.modal__box--large { width: min(760px, 100%); }

/* La page ne doit pas défiler derrière la fenêtre : on la fige le temps
   que la fenêtre est ouverte. */
/* Le fond ne glisse plus tant qu'une fenêtre est ouverte.

   « position: fixed » plutôt que le seul « overflow: hidden » : sur iOS,
   celui-ci ne suffit pas et la page continue de bouger derrière. La largeur
   est maintenue pour que le contenu ne se réorganise pas au moment où la
   barre de défilement disparaît. */
body.modal-ouverte {
    overflow: hidden;
    width: 100%;
}

@media (max-width: 560px) {
    .modal { padding: 12px; }
    .modal__box { padding: 18px; box-shadow: 5px 5px 0 var(--ink); }
}
.modal__box p { color: var(--ink-2); }
/* Le pied reste visible quoi qu'il arrive au contenu.
   « flex-shrink: 0 » et le fond opaque : sans eux, un corps qui déborde le
   comprimait puis le poussait hors de la boîte, et l'on ne pouvait plus ni
   valider ni fermer. */
.modal__box .row {
    display: flex;
    flex-shrink: 0;
    gap: 10px;
    justify-content: flex-end;
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid var(--paper-deep);
    background: var(--paper-hi);
}

/* ---------- Nuancier des rangs ---------------------------------------- */
.nuancier {
    position: fixed;
    z-index: 970;
    display: none;
    width: 268px;
    padding: 12px;
    border: 3px solid var(--ink);
    border-radius: 14px;
    background: var(--paper-hi);
    box-shadow: 6px 6px 0 var(--ink);
}

.nuancier.is-open { display: block; animation: toast-in .16s var(--ease); }

.nuancier__grille {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: 6px;
}

.nuancier__teinte {
    aspect-ratio: 1;
    padding: 0;
    border: 2px solid var(--ink);
    border-radius: 7px;
    cursor: pointer;
    transition: transform .12s var(--ease), box-shadow .12s var(--ease);
}

.nuancier__teinte:hover { transform: translate(-1px, -1px) scale(1.08); box-shadow: 2px 2px 0 var(--ink); }
.nuancier__teinte.is-active { box-shadow: 0 0 0 2px var(--paper-hi), 0 0 0 4px var(--ink); }

.nuancier__libre {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 12px;
    padding-top: 11px;
    border-top: 1.5px dashed var(--ink-mute);
}

.nuancier__apercu {
    width: 26px; height: 26px;
    flex: none;
    border: 2px solid var(--ink);
    border-radius: 7px;
}

.nuancier__libre input {
    flex: 1;
    min-width: 0;
    padding: 6px 9px;
    border: 2px solid var(--ink);
    border-radius: 7px;
    background: var(--paper);
    font-family: var(--font-mono);
    font-size: 12.5px;
    text-transform: uppercase;
}

.nuancier__libre input:focus { background: #fff; outline: none; }

/* Les outils du rang restent visibles tant que le nuancier est ouvert. */
.tier.is-picking .tier__tools { opacity: 1; }

/* ---------- Lecteur intégré -------------------------------------------- */
.player__box {
    position: relative;
    /* Dimensionné par la hauteur disponible : une vidéo 16/9 large déborderait
       sinon par le bas sur un écran peu haut. */
    width: min(1560px, 96vw, calc((100vh - 150px) * 16 / 9));
    background: var(--paper-hi);
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    box-shadow: 8px 8px 0 var(--ink);
    overflow: hidden;
    animation: toast-in .22s var(--ease);
}

.player__head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 13px 18px;
    border-bottom: var(--border);
}

.player__head > div { flex: 1; min-width: 0; }
.player__head b { display: block; font-size: 17px; line-height: 1.2; font-family: var(--font-display); }
.player__head small { display: block; font-size: 12.5px; color: var(--ink-mute); }

.player__found {
    display: block;
    font-style: normal;
    font-size: 12px;
    color: var(--teal);
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Diagnostic d'accès, dans les réglages */
.diag { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 12px 0; }
.diag__resultat { font-size: 12.5px; color: var(--ink-mute); flex: 1; min-width: 200px; }
.diag__resultat[data-etat="ok"] { color: #0f6b63; font-weight: 500; }
.diag__resultat[data-etat="ko"] { color: var(--red-deep); font-weight: 500; }
.player__frame { position: relative; aspect-ratio: 16 / 9; background: var(--ink); }
.player__frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.player__vide {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    margin: 0;
    padding: 28px;
    text-align: center;
    color: var(--paper);
    font-size: 14px;
    line-height: 1.5;
}

.player__head .btn { flex: none; }

.card__links a.is-loading { opacity: .45; pointer-events: none; }

/* ---------- État vide ------------------------------------------------- */
.empty {
    display: grid;
    justify-items: center;
    gap: 14px;
    text-align: center;
    padding: 56px 24px;
    border: 2px dashed var(--ink-mute);
    border-radius: var(--radius);
    background: rgba(251,244,230,.78);
}

.empty p { max-width: 44ch; color: var(--ink-mute); margin: 0; }

/* ---------- Connexion ------------------------------------------------- */
.login {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 24px;
    position: relative;
}

.login::before {
    content: '';
    position: absolute; inset: 0;
    pointer-events: none;
    opacity: .11;
    background: repeating-conic-gradient(from 0deg at 50% 42%, var(--red) 0deg 6deg, transparent 6deg 12deg);
    -webkit-mask-image: radial-gradient(circle at 50% 42%, #000 8%, transparent 62%);
            mask-image: radial-gradient(circle at 50% 42%, #000 8%, transparent 62%);
}

.login__box {
    position: relative;
    width: min(392px, 100%);
    padding: 34px 30px;
    background: var(--paper-hi);
    border: 3px solid var(--ink);
    border-radius: 20px;
    box-shadow: 8px 8px 0 var(--ink);
    text-align: center;
}

.login__box img { width: 92px; height: 92px; border-radius: 18px; border: 3px solid var(--ink); margin-bottom: 16px; }
.login__box h1 { font-size: 30px; }
.login__box p { color: var(--ink-mute); font-size: 14px; margin: 6px 0 24px; }

.field { display: grid; gap: 6px; text-align: left; margin-bottom: 14px; }
.field label { font-size: 12.5px; font-weight: 600; color: var(--ink-2); }

.field input {
    padding: 12px 15px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper);
    font-size: 15px;
}

.field input:focus { background: #fff; }

.alert {
    display: flex; align-items: center; gap: 9px;
    padding: 11px 14px;
    border: 2px solid var(--red-deep);
    border-radius: 10px;
    background: rgba(217,59,43,.12);
    color: var(--red-deep);
    font-size: 13.5px;
    font-weight: 500;
    margin-bottom: 16px;
    text-align: left;
}

/* ---------- Site public ---------------------------------------------- */
.pub-header {
    position: relative;
    padding: 22px clamp(18px, 4vw, 56px) 18px;
    border-bottom: 3px solid var(--ink);
    background: var(--ink);
    color: var(--paper);
    display: flex;
    align-items: center;
    /* Les liens du menu se resserrent avant que quoi que ce soit passe à la
       ligne : logo, menu, butin et compte totalisent quelques dizaines de
       pixels de trop sur une barre ordinaire. */
    gap: 14px;
    flex-wrap: wrap;
    justify-content: space-between;
}

.pub-header::before {
    content: '';
    position: absolute; inset: 0;
    opacity: .1;
    pointer-events: none;
    background: repeating-linear-gradient(180deg, rgba(255,255,255,.7) 0 1px, transparent 1px 4px);
}

.pub-header .brand { border: 0; padding: 0; margin: 0; }

/* Le menu est centré sur la barre, pas sur ce qui reste entre le logo et le
   bloc de droite.

   Ces deux-là n'ont jamais la même largeur — logo 182 px, bouton de connexion
   151, nom de compte 100 — et le menu glissait donc d'un côté ou de l'autre
   selon qu'on était connecté ou non. Le sortir du flux le rend indifférent à
   ses voisins.

   Il reste sous eux dans l'ordre d'empilement : si la barre est trop étroite
   pour les trois, ce sont les liens du menu qui passent dessous, pas le nom
   de compte. */
/* Le menu se centre sans s'étendre.

   Avec « flex: 1 » il réclamait toute la place libre — 1160 px sur une barre
   de 1440 — et poussait le butin puis le nom de compte chacun sur sa propre
   ligne. En ne prenant que sa largeur, les trois tiennent de front, et les
   marges automatiques le centrent quand même.

   Le décalage d'origine venait d'ailleurs : une règle du bloc « Comptes
   visiteurs », plus bas dans la feuille, imposait « justify-content:
   flex-end » et collait les liens à droite. Elle a été retirée. */
.pub-header__menu {
    display: flex;
    flex: 0 1 auto;
    align-items: center;
    justify-content: center;
    gap: 12px;
    flex-wrap: wrap;
    margin: 0 auto;
    min-width: 0;
}

/* Sans bloc de droite — Twitch pas configuré, par exemple — une réserve
   vide tient la place, sinon le menu glisse vers la droite. Elle disparaît
   dès qu'il y a un compte ou un bouton de connexion.

   Tenter d'égaliser les largeurs du logo et du bloc de droite a été essayé :
   ça écrasait le nom du site sur quatre lignes. */
.pub-header::after {
    content: '';
    flex: 1 1 0;
}

.pub-header:has(.pub-compte)::after,
.pub-header:has(.pub-connexion)::after { display: none; }

.pub-header__side { display: flex; align-items: center; gap: 10px; }

.pub-header .burger { display: none; }

.pubnav { display: flex; gap: 2px; align-items: center; flex-wrap: wrap; }

.pubnav a, .pubnav .is-soon {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    border-radius: 999px;
    border: 2px solid transparent;
    color: rgba(239,226,204,.84);
    text-decoration: none;
    font-weight: 600;
    font-size: 14px;
    transition: background .16s, color .16s;
}

.pubnav a:hover { background: rgba(239,226,204,.1); color: var(--paper-hi); }

.pubnav a.is-active {
    background: var(--red);
    border-color: var(--paper);
    color: var(--paper-hi);
}

.pubnav .is-soon { color: rgba(239,226,204,.4); cursor: default; }
.pubnav .is-soon em {
    font-style: normal;
    font-size: 10.5px;
    padding: 2px 7px;
    border: 1px solid rgba(239,226,204,.26);
    border-radius: 999px;
}
.pub-header .brand img { border-color: var(--paper); }

/* Le pied de page reste en bas.
   Sur les pages courtes il remontait au milieu de l'écran : la colonne prend
   maintenant toute la hauteur, et le contenu s'étire pour occuper ce qui
   reste. */
body:has(.pub-main) {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.pub-main {
    flex: 1;
    padding: 34px clamp(18px, 4vw, 56px) 80px;
    position: relative;
}

.pub-hero { margin-bottom: 26px; }

.live-dot {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 5px 13px;
    border: 2px solid var(--paper);
    border-radius: 999px;
    font-size: 12px; font-weight: 600;
    color: var(--paper);
}

.live-dot i { width: 8px; height: 8px; border-radius: 50%; background: var(--red); animation: pulse 1.8s infinite; }

.pub-footer {
    padding: 26px clamp(18px, 4vw, 56px);
    border-top: 2px dashed var(--ink-mute);
    color: var(--ink-mute);
    font-size: 13px;
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
    justify-content: space-between;
}

/* Cartes titres en lecture seule */
.card--static { cursor: default; touch-action: auto; }
.card--static:hover { transform: none; box-shadow: 2px 2px 0 var(--ink); }

/* ---------- Barre mobile --------------------------------------------- */
.mobilebar {
    display: none;
    position: sticky;
    top: 0;
    z-index: 50;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    background: var(--ink);
    color: var(--paper);
    border-bottom: 3px solid var(--ink);
}

.mobilebar img { width: 34px; height: 34px; border-radius: 8px; }
.mobilebar b { font-family: var(--font-display); }

.burger {
    margin-left: auto;
    width: 40px; height: 40px;
    display: grid; place-items: center;
    border: 2px solid var(--paper);
    border-radius: 9px;
    background: transparent;
    color: var(--paper);
    cursor: pointer;
}

/* ---------- Adaptatif ------------------------------------------------- */
@media (max-width: 900px) {
    .mobilebar { display: flex; }

    .shell { flex-direction: column; }
    .shell::before { display: none; }

    .sidebar {
        position: fixed;
        inset: 0 auto 0 0;
        height: 100vh;
        transform: translateX(-100%);
        transition: transform .26s var(--ease);
        box-shadow: 0 0 0 100vmax rgba(23,18,15,0);
    }

    .sidebar.is-open { transform: none; box-shadow: 0 0 0 100vmax rgba(23,18,15,.55); }

    .main { padding: 22px 16px 64px; }
    .editor-head .side { justify-items: start; }

    /* En-tête public : le menu se replie sous le logo */
    .pub-header { padding: 14px 16px; gap: 12px; }
    .pub-header .brand img { width: 40px; height: 40px; }
    /* Le tiroir du bas remplace ce bouton sur mobile : deux entrées vers
       le même menu ne font qu'encombrer l'en-tête. */
    .pub-header .burger { display: none; }

    .pub-header__menu {
        display: none;
        width: 100%;
        flex-direction: column;
        align-items: stretch;
        gap: 12px;
        padding-top: 12px;
        border-top: 1px dashed rgba(239,226,204,.24);
    }

    .pub-header__menu.is-open { display: flex; }
    .pubnav { flex-direction: column; align-items: stretch; gap: 4px; }
    .pubnav a, .pubnav .is-soon { justify-content: flex-start; }
    .pubnav .is-soon em { margin-left: auto; }
    .pub-header__side { justify-content: space-between; }

    .pub-main { padding: 22px 16px 64px; }
    .pub-footer { padding: 22px 16px; }

    /* Deux lignes au lieu de trois : le bouton remonte à côté du badge. */
    .livebar__inner { flex-wrap: wrap; gap: 8px 12px; padding: 9px 16px; }
    .livebar__badge { order: 1; }
    .livebar__cta { order: 2; margin-left: auto; }
    .livebar__meta { order: 3; flex-basis: 100%; margin-left: 0; gap: 12px; font-size: 12px; }
    .livebar__meta b { font-size: 13.5px; }
    .livebar__marquee { order: 4; flex-basis: 100%; }
    .channel__thumb { width: 100%; }
    .pub-hero h1 { font-size: clamp(28px, 8vw, 44px); }
}

/* ---------- Mise à l'échelle progressive -------------------------------
   Les repères sont pris sur des écrans réels : 1920, 1600, 1440, 1280.
   L'interface se resserre à chaque palier au lieu de garder la taille
   prévue pour un grand moniteur. */

@media (max-width: 1800px) {
    :root { --card-w: 180px; --tier-min: 110px; --sidebar-w: 252px; --panel-pad: 20px; }
}

@media (max-width: 1500px) {
    :root {
        --card-w: 172px; --acard-w: 104px; --tier-min: 104px;
        --tier-label-w: 88px; --sidebar-w: 236px; --panel-pad: 18px;
    }
    body { font-size: 14.5px; }
    h1 { font-size: clamp(26px, 3vw, 36px); }
    h2 { font-size: clamp(19px, 2vw, 23px); }
    .main { padding: 26px clamp(16px, 2.4vw, 32px) 60px; }
    .pub-main { padding: 26px clamp(16px, 3vw, 40px) 64px; }
    .pub-header { padding: 20px clamp(16px, 3vw, 40px) 18px; }
    .slot--album { height: 132px; }
    .tier--albums .tier__drop { min-height: 96px; }
    .editor-head .crt { width: 92px; }
    .editor-head { padding: 14px; gap: 16px; }
    .verdict { padding: 16px; gap: 18px; }
    .verdict__value input, .verdict__value b { font-size: 42px; width: 122px; }
    .verdict__hint { display: none; }
    .verdict__review textarea { min-height: 58px; }
    .rankbar__stats b { font-size: 23px; }
    .landing { padding: 26px 0 12px; }
    .landing__screen { width: clamp(130px, 22vw, 168px); }
}

@media (max-width: 1280px) {
    :root {
        --card-w: 162px; --acard-w: 96px; --tier-min: 98px;
        --tier-label-w: 80px; --sidebar-w: 216px; --panel-pad: 16px;
    }
    body { font-size: 14px; }
    .card { padding: 9px 10px 8px; }
    .card__title { font-size: 12.5px; }
    .tier__label input { font-size: 28px; }
    .slot--album { height: 120px; }
    .tier--albums .tier__drop { min-height: 88px; }
    .editor-head { padding: 12px; }
    .editor-head .crt { width: 80px; }
    .editor-head .info h1 { font-size: clamp(20px, 2.4vw, 26px); }
    .verdict__value input, .verdict__value b { font-size: 36px; width: 106px; }
    .verdict__review textarea { min-height: 52px; }
    .tiers { gap: 7px; }
    .pool { margin-top: 16px; }
    .grid--lists { grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); }
    .grid--albums { grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); }
    .verdict { grid-template-columns: minmax(160px, 200px) 1fr; }
    .verdict__value input, .verdict__value b { font-size: 40px; width: 116px; }
    .rankbar { padding: 13px 16px; }
    .rankbar__title b { font-size: 17px; }
    .rankbar__stats { gap: 18px; }
    .rankbar__stats b { font-size: 21px; }
}

@media (max-width: 860px) {
    .verdict, .verdict--static { grid-template-columns: 1fr; gap: 16px; }
    .rankbar__chevron { top: 18px; right: 16px; }
    .rankbar__stats { margin-right: 0; }
    .verdict__hint { max-width: none; }
    .rankbar { gap: 12px; }
    .rankbar__stats { margin-left: 0; width: 100%; justify-content: space-between; }
    .rankbar__chevron { position: absolute; right: 20px; top: 22px; }
    .rankbar { position: relative; }
}

/* Téléphone : le bandeau du rang passe au-dessus, les cartes prennent la largeur */
@media (max-width: 680px) {
    .tier { flex-direction: column; }

    .tier__label {
        flex: none;
        width: 100%;
        flex-direction: row;
        justify-content: flex-start;
        gap: 10px;
        padding: 7px 12px;
        border-right: 0;
        border-bottom: var(--border);
    }

    .tier__label input { width: auto; min-width: 46px; text-align: left; font-size: 22px; }
    .tier__letter { font-size: 22px; }
    .tier__tools { opacity: 1; margin-left: auto; }
    .tier__drop:empty::after, .pool__drop:empty::after { align-self: flex-start; }

    .main::before { left: 50%; }
    .main::before, .pub-main::before, .login::before { width: 150vmin; }

    .tier { min-height: 0; }
    .tier__label { flex-basis: 58px; }
    .tier__label input, .tier__letter { font-size: 24px; }
    .tier__drop, .pool__drop { padding: 9px; gap: 8px; }

    .tier__drop, .pool__drop { grid-template-columns: 1fr; }
    .card__foot .mono { display: inline; }

    .acard, .slot--album { width: 96px; }
    .tier--albums .tier__drop, .board .pool__drop { grid-template-columns: repeat(auto-fill, 96px); }
    .slot--album { height: 148px; }
    .tier--albums, .tier--albums .tier__drop { min-height: 0; }
    .acard__open { opacity: 1; }

    .board { padding: 14px 12px; }
    .settings { max-width: none; }
    .stack { max-width: none; }
    .userlist li { align-items: flex-start; }
    .userlist__actions { margin-left: 0; width: 100%; }
    .channel { gap: 14px; }
    .channel__avatar { width: 58px; height: 58px; }
    .verdict { padding: 14px; }
    .verdict__value input, .verdict__value b { font-size: 44px; width: 126px; }
    .landing__counts { gap: 22px; padding: 14px 0; }
    .rankbar { padding: 13px 14px; gap: 10px; }
    .rankbar__title b { font-size: 16px; }
    .rankbar__stats b { font-size: 19px; }
    .landing__playerhead { padding: 10px 13px; }
    .linked .btn { margin-left: 0; }
    .devbox > *:not(summary) { padding-left: 13px; padding-right: 13px; }
    .editor-head { padding: 14px; gap: 14px; }
    .editor-head .crt { width: 84px; }
    .page-head { gap: 12px; }
    .grid--lists { grid-template-columns: 1fr; }
    .grid--albums { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
    .searchbar input { padding: 15px 16px 15px 48px; font-size: 16px; }
    .toasts { right: 12px; left: 12px; bottom: 12px; justify-items: stretch; }
    .toast { justify-content: center; }
}

@media (max-width: 420px) {
    .acard, .slot--album { width: 88px; }
    .tier--albums .tier__drop, .board .pool__drop { grid-template-columns: repeat(auto-fill, 88px); }
    .slot--album { height: 132px; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        transition-duration: .001ms !important;
    }
}

@media print {
    .sidebar, .mobilebar, .btn, .toasts { display: none !important; }
}

/* =========================================================================
   Source OBS : mise en page figée.
   La largeur de la source n'a rien à voir avec celle d'un téléphone. Sans
   ça, une source en 854 ou 640 déclenchait la mise en page mobile et
   empilait les rangs, alors qu'on veut exactement le rendu de la régie,
   simplement réduit à l'échelle.
   ========================================================================= */
.overlay-body {
    --card-w: 186px;
    --acard-w: 122px;
    --tier-min: 116px;
    --tier-label-w: 88px;
    font-size: 15px;
}

.overlay-body .tier { flex-direction: row; min-height: var(--tier-min); }

.overlay-body .tier__label {
    flex: 0 0 var(--tier-label-w);
    width: auto;
    flex-direction: column;
    justify-content: center;
    padding: 6px;
    border-right: var(--border);
    border-bottom: 0;
}

.overlay-body .tier__label .tier__letter { font-size: 34px; }
.overlay-body .tier__drop { grid-template-columns: repeat(auto-fill, minmax(var(--card-w), 1fr)); }
.overlay-body .card__foot .mono { display: inline; }
.overlay-body .card__title { -webkit-line-clamp: 2; }

/* ---------- Comptes visiteurs -------------------------------------------
   Identité Twitch dans l'en-tête public, et page de compte. */

/* Le menu se centre plus haut ; cette règle datait d'un en-tête où il était
   aligné à droite, et l'écrasait silencieusement — les liens restaient donc
   collés au bord, connecté comme non connecté. */
.pub-moi, .pub-connexion { flex: 0 0 auto; order: 3; }

.pub-connexion,
.pub-moi {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 14px;
    border: 2px solid var(--paper);
    border-radius: 999px;
    color: var(--paper);
    text-decoration: none;
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
}

.pub-connexion:hover, .pub-moi:hover { background: var(--paper); color: var(--ink); }
.pub-connexion svg { flex: none; }

.pub-moi {
    padding-left: 6px;
    background: none;
    font-family: inherit;
    cursor: pointer;
}

.pub-moi img { width: 26px; height: 26px; border-radius: 50%; flex: none; }
.pub-moi svg { flex: none; transition: transform .18s var(--ease); }

/* Menu du compte : au survol sur ordinateur, au clic ailleurs. Le survol seul
   laisserait les écrans tactiles sans solution. */
.pub-compte { position: relative; flex: 0 0 auto; order: 3; }

.pub-compte__menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 60;
    min-width: 190px;
    padding: 6px;
    display: grid;
    gap: 2px;
    border: 3px solid var(--ink);
    border-radius: 12px;
    background: var(--paper-hi);
    box-shadow: 5px 5px 0 rgba(0, 0, 0, .35);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity .16s var(--ease), transform .16s var(--ease), visibility .16s;
}

.pub-compte:hover .pub-compte__menu,
.pub-compte:focus-within .pub-compte__menu,
.pub-compte.est-ouvert .pub-compte__menu {
    opacity: 1;
    visibility: visible;
    transform: none;
}

.pub-compte:hover .pub-moi svg,
.pub-compte.est-ouvert .pub-moi svg { transform: rotate(180deg); }

.pub-compte:hover .pub-moi,
.pub-compte.est-ouvert .pub-moi { background: var(--paper); color: var(--ink); }

.pub-compte__menu a {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 12px;
    border-radius: 8px;
    color: var(--ink);
    text-decoration: none;
    font-size: 13.5px;
    font-weight: 600;
}

.pub-compte__menu a:hover { background: var(--ink); color: var(--paper-hi); }

/* Une zone de garde sous le bouton : sans elle, le menu se referme quand la
   souris traverse l'espace qui l'en sépare. */
.pub-compte::after {
    content: '';
    position: absolute;
    top: 100%;
    right: 0;
    width: 100%;
    height: 12px;
}

.avis {
    padding: 12px 16px;
    margin: 0 0 20px;
    border: var(--border);
    border-radius: var(--radius);
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    font-size: 14px;
}

.avis--erreur { border-color: var(--red); color: var(--red-deep); }

/* ---------- Écran de choix du compte ------------------------------------
   Proposer le compte déjà utilisé plutôt que d'imposer l'écran de Twitch :
   un clic pour revenir, un clic pour changer. */

.connexion { width: min(460px, 100%); margin: 30px auto; text-align: center; }
.connexion h1 { margin: 0 0 6px; }
.connexion .lede { margin: 0 0 22px; }
.connexion__choix { display: grid; gap: 10px; text-align: left; }

.connexion__compte,
.connexion__autre {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 13px 16px;
    border: var(--border);
    border-radius: var(--radius);
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    color: var(--ink);
    text-decoration: none;
    transition: transform .15s var(--ease), box-shadow .15s var(--ease);
}

.connexion__compte:hover,
.connexion__autre:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--ink); }
.connexion__compte { border-left: 5px solid var(--red); }
.connexion__autre { border-style: dashed; box-shadow: none; }
.connexion__autre:hover { border-style: solid; }

.connexion__avatar {
    width: 46px; height: 46px;
    flex: none;
    display: grid;
    place-items: center;
    border: var(--border);
    border-radius: 50%;
    background: var(--paper-deep);
    overflow: hidden;
}

.connexion__avatar img { width: 100%; height: 100%; object-fit: cover; }
.connexion__avatar b { font-family: var(--font-display); font-size: 19px; }
.connexion__avatar--vide { border-style: dashed; color: var(--ink-mute); }

.connexion__nom { flex: 1; min-width: 0; }
.connexion__nom b { display: block; font-size: 15px; line-height: 1.2; }
.connexion__nom small { font-size: 12px; color: var(--ink-mute); }
.connexion__compte svg, .connexion__autre svg { flex: none; color: var(--ink-mute); transform: rotate(-90deg); }

.connexion__note { margin: 22px 0 0; font-size: 12.5px; color: var(--ink-mute); line-height: 1.5; }
.connexion__note a { color: var(--ink-mute); }

/* ---------- Page « Mon compte » -----------------------------------------
   Une carte de membre, dans l'esprit d'une carte d'abonné imprimée. */

.carte-membre {
    position: relative;
    margin-bottom: 22px;
    border: 3px solid var(--ink);
    border-radius: var(--radius);
    background: var(--paper-hi);
    box-shadow: var(--lift);
    overflow: hidden;
}

.carte-membre__ruban {
    height: 10px;
    background: repeating-linear-gradient(
        135deg,
        var(--red) 0 18px,
        var(--gold) 18px 36px,
        var(--teal) 36px 54px
    );
    border-bottom: 3px solid var(--ink);
}

.carte-membre__corps {
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 22px;
    flex-wrap: wrap;
}

.carte-membre__avatar {
    width: 84px; height: 84px;
    flex: none;
    display: grid;
    place-items: center;
    border: 3px solid var(--ink);
    border-radius: 50%;
    background: var(--paper-deep);
    overflow: hidden;
    box-shadow: var(--lift-sm);
}

.carte-membre__avatar img { width: 100%; height: 100%; object-fit: cover; }
.carte-membre__avatar span { font-family: var(--font-display); font-size: 34px; }

.carte-membre__qui { flex: 1; min-width: 0; }
.carte-membre__qui h2 { margin: 0 0 2px; font-size: clamp(21px, 3.6vw, 28px); line-height: 1.1; }

.carte-membre__login {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: var(--ink-mute);
    text-decoration: none;
    font-size: 13px;
}

.carte-membre__login:hover { color: var(--red-deep); }

.compte-liste { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }

.compte-liste li {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 6px 13px 6px 6px;
    border: var(--border);
    border-radius: 999px;
    background: var(--paper-hi);
    font-size: 13px;
}

.compte-liste img { width: 26px; height: 26px; border-radius: 50%; }
.compte-liste .mono { font-size: 11.5px; color: var(--ink-mute); }

/* Les trois modes de jeu. Chacun a sa teinte, pour qu'on les distingue
   d'un regard plutôt qu'en lisant les titres. */

/* Dans la fenêtre du stock, chaque vignette peut être retirée. */

/* Toujours visible : au survol seulement, le bouton était inatteignable
   sur écran tactile. */

/* ---------- Fil d'Ariane -------------------------------------------------- */

.fil { margin: 0 0 18px; }
.fil ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.fil li { display: flex; align-items: center; gap: 6px; font-size: 13px; }

/* Le chevron est dessiné en CSS : un caractère aurait suivi la police et
   n'aurait pas été aligné de la même façon partout. */
.fil li + li::before {
    content: '';
    width: 5px; height: 5px;
    border-right: 2px solid var(--ink-mute);
    border-top: 2px solid var(--ink-mute);
    transform: rotate(45deg);
    opacity: .7;
}

.fil a { color: var(--ink-mute); text-decoration: none; }
.fil a:hover { color: var(--red-deep); text-decoration: underline; }
.fil [aria-current] { color: var(--ink); font-weight: 600; }

/* ---------- Identité corrigeable dans l'éditeur --------------------------- */

.champ {
    border-bottom: 2px dashed transparent;
    outline: none;
    cursor: text;
}

.champ:hover { border-bottom-color: var(--ink-mute); }
.champ:focus { border-bottom-color: var(--red); background: var(--paper-hi); }
.champ--court { min-width: 46px; display: inline-block; }
.champ:empty::before { content: attr(data-vide); color: var(--ink-mute); }

.compteur { display: block; margin-top: 5px; font-size: 11.5px; color: var(--ink-mute); font-family: var(--font-mono); }

/* L'avis complet : du texte courant, sans cadre. Une boîte l'enfermait
   alors qu'il doit se lire comme un paragraphe. */
.avis-long {
    margin: 12px 0 0;
    max-width: none;
    font-size: 15px;
    font-weight: 300;
    line-height: 1.7;
    color: var(--ink-2);
}

.avis-court {
    margin: 10px 0 0;
    font-family: var(--font-display);
    font-size: clamp(16px, 2.2vw, 20px);
    line-height: 1.35;
    color: var(--ink);
}

/* ---------- Planches Instagram -------------------------------------------- */

.insta__etat { color: var(--ink-mute); font-size: 13px; }

/* Aperçu en carrousel : on voit la planche en grand, comme elle paraîtra. */

.insta__scene { position: relative; margin: 16px 0 18px; }

.insta__piste {
    display: flex;
    gap: 16px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    padding: 4px 2px 10px;

    /* La barre de défilement gênerait la lecture : le déplacement se fait
       aux flèches, aux points ou au doigt. */
    scrollbar-width: none;
}

.insta__piste::-webkit-scrollbar { display: none; }

.insta__planche {
    flex: 0 0 100%;
    margin: 0;
    scroll-snap-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
}

.insta__planche canvas {
    /* Le 4:5 tient dans la fenêtre sans la faire défiler. */
    max-height: min(52vh, 560px);
    width: auto;
    max-width: 100%;
    border: var(--border);
    border-radius: 14px;
    box-shadow: var(--lift);
    background: var(--paper);
}

.insta__fleche {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 3;
    width: 44px; height: 44px;
    display: grid; place-items: center;
    border: var(--border);
    border-radius: 50%;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    font-size: 26px;
    line-height: 1;
    color: var(--ink);
    cursor: pointer;
    transition: transform .15s var(--ease);
}

.insta__fleche:hover:not(:disabled) { transform: translateY(-50%) scale(1.08); }
.insta__fleche:disabled { opacity: .3; cursor: default; }
.insta__fleche--avant { left: -6px; }
.insta__fleche--apres { right: -6px; }

.insta__points { display: flex; justify-content: center; gap: 8px; margin-top: 4px; }

.insta__points button {
    width: 9px; height: 9px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(23, 18, 15, .22);
    cursor: pointer;
    transition: background .15s, transform .15s;
}

.insta__points button.est-on { background: var(--ink); transform: scale(1.3); }

/* Les stories partagent le carrousel mais gardent leur format vertical :
   elles sont donc bornées en hauteur, pas en largeur. */
.insta__planche--story { gap: 8px; }
.insta__planche--story canvas { max-height: min(48vh, 520px); }

.insta__dl { margin-top: 2px; }

.insta__planche figcaption {
    font-family: var(--font-mono);
    font-size: 11.5px;
    color: var(--ink-mute);
    text-align: center;
}

.insta__legende { display: grid; gap: 7px; margin-bottom: 16px; }
.insta__legende label { font-size: 13px; font-weight: 600; }

.insta__legende textarea {
    width: 100%;
    padding: 12px 14px;
    border: var(--border);
    border-radius: 12px;
    background: var(--paper-hi);
    font-family: var(--font-mono);
    font-size: 12.5px;
    line-height: 1.5;
    resize: vertical;
}

.insta__legende button { justify-self: start; }

/* Un nom comme « Interlude » doit tenir dans la case : le script réduit sa
   taille jusqu'à ce qu'il entre, la largeur du rang restant la même pour tous. */
.tier__label input {
    text-align: center;
    width: 100%;
    padding: 2px;
    line-height: 1.05;
}

.tier.est-exclu .tier__label { opacity: .62; }

/* Une mention discrète signale que le rang ne compte pas dans la note.
   Elle ne doit pas intercepter les clics : elle recouvrait les boutons
   d'outils du rang, qui devenaient inatteignables. */
.tier.est-exclu .tier__label::after {
    content: 'hors note';
    position: absolute;
    left: 0; right: 0; bottom: 3px;
    pointer-events: none;
    text-align: center;
    font-family: var(--font-mono);
    font-size: 9px;
    line-height: 1;
    text-transform: uppercase;
    letter-spacing: .06em;
    opacity: .8;
}

.tier.est-exclu .tier__drop { background-image:
    repeating-linear-gradient(135deg, transparent 0 12px, rgba(23,18,15,.045) 12px 24px); }

.tier__label { position: relative; }

/* Une carte de statistique qui s'ouvre : elle doit se signaler comme
   cliquable sans cesser de ressembler aux autres. */
.stat--action {
    cursor: pointer;
    font: inherit;
    text-align: inherit;
    transition: transform .15s var(--ease), box-shadow .15s var(--ease);
}

.stat--action:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--ink); }

.membres {
    list-style: none;
    margin: 14px 0 18px;
    padding: 0;
    display: grid;
    gap: 6px;
    max-height: 52vh;
    overflow-y: auto;
}

.membres li {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 8px 12px;
    border: var(--border);
    border-radius: 11px;
    background: var(--paper-hi);
}

.membres img { width: 34px; height: 34px; border-radius: 50%; flex: none; }
.membres__qui { flex: 1; min-width: 0; }
.membres__qui b { display: block; font-size: 14px; }
.membres__qui small { font-size: 11.5px; color: var(--ink-mute); }
.membres__vu { flex: none; font-size: 11.5px; color: var(--ink-mute); }

/* Case maîtresse de mise en lice, dans l'en-tête de la colonne. */
.tout-cocher {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--ink-mute);
    cursor: pointer;
}

.tout-cocher input { width: 16px; height: 16px; accent-color: var(--red); cursor: pointer; }
.tout-cocher:hover { color: var(--ink); }

/* Purge de l'historique : des boutons avec leur compte, désactivés quand il
   n'y a rien à effacer. */

/* ---------- Attente ------------------------------------------------------
   Un bouton qui déclenche un appel doit le montrer : sans cela on reclique,
   on croit que rien ne se passe, et l'on finit par croire que c'est cassé. */

@keyframes noiz-tourne { to { transform: rotate(360deg); } }

.btn.est-occupe {
    position: relative;
    pointer-events: none;
    color: transparent !important;
}

/* Le contenu s'efface mais garde sa place : le bouton ne doit pas changer de
   taille en cours de route, sinon la mise en page saute. */
.btn.est-occupe > * { visibility: hidden; }

.btn.est-occupe::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 15px; height: 15px;
    margin: -8px 0 0 -8px;
    border: 2.5px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    color: var(--ink);
    animation: noiz-tourne .62s linear infinite;
}

.btn--primary.est-occupe::after,
.btn--ink.est-occupe::after { color: var(--paper-hi); }

/* Une zone qui se remplit : on la grise et on pose un rond au centre. */
.en-chargement { position: relative; min-height: 90px; }
.en-chargement > * { opacity: .32; pointer-events: none; }

.en-chargement::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 30px; height: 30px;
    margin: -15px 0 0 -15px;
    border: 3px solid var(--ink);
    border-top-color: transparent;
    border-radius: 50%;
    animation: noiz-tourne .62s linear infinite;
}

/* Attente longue : on annonce ce qui se passe, sinon on croit à un blocage. */
.attente-longue {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 13px 16px;
    margin-top: 14px;
    border: var(--border);
    border-radius: var(--radius);
    background: var(--paper-hi);
    font-size: 13.5px;
}

.attente-longue i {
    flex: none;
    width: 18px; height: 18px;
    border: 2.5px solid var(--ink);
    border-top-color: transparent;
    border-radius: 50%;
    animation: noiz-tourne .62s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    .btn.est-occupe::after,
    .en-chargement::after,
    .attente-longue i { animation-duration: 2s; }
}

/* Essai de tirage : beaucoup de vignettes, petites, pour juger la variété
   d'un seul coup d'œil plutôt qu'en faisant défiler. */

/* Répartition par famille musicale : d'un coup d'œil, on voit si le
   catalogue est varié ou s'il penche d'un côté. */

/* L'adresse réellement appelée : c'est souvent elle qui trahit le problème,
   une surcharge de configuration oubliée par exemple. */

/* Les trois modes, empilés : sur téléphone comme sur écran, le choix se
   fait d'un pouce. */

/* Le nom du défi, toujours visible au-dessus de la pochette. */

/* Un disque à côté du titre : la signature du jeu, en petit. */

/* Le point d'interrogation des règles : discret, toujours à portée. */

/* Les règles, en fenêtre. */

/* Sous la pochette : on regarde l'image, puis on compte ce qui reste. */

/* Un vinyle par vie : disque noir, pastille centrale, sillon. */

/* Manche pas encore atteinte : présente mais en retrait. */

/* Une couleur d'étiquette par manche, pour lire la partie d'un regard. */

/* Un écart entre les groupes : trois familles, pas dix disques en vrac. */

/* Le dernier vinyle tremble : c'est le seul avertissement avant la fin. */

/* Ce qu'il reste à jouer, sous les boutons de fin. */

/* Ce qui a déjà été trouvé, sous la pochette. */

/* Une réponse révélée après un échec se distingue d'une réponse trouvée :
   on l'a apprise, pas gagnée. */

/* Au-delà de huit titres, deux colonnes : la liste tient à l'écran sans
   qu'on ait à la faire défiler. */

/* Le bandeau de reprise : quitter une partie ne doit pas la perdre. */

/* Les trois difficultés côte à côte : elles se comparent d'un regard, là
   où les modes de jeu se lisent l'un après l'autre. */

/* Le disque : sillons concentriques et étiquette teintée selon le mode. */

/* Défi déjà joué : la carte reste lisible mais n'invite plus. */

/* Le genre se distingue de la mise : c'est un indice, pas un enjeu.

/* Sur l'année, la direction à prendre. Sans cet indice, trois essais sur
   un siècle relèvent du tirage au sort. */

/* Le feu d'artifice couvre l'écran : trois foyers décalés, chacun ouvrant
   sa gerbe. Enfermé dans la pochette, il était rogné et l'on n'en voyait
   presque rien. */

/* Partir du foyer, s'ouvrir en tous sens, puis retomber en s'effaçant. */

/* Une ligne d'outils : tout sur un rang, et qui se replie proprement sur
   écran étroit plutôt que de s'empiler au hasard. */

/* Un disque qui tourne : la seule animation qui ait du sens ici. */

/* Ce qui attend le défi s'efface le temps de la recherche. Le nom évite
   « est-attente », déjà porté par les vinyles des manches à venir : les
   deux opacités se seraient cumulées. */

/* ======================================================================
   10Cover — la régie
   ====================================================================== */

.dc-compte {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    max-width: 340px;
    margin: 16px 0;
}

.dc-compte__case {
    padding: 12px;
    border: var(--border);
    border-radius: 11px;
    background: var(--paper-hi);
    text-align: center;
}

.dc-compte__case b {
    display: block;
    font-family: var(--font-display);
    font-size: 22px;
    line-height: 1.1;
}

.dc-compte__case small { font-size: 11px; color: var(--ink-mute); }

/* ---------- Import ------------------------------------------------------ */

/* Les rangées d'une fenêtre s'alignent à droite — bon pour un pied de
   dialogue, mauvais au fil d'un formulaire, où le bouton se retrouvait seul
   dans un coin, son ombre portée rognée par le bord qui défile. */
.modal__box .modal__corps .row {
    justify-content: flex-start;
    align-items: center;
    margin: 12px 0 6px;
    padding: 0 2px 4px;
}

/* ---------- Réglages d'import ------------------------------------------- */

.dc-reglages {
    padding: 14px 16px;
    border: var(--border);
    border-radius: 12px;
    background: var(--paper-hi);
}

.dc-reglages__nb {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
    padding-bottom: 12px;
    border-bottom: 1px dashed var(--paper-deep);
}

.dc-reglages__nb label { font-size: 13px; }

.dc-reglages__nb input {
    width: 76px;
    padding: 6px 10px;
    border: var(--border);
    border-radius: 9px;
    background: var(--paper);
    font-family: var(--font-mono);
    font-size: 13px;
    text-align: center;
}

.dc-apercu { font-size: 11.5px; color: var(--ink-mute); }

.dc-poids {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 6px 20px;
}

.dc-poids__ligne {
    display: grid;
    grid-template-columns: 96px 1fr 22px;
    align-items: center;
    gap: 9px;
}

.dc-poids__ligne b { font-size: 12.5px; font-weight: 500; font-family: var(--font-ui); }
.dc-poids__ligne input { width: 100%; accent-color: var(--red); }

.dc-poids__ligne .mono {
    font-size: 11.5px;
    text-align: right;
    color: var(--teal);
}

@media (max-width: 620px) {
    .dc-poids { grid-template-columns: 1fr; }
}

.dc-etape {
    margin: 18px 0 8px;
    font-family: var(--font-display);
    font-size: 14px;
}

.dc-etape:first-child { margin-top: 0; }

.dc-zone {
    width: 100%;
    padding: 11px 13px;
    border: var(--border);
    border-radius: 11px;
    background: var(--paper-hi);
    font-family: var(--font-mono);
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--ink);
    resize: vertical;
}

.dc-cle { font-size: 12px; color: var(--ink-mute); align-self: center; }

.dc-option {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-top: 10px;
    font-size: 12.5px;
    color: var(--ink-mute);
}

/* ---------- Bilan d'import ---------------------------------------------- */

.dc-verdict {
    margin-top: 12px;
    padding: 11px 14px;
    border: var(--border);
    border-left: 4px solid var(--ink-mute);
    border-radius: 10px;
    background: var(--paper-hi);
}

.dc-verdict[data-verdict="ok"] { border-left-color: var(--teal); }
.dc-verdict[data-verdict="doublon"] { border-left-color: var(--gold); }
.dc-verdict[data-verdict="introuvable"],
.dc-verdict[data-verdict="incomplet"],
.dc-verdict[data-verdict="injoignable"] { border-left-color: var(--red-deep); }

.dc-verdict b { font-family: var(--font-display); font-size: 14px; }
.dc-verdict small { display: block; margin-top: 3px; font-size: 11.5px; color: var(--ink-mute); }
.dc-verdict ul { margin: 6px 0 0; padding-left: 18px; }
.dc-verdict li { font-size: 12px; color: var(--ink-2); }

/* ---------- Garde de consultation ---------------------------------------
   Voir le catalogue gâche le jeu : on le masque, et l'on demande à qui veut
   passer outre de le dire explicitement.
   ---------------------------------------------------------------------- */

.dc-garde {
    max-width: 380px;
    margin: 0 auto 18px;
    padding: 22px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
    box-shadow: 0 4px 16px rgba(23, 18, 15, .18);
    text-align: center;
}

.dc-garde b {
    display: block;
    margin-bottom: 8px;
    font-family: var(--font-display);
    font-size: 18px;
    color: var(--red-deep);
}

.dc-garde p { margin: 0 0 10px; font-size: 13px; line-height: 1.5; }

.dc-garde input {
    width: 100%;
    margin-bottom: 10px;
    padding: 9px 13px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper);
    font-family: var(--font-ui);
    font-size: 14px;
    text-align: center;
}

.dc-garde input.est-ko { border-color: var(--red); animation: dc-refus .35s; }

@keyframes dc-refus {
    0%, 100% { transform: translateX(0); }
    25%      { transform: translateX(-5px); }
    75%      { transform: translateX(5px); }
}

.dc-liste.est-floue {
    filter: blur(9px);
    opacity: .5;
    pointer-events: none;
    min-height: 120px;
}

.dc-liste__leurre { text-align: center; color: var(--ink-mute); padding: 40px 0; }

/* ---------- Progression d'import ---------------------------------------- */

.dc-progression { margin-top: 16px; }
.dc-progression b { display: block; font-size: 13px; margin-bottom: 7px; }

.dc-progression small {
    display: block;
    margin-top: 6px;
    font-size: 11.5px;
    color: var(--ink-mute);
}

.dc-jauge {
    height: 7px;
    border-radius: 999px;
    background: var(--paper-deep);
    overflow: hidden;
}

.dc-jauge i {
    display: block;
    width: 0;
    height: 100%;
    background: var(--teal);
    transition: width .3s var(--ease);
}

/* Les rejets se déplient : soixante lignes d'erreur noieraient le reste. */
.dc-verdict details { margin-top: 6px; }

.dc-verdict summary {
    font-size: 12px;
    color: var(--ink-mute);
    cursor: pointer;
}

.dc-verdict summary:hover { color: var(--ink); }

/* ---------- Le catalogue, une fois ouvert -------------------------------- */

/* Un titre de rang inférieur, dans un panneau. */
.dc-sous-titre {
    margin: 22px 0 8px;
    font-size: 15px;
    display: flex;
    align-items: center;
    gap: 9px;
}

.dc-grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 12px;
}

.dc-carte {
    position: relative;
    display: flex;
    gap: 12px;
    padding: 10px;
    border: var(--border);
    border-left: 4px solid var(--ink-mute);
    border-radius: 12px;
    background: var(--paper-hi);
}

.dc-carte[data-niveau="easy"]   { border-left-color: var(--teal); }
.dc-carte[data-niveau="medium"] { border-left-color: var(--gold); }
.dc-carte[data-niveau="hard"]   { border-left-color: var(--red); }

.dc-carte__pochette {
    flex: 0 0 62px;
    width: 62px;
    height: 62px;
    border-radius: 8px;
    background: var(--paper-deep);
    overflow: hidden;
}

.dc-carte__pochette img { width: 100%; height: 100%; object-fit: cover; display: block; }

.dc-carte__texte {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    padding-right: 16px;
}

.dc-carte__texte b {
    font-family: var(--font-display);
    font-size: 14px;
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.dc-carte__texte small {
    font-size: 12px;
    color: var(--ink-mute);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dc-carte__pied {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-top: auto;
    padding-top: 4px;
}

.dc-carte__pied .mono { font-size: 11px; color: var(--ink-mute); }

.dc-badge {
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--paper-deep);
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--ink-2);
}

.dc-carte__oter {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 20px;
    height: 20px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: transparent;
    font-size: 16px;
    line-height: 1;
    color: var(--ink-mute);
    cursor: pointer;
    opacity: 0;
    transition: opacity .14s;
}

.dc-carte:hover .dc-carte__oter { opacity: 1; }
.dc-carte__oter:hover { background: var(--red); color: var(--paper-hi); }

/* ======================================================================
   10Cover — le jeu
   ====================================================================== */

/* Le contenu se pose en haut : le centrage vertical faisait descendre le
   titre au milieu de l'écran, et l'on ne savait plus sur quelle page on
   était. C'est au pied de page de tenir le bas, pas au titre. */
.dcj { max-width: 440px; margin: 0 auto; }

/* ---------- Le choix de la difficulté ------------------------------------ */

.dcj-accueil { text-align: center; padding: 20px 0; }

.dcj-accueil h1 { margin: 0 0 8px; font-size: 46px; letter-spacing: -.01em; }

/* « margin: 0 auto » : le paragraphe de connexion est plus étroit que la
   colonne, et sans marge automatique il se collait à gauche — soixante
   pixels de décalage que rien n'expliquait à la lecture. */
.dcj-accueil > p { margin: 0 auto 34px; font-size: 15px; color: var(--ink-mute); }

.dcj-niveaux { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }

.dcj-niveau {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 24px 16px;
    border: var(--border);
    border-radius: 16px;
    background: var(--paper-hi);
    box-shadow: 0 3px 0 var(--paper-deep);
    cursor: pointer;
    transition: transform .14s, box-shadow .14s, border-color .14s;
}

.dcj-niveau:hover:not([data-fait]) {
    transform: translateY(-3px);
    box-shadow: 0 6px 0 var(--paper-deep);
}

/* Un niveau déjà joué reste lisible mais n'invite plus.

   Un petit vinyle au survol plutôt que le cercle barré du navigateur :
   celui-ci est laid et gronde, alors qu'il n'y a rien de fautif à revenir
   sur une carte qu'on a déjà jouée. */
.dcj-niveau[data-fait] {
    opacity: .55;
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='26' viewBox='0 0 26 26'%3E%3Ccircle cx='13' cy='13' r='11.5' fill='%23211a16'/%3E%3Ccircle cx='13' cy='13' r='8.5' fill='none' stroke='%23000' stroke-opacity='.5'/%3E%3Ccircle cx='13' cy='13' r='6' fill='none' stroke='%23000' stroke-opacity='.5'/%3E%3Ccircle cx='13' cy='13' r='4' fill='%23c9a227'/%3E%3Ccircle cx='13' cy='13' r='1.1' fill='%23efe2cc'/%3E%3C/svg%3E") 13 13, default;
    border-color: var(--paper-deep);
}

.dcj-niveau[data-fait]:hover { transform: none; box-shadow: 0 3px 0 var(--paper-deep); }
.dcj-niveau b { font-family: var(--font-display); font-size: 20px; }
.dcj-niveau small { font-size: 11.5px; color: var(--ink-mute); }

/* ---------- La pochette --------------------------------------------------- */

/* La pochette : réduite d'un bon tiers. À 440 px elle mangeait l'écran et
   repoussait les champs sous la ligne de flottaison. */
.dcj-cover {
    width: 100%;
    aspect-ratio: 1;
    max-width: 290px;
    margin: 0 auto 16px;
    border: 3px solid var(--ink);
    border-radius: 16px;
    background: #17120F;
    overflow: hidden;
    box-shadow: 0 6px 0 var(--paper-deep);
}

.dcj-cover canvas { width: 100%; height: 100%; display: block; }

/* ---------- La netteté ---------------------------------------------------
   Le seul arbitrage du jeu : voir plus clair, ou garder la mise. Il tient
   sur une ligne, juste sous l'image.
   ---------------------------------------------------------------------- */

.dcj-nettete {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 18px;
    padding: 12px 16px;
    border: var(--border);
    border-radius: 13px;
    background: var(--paper-hi);
}

.dcj-nettete__barre {
    flex: 0 0 90px;
    height: 8px;
    border-radius: 999px;
    background: var(--paper-deep);
    overflow: hidden;
}

.dcj-nettete__barre i {
    display: block;
    width: 0;
    height: 100%;
    background: var(--gold);
    transition: width .3s var(--ease);
}

.dcj-nettete__txt {
    flex: 1;
    margin: 0;
    font-size: 12px;
    color: var(--ink-mute);
}

/* ---------- Les trois champs ---------------------------------------------- */

.dcj-champs { display: grid; gap: 10px; margin-bottom: 16px; }

.dcj-champ {
    padding: 13px 16px;
    border: var(--border);
    border-left: 4px solid var(--ink-mute);
    border-radius: 13px;
    background: var(--paper-hi);
}

.dcj-champ[data-champ="artiste"] { border-left-color: var(--red); }
.dcj-champ[data-champ="album"]   { border-left-color: var(--gold); }
.dcj-champ[data-champ="annee"]   { border-left-color: var(--teal); }

/* Un champ réglé s'efface : il n'attend plus rien. */
.dcj-champ.est-clos { background: var(--paper); }
.dcj-champ[data-etat="rate"] { opacity: .7; }

.dcj-champ__tete {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 9px;
}

.dcj-champ__tete b { font-family: var(--font-display); font-size: 15px; }

.dcj-champ__vaut {
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--paper-deep);
    font-family: var(--font-mono);
    font-size: 11.5px;
    color: var(--ink-2);
}

.dcj-champ[data-etat="trouve"] .dcj-champ__vaut { background: var(--teal); color: var(--paper-hi); }
.dcj-champ[data-etat="rate"] .dcj-champ__vaut { background: var(--red-deep); color: var(--paper-hi); }

.dcj-champ__reponse {
    margin: 0;
    font-family: var(--font-display);
    font-size: 16px;
}

.dcj-champ[data-etat="trouve"] .dcj-champ__reponse { color: var(--teal); }
.dcj-champ[data-etat="rate"] .dcj-champ__reponse { color: var(--red-deep); }

.dcj-champ__form { display: flex; gap: 8px; }

.dcj-champ__form input {
    flex: 1;
    min-width: 0;
    padding: 9px 14px;
    border: 2px solid var(--paper-deep);
    border-radius: 999px;
    background: var(--paper);
    font-family: var(--font-ui);
    font-size: 14px;
    color: var(--ink);
}

.dcj-champ__form input:focus { outline: none; border-color: var(--teal); }

.dcj-champ__pied {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 9px;
}

/* Les essais restants : trois pastilles qui s'éteignent. */
.dcj-essais { display: flex; gap: 5px; }

.dcj-essais i {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--ink-mute);
}

.dcj-essais i.est-usee { background: var(--paper-deep); }

.dcj-champ__indice { flex: 1; font-size: 12px; font-weight: 500; }
.dcj-champ__indice[data-sens="plus"]  { color: var(--gold); }
.dcj-champ__indice[data-sens="moins"] { color: var(--cyan); }

.dcj-champ__passer {
    margin-left: auto;
    padding: 0;
    border: none;
    background: none;
    font-family: var(--font-ui);
    font-size: 12px;
    color: var(--ink-mute);
    text-decoration: underline;
    cursor: pointer;
}

.dcj-champ__passer:hover { color: var(--red); }

/* ---------- Pied et fin --------------------------------------------------- */

.dcj-pied {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.dcj-total { margin: 0; font-family: var(--font-mono); font-size: 12.5px; color: var(--teal); }

.dcj-fin { text-align: center; padding-top: 8px; }

.dcj-fin__score {
    margin: 0 0 16px;
    font-family: var(--font-display);
    font-size: 34px;
    color: var(--teal);
}

/* ---------- Bulles -------------------------------------------------------- */

/* En bas plutôt qu'en haut : l'action se passe au centre de l'écran, et un
   message qui surgit tout en haut oblige à lever les yeux hors du jeu. Un
   peu au-dessus du bord, pour ne pas se confondre avec le pied de page. */
.dcj-bulles {
    position: fixed;
    bottom: 64px;
    left: 50%;
    z-index: 70;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 9px;
    transform: translateX(-50%);
    pointer-events: none;
}

/* Une pastille sombre, pas une carte : le message passe et s'en va, il n'a
   pas à se faire passer pour un élément de la page. Le liseré coloré sur le
   côté disait la même chose que la couleur du titre, en moins lisible. */
.dcj-bulle {
    display: flex;
    flex-direction: column;
    gap: 3px;
    max-width: min(420px, 88vw);
    padding: 13px 22px;
    border-radius: 14px;
    background: rgba(23, 18, 15, .94);
    box-shadow: 0 10px 30px rgba(23, 18, 15, .34);
    color: var(--paper);
    text-align: center;
    animation: dcj-bulle-entre .34s cubic-bezier(.2, .9, .3, 1.2);
}

.dcj-bulle b {
    font-family: var(--font-display);
    font-size: 16px;
    line-height: 1.2;
}

.dcj-bulle span {
    font-size: 13px;
    line-height: 1.45;
    color: rgba(239, 226, 204, .72);
}

/* La couleur du titre suffit à dire l'issue : sur fond sombre elle se voit
   mieux qu'un liseré de cinq pixels sur le côté. */
.dcj-bulle[data-issue="gagne"] b { color: #4fd1c0; }
.dcj-bulle[data-issue="perdu"] b { color: #f0a89c; }

.dcj-bulle.sort { animation: dcj-bulle-sort .4s forwards; }

/* Elles montent en apparaissant et redescendent en partant : le mouvement
   suit le sens de lecture depuis le bas de l'écran. */
@keyframes dcj-bulle-entre {
    from { transform: translateY(18px) scale(.96); opacity: 0; }
    to   { transform: translateY(0) scale(1); opacity: 1; }
}

@keyframes dcj-bulle-sort {
    to { transform: translateY(14px) scale(.97); opacity: 0; }
}

@media (max-width: 620px) {
    .dcj-accueil h1 { font-size: 34px; }
    .dcj-niveaux { grid-template-columns: 1fr; }
    .dcj-nettete { flex-wrap: wrap; }
}

.dcj-connexion {
    max-width: 380px;
    margin: 0 auto 22px;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--ink-mute);
}

/* Le vinyle d'or : même galette, mais dorée, avec un éclat qui la traverse. */

/* Le diamant : facetté plutôt que rond, pour qu'il ne se confonde pas. */

/* Les statistiques générales, sous le choix des niveaux. */

/* Le genre, guide permanent sous la pochette. */
/* Le genre : c'est un indice, il doit se lire sans qu'on le cherche. */
.dcj-guide {
    display: block;
    margin: 0 auto 16px;
    padding: 5px 16px;
    width: fit-content;
    border-radius: 999px;
    background: var(--paper-hi);
    border: var(--border);
    font-family: var(--font-display);
    font-size: 15px;
    color: var(--ink);
    text-align: center;
}

/* ---------- Les gains qui bougent ----------------------------------------
   Un chiffre qui change sans bouger ne se remarque pas. Celui qui traverse
   l'écran dit d'où vient le gain et où il atterrit.
   ---------------------------------------------------------------------- */

.dcj-vol {
    position: fixed;
    z-index: 80;
    font-family: var(--font-display);
    font-size: 22px;
    color: var(--teal);
    text-shadow: 0 2px 6px rgba(23, 18, 15, .3);
    pointer-events: none;
    animation: dcj-vol .75s cubic-bezier(.4, 0, .2, 1) forwards;
}

@keyframes dcj-vol {
    0%   { transform: translate(-50%, -50%) scale(.6); opacity: 0; }
    18%  { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
    100% {
        transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(.7);
        opacity: 0;
    }
}

/* Le compteur qui reçoit : un sursaut bref, en teal. */
.est-gagnant {
    color: var(--teal);
    animation: dcj-sursaut .45s ease-out;
}

@keyframes dcj-sursaut {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.32); }
    100% { transform: scale(1); }
}

/* Le trophée décroché : il se pose, il ne surgit pas. */
.dcj-fin__prix.est-decroche {
    animation: dcj-trophee .7s cubic-bezier(.2, .8, .3, 1.1);
}

.dcj-fin__prix.est-decroche 
@keyframes dcj-trophee {
    0%   { transform: scale(.85); opacity: 0; }
    100% { transform: scale(1); opacity: 1; }
}

@keyframes dcj-tourne-prix {
    0%   { transform: rotate(-180deg) scale(.4); }
    100% { transform: rotate(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .dcj-vol, .est-gagnant, .dcj-fin__prix.est-decroche,
    .dcj-fin__prix.est-decroche }

/* Le prix décroché, en fin de partie. */
.dcj-fin__prix {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    margin-bottom: 18px;
    padding: 16px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
}

.dcj-fin__prix b { font-family: var(--font-display); font-size: 17px; color: var(--gold); }
.dcj-fin__prix small { font-size: 12px; color: var(--ink-mute); }

/* ---------- Régie 10Cover : outils, chiffres, classement ------------------ */

.dc-outils {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 16px;
}

.dc-outils--espacee { justify-content: space-between; }

.dc-champ-select {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12.5px;
    color: var(--ink-mute);
}

.dc-champ-select select {
    padding: 6px 10px;
    border: var(--border);
    border-radius: 9px;
    background: var(--paper-hi);
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--ink);
}

.dc-filtre { display: flex; gap: 5px; }

.dc-filtre button {
    padding: 5px 12px;
    border: var(--border);
    border-radius: 999px;
    background: transparent;
    font-family: var(--font-ui);
    font-size: 12px;
    color: var(--ink-mute);
    cursor: pointer;
}

.dc-filtre button.is-actif {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--paper-hi);
}

.dc-chiffres {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
    gap: 9px;
    margin: 18px 0 20px;
}

.dc-chiffre {
    padding: 12px 10px;
    border: var(--border);
    border-radius: 11px;
    background: var(--paper-hi);
    text-align: center;
}

.dc-chiffre b {
    display: block;
    font-family: var(--font-display);
    font-size: 21px;
    line-height: 1.1;
}

.dc-chiffre small { font-size: 10.5px; color: var(--ink-mute); }

.dc-podium { margin: 0 0 12px; padding-left: 20px; }

.dc-podium li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 5px 0;
    border-bottom: 1px dashed var(--paper-deep);
}

.dc-podium li:last-child { border-bottom: none; }
.dc-podium span { font-family: var(--font-display); font-size: 14px; }
.dc-podium em { font-style: normal; font-family: var(--font-mono); font-size: 12px; color: var(--ink-mute); }

.dc-message {
    margin: 12px 0 0;
    font-size: 12.5px;
    color: var(--teal);
}

.dc-message[data-etat="ko"] { color: var(--red-deep); }

/* ---------- La barre du joueur -------------------------------------------
   Ses points et ses trophées, toujours en vue, sans encombrer le jeu.
   ---------------------------------------------------------------------- */

.dcj-barre {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-bottom: 22px;
    padding: 11px 18px;
    border: var(--border);
    border-radius: 999px;
    background: var(--paper-hi);
}

.dcj-barre__points { display: flex; align-items: baseline; gap: 5px; }

.dcj-barre__points b {
    font-family: var(--font-display);
    font-size: 21px;
    line-height: 1;
}

.dcj-barre__points small { font-size: 11px; color: var(--ink-mute); }

.dcj-barre__prix { display: flex; gap: 14px; margin-left: auto; }

.dcj-prix { display: flex; align-items: center; gap: 6px; }
.dcj-prix b { font-family: var(--font-mono); font-size: 14px; }

.dcj-barre__lien {
    padding: 5px 14px;
    border: var(--border);
    border-radius: 999px;
    font-size: 12.5px;
    color: var(--ink);
    text-decoration: none;
}

.dcj-barre__lien:hover { background: var(--ink); color: var(--paper-hi); }

/* ---------- Les gains qui bougent ----------------------------------------
   Un chiffre qui change sans bouger ne se remarque pas. Celui qui traverse
   l'écran dit d'où vient le gain et où il atterrit.
   ---------------------------------------------------------------------- */

.dcj-vol {
    position: fixed;
    z-index: 80;
    font-family: var(--font-display);
    font-size: 22px;
    color: var(--teal);
    text-shadow: 0 2px 6px rgba(23, 18, 15, .3);
    pointer-events: none;
    animation: dcj-vol .75s cubic-bezier(.4, 0, .2, 1) forwards;
}

@keyframes dcj-vol {
    0%   { transform: translate(-50%, -50%) scale(.6); opacity: 0; }
    18%  { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
    100% {
        transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(.7);
        opacity: 0;
    }
}

/* Le compteur qui reçoit : un sursaut bref, en teal. */
.est-gagnant {
    color: var(--teal);
    animation: dcj-sursaut .45s ease-out;
}

@keyframes dcj-sursaut {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.32); }
    100% { transform: scale(1); }
}

/* Le trophée décroché : il se pose, il ne surgit pas. */
.dcj-fin__prix.est-decroche {
    animation: dcj-trophee .7s cubic-bezier(.2, .8, .3, 1.1);
}

.dcj-fin__prix.est-decroche 
@keyframes dcj-trophee {
    0%   { transform: scale(.85); opacity: 0; }
    100% { transform: scale(1); opacity: 1; }
}

@keyframes dcj-tourne-prix {
    0%   { transform: rotate(-180deg) scale(.4); }
    100% { transform: rotate(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .dcj-vol, .est-gagnant, .dcj-fin__prix.est-decroche,
    .dcj-fin__prix.est-decroche }

/* Le prix décroché, en fin de partie. */
.dcj-fin__prix {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    margin-bottom: 18px;
    padding: 16px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
}

.dcj-fin__prix .dcj-fin__prix .dcj-fin__prix b { font-family: var(--font-display); font-size: 17px; color: var(--gold); }
.dcj-fin__prix small { font-size: 12px; color: var(--ink-mute); }

/* ---------- La page de classement ----------------------------------------- */

.dcl-titre { margin: 0 0 18px; font-size: 34px; text-align: center; }

.dcl-onglets {
    display: flex;
    justify-content: center;
    gap: 6px;
    margin-bottom: 22px;
}

.dcl-onglets button {
    padding: 7px 18px;
    border: var(--border);
    border-radius: 999px;
    background: transparent;
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--ink-mute);
    cursor: pointer;
}

.dcl-onglets button.is-actif {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--paper-hi);
}

/* ---------- Le classement, en compte rendu ---------------------------------
   Chaque ligne était une carte bordée sur fond clair, et chaque chiffre une
   tuile. Empilés, ces cadres pesaient plus que les données qu'ils portaient.

   Un classement se lit comme un tableau : des lignes séparées par un filet,
   des colonnes alignées, rien d'autre. Le décor du site n'a pas à s'inviter
   dans un relevé de scores.
   -------------------------------------------------------------------- */

.dcl-table { margin: 0; padding: 0; list-style: none; }

.dcl-table li {
    display: grid;
    grid-template-columns: 30px 1fr auto auto;

    /* Centré, et non aligné sur la ligne d'écriture : un portrait posé sur
       une base de texte pend sous la ligne. */
    align-items: center;
    gap: 14px;
    padding: 9px 4px;
    border-bottom: 1px solid var(--paper-deep);
}

.dcl-table li:last-child { border-bottom: none; }

/* Les trois premiers se détachent par le rang, pas par un liseré coloré. */
.dcl-table li:nth-child(-n+3) .dcl-rang {
    font-family: var(--font-display);
    font-size: 15px;
    color: var(--ink);
}

.dcl-rang {
    font-family: var(--font-mono);
    font-size: 13px;
    color: var(--ink-mute);
    text-align: right;
}

.dcl-nom { font-size: 15px; }
.dcl-detail { font-size: 11px; color: var(--ink-mute); }

.dcl-valeur {
    font-family: var(--font-mono);
    font-size: 15px;
    font-weight: 700;
}

/* Les chiffres généraux : un simple relevé en deux colonnes, libellé à
   gauche et valeur à droite, sans tuile ni bordure. */
.dcl-chiffres {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 0 34px;
}

.dcl-chiffre {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 4px;
    border-bottom: 1px solid var(--paper-deep);
}

.dcl-chiffre b {
    order: 2;
    font-family: var(--font-mono);
    font-size: 15px;
}

.dcl-chiffre small { font-size: 12.5px; color: var(--ink-mute); }

@media (max-width: 560px) {
    .dcj-barre { flex-wrap: wrap; border-radius: 16px; }
    .dcl-table li { grid-template-columns: 26px 1fr auto; }
    .dcl-detail { display: none; }
}

/* ---------- Le butin dans l'en-tête --------------------------------------
   À gauche du nom de compte : le joueur voit son score partout sur le site,
   pas seulement sur la page du jeu.
   ---------------------------------------------------------------------- */

/* Le butin occupe sa propre ligne, sous le menu.
   Depuis que le menu est en position absolue, il ne réserve plus de hauteur
   dans le flux : le butin remontait à son niveau et passait sous les liens.
   La marge rend cette hauteur. */
/* Le butin se glisse entre le menu et le nom de compte, sans réclamer de
   place : avec « flex: 1 0 100% » il occupait une ligne entière et rejetait
   le compte sur une troisième. */
.pub-butin-zone {
    display: flex;
    flex: 0 1 auto;
    justify-content: center;
    min-width: 0;
}

.pub-butin {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: 5px 16px;
    border: 1px solid rgba(239, 226, 204, .18);
    border-radius: 999px;
}

/* Ses éléments se centrent aussi les uns par rapport aux autres. */
.pub-butin > * { flex: 0 0 auto; }

.pub-butin__points {
    display: flex;
    align-items: baseline;
    gap: 4px;
}

.pub-butin__points small {
    font-size: 10.5px;
    color: var(--paper-hi);
    opacity: .6;
}

.pub-butin__points b {
    font-family: var(--font-display);
    font-size: 15px;
    color: var(--paper-hi);
}

.pub-butin__prix { display: flex; align-items: center; gap: 5px; }

.pub-butin__prix b {
    font-family: var(--font-mono);
    font-size: 12.5px;
    color: var(--paper-hi);
    opacity: .85;
}

/* Cliquables : on veut pouvoir les regarder de près. */
button.pub-butin__prix {
    padding: 2px 4px;
    border: none;
    border-radius: 9px;
    background: none;
    cursor: pointer;
    transition: transform .14s;
}

button.pub-butin__prix:hover { transform: scale(1.12); }

/* Sur écran étroit, seuls les trophées restent : le score prend trop de
   place à côté de la navigation. */
@media (max-width: 900px) {
    .pub-butin { gap: 9px; padding: 4px 10px; margin-right: 8px; }
    .pub-butin__points { display: none; }
}

@media (max-width: 560px) {
    .pub-butin { display: none; }
}

/* ---------- Un trophée vu de près ----------------------------------------
   À vingt-huit pixels, on devine une couleur. En grand, on voit les sillons
   de l'or et les facettes du diamant.
   ---------------------------------------------------------------------- */

.gemme-vue {
    position: fixed;
    inset: 0;
    z-index: 120;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(23, 18, 15, .72);
    animation: gemme-fond .2s ease-out;
}

.gemme-vue.sort { animation: gemme-fond .22s ease-in reverse forwards; }

.gemme-vue__boite {
    max-width: 380px;
    padding: 32px 30px 26px;
    border: var(--border);
    border-radius: 20px;
    background: var(--paper-hi);
    box-shadow: 0 16px 46px rgba(0, 0, 0, .45);
    text-align: center;
    animation: gemme-boite .32s cubic-bezier(.2, .8, .3, 1.1);
}

/* La pièce en grand : c'est elle qu'on est venu voir. */
.gemme-vue__piece {
    width: 160px !important;
    height: 160px !important;
    margin: 0 auto 18px;
    animation: gemme-tourne 1.4s cubic-bezier(.15, .7, .3, 1);
}

.gemme-vue__piece::after { width: 18px !important; height: 18px !important; }

.gemme-vue__boite b {
    display: block;
    margin-bottom: 4px;
    font-family: var(--font-display);
    font-size: 23px;
}

.gemme-vue__compte {
    margin: 0 0 16px;
    font-family: var(--font-mono);
    font-size: 12.5px;
    color: var(--ink-mute);
}

.gemme-vue__regle {
    margin: 0 0 10px;
    padding: 11px 14px;
    border-radius: 11px;
    background: var(--paper);
    font-size: 14px;
    line-height: 1.5;
}

.gemme-vue__note {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--ink-mute);
}

@keyframes gemme-fond {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes gemme-boite {
    from { transform: translateY(18px) scale(.94); opacity: 0; }
    to   { transform: translateY(0) scale(1); opacity: 1; }
}

@keyframes gemme-tourne {
    from { transform: rotate(-200deg) scale(.5); }
    to   { transform: rotate(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .gemme-vue, .gemme-vue__boite, .gemme-vue__piece { animation-duration: .01s; }
}

/* ---------- Les pièces, dessinées en SVG ---------------------------------
   Le même tracé sert partout : vignette de l'en-tête, trophée de fin de
   partie, aperçu en grand. On ne fait que changer sa taille.
   ---------------------------------------------------------------------- */

.vnl { display: block; }

.pub-butin .vnl { filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .35)); }

button.pub-butin__prix {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 2px 4px;
    border: none;
    border-radius: 9px;
    background: none;
    cursor: pointer;
    transition: transform .14s;
}

button.pub-butin__prix:hover { transform: scale(1.12); }

/* Le trophée de fin de partie. */
.dcj-prix-piece {
    margin-bottom: 4px;
    animation: dcj-tourne-prix 1.1s cubic-bezier(.15, .7, .3, 1);
}

.dcj-prix-piece .vnl { width: 74px; height: 74px; }

/* L'aperçu en grand : c'est lui qu'on est venu voir. */
.gemme-vue__piece {
    display: flex;
    justify-content: center;
    margin-bottom: 18px;
    animation: gemme-tourne 1.4s cubic-bezier(.15, .7, .3, 1);
    filter: drop-shadow(0 6px 16px rgba(0, 0, 0, .28));
}

/* Le vinyle d'un niveau : il tourne au survol, comme une platine qui
   démarre. */
.vnl--niveau {
    transition: transform .6s cubic-bezier(.2, .7, .3, 1);
    filter: drop-shadow(0 3px 6px rgba(23, 18, 15, .3));
}

.dcj-niveau:hover:not([data-fait]) .vnl--niveau { transform: rotate(200deg); }
.dcj-niveau[data-fait] .vnl--niveau { filter: grayscale(.85) opacity(.7); }

/* ---------- Le rideau de lancement ----------------------------------------
   Une respiration entre le menu et la partie : le vinyle du niveau tourne,
   puis s'efface. Sans fond opaque — la page reste visible derrière, seulement
   assombrie, ce qui garde le contexte.
   ---------------------------------------------------------------------- */

.dcj-rideau {
    position: fixed;
    inset: 0;
    z-index: 110;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(23, 18, 15, .88);
    animation: dcj-rideau-entre .3s ease-out;
}

.dcj-rideau.sort { animation: dcj-rideau-sort .38s ease-in forwards; }

.dcj-rideau__boite {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    text-align: center;
}

/* Le disque tourne : deux tours et demi, freinés sur la fin, comme une
   platine qui trouve sa vitesse. */
.dcj-rideau__piece {
    margin-bottom: 18px;
    filter: drop-shadow(0 8px 24px rgba(0, 0, 0, .5));
    animation: dcj-rideau-tourne 1.3s cubic-bezier(.2, .65, .25, 1);
}

.dcj-rideau__boite b {
    font-family: var(--font-display);
    font-size: 46px;
    color: var(--paper-hi);
    animation: dcj-rideau-texte .5s .2s backwards;
}

.dcj-rideau__boite small {
    font-size: 14px;
    color: var(--paper);
    opacity: .7;
    animation: dcj-rideau-texte .5s .32s backwards;
}

/* La couleur du niveau teinte le mot. */
.dcj-rideau[data-niveau="easy"] b   { color: var(--teal); }
.dcj-rideau[data-niveau="medium"] b { color: var(--gold); }
.dcj-rideau[data-niveau="hard"] b   { color: var(--red); }

@keyframes dcj-rideau-entre {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes dcj-rideau-sort {
    from { opacity: 1; transform: scale(1); }
    to   { opacity: 0; transform: scale(1.08); }
}

@keyframes dcj-rideau-tourne {
    from { transform: rotate(0) scale(.55); }
    to   { transform: rotate(900deg) scale(1); }
}

@keyframes dcj-rideau-texte {
    from { transform: translateY(10px); opacity: 0; }
    to   { transform: translateY(0); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .dcj-rideau, .dcj-rideau__piece, .dcj-rideau__boite b,
    .dcj-rideau__boite small { animation-duration: .01s; }
}

/* ---------- Catalogue et défis, côte à côte ------------------------------
   Les deux se consultent ensemble : on regarde ce qu'on a en stock avant de
   décider d'un défi. Les séparer obligeait à faire défiler entre les deux.
   ---------------------------------------------------------------------- */

.dc-duo {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 28px;
}

/* Un trait entre les deux, plutôt qu'un simple espace : sans lui, les
   colonnes se lisent comme un seul bloc. */
.dc-duo__part + .dc-duo__part {
    padding-left: 28px;
    border-left: 1px dashed var(--paper-deep);
}

.dc-duo__part > h2:first-child { margin-top: 0; }

/* Les compteurs passent sur une seule ligne : la colonne est deux fois plus
   étroite qu'un panneau entier. */
.dc-duo .dc-compte { max-width: none; }

@media (max-width: 900px) {
    .dc-duo { grid-template-columns: 1fr; gap: 22px; }

    .dc-duo__part + .dc-duo__part {
        padding-left: 0;
        padding-top: 22px;
        border-left: none;
        border-top: 1px dashed var(--paper-deep);
    }
}

/* ---------- L'état du jour, en régie -------------------------------------
   Une case par difficulté : attribué ou non, et combien l'ont joué. C'est ce
   qu'on regarde avant de décider de relancer.
   ---------------------------------------------------------------------- */

.dc-jour {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    margin: 16px 0 4px;
}

.dc-jour__case {
    padding: 10px 12px;
    border: var(--border);
    border-left: 4px solid var(--paper-deep);
    border-radius: 11px;
    background: var(--paper-hi);
}

.dc-jour__case b {
    display: block;
    font-family: var(--font-display);
    font-size: 14px;
}

.dc-jour__case small {
    font-size: 10.5px;
    color: var(--ink-mute);
}

/* Attribué : le liseré prend la couleur du niveau. Libre : il reste terne. */
.dc-jour__case[data-etat="pris"][data-niveau="easy"]   { border-left-color: var(--teal); }
.dc-jour__case[data-etat="pris"][data-niveau="medium"] { border-left-color: var(--gold); }
.dc-jour__case[data-etat="pris"][data-niveau="hard"]   { border-left-color: var(--red); }

.dc-jour__case[data-etat="libre"] { opacity: .6; }
.dc-jour__case[data-etat="libre"] small { font-style: italic; }

/* Le lien vers l'autre page du jeu : discret mais toujours là. */
/* Le lien vers l'autre page du jeu. La marge basse est plus large que la
   haute : il se collait aux cartes de difficulté juste en dessous. */
/*
 * Deux liens côte à côte, sur une ligne de flux.
 *
 * En texte simple avec des marges tactiles négatives, leurs zones sensibles
 * se recouvraient : on visait l'un et on ouvrait l'autre. En boutons
 * distincts, chacun a ses limites.
 */
.dcj-liens {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 10px;
    margin: 22px 0 34px;
}

.dcj-liens a {
    padding: 9px 16px;
    border: var(--border);
    border-radius: 999px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    font-size: 13.5px;
    font-weight: 600;
    text-decoration: none;
}

@media (max-width: 620px) {
    /*
     * Chacun prend la moitié.
     *
     * Laissés à leur largeur naturelle, ils passaient l'un sous l'autre dès
     * que la somme dépassait la ligne — ce qui arrive presque toujours sur un
     * téléphone. Partagés en deux, ils tiennent côte à côte.
     */
    .dcj-liens { flex-wrap: nowrap; }

    .dcj-liens a {
        flex: 1 1 0;
        min-width: 0;
        text-align: center;
        padding: 10px 6px;
        font-size: 12.5px;
    }
}

/* Hors connexion le lien vient après le bouton Twitch et ferme la page : il
   n'a pas besoin de marge basse. Connecté, il précède les cartes de
   difficulté, et doit s'en écarter — d'où la règle générale plus haut, qu'on
   ne surcharge que dans le premier cas. */
.dcj-accueil:has(.btn--primary) .dcj-liens { margin: 18px 0 0; }

.dcj-liens a {
    display: inline-block;
    padding: 6px 18px;
    border: var(--border);
    border-radius: 999px;
    font-size: 13px;
    color: var(--ink-2);
    text-decoration: none;
}

.dcj-liens a:hover { background: var(--ink); border-color: var(--ink); color: var(--paper-hi); }

/* ======================================================================
   La remise du trophée
   ----------------------------------------------------------------------
   La pochette devinée glisse jusqu'au centre, tremble, et rend son disque —
   comme on tire un vinyle de son carton. La galette s'avance ensuite et
   s'écrase.

   Trois temps, marqués par des classes posées en JavaScript :
     départ        la pochette rejoint le centre, puis vibre
     est-tiree     le vinyle sort, la pochette s'écarte
     est-frappe    l'impact
   ====================================================================== */

.dcj-sacre {
    position: fixed;
    inset: 0;
    z-index: 130;
    display: flex;
    align-items: center;
    justify-content: center;
    background: radial-gradient(circle at 50% 48%,
        rgba(18, 14, 12, .93) 0%, rgba(12, 9, 8, .98) 68%);
    cursor: pointer;
    animation: sacre-fond .35s ease-out;
}

.dcj-sacre.sort { animation: sacre-sortie .45s ease-in forwards; }

.dcj-sacre[data-prix="or"]      { --eclat: #f3c661; --profond: #8a5a12; }
.dcj-sacre[data-prix="argent"]  { --eclat: #dce4ea; --profond: #6f7c88; }
.dcj-sacre[data-prix="diamant"] { --eclat: #dceaf5; --profond: #2c5f7d; }

.dcj-sacre__scene {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Une taille propre : sans elle, les disques en absolu n'auraient aucun
       repère et se caleraient chacun où ils peuvent. */
    width: 340px;
    height: 340px;
    margin-bottom: 6vh;
    perspective: 1200px;
}

@media (max-width: 620px) {
    .dcj-sacre__scene { width: 230px; height: 230px; }
}

/* ---------- La pochette --------------------------------------------------
   Elle part de sa position réelle à l'écran — les variables posées en
   JavaScript disent d'où — puis rejoint le centre en grandissant. On suit
   des yeux le même objet du début à la fin.
   ---------------------------------------------------------------------- */

.dcj-sacre__pochette {
    position: absolute;
    z-index: 3;
    width: 340px;
    height: 340px;
    border: 3px solid #17120f;
    border-radius: 16px;
    background: #17120f;
    overflow: hidden;
    box-shadow: 0 22px 55px rgba(0, 0, 0, .6);
    /* Devant le vinyle : le disque est encore dedans, on ne doit pas le
       voir. Il ne passera devant qu'une fois sorti. */
}

/* Le trajet depuis la place d'origine, puis le tremblement.
   Une transition plutôt qu'une animation : le point de départ est posé en
   JavaScript, il ne peut pas vivre dans une règle. */
.dcj-sacre__pochette.est-partie {
    transition: transform .9s cubic-bezier(.22, .68, .3, 1);
    animation: sacre-tremble .7s .95s ease-in-out;
}

.dcj-sacre__pochette img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Une fois le disque sorti, le carton bascule et s'efface. */
.dcj-sacre.est-tiree .dcj-sacre__pochette {
    animation: sacre-carton 1.3s cubic-bezier(.5, 0, .55, 1) forwards;
}

/* ---------- Le vinyle ----------------------------------------------------
   Il commence caché derrière la pochette, glisse hors d'elle par la droite,
   puis revient au centre et s'écrase.
   ---------------------------------------------------------------------- */

/* ---------- Deux disques d'un coup ---------------------------------------
   Ils sortent ensemble de la même pochette et se posent côte à côte. Aucun
   ne change de taille : ce sont deux disques sur la même table, pas un
   premier plan et un lointain.
   ---------------------------------------------------------------------- */

/*
 * Les deux se superposent exactement au départ.
 *
 * L'un était en flux et l'autre en absolu : leurs origines ne coïncidaient
 * pas, et l'on voyait le second sortir décalé vers la gauche avant même le
 * début du mouvement. Les deux occupent maintenant la même boîte, centrée
 * sur la scène.
 */
.dcj-sacre[data-nombre="2"] .dcj-sacre__piece {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Les deux sortent ensemble, sur la même courbe : le décalage donnait deux
   temps morts, un pour chaque disque. Seule leur destination diffère. */
.dcj-sacre[data-nombre="2"].est-tiree .dcj-sacre__piece[data-rang="1"] {
    animation: sacre-sortie-cote 1.55s cubic-bezier(.34, .12, .3, 1) forwards;
}

.dcj-sacre[data-nombre="2"].est-tiree .dcj-sacre__piece[data-rang="0"] {
    animation: sacre-extraction 1.15s cubic-bezier(.34, .12, .28, 1) forwards,
               sacre-choc .6s 1.15s cubic-bezier(.2, .95, .3, 1.5);
}

/* Le disque qui se pose à côté.
   Le contrecoup est inclus dans la trajectoire : une seconde animation ne
   pouvait pas le porter, car deux « transform » sur le même élément se
   remplacent — le choc ramenait le disque au centre en effaçant sa
   translation. */
@keyframes sacre-sortie-cote {
    0%   { transform: translate(-40px, 0) scale(1); opacity: 0; }
    10%  { opacity: 1; }
    50%  { transform: translate(410px, 12px) scale(1); opacity: 1; }
    86%  { transform: translate(178px, 34px) scale(1.16, .86); opacity: 1; }
    94%  { transform: translate(178px, 34px) scale(.96, 1.05); opacity: 1; }
    100% { transform: translate(178px, 34px) scale(1); opacity: 1; }
}

.dcj-sacre__piece {
    position: relative;
    z-index: 1;
    /* Pas de halo tant que le disque est dans la pochette : il transparaissait
       à travers le carton, et on devinait la couleur du prix avant qu'il
       sorte. Il s'allume au moment où le disque se dégage. */
    filter: none;
    transition: filter .5s ease-out;
    transform: translateX(0);
    opacity: 0;
}

/* Le disque ne passe devant qu'une fois dégagé de la pochette. Le faire plus
   tôt le montrait par-dessus le carton alors qu'il est censé être dedans. */
.dcj-sacre.est-degagee .dcj-sacre__piece {
    z-index: 4;
    filter: drop-shadow(0 0 30px var(--eclat));
}

.dcj-sacre.est-tiree .dcj-sacre__piece {
    animation: sacre-extraction 1.15s cubic-bezier(.34, .12, .28, 1) forwards,
               sacre-choc .6s 1.15s cubic-bezier(.2, .95, .3, 1.5);
}

.dcj-sacre__piece .vnl {
    /* La pochette fait 340 : un disque en fait toujours un peu moins, jamais
       beaucoup moins. À 300 il paraissait perdu dedans. */
    width: 326px;
    height: 326px;
    /* Un disque ne s'immobilise pas : il tourne lentement, du début à la
       fin. La rotation vit sur le SVG, pas sur son conteneur, qui porte déjà
       l'extraction et le contrecoup. */
    animation: sacre-tourne-lent 14s linear infinite;
}

@keyframes sacre-tourne-lent {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@media (max-width: 620px) {
    .dcj-sacre__pochette { width: 230px; height: 230px; }
    .dcj-sacre__piece .vnl { width: 220px; height: 220px; }
}

/* ---------- L'onde de choc ----------------------------------------------- */

.dcj-sacre__onde {
    position: absolute;
    top: 44%;
    left: 50%;
    width: 120px;
    height: 120px;
    border: 4px solid var(--eclat);
    border-radius: 50%;
    opacity: 0;
    transform: translate(-50%, -50%);
    pointer-events: none;
}

.dcj-sacre.est-frappe .dcj-sacre__onde {
    animation: sacre-onde 1s cubic-bezier(.1, .7, .3, 1) forwards;
}

.dcj-sacre.est-frappe .dcj-sacre__onde--2 {
    animation: sacre-onde 1.1s cubic-bezier(.1, .7, .3, 1) .15s forwards;
    border-width: 2px;
}

/* ---------- Les éclats ---------------------------------------------------- */

.dcj-sacre__eclats {
    position: absolute;
    top: 44%;
    left: 50%;
    pointer-events: none;
}

.dcj-sacre__eclats i {
    position: absolute;
    width: 9px;
    height: 9px;
    border-radius: 2px;
    background: var(--eclat);
    opacity: 0;
    animation: sacre-eclat .95s cubic-bezier(.2, .7, .4, 1) forwards;
}

/* ---------- Le nom -------------------------------------------------------- */

.dcj-sacre__texte {
    position: absolute;
    top: calc(44% + 200px);
    left: 50%;
    z-index: 3;
    width: min(420px, 84vw);
    text-align: center;
    transform: translateX(-50%);
}

.dcj-sacre__texte b {
    display: block;
    font-family: var(--font-display);
    font-size: clamp(28px, 7vw, 44px);
    line-height: 1.1;
    color: var(--eclat);
    text-shadow: 0 0 26px var(--eclat), 0 3px 0 var(--profond);
    opacity: 0;
    animation: sacre-nom .55s 2.85s cubic-bezier(.2, .9, .3, 1.3) forwards;
}

.dcj-sacre__texte small {
    display: block;
    margin-top: 8px;
    font-size: 13.5px;
    color: var(--paper);
    opacity: 0;
    animation: sacre-note .5s 3.1s ease-out forwards;
}

/* ---------- Le déroulé ---------------------------------------------------- */

@keyframes sacre-fond {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes sacre-sortie {
    to { opacity: 0; transform: scale(1.06); }
}

/* Elle tremble : d'abord à peine, puis de plus en plus — quelque chose
   pousse à l'intérieur. */
/* Le tremblement s'intensifie. Six oscillations, pas dix : au-delà, les
   étapes sont trop rapprochées pour que le navigateur les interpole, et le
   mouvement devient une vibration illisible. */
@keyframes sacre-tremble {
    0%   { transform: translate(0, 0) rotate(0deg) scale(1); }
    18%  { transform: translate(-3px, 2px) rotate(-.6deg); }
    36%  { transform: translate(5px, -2px) rotate(1deg); }
    54%  { transform: translate(-7px, 3px) rotate(-1.4deg) scale(1.01); }
    72%  { transform: translate(8px, -3px) rotate(1.7deg) scale(1.02); }
    88%  { transform: translate(-6px, 2px) rotate(-1.2deg) scale(1.03); }
    100% { transform: translate(0, 0) rotate(0deg) scale(1); }
}

/* Le carton, vidé, bascule sur le côté et s'en va. */
/* Le carton reste en place le temps que le disque en sorte, puis se pose en
   biais sur le côté. Il s'effaçait : la pochette qu'on venait de deviner
   disparaissait alors qu'elle mérite de rester en vue. */
/* La pochette garde sa taille : elle se pose à côté, elle ne s'éloigne pas.
   La réduire donnait l'impression qu'elle partait au loin, alors qu'elle
   reste sur la même table. */
@keyframes sacre-carton {
    0%   { transform: translate(0, 0) rotate(0deg); }
    45%  { transform: translate(-16px, 6px) rotate(-3deg); }
    100% { transform: translate(-235px, 66px) rotate(-13deg); }
}

/* Le disque sort par la droite, comme d'une vraie pochette : il glisse
   horizontalement, se dégage entièrement, puis revient se poser au centre.

   Les temps sont espacés — les précédents étaient si serrés que le
   navigateur passait de l'un à l'autre sans interpoler, ce qui donnait ces
   à-coups. */
/* La pochette fait 340 de large : le disque doit parcourir au moins autant
   pour en sortir vraiment. À 215 il restait à cheval dessus et semblait la
   traverser. */
/* Le disque sort à sa taille définitive : le voir grandir en chemin donnait
   l'impression qu'il venait de plus loin que la pochette. */
@keyframes sacre-extraction {
    0%   { transform: translate(-40px, 0); opacity: 0; }
    10%  { opacity: 1; }
    58%  { transform: translate(370px, 0); opacity: 1; }
    100% { transform: translate(0, 0); opacity: 1; }
}

/* Le contrecoup de l'atterrissage. */
@keyframes sacre-choc {
    0%   { transform: scale(1); }
    28%  { transform: scale(1.18, .84); }
    62%  { transform: scale(.95, 1.06); }
    100% { transform: scale(1); }
}

@keyframes sacre-onde {
    0%   { opacity: .9; width: 100px; height: 100px; border-width: 5px; }
    100% { opacity: 0; width: min(150vw, 900px); height: min(150vw, 900px); border-width: 1px; }
}

@keyframes sacre-eclat {
    0%   { opacity: 1; transform: translate(-50%, -50%) scale(1.3) rotate(0deg); }
    100% {
        opacity: 0;
        transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy)))
                   scale(.2) rotate(var(--tour));
    }
}

@keyframes sacre-nom {
    from { opacity: 0; transform: translateY(26px) scale(.86); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes sacre-note {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: .75; transform: translateY(0); }
}

/* Le mouvement peut gêner : on garde l'annonce, on retire la mise en scène. */
@media (prefers-reduced-motion: reduce) {
    .dcj-sacre__pochette,
    .dcj-sacre__piece,
    .dcj-sacre.est-tiree .dcj-sacre__pochette,
    .dcj-sacre.est-tiree .dcj-sacre__piece,
    .dcj-sacre__texte b,
    .dcj-sacre__texte small,
    .dcj-sacre__eclats i,
    .dcj-sacre.est-frappe .dcj-sacre__onde {
        animation-duration: .01s;
        animation-delay: 0s;
    }
}

/* ---------- Le diamant scintille -----------------------------------------
   Des éclats naissent et meurent sur la pierre, à des endroits et des
   moments différents. Rien de fixe : une gemme ne brille pas au même
   endroit deux secondes de suite.

   Uniquement en grand — sur la vignette de l'en-tête, ces effets ne seraient
   qu'un tremblotement illisible.
   ---------------------------------------------------------------------- */

.dcj-sacre__poussiere {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 6;
    pointer-events: none;
}

/* Chaque éclat : une étoile à quatre branches, dessinée en deux barres
   croisées. Elle naît, gonfle, tourne un peu, puis s'éteint. */
.dcj-sacre__poussiere i,
.gemme-vue__piece .etincelle {
    position: absolute;
    width: var(--taille, 14px);
    height: var(--taille, 14px);
    opacity: 0;
    background:
        linear-gradient(to right, transparent 46%, #ffffff 50%, transparent 54%),
        linear-gradient(to bottom, transparent 46%, #ffffff 50%, transparent 54%);
    filter: drop-shadow(0 0 6px rgba(230, 244, 252, .95));
    animation-name: sacre-etincelle;
    animation-timing-function: cubic-bezier(.3, 0, .4, 1);
    animation-iteration-count: infinite;
}

/* L'éclat apparaît d'un point, s'ouvre en croix, puis se referme. */
@keyframes sacre-etincelle {
    0%, 100% { opacity: 0; transform: translate(-50%, -50%) scale(.1) rotate(0deg); }
    12%      { opacity: 1; transform: translate(-50%, -50%) scale(1.15) rotate(25deg); }
    28%      { opacity: .85; transform: translate(-50%, -50%) scale(.85) rotate(45deg); }
    46%      { opacity: 0; transform: translate(-50%, -50%) scale(.2) rotate(70deg); }
}

/* Le balayage a été retiré : la bande claire suivait la boîte du
   conteneur, pas le disque, et traversait tout l'écran. Le halo qui respire
   et les étincelles suffisent. */

/* Le halo du diamant respire, au lieu de rester fixe.

   Cette règle déclenchait aussi l'extraction, et sans « est-tiree » : le
   disque de diamant partait donc dès l'apparition de la scène, alors que
   les autres attendaient d'être tirés de la pochette. D'où ce mouvement qui
   ne ressemblait à aucun autre. */
.dcj-sacre[data-prix="diamant"].est-tiree .dcj-sacre__piece {
    animation-name: sacre-extraction, sacre-choc, sacre-respire;
    animation-duration: 1.15s, .6s, 3.2s;
    /* La respiration attend que le disque soit dehors : elle porte un
       « filter », qui écraserait le « filter: none » du départ. */
    animation-delay: 0s, 1.15s, 1.15s;
    animation-iteration-count: 1, 1, infinite;
    animation-fill-mode: forwards, none, none;
}

/* En combo, c'est le diamant qui attend sur le côté, et l'or qui prend le
   centre. Chacun garde donc sa propre trajectoire. */
.dcj-sacre[data-prix="diamant"][data-nombre="2"].est-tiree
.dcj-sacre__piece[data-rang="1"] {
    animation-name: sacre-sortie-cote, sacre-respire;
    animation-duration: 1.55s, 3.2s;
    animation-delay: 0s, 1.15s;
    animation-iteration-count: 1, infinite;
    animation-fill-mode: forwards, none;
}

.dcj-sacre[data-prix="diamant"][data-nombre="2"].est-tiree
.dcj-sacre__piece[data-rang="0"] {
    animation-name: sacre-extraction, sacre-choc;
    animation-duration: 1.15s, .6s;
    animation-delay: 0s, 1.15s;
    animation-iteration-count: 1, 1;
    animation-fill-mode: forwards, none;
}
@keyframes sacre-respire {
    0%, 100% { filter: drop-shadow(0 0 26px var(--eclat)); }
    50%      { filter: drop-shadow(0 0 48px var(--eclat))
                       drop-shadow(0 0 14px rgba(255, 255, 255, .7)); }
}

.gemme-vue__piece.est-precieux {
    animation: gemme-tourne 1.4s cubic-bezier(.15, .7, .3, 1),
               sacre-respire 3.2s 1.4s infinite;
}


/* Les particules partent du disque et s'élèvent en s'effaçant. */
@keyframes sacre-poussiere {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(.3); }
    18%  { opacity: 1; transform: translate(calc(-50% + var(--px) * .3),
                                           calc(-50% + var(--py) * .3)) scale(1); }
    100% {
        opacity: 0;
        transform: translate(calc(-50% + var(--px)), calc(-50% + var(--py) - 60px))
                   scale(.35);
    }
}

/* Le halo du diamant respire, au lieu de rester fixe.

   Cette règle déclenchait aussi l'extraction, et sans « est-tiree » : le
   disque de diamant partait donc dès l'apparition de la scène, alors que
   les autres attendaient d'être tirés de la pochette. D'où ce mouvement qui
   ne ressemblait à aucun autre. */

/* En combo, c'est le diamant qui attend sur le côté, et l'or qui prend le
   centre. Chacun garde donc sa propre trajectoire. */
.dcj-sacre[data-prix="diamant"][data-nombre="2"].est-tiree
.dcj-sacre__piece[data-rang="1"] {
    animation-name: sacre-sortie-cote, sacre-respire;
    animation-duration: 1.55s, 3.2s;
    animation-delay: 0s, 1.15s;
    animation-iteration-count: 1, infinite;
    animation-fill-mode: forwards, none;
}

.dcj-sacre[data-prix="diamant"][data-nombre="2"].est-tiree
.dcj-sacre__piece[data-rang="0"] {
    animation-name: sacre-extraction, sacre-choc;
    animation-duration: 1.15s, .6s;
    animation-delay: 0s, 1.15s;
    animation-iteration-count: 1, 1;
    animation-fill-mode: forwards, none;
}

/* Le mouvement peut gêner : on garde l'annonce, on retire la mise en scène. */
@media (prefers-reduced-motion: reduce) {
    .dcj-sacre__poussiere i,
    .dcj-sacre__piece .vnl,
    .dcj-sacre__pochette,
    .dcj-sacre__pochette.est-partie,
    .dcj-sacre__piece,
    .dcj-sacre.est-tiree .dcj-sacre__pochette,
    .dcj-sacre.est-tiree .dcj-sacre__piece,
    .dcj-sacre[data-prix="diamant"].est-tiree .dcj-sacre__piece,
    .dcj-sacre__texte b,
    .dcj-sacre__texte small,
    .dcj-sacre__eclats i,
    .dcj-sacre.est-frappe .dcj-sacre__onde {
        animation-duration: .01s;
        animation-delay: 0s;
        transition-duration: .01s;
    }
}




/* ---------- Mes chiffres, sur la page de compte ---------------------------
   Le même relevé sobre que le classement public, précédé du butin : les
   pièces qu'on a décrochées se regardent, les chiffres se lisent.
   -------------------------------------------------------------------- */

.mes-stats { margin-top: 30px; }

.mes-stats h2 {
    margin: 0 0 16px;
    font-family: var(--font-display);
    font-size: 22px;
}

.mes-stats__butin {
    display: grid;
    /* Trois cases juste assez larges pour leur chiffre, plutôt que trois
       tiers de la page : le disque qui déborde donne déjà l'ampleur. */
    grid-template-columns: repeat(3, minmax(0, 200px));

    /* L'écart tient compte du disque qui déborde de trente-huit pixels à
       gauche : avec moins, celui d'une case venait mordre la voisine. */
    gap: 62px;

    /* Les trois cases au milieu de la page.

       Le décalage se fait par la marge, pas par un remplissage à gauche :
       celui-ci poussait la grille vers la droite au lieu de la déplacer, et
       l'ensemble finissait de travers. */
    justify-content: center;
    width: fit-content;
    margin: 18px auto 30px;
    transform: translateX(19px);
}

@media (max-width: 620px) {
    .mes-stats__butin {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        width: auto;
        gap: 38px;
        transform: translateX(14px);
    }
}

.mes-stats__piece {
    position: relative;
    /* Basse et large : le chiffre tient sur une ligne, le reste n'était que
       du vide au-dessus et au-dessous. */
    display: flex;
    flex-direction: column;
    justify-content: center;
    /* Basse : le chiffre tient sur une ligne, le reste n'était que du vide.
       Le remplissage reste symétrique — le disque déborde par la gauche, la
       boîte n'a pas à s'en écarter. */
    min-height: 64px;
    padding: 8px 14px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
    text-align: center;

    /* La boîte se resserre : le chiffre n'a pas besoin de tant de place, et
       le disque qui déborde donne déjà de l'ampleur à l'ensemble. */
    overflow: visible;
}

/* Le disque, à cheval sur le coin haut-gauche.
   Il tourne lentement, comme sur une platine : un butin qui bouge se regarde
   plus volontiers qu'une image posée. */
.mes-stats__disque {
    position: absolute;
    /* Centré sur le bord gauche : « top » et « bottom » à zéro avec une
       marge automatique le posent au milieu de la hauteur, sans passer par
       « transform » — qui est déjà pris par la rotation. */
    top: 0;
    bottom: 0;
    left: -38px;
    /*
     * Carré, et tournant sur son centre.
     *
     * Sans largeur déclarée, la boîte s'ajustait au contenu de travers et le
     * centre de rotation tombait à côté du disque : il décrivait un cercle au
     * lieu de tourner sur lui-même.
     */
    width: 96px;
    height: 96px;
    margin: auto 0;
    display: flex;
    transform-origin: 50% 50%;
    filter: drop-shadow(0 6px 14px rgba(23, 18, 15, .3));
    animation: piece-tourne 9s linear infinite;
}

/* Le dessin remplit sa boîte : un SVG plus petit décalerait à nouveau le
   centre. */
.mes-stats__disque svg,
.mes-stats__disque .vnl {
    width: 100%;
    height: 100%;
    display: block;
}

@keyframes piece-tourne {
    to { transform: rotate(360deg); }
}

/* Une pièce jamais obtenue reste en sourdine, et son disque s'arrête : rien
   ne tourne pour ce qu'on n'a pas gagné. */
.mes-stats__piece[data-vide="1"] { opacity: .45; }
.mes-stats__piece[data-vide="1"] .mes-stats__disque { animation: none; }

/* Le chiffre au centre de la boîte : c'est lui qu'on vient lire. */
.mes-stats__piece b {
    display: block;
    margin: 0;
    font-family: var(--font-display);
    font-size: 29px;
    line-height: 1.05;
}

/* Le libellé s'écarte de la gauche : le disque en déborde et lui passait
   dessus. Le chiffre, plus court, reste au milieu de la boîte. */
.mes-stats__piece small {
    display: block;
    padding-left: 22px;
    font-size: 11px;
    color: var(--ink-mute);
}

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

@media (max-width: 520px) {
    .mes-stats__butin { gap: 8px; }
    .mes-stats__piece { padding: 12px 6px; }
}


/* ---------- Les barres de la régie 10Cover --------------------------------
   Catalogue et défis se surveillent souvent mais se règlent rarement : la
   barre dit l'essentiel, le bouton ouvre le reste.
   -------------------------------------------------------------------- */

.dc-barres {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
    margin-bottom: 18px;
}

.dc-barre {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
}

.dc-barre__titre {
    display: flex;
    align-items: center;
    gap: 8px;
}

.dc-barre__titre b { font-family: var(--font-display); font-size: 16px; }

.dc-barre__chiffres {
    display: flex;
    gap: 14px;
    margin-left: auto;
    font-size: 12px;
    color: var(--ink-mute);
}

.dc-barre__chiffres b {
    font-family: var(--font-mono);
    font-size: 14px;
    color: var(--ink);
}

@media (max-width: 900px) {
    .dc-barres { grid-template-columns: 1fr; }
    .dc-barre { flex-wrap: wrap; }
    .dc-barre__chiffres { margin-left: 0; width: 100%; }
}

/* Le choix du mode d'alimentation. */
.dc-modes {
    display: flex;
    gap: 8px;
    margin-bottom: 14px;
}

.dc-mode-corps { margin-bottom: 6px; }

.dc-separation {
    margin: 20px 0;
    border: none;
    border-top: 1px dashed var(--paper-deep);
}

/* L'adresse de la tâche planifiée : longue, à copier d'un bloc. */
.dc-url {
    width: 100%;
    margin-top: 8px;
    padding: 9px 12px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper);
    font-family: var(--font-mono);
    font-size: 11.5px;
    color: var(--ink-2);
}


/* ---------- Les réglages de la file ---------------------------------------
   Le bouton et sa quantité sur la même ligne : séparés, on ne voyait pas que
   le nombre servait au bouton juste en dessous.
   -------------------------------------------------------------------- */

.dc-duo-champ {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px 20px;
    margin: 12px 0 18px;
}

.dc-duo-champ__avec {
    display: flex;
    align-items: center;
    gap: 9px;
}

.dc-duo-champ__avec label {
    font-size: 13px;
    color: var(--ink-2);
}

.dc-duo-champ input {
    width: 74px;
    padding: 6px 10px;
    border: var(--border);
    border-radius: 9px;
    background: var(--paper-hi);
    font-family: var(--font-mono);
    font-size: 13px;
    text-align: center;
}

/* Les trois cartes du haut occupent toute la largeur de la modale.
   « .dc-compte » les brimait à 340 px, ce qui laissait les deux tiers de la
   modale vides à leur droite. */
.dc-file-cartes.dc-compte {
    max-width: none;
    margin: 0 0 22px;
}


/* ---------- La liste des comptes proposés ---------------------------------
   Sous le champ « De la part de », jusqu'à dix comptes avec leur avatar.
   L'image confirme qu'on parle du bon spectateur : deux pseudos peuvent se
   ressembler à une lettre près.
   -------------------------------------------------------------------- */

.sugg-viewer { position: relative; }

/* Le champ garde la largeur des autres : il était plus étroit parce qu'il se
   partageait sa ligne avec la pastille du compte trouvé. */
.sugg-viewer input { width: 100%; }

.sugg-viewer__liste {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 4px);
    z-index: 30;
    /* Six lignes visibles : au-delà la liste sortait de la modale sur les
       petits écrans. Le reste se déroule. */
    max-height: 232px;
    margin: 0;
    padding: 4px;
    border: var(--border);
    border-radius: 12px;
    background: var(--paper-hi);
    box-shadow: 0 12px 30px rgba(23, 18, 15, .18);
    list-style: none;
    overflow-y: auto;
}

.sugg-viewer__liste li {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 6px 9px;
    border-radius: 9px;
    cursor: pointer;
}

.sugg-viewer__liste li:hover { background: var(--paper-deep); }

.sugg-viewer__liste img {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    object-fit: cover;
    flex: 0 0 auto;
}

.sugg-viewer__liste b {
    font-size: 13.5px;
    font-weight: 600;
}

.sugg-viewer__liste small {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--ink-mute);
}


/* ---------- La fiche d'un album proposé -----------------------------------
   La pochette en grand, ce qu'on sait de l'album, puis ses titres. C'est le
   dos d'une pochette : on y cherche une durée, un ordre, un nom.
   -------------------------------------------------------------------- */

/* La carte de suggestion mène à sa fiche : elle doit se signaler comme un
   lien, sans virer au bleu souligné. */
.listcard--lien {
    display: block;
    color: inherit;
    text-decoration: none;
    transition: transform .12s ease-out, box-shadow .12s ease-out;
}

.listcard--lien:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 18px rgba(23, 18, 15, .13);
}

.fiche { max-width: 760px; margin: 0 auto; }

.fiche__tete {
    display: flex;
    gap: 26px;
    align-items: flex-start;
    margin-bottom: 34px;
}

.fiche__pochette {
    flex: 0 0 240px;
    aspect-ratio: 1;
    border: var(--border);
    border-radius: 16px;
    background: var(--paper-deep);
    overflow: hidden;
    box-shadow: var(--shadow);
}

.fiche__pochette img { width: 100%; height: 100%; object-fit: cover; display: block; }

.fiche__qui { min-width: 0; flex: 1; }

.fiche__qui h1 {
    margin: 0 0 4px;
    font-size: clamp(24px, 4vw, 34px);
    line-height: 1.15;
}

.fiche__artiste {
    margin: 0 0 20px;
    font-size: 17px;
    color: var(--ink-2);
}

/* Les faits en colonnes étroites : chacun tient sur une ligne, et l'œil les
   parcourt sans revenir en arrière. */
.fiche__faits {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
    gap: 14px 20px;
    margin: 0 0 22px;
    padding: 0;
    list-style: none;
}

.fiche__faits small {
    display: block;
    font-size: 11px;
    color: var(--ink-mute);
    text-transform: uppercase;
    letter-spacing: .05em;
}

.fiche__faits b { font-size: 15px; }

.fiche__liens { display: flex; gap: 9px; flex-wrap: wrap; margin: 0; }

/* ---------- Les titres ---------------------------------------------------- */

.fiche__pistes h2 {
    margin: 0 0 12px;
    font-size: 20px;
}

.fiche__pistes ol {
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: piste;
}

.fiche__pistes li {
    display: grid;
    grid-template-columns: 30px 1fr auto;
    align-items: baseline;
    gap: 14px;
    padding: 10px 4px;
    border-bottom: 1px solid var(--paper-deep);
}

.fiche__pistes li:last-child { border-bottom: none; }

.fiche__num {
    font-family: var(--font-mono);
    font-size: 12.5px;
    color: var(--ink-mute);
    text-align: right;
}

/* Le bouton d'écoute prend la place du numéro quand un extrait existe.
   Trente secondes, fournies par la source. */
.fiche__ecoute {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: var(--border);
    border-radius: 50%;
    background: var(--paper-hi);
    color: var(--ink);
    cursor: pointer;
    transition: background .15s, color .15s, transform .15s;
}

.fiche__ecoute:hover { background: var(--ink); color: var(--paper-hi); }

/* Pendant la recherche : chercher chez YouTube prend une seconde, et sans
   signe le clic paraît sans effet. */
.fiche__ecoute.cherche {
    background: var(--teal);
    border-color: var(--teal);
    color: var(--paper-hi);
    animation: fiche-pulse 1.4s ease-in-out infinite;
}

@keyframes fiche-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(23, 148, 139, .5); }
    50%      { box-shadow: 0 0 0 6px rgba(23, 148, 139, 0); }
}

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

.fiche__titre { font-size: 15px; }
.fiche__duree { font-size: 13px; color: var(--ink-mute); }

@media (max-width: 620px) {
    .fiche__tete { flex-direction: column; gap: 18px; }
    .fiche__pochette { flex: none; width: min(240px, 60vw); }
}


/* ---------- La fiche d'un album proposé -----------------------------------
   Pochette et détails côte à côte, puis les titres en liste. Le dos d'une
   pochette, en somme.
   -------------------------------------------------------------------- */

.fiche { max-width: 780px; margin: 0 auto; }

.fiche__tete {
    display: grid;
    grid-template-columns: 260px 1fr;
    gap: 28px;
    margin-bottom: 34px;
}

.fiche__pochette {
    aspect-ratio: 1;
    border: var(--border);
    border-radius: 16px;
    background: var(--paper-deep);
    overflow: hidden;
    box-shadow: var(--shadow);
}

.fiche__pochette img { width: 100%; height: 100%; object-fit: cover; display: block; }

.fiche__qui h1 {
    margin: 0 0 4px;
    font-family: var(--font-display);
    font-size: clamp(24px, 4vw, 34px);
    line-height: 1.15;
}

.fiche__artiste {
    margin: 0 0 20px;
    font-size: 17px;
    color: var(--ink-2);
}

/* Les faits en colonnes : libellé au-dessus, valeur en dessous. Un tableau
   à deux colonnes aurait laissé trop de blanc à droite. */
.fiche__faits {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: 14px 18px;
    margin: 0 0 22px;
    padding: 0;
    list-style: none;
}

.fiche__faits small {
    display: block;
    font-size: 11px;
    color: var(--ink-mute);
    text-transform: uppercase;
    letter-spacing: .05em;
}

.fiche__faits b { font-size: 15px; }

.fiche__liens { display: flex; gap: 8px; flex-wrap: wrap; margin: 0; }

/* ---------- Les titres ---------------------------------------------------- */

.fiche__pistes h2 {
    margin: 0 0 12px;
    font-family: var(--font-display);
    font-size: 20px;
}

.fiche__pistes ol {
    margin: 0;
    padding: 0;
    list-style: none;
}

.fiche__pistes li {
    display: grid;
    grid-template-columns: 34px 1fr auto;
    align-items: baseline;
    gap: 12px;
    padding: 10px 4px;
    border-bottom: 1px solid var(--paper-deep);
}

.fiche__pistes li:last-child { border-bottom: none; }

.fiche__num {
    font-family: var(--font-mono);
    font-size: 12.5px;
    color: var(--ink-mute);
    text-align: right;
}

.fiche__titre { font-size: 15px; }
.fiche__duree { font-size: 13px; color: var(--ink-mute); }

@media (max-width: 620px) {
    .fiche__tete { grid-template-columns: 1fr; gap: 20px; }
    .fiche__pochette { max-width: 240px; }
}


/* Le compte Twitch personnel, dans les réglages. */
.montw {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
}

.montw img {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    object-fit: cover;
}

.montw b { display: block; font-size: 15px; }
.montw small { font-size: 12px; color: var(--ink-mute); }

/* Le bouton se colle à droite, quelle que soit la longueur du pseudo. */
.montw button { margin-left: auto; }


/* ---------- L'écran de retouche d'un album --------------------------------
   Un titre par ligne : la case qui décide s'il part au classement, son
   numéro, puis son libellé. Décocher n'efface rien.
   -------------------------------------------------------------------- */

.retouches { margin: 4px 0 0; padding: 0; list-style: none; }

.retouches li {
    display: grid;
    grid-template-columns: 26px 30px 1fr;
    align-items: center;
    gap: 10px;
    padding: 7px 2px;
    border-bottom: 1px solid var(--paper-deep);
}

.retouches li:last-child { border-bottom: none; }

/* Un titre écarté reste lisible mais s'efface : on doit voir qu'il existe
   sans le confondre avec ceux qui partent au classement. */
.retouches li.est-ecarte input[type="text"] {
    opacity: .45;
    text-decoration: line-through;
}

.retouches__num { font-size: 12px; color: var(--ink-mute); text-align: right; }

/* ---------- La case qui décide si un titre part au classement -------------
   La case native est grise, minuscule, et son style dépend du navigateur.
   Celle-ci est dessinée : un carré au trait, une coche qui apparaît.
   -------------------------------------------------------------------- */

.retouches__actif { display: flex; }

.retouches__actif input {
    appearance: none;
    width: 19px;
    height: 19px;
    margin: 0;
    border: 1.8px solid var(--ink-mute);
    border-radius: 6px;
    background: var(--paper-hi);
    cursor: pointer;
    transition: background .14s, border-color .14s;
    position: relative;
}

.retouches__actif input:hover { border-color: var(--ink); }

.retouches__actif input:checked {
    border-color: var(--teal);
    background: var(--teal);
}

/* La coche est tracée en deux traits, pas écrite en caractère : une police
   manquante laisserait la case vide sans qu'on comprenne pourquoi. */
.retouches__actif input:checked::after {
    content: '';
    position: absolute;
    left: 5.5px;
    top: 2px;
    width: 5px;
    height: 9px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(42deg);
}

.retouches__actif input:focus-visible {
    outline: 2px solid var(--teal);
    outline-offset: 2px;
}

/* Une case verrouillée — un titre qu'on vient d'écrire — reste lisible mais
   ne se laisse pas décocher avant d'avoir été enregistrée. */
.retouches__actif input:disabled { opacity: .55; cursor: default; }

/* Un titre ajouté à la main se signale par son fond. */
.retouches li.est-ajoute { background: rgba(23, 148, 139, .06); }

.retouches__ajout {
    display: flex;
    gap: 8px;
    margin-top: 12px;
}

.retouches__ajout input {
    flex: 1;
    padding: 6px 11px;
    border: var(--border);
    border-radius: 9px;
    background: var(--paper-hi);
    font-size: 13.5px;
}

.retouches input[type="text"] {
    width: 100%;
    padding: 5px 10px;
    border: var(--border);
    border-radius: 8px;
    background: var(--paper-hi);
    font-size: 13.5px;
}

/* Ce que la source annonçait, quand la régie en a décidé autrement. */
.retouche__origine {
    grid-column: 3;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--ink-mute);
}


/* L'adresse de la tâche planifiée : longue, à copier, jamais à taper. */
.dc-cron {
    width: 100%;
    margin: 4px 0 14px;
    padding: 9px 12px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper-hi);
    font-family: var(--font-mono);
    font-size: 12px;
    cursor: text;
}


/* Les chiffres de la barre Défis ne se coupent pas : « à l'instant » sur deux
   lignes déformait la barre entière. */
#dc-cron-etat span { white-space: nowrap; }
#dc-cron-etat b { white-space: nowrap; }


/* Une carte sans défi programmé : visible, mais clairement hors service.
   La griser sans la retirer dit qu'elle reviendra. */
.dcj-niveau[data-vide] {
    opacity: .38;
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='26' viewBox='0 0 26 26'%3E%3Ccircle cx='13' cy='13' r='11.5' fill='%23211a16'/%3E%3Ccircle cx='13' cy='13' r='8.5' fill='none' stroke='%23000' stroke-opacity='.5'/%3E%3Ccircle cx='13' cy='13' r='6' fill='none' stroke='%23000' stroke-opacity='.5'/%3E%3Ccircle cx='13' cy='13' r='4' fill='%23c9a227'/%3E%3Ccircle cx='13' cy='13' r='1.1' fill='%23efe2cc'/%3E%3C/svg%3E") 13 13, default;
    filter: grayscale(1);
}

.dcj-niveau[data-vide]:hover { transform: none; box-shadow: var(--shadow); }
.dcj-niveau[data-vide] .vnl { animation: none; }


/* ---------- Le lecteur vidéo ----------------------------------------------
   La vidéo n'est mise en place qu'à l'ouverture, et retirée à la fermeture :
   masquer la fenêtre laisserait le son tourner derrière.
   -------------------------------------------------------------------- */

.lecteur {
    position: fixed;
    inset: 0;
    z-index: 120;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

.lecteur__voile {
    position: absolute;
    inset: 0;
    background: rgba(16, 12, 10, .88);
}

.lecteur__boite {
    position: relative;

    /*
     * La même largeur que le lecteur des classements.
     *
     * Il était borné à 880 pixels alors que l'autre va jusqu'à 1560 : la même
     * vidéo paraissait deux fois plus petite selon la page d'où on l'ouvrait.
     * La hauteur disponible borne aussi, pour qu'une vidéo 16/9 large ne
     * déborde pas par le bas sur un écran peu haut.
     */
    width: min(1560px, 96vw, calc((100vh - 150px) * 16 / 9));
    border: var(--border);
    border-radius: 16px;
    background: var(--paper-hi);
    box-shadow: 0 20px 60px rgba(23, 18, 15, .5);
    overflow: hidden;
}

.lecteur__tete {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 13px 16px;
}

.lecteur__tete b {
    flex: 1;
    min-width: 0;
    font-size: 15px;
    /* Un titre long ne doit pas pousser la croix hors de la boîte. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.lecteur__croix {
    flex: 0 0 auto;
    width: 30px;
    height: 30px;
    padding: 0;
    border: var(--border);
    border-radius: 50%;
    background: transparent;
    font-size: 19px;
    line-height: 1;
    cursor: pointer;
}

.lecteur__croix:hover { background: var(--ink); color: var(--paper-hi); }

/* Le cadre garde les proportions de la vidéo quelle que soit la largeur. */
.lecteur__cadre {
    aspect-ratio: 16 / 9;
    background: #000;
}

.lecteur__cadre iframe {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
}


/* ---------- Les pages d'erreur --------------------------------------------
   Un vinyle qui tourne au centre : une page immobile a l'air en panne, alors
   que seule l'adresse est fautive.
   -------------------------------------------------------------------- */

.erreur {
    max-width: 460px;
    margin: 0 auto;
    padding: 30px 0 20px;
    text-align: center;
}

.erreur__disque {
    display: flex;
    justify-content: center;
    margin-bottom: 26px;
}

.erreur__disque .vnl {
    animation: erreur-tourne 4.2s linear infinite;
    filter: drop-shadow(0 12px 26px rgba(23, 18, 15, .3));
}

@keyframes erreur-tourne {
    to { transform: rotate(360deg); }
}

/* Le disque s'arrête pour qui ne veut pas d'animation : un mouvement
   perpétuel dérange plus qu'il n'égaie. */
@media (prefers-reduced-motion: reduce) {
    .erreur__disque .vnl { animation: none; }
}

.erreur__code {
    margin: 0 0 6px;
    font-size: 13px;
    letter-spacing: .18em;
    color: var(--ink-mute);
}

.erreur h1 {
    margin: 0 0 10px;
    font-family: var(--font-display);
    font-size: clamp(26px, 5vw, 34px);
}

.erreur__texte {
    margin: 0 0 24px;
    font-size: 15px;
    line-height: 1.6;
    color: var(--ink-2);
}


/* La raison pour laquelle un niveau ne se joue pas.
   Discrète en temps normal, elle s'éclaire au survol : on la cherche
   justement au moment où l'on essaie de cliquer. */
.dcj-niveau__raison {
    margin-top: 4px;
    font-size: 11px;
    font-style: normal;
    line-height: 1.35;
    color: var(--ink-mute);
    opacity: .8;
    transition: opacity .15s;
}

.dcj-niveau:hover .dcj-niveau__raison { opacity: 1; }


/* Un chiffre accompagné de son vinyle : le disque dit de quoi on parle mieux
   qu'un mot sous un nombre. */
.dc-chiffre--vinyle {
    display: flex;
    align-items: center;
    gap: 11px;
    text-align: left;

    /* « Vinyles de diamant » se cassait sur trois lignes dans une case
       calibrée pour un nombre : ces cartes en prennent deux. */
    grid-column: span 2;
    padding-right: 16px;
}

.dc-chiffre--vinyle small { white-space: nowrap; }

.dc-chiffre__disque { flex: 0 0 auto; display: flex; }

.dc-chiffre--vinyle b { margin: 0; }

/* Aucun vinyle de ce type décerné : le compteur s'efface sans disparaître,
   pour qu'on voie ce qui reste à gagner. */
.dc-chiffre--vinyle[data-vide] { opacity: .45; }


/* ---------- Les albums déjà passés en défi --------------------------------
   Une ligne par défi, groupée par journée. La pochette en petit suffit à
   reconnaître l'album, et les chiffres disent s'il était trouvable.
   -------------------------------------------------------------------- */

.dcp-liste { margin: 0; padding: 0; list-style: none; }

/* La date, une seule fois par journée : la répéter à chaque ligne hache la
   lecture sans rien apprendre. */
.dcp-jour {
    margin: 20px 0 6px;
    font-family: var(--font-mono);
    font-size: 11.5px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.dcp-jour:first-child { margin-top: 4px; }

/* Des colonnes fixes plutôt qu'ajustées au contenu : les chiffres et les
   pastilles s'alignent d'une ligne à l'autre, on les compare d'un coup
   d'œil au lieu de les chercher. */
.dcp-album {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr) 78px 168px 96px;
    align-items: center;
    align-items: center;
    gap: 13px;
    padding: 8px 6px;
    border-bottom: 1px solid var(--paper-deep);
    color: inherit;
    text-decoration: none;
    transition: background .14s;
}

.dcp-album:hover { background: var(--paper-hi); }

.dcp-album__cover {
    width: 44px;
    height: 44px;
    border-radius: 8px;
    background: var(--paper-deep);
    overflow: hidden;
}

.dcp-album__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

.dcp-album__quoi { min-width: 0; }

/* Un titre long ne doit pas pousser les chiffres hors de la ligne. */
.dcp-album__quoi b,
.dcp-album__quoi small {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dcp-album__quoi b { font-size: 14.5px; }
.dcp-album__quoi small { font-size: 12px; color: var(--ink-mute); }

.dcp-album__niveau {
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--paper-deep);
    font-size: 11px;
    font-weight: 600;
}

.dcp-album__niveau[data-ton="easy"]   { background: rgba(23, 148, 139, .16); }
.dcp-album__niveau[data-ton="medium"] { background: rgba(201, 162, 39, .18); }
.dcp-album__niveau[data-ton="hard"]   { background: rgba(200, 62, 44, .14); }

.dcp-album__chiffres { font-size: 11.5px; color: var(--ink-mute); }

@media (max-width: 620px) {
    /* (règle reprise plus bas, en deux lignes) */

}


/* La date et le niveau, au-dessus du titre de l'album. */
.dcp-fiche__jour {
    margin: 0 0 6px;
    font-size: 12px;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--ink-mute);
}


/* Le bonus de la journée parfaite, sous le nom du prix.
   Une mention, pas une récompense : elle rapporte des points, pas un vinyle
   de plus. */
.dcj-sacre__bonus {
    display: block;
    margin-top: 8px;
    padding: 4px 14px;
    border-radius: 999px;
    background: rgba(23, 148, 139, .22);
    font-size: 12.5px;
    font-style: normal;
    font-weight: 600;
    color: #7fe3d4;
}


/* Deux liens côte à côte sous le titre du jeu. */
.dcj-liens { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; }


/* Ce que j'ai fait d'un défi passé.

   Un cartouche, pas une simple icône : c'est ce qu'on cherche du regard en
   parcourant la liste, et un disque de vingt pixels au bout d'une ligne
   passait inaperçu. */
.dcp-album__mien {
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 92px;
    padding: 5px 12px 5px 8px;
    border: 1.5px solid var(--teal);
    border-radius: 999px;
    background: rgba(23, 148, 139, .12);
    font-size: 11.5px;
    font-weight: 600;
    color: var(--teal-deep, #0f6d66);
    white-space: nowrap;
}

/* Le disque prend la couleur du cartouche : or et diamant se distinguent
   d'un simple « joué ». */
.dcp-album__mien[data-vinyle="or"] {
    border-color: #c9a227;
    background: rgba(201, 162, 39, .16);
    color: #8a6d10;
}

.dcp-album__mien[data-vinyle="diamant"] {
    border-color: #6fa8c8;
    background: rgba(111, 168, 200, .18);
    color: #2f6b8c;
}

.dcp-album__mien[data-vinyle="argent"] {
    border-color: #9aa3ab;
    background: rgba(154, 163, 171, .18);
    color: #55606a;
}

/* Joué sans rien décrocher : le cartouche reste, mais discret. Le disque du
   niveau y tient sa place, à sa couleur. */
.dcp-album__mien[data-vinyle=""] {
    border-color: var(--ink-mute);
    background: transparent;
    color: var(--ink-mute);
}

.dcp-album__mien svg { flex: 0 0 auto; }

@media (max-width: 620px) {
    /* (règle reprise plus bas, en deux lignes) */
}


/* ---------- Les annonces de 10Cover sur l'incrustation --------------------
   Le portrait devant, le bandeau derrière, le disque qui dépasse à droite.
   Rien n'est tout à fait droit : le bandeau penche, le nom penche à l'inverse.
   C'est ce qui distingue la notification de tout ce qui est aligné à l'écran.
   -------------------------------------------------------------------- */

.annonces {
    position: fixed;
    left: 50%;
    bottom: 46px;
    z-index: 40;
    transform: translateX(-50%);
    pointer-events: none;
}

.annonce {
    /* Repère des éléments posés en absolu — le score et les confettis.
       Sans lui, ils se calaient sur « .annonces », fixé au bas de l'écran,
       et se retrouvaient n'importe où. */
    position: relative;
    display: flex;
    align-items: center;
}

/* ---------- Le portrait, devant le bandeau -------------------------------- */

.annonce__avatar {
    position: relative;
    z-index: 2;
    width: 46px;
    height: 46px;
    border-radius: 50%;
    object-fit: cover;
    flex: 0 0 auto;
    border: 2px solid rgba(23, 18, 15, .16);
    animation: portrait-arrive .58s cubic-bezier(.16, 1.05, .3, 1.32) backwards;
}

.annonce.sort .annonce__avatar {
    animation: element-tombe .58s .22s cubic-bezier(.5, 0, .78, .34) forwards;
}

/* ---------- Le bandeau ---------------------------------------------------- */

.annonce__bloc {
    position: relative;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 22px 16px;

    /* Des coins bien ronds : le bout plat coupait l'image net, comme une
       bande découpée aux ciseaux. */
    border-radius: 22px;

    /* Fond clair, comme le papier du site. Il faut alors une ombre franche
       pour que la notification se détache d'une image claire derrière. */
    background: linear-gradient(158deg, #fdf6e9 0%, #f0e3cc 100%);
    box-shadow: 0 16px 42px rgba(23, 18, 15, .42),
                inset 0 1px 0 rgba(255, 255, 255, .8);

    /* Le décor déborderait sinon des coins arrondis. Le disque, lui, est
       posé hors du bandeau pour pouvoir en dépasser. */
    overflow: hidden;

    /* Un biais à peine perceptible : assez pour sortir de la grille, pas
       assez pour qu'on remarque l'inclinaison elle-même. */
    transform: rotate(-1deg);
    animation: bloc-deploie .6s .1s cubic-bezier(.16, 1, .3, 1.1) backwards;
}

.annonce.sort .annonce__bloc {
    animation: bloc-tombe .6s .1s cubic-bezier(.5, 0, .78, .34) forwards;
}

/* ---------- Le nom et sa pastille ----------------------------------------- */

.annonce__texte {
    /* Droit : le bandeau penche déjà d'un degré, en rajouter donnerait un
       texte de travers. */
    position: relative;
    z-index: 2;
    min-width: 0;
}

.annonce__pseudo {
    display: block;
    font-family: var(--font-display);
    font-size: 22px;
    line-height: 1.1;
    letter-spacing: -.012em;
    color: #1a1310;

    /* Un titre long ne doit pas étirer le bandeau sans fin. */
    max-width: 320px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-shadow: 2px 2px 0 rgba(23, 18, 15, .14);
    animation: pseudo-arrive .56s .3s cubic-bezier(.16, 1.1, .3, 1.32) backwards;
}

.annonce.sort .annonce__pseudo {
    animation: element-tombe .56s .14s cubic-bezier(.5, 0, .78, .34) forwards;
}

.annonce__pille {
    display: inline-block;
    margin: 4px 0 0 2px;
    padding: 1px 0;

    /* Ni fond ni cadre : une ligne de texte en chasse fixe, espacée, qui se
       lit comme une légende et non comme un second titre. */
    font-family: var(--font-mono);
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: rgba(23, 18, 15, .5);

    animation: pille-arrive .5s .44s cubic-bezier(.2, 1.1, .3, 1.3) backwards;
}

.annonce.sort .annonce__pille {
    animation: element-tombe .56s .2s cubic-bezier(.5, 0, .78, .34) forwards;
}

.annonce__pille[data-ton="easy"]   { color: #12796f; }
.annonce__pille[data-ton="medium"] { color: #8a6d10; }
.annonce__pille[data-ton="hard"]   { color: #a8321f; }

/* ---------- Le disque, qui dépasse à droite ------------------------------- */

.annonce__disque {
    display: flex;
    flex: 0 0 auto;

    /* Il dépasse par le haut et la droite, et remonte franchement : centré
       sur la hauteur, il n'aurait été qu'une vignette de plus.

       « order » le maintient en dernier : le bandeau est caché en débordement
       pour ses coins ronds, il faut donc que le disque soit posé sur le
       conteneur du dehors, où l'ordre d'écriture ne le suit plus. */
    position: relative;
    z-index: 3;
    order: 9;
    margin: -44px -26px 0 -30px;
    align-self: flex-start;
    filter: drop-shadow(0 10px 24px rgba(0, 0, 0, .6));
    /* Il arrive en roulant, puis tourne sans s'arrêter, comme sur une
       platine. La rotation continue est ce qui le rend vivant ; une simple
       respiration se remarquait à peine. */
    animation: disque-arrive .78s cubic-bezier(.16, 1.02, .3, 1.26) backwards,
               disque-tourne 2.4s .8s linear infinite;
}

.annonce.sort .annonce__disque {
    animation: disque-tombe .64s cubic-bezier(.5, 0, .78, .34) forwards;
}

/* ---------- Les mouvements ------------------------------------------------ */

@keyframes portrait-arrive {
    from { transform: scale(.3) rotate(-30deg); opacity: 0; }
    to   { transform: scale(1) rotate(0); opacity: 1; }
}

@keyframes bloc-deploie {
    from { transform: scaleX(.2) rotate(-1deg); transform-origin: left center; opacity: 0; }
    60%  { opacity: 1; }
    to   { transform: scaleX(1) rotate(-1deg); transform-origin: left center; opacity: 1; }
}

@keyframes pseudo-arrive {
    from { transform: translateY(14px) scale(.88); opacity: 0; }
    to   { transform: translateY(0) scale(1); opacity: 1; }
}

@keyframes pille-arrive {
    from { transform: translateY(-8px) scale(.7); opacity: 0; }
    to   { transform: translateY(0) scale(1); opacity: 1; }
}

@keyframes disque-arrive {
    from { transform: translateX(56px) rotate(250deg) scale(.3); opacity: 0; }
    to   { transform: translateX(0) rotate(0) scale(1); opacity: 1; }
}

/* Le tour complet, en boucle : deux secondes et demie par tour, assez lent
   pour ne pas donner le tournis, assez net pour qu'on le voie tourner. */
@keyframes disque-tourne {
    from { transform: rotate(0); }
    to   { transform: rotate(360deg); }
}

/* La sortie : chacun tombe à son moment. Tomber ensemble ferait un bloc qui
   disparaît ; tomber décalé fait un départ. */
@keyframes disque-tombe {
    from { transform: translateY(0) rotate(0); opacity: 1; }
    to   { transform: translateY(180px) rotate(210deg) scale(.62); opacity: 0; }
}

@keyframes bloc-tombe {
    from { transform: translateY(0) rotate(-1deg); opacity: 1; }
    to   { transform: translateY(160px) rotate(-9deg); opacity: 0; }
}

@keyframes element-tombe {
    from { transform: translateY(0) rotate(0); opacity: 1; }
    to   { transform: translateY(130px) rotate(-6deg); opacity: 0; }
}

/* Tout s'arrête pour qui ne veut pas d'animation : sur une incrustation de
   direct, un mouvement perpétuel peut gêner. */
@media (prefers-reduced-motion: reduce) {
    .annonce__avatar,
    .annonce__bloc,
    .annonce__pseudo,
    .annonce__pille,
    .annonce__disque { animation: none; }
}


/* ---------- Le décor du bandeau ------------------------------------------- */

/* La bande striée au bord bas : le même motif que les stories du
   back-office, réduit à un liseré. */
.annonce__stries {
    position: absolute;
    inset: auto 0 0 0;
    height: 8px;
    overflow: hidden;
}

/*
 * Les bandes sont droites, puis penchées par « skewX ».
 *
 * Un dégradé incliné a une période mesurée le long de son axe, pas le long
 * de l'horizontale : le décalage qui le fait boucler ne tombe alors jamais
 * juste, et le raccord se voyait à chaque tour. Des bandes verticales
 * penchées après coup se répètent exactement tous les cinquante-quatre
 * pixels.
 */
.annonce__stries::before {
    content: '';
    position: absolute;
    /* Plus large que le bandeau : le biais découvrirait sinon les bords. */
    inset: 0 -14px;
    background: repeating-linear-gradient(
        90deg,
        #FF5A44   0 9px,
        #FFF3D6   9px 18px,
        #FFC63D  18px 27px,
        #FFF3D6  27px 36px,
        #57D98A  36px 45px,
        #FFF3D6  45px 54px
    );
    transform: skewX(-22deg);

    /* Le défilement ne commence qu'une fois le bandeau déployé : pendant
       l'étirement, le fond est comprimé avec lui et le motif paraît sauter. */
    animation: annonce-stries 2.8s .75s linear infinite;
}

@keyframes annonce-stries {
    from { background-position: 0 0; }
    to   { background-position: 54px 0; }
}

/* Des points de lumière qui montent dans le bandeau : le fond clair a besoin
   d'un peu de vie, sans quoi il ne serait qu'un rectangle de plus. */
.annonce__poussiere {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
}

.annonce__poussiere i {
    position: absolute;
    bottom: -6px;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: rgba(201, 162, 39, .75);
    animation: annonce-monte 3s linear infinite;
}

@keyframes annonce-monte {
    from { transform: translateY(0) scale(.5); opacity: 0; }
    25%  { opacity: .9; }
    to   { transform: translateY(-80px) scale(1); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .annonce__stries,
    .annonce__poussiere i { animation: none; }
}


/* Une ombre douce sous la notification : elle la pose sur l'image au lieu de
   la laisser flotter. Plus large que le bandeau et floue, pour ne pas
   dessiner un second rectangle. */
.annonce__bloc::after {
    content: '';
    position: absolute;
    inset: auto 8% -16px 8%;
    height: 22px;
    border-radius: 50%;
    background: rgba(23, 18, 15, .32);
    filter: blur(9px);
    z-index: -1;
}

/* Les confettis, lâchés à l'arrivée du disque.
   Ils tombent une fois et disparaissent : une pluie continue distrairait de
   ce qui est écrit. */
/* L'explosion se fait au-dessus de la carte, et déborde franchement de
   chaque côté : contenue dans le bandeau, elle ne se verrait pas. */
/* ---------- L'explosion de confettis ---------------------------------------
   Ils partent du centre de la carte et fusent vers l'extérieur, chacun avec
   son angle et sa portée. Une explosion brève, pas une pluie : rien ne reste
   à l'écran une fois retombé.
   -------------------------------------------------------------------- */

.annonce__confettis {
    position: absolute;
    inset: 0;
    z-index: 4;
    pointer-events: none;
}

.annonce__confettis i {
    position: absolute;
    /* Tous partent du même point : le centre de la carte. */
    top: 50%;
    left: 50%;
    width: 6px;
    height: 8px;
    border-radius: 1px;

    /* « forwards » et non « backwards » : ils doivent finir invisibles, pas
       revenir se figer à leur point de départ. */
    /* Un léger retard : l'explosion accompagne l'arrivée du disque plutôt
       que de la précéder, sinon elle est finie avant qu'il soit en place. */
    /* « both » : invisibles avant leur départ, et invisibles après leur
       arrivée. Avec « backwards » seul, ils reprenaient leur opacité normale
       en fin d'animation et réapparaissaient d'un coup. */
    animation: confetti-explose 1s .45s cubic-bezier(.12, .78, .32, 1) both;
}

/* La projection se fait sur les deux axes en même temps, avec un
   ralentissement en fin de course : c'est ce qui donne l'impression d'un
   souffle plutôt que d'un déplacement régulier. */
@keyframes confetti-explose {
    from {
        transform: translate(-50%, -50%) scale(.3) rotate(0);
        opacity: 1;
    }
    70% { opacity: 1; }
    to {
        transform:
            translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--dy, 0px)))
            scale(.85) rotate(var(--tour, 360deg));
        opacity: 0;
    }
}

/* Le score de la manche, au-dessus du disque. Il monte et s'efface : c'est
   une information de l'instant, pas une mention à garder. */
.annonce__score {
    position: absolute;

    /*
     * Au-dessus du disque, qui déborde en haut à droite.
     *
     * Sans vinyle il n'y a rien qui dépasse : le score descend alors se
     * poser sur le bandeau, sinon il flotterait dans le vide.
     */
    top: -64px;
    right: 8px;
    z-index: 6;
    font-family: var(--font-display);
    font-size: 34px;
    line-height: 1;
    color: #3fbf7a;
    text-shadow: 0 2px 0 #fdf6e9, 2px 3px 6px rgba(23, 18, 15, .45);
    pointer-events: none;
    /*
     * « both » et non « forwards ».
     *
     * Avec « forwards » seul, l'élément gardait son style normal pendant le
     * délai : il était donc affiché en clair, disparaissait au démarrage de
     * l'animation, puis revenait. « both » applique aussi l'état de départ,
     * et il reste invisible jusqu'à son entrée.
     */
    animation: score-monte 2.1s .95s ease-out both;
}

@keyframes score-monte {
    from { transform: translateY(20px) scale(.6); opacity: 0; }
    22%  { transform: translateY(0) scale(1.1); opacity: 1; }
    34%  { transform: translateY(0) scale(1); opacity: 1; }
    70%  { opacity: 1; }
    to   { transform: translateY(-52px) scale(.95); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .annonce__confettis { display: none; }
    .annonce__score { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
    .annonce__stries::before,
    .annonce__confettis i { animation: none; }
    .annonce__confettis { display: none; }
}


/* ---------- 10Cover en direct ---------------------------------------------
   Une page à part, sans menu : elle passe à l'antenne, tout ce qui n'est pas
   le jeu vole de la place à l'image. Mêmes couleurs que le site, avec le
   soleil du logo en filigrane.
   -------------------------------------------------------------------- */

.live {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
    background: var(--paper);
    color: var(--ink);
}

/* Le soleil du logo, comme derrière les autres pages. */
.live::before {
    content: '';
    position: fixed;
    top: 50%;
    left: 50%;
    width: min(1180px, 150vmin);
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: 0;
    opacity: .09;
    background: repeating-conic-gradient(
        from 0deg at 50% 50%,
        var(--red) 0deg 6deg, transparent 6deg 12deg
    );
    -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 5%, transparent 60%);
            mask-image: radial-gradient(circle at 50% 50%, #000 5%, transparent 60%);
}

.live__barre {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 20px;
    border-bottom: 2px dashed var(--ink-mute);
}

.live__manche {
    display: flex;
    align-items: center;
    gap: 12px;
    font-family: var(--font-display);
    font-size: 17px;
}

/* Les crans dépensés : trois traits qui s'allument. On voit d'un coup d'œil
   ce qu'il reste à dévoiler. */
.live__crans { display: flex; gap: 4px; }

.live__crans i {
    width: 22px;
    height: 4px;
    border-radius: 2px;
    background: var(--paper-deep);
}

.live__crans i.est-passe { background: var(--teal); }

.live__actions { display: flex; gap: 8px; margin-left: auto; }

.live__chat { font-size: 11px; color: var(--ink-mute); }

.live__scene {
    position: relative;
    z-index: 1;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 26px 20px;
}

/* ---------- Le repos ------------------------------------------------------ */

.live__accueil { text-align: center; }

/* Le bouton est posé au centre du disque : c'est le seul geste à faire, il
   n'a pas à être ailleurs. */
/* La galette : le numéro au-dessus, le disque et son bouton en dessous. Le
   tout en colonne, sinon le numéro se plaçait à côté du disque. */
.live__galette {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

/* C'est ce bloc qui sert de repère au bouton : posé sur la galette entière,
   il se centrait entre le numéro et le disque. */
.live__galette__disque {
    position: relative;
    display: inline-flex;
}

.live__lancer {
    position: absolute;
    inset: 0;
    margin: auto;
    width: 128px;
    height: 128px;
    border: 3px solid var(--ink);
    border-radius: 50%;
    background: var(--paper-hi);
    color: var(--ink);
    font-family: var(--font-display);
    font-size: 25px;
    cursor: pointer;
    box-shadow: 5px 5px 0 var(--ink);
    transition: transform .15s, background .15s, color .15s;
}

.live__lancer:hover {
    transform: scale(1.06);
    background: var(--red);
    color: var(--paper-hi);
}

.live__dispo { margin-top: 22px; color: var(--ink-mute); font-size: 12px; }

/* ---------- L'annonce de la manche ---------------------------------------- */

.live__annonce { text-align: center; animation: live-annonce .5s var(--ease); }

.live__annonce small {
    display: block;
    font-size: 14px;
    letter-spacing: .3em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.live__annonce b {
    display: block;
    margin-top: 10px;
    font-family: var(--font-display);
    font-size: clamp(56px, 12vw, 120px);
    line-height: 1;
    text-shadow: 6px 6px 0 var(--paper-deep);
}

@keyframes live-annonce {
    from { transform: scale(.82); opacity: 0; }
    to   { transform: scale(1); opacity: 1; }
}

/* ---------- Le jeu -------------------------------------------------------- */

.live__jeu { width: min(1500px, 98vw); margin: 0 auto; }

/*
 * L'écran vraiment scindé en deux, à parts égales : la pochette d'un côté,
 * les trois zones de l'autre — chacune a maintenant sa propre saisie, il
 * leur faut autant de place qu'à l'image.
 */
.live__disposition {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    justify-content: center;
    gap: 44px;
    text-align: left;
}

.live__col-cover {
    flex: 1 1 0;
    text-align: center;
}

/*
 * Toute la colonne s'aligne en haut désormais — le titre, le minuteur juste
 * en dessous, puis le reste. Rien ne se recentre plus au milieu d'un espace
 * qui change de taille : c'est justement ce qui faisait tout bouger d'une
 * phase à l'autre.
 */
.live__col-technique {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 1 1 0;
    text-align: center;
}

.live__pochette {
    /* Remplit sa colonne, sans jamais dépasser une hauteur d'écran
       raisonnable — les deux colonnes se valent, la pochette n'a donc plus
       à deviner une largeur : c'est celle de sa colonne. */
    width: min(100%, 78vh, 760px);
    margin: 0 auto;
    aspect-ratio: 1;
    border: 3px solid var(--ink);
    border-radius: 14px;
    box-shadow: 7px 7px 0 var(--ink);
    overflow: hidden;
    background: var(--paper-deep);
}

.live__pochette img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Sous une largeur d'écran modeste, deux colonnes deviendraient plus
   illisibles qu'une seule qui défile un peu — on repasse alors à
   l'empilement classique, centré. */
@media (max-width: 900px) {
    .live__jeu { width: min(680px, 100%); }

    .live__disposition {
        flex-direction: column;
        align-items: center;
        text-align: center;
    }

    .live__col-cover,
    .live__col-technique {
        width: 100%;
        max-width: none;
    }

    .live__pochette {
        width: min(100%, calc(100vh - 380px));
        max-width: min(560px, 78vw);
    }
}

/* ---------- Les trois zones, une par champ ---------------------------------

   Chacune porte sa propre saisie : plus de case à cliquer avant de pouvoir
   taper, les trois se jouent en parallèle. Empilées plutôt que côte à
   côte — chacune a besoin de largeur pour son champ et son bouton, trois
   colonnes les auraient trop resserrées.
   ---------------------------------------------------------------------- */

.live__zones {
    display: flex;
    flex-direction: column;
    gap: 14px;
    width: 100%;
    margin: 18px 0;
}

.live__zone {
    padding: 14px 16px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
    text-align: left;
    transition: opacity .2s var(--ease);
}

.live__zone[data-etat="trouve"] {
    border-color: var(--teal);
    background: rgba(23, 148, 139, .08);
}

.live__zone__tete {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
}

.live__zone__logo {
    display: grid;
    place-items: center;
    color: var(--ink-mute);
}

.live__zone__nom {
    font-family: var(--font-display);
    font-size: 15px;
}

.live__zone__chat {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: 11.5px;
    color: var(--ink-mute);
}

.live__zone__chat.est-vif { color: var(--teal); font-weight: 700; }

.live__zone__form {
    display: flex;
    gap: 8px;
}

.live__zone__form input {
    flex: 1;
    min-width: 0;
    padding: 10px 14px;
    border: 2px solid var(--ink);
    border-radius: 10px;
    background: var(--paper);
    font-size: 15px;
}

.live__zone__form input:disabled {
    opacity: .5;
    background: var(--paper-deep);
}

/* La liste des essais déjà tapés — un par ligne, comme dans le journal du
   jeu quotidien : la même idée doit se reconnaître d'un écran à l'autre. */
.live__zone__tapes {
    margin: 8px 0 0;
    padding: 0;
    list-style: none;
    font-size: 12px;
    color: var(--ink-mute);
}

.live__zone__tapes li {
    display: flex;
    gap: 8px;
    padding: 2px 0;
}

.live__zone__tapes-no {
    flex: 0 0 auto;
    min-width: 52px;
    font-weight: 600;
}

/* L'indice de sens sur l'année — même idée que dans le jeu quotidien :
   dire de quel côté chercher plutôt que de laisser deviner à l'aveugle. */
.live__zone__tapes-sens {
    margin-left: auto;
    font-size: 11px;
    font-style: italic;
    color: var(--ink-mute);
}

.live__zone__pied {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-top: 9px;
}

.live__zone__essais {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--ink-mute);
}

.live__champs {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.live__champs li {
    padding: 11px 10px;
    border: var(--border);
    border-radius: 12px;
    background: var(--paper-hi);
}

/* Trouvé, passé : deux états distincts. Le premier se félicite, le second
   se constate — l'un et l'autre font avancer la manche. */
.live__champs li.est-trouve {
    border-color: var(--teal);
    background: rgba(23, 148, 139, .12);
}

.live__champs li.est-passe { opacity: .55; }

.live__champs small {
    display: block;
    font-size: 10.5px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.live__champs b {
    display: block;
    margin-top: 4px;
    font-size: 16px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.live__gain { display: block; margin-top: 3px; font-size: 10.5px; color: var(--teal); }

/* ---------- Le bilan ------------------------------------------------------ */

.live__bilan { text-align: center; width: min(520px, 100%); }

.live__bilan h2 { font-family: var(--font-display); font-size: 40px; margin: 0; }

.live__reponse { margin: 8px 0 24px; font-size: 18px; color: var(--ink-2); }

.live__tableau {
    margin: 0 0 24px;
    padding: 0;
    list-style: none;
    text-align: left;
}

.live__tableau li {
    display: flex;
    justify-content: space-between;
    gap: 14px;
    padding: 9px 4px;
    border-bottom: 1px solid var(--paper-deep);
}

.live__tableau li:first-child b { color: var(--red-deep); }
.live__vide { justify-content: center; color: var(--ink-mute); }

@media (max-width: 620px) {
    .live__champs { grid-template-columns: 1fr; }
    .live__barre { flex-wrap: wrap; }
}


/* ---------- Les points en jeu ---------------------------------------------
   Ce qu'il reste à gagner sur le champ en cours, pour le premier et pour le
   second. Une mise prise se barre et s'efface ; la suivante grossit.
   -------------------------------------------------------------------- */

/* Les deux mises l'une sous l'autre : on lit d'abord ce qui est en jeu
   maintenant, puis ce qui restera après. */
.live__enjeu {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    margin: 6px 0 0;
}

.live__mise {
    display: flex;
    align-items: baseline;
    gap: 9px;
    transition: transform .35s var(--ease), opacity .35s;
}

.live__mise b {
    font-family: var(--font-display);
    font-size: 30px;
    line-height: 1;
    color: var(--ink-mute);
    transition: font-size .35s var(--ease), color .35s;
}

.live__mise small {
    font-size: 10.5px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

/* La mise à gagner maintenant : c'est elle qu'on regarde. */
.live__mise.est-suivante b {
    font-size: 52px;
    color: var(--teal);
}

/* Déjà prise : barrée et réduite, elle reste visible pour qu'on comprenne
   d'où vient la mise suivante. */
.live__mise.est-prise {
    opacity: .4;
    transform: scale(.8);
}

.live__mise.est-prise b {
    font-size: 24px;
    text-decoration: line-through;
}

/* ---------- Les visages du chat -------------------------------------------
   Les portraits et les emotes de ceux qui écrivent, lâchés sur les côtés.
   Ils passent sans rien recouvrir : le calque ne reçoit aucun clic.
   -------------------------------------------------------------------- */

.live__visages {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
}

.live__visage,
.live__emote {
    position: absolute;
    display: block;
    animation: visage-passe 5.5s ease-out forwards;
}

.live__visage img {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
    display: block;
    border: 3px solid var(--paper-hi);
    box-shadow: 0 6px 18px rgba(23, 18, 15, .28);
}

/* Les emotes sans cadre ni cercle : ce sont des dessins, pas des portraits.
   Une simple ombre suffit à les décoller du fond. */
.live__emote img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
    filter: drop-shadow(0 4px 10px rgba(23, 18, 15, .3));
}

/* Ils montent en s'effaçant : un simple fondu sur place passerait inaperçu
   au milieu du jeu. */
@keyframes visage-passe {
    from { transform: translateY(30px) scale(.5); opacity: 0; }
    16%  { transform: translateY(0) scale(1); opacity: 1; }
    72%  { opacity: 1; }
    to   { transform: translateY(-76px) scale(.9); opacity: 0; }
}

/* Les deux issues de fin de manche, côte à côte. */
.live__fin {
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
}

@media (prefers-reduced-motion: reduce) {
    .live__visage,
    .live__emote { animation: none; }
}


/* ---------- Le bilan de la partie ------------------------------------------
   Le cumul en grand, puis le détail des manches jouées.
   -------------------------------------------------------------------- */

.live__partie {
    margin: 0 0 22px;
    padding: 16px 18px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
}

.live__total { margin: 0 0 14px; }

.live__total b {
    font-family: var(--font-display);
    font-size: 44px;
    line-height: 1;
    color: var(--teal);
}

.live__total small {
    display: block;
    margin-top: 2px;
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.live__manches {
    width: 100%;
    border-collapse: collapse;
    text-align: left;
}

.live__manches tr { border-top: 1px dashed var(--paper-deep); }

.live__manches th,
.live__manches td {
    padding: 8px 4px;
    font-size: 13.5px;
    font-weight: 400;
    vertical-align: baseline;
}

/* Le niveau, coloré comme partout ailleurs dans le jeu. */
.live__manches th {
    width: 78px;
    font-weight: 600;
}

.live__manches th[data-ton="easy"]   { color: #12796f; }
.live__manches th[data-ton="medium"] { color: #8a6d10; }
.live__manches th[data-ton="hard"]   { color: #a8321f; }

.live__manches td:last-child {
    width: 76px;
    text-align: right;
    font-weight: 600;
}

.live__soustitre {
    margin: 0 0 8px;
    font-size: 12px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--ink-mute);
    text-align: left;
}

/* Le rang et le nombre de trouvailles, dans le classement final. */
.live__rang {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    margin-right: 10px;
    border-radius: 50%;
    background: var(--paper-deep);
    font-size: 11px;
    font-weight: 600;
}

.live__tableau li b { flex: 1; }

.live__trouves {
    margin-right: 16px;
    font-size: 11px;
    color: var(--ink-mute);
}

/* Le premier se distingue : c'est le vainqueur de la soirée. */
.live__tableau li:first-child .live__rang {
    background: var(--red);
    color: var(--paper-hi);
}


/* Sans vinyle, rien ne dépasse en haut : le score se pose plus bas, contre
   le bandeau, et n'a pas à attendre un disque qui n'arrive pas. */
.annonce[data-vinyle=""] .annonce__score {
    top: -28px;
    right: 14px;
    animation-delay: .55s;
    animation-fill-mode: both;
}


/* La régie, au-dessus du classement du chat : elle joue au même barème, mais
   n'est pas en lice avec les spectateurs. */
.live__regie {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    margin: 0 0 16px;
    padding: 11px 16px;
    border: 2px solid var(--ink);
    border-radius: 12px;
    background: var(--ink);
    color: var(--paper-hi);
}

.live__regie__nom {
    font-family: var(--font-display);
    font-size: 17px;
}

.live__regie__pts { font-size: 14px; font-weight: 600; }


/* Avec un vinyle, le bandeau s'allonge à droite.

   Le disque le chevauche de trente pixels : sans cette réserve, il venait
   mordre la fin du pseudo. On compte le chevauchement plus une marge, pour
   que la dernière lettre reste franchement dégagée. */
.annonce[data-vinyle="or"] .annonce__bloc,
.annonce[data-vinyle="argent"] .annonce__bloc,
.annonce[data-vinyle="diamant"] .annonce__bloc {
    padding-right: 62px;
}


/* ---------- Le tableau de fin de partie ------------------------------------
   Une ligne par joueur, une colonne par manche. La régie en tête, mais avec
   le rang qu'elle a vraiment décroché.
   -------------------------------------------------------------------- */

.live__final {
    width: 100%;
    margin: 0 0 24px;
    border-collapse: collapse;
    text-align: left;
}

.live__final thead th {
    padding: 0 8px 8px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.live__final thead th:nth-child(n+2) { text-align: right; }
.live__final thead th:last-child { text-align: center; }

.live__final tbody tr { border-top: 1px solid var(--paper-deep); }

.live__final tbody th,
.live__final tbody td {
    padding: 9px 8px;
    font-size: 14px;
    vertical-align: middle;
}

.live__final tbody th {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
}

.live__final tbody td { text-align: right; }

/* Une manche non jouée reste discrète : le tiret dit l'absence sans attirer
   l'œil autant qu'un chiffre. */
.live__final td.est-vide { color: var(--ink-mute); opacity: .5; }

.live__final__total { font-weight: 700; color: var(--teal); }

/* La régie, en tête et détachée du reste. */
.live__final tbody tr.est-regie {
    background: var(--ink);
    color: var(--paper-hi);
}

.live__final tbody tr.est-regie th,
.live__final tbody tr.est-regie td { color: var(--paper-hi); }

.live__final tbody tr.est-regie th { border-radius: 10px 0 0 10px; }
.live__final tbody tr.est-regie td:last-child { border-radius: 0 10px 10px 0; }
.live__final tbody tr.est-regie .live__final__total { color: #7fe3d4; }

/* ---------- La répartition des points, par champ ---------------------------

   Même charpente que le tableau final : les deux se ressemblent, ils
   répondent juste à des questions différentes — combien en tout, contre
   d'où ça vient.
   ---------------------------------------------------------------------- */

.live__repartition {
    width: 100%;
    margin: 0 0 24px;
    border-collapse: collapse;
    text-align: left;
}

.live__repartition thead th {
    padding: 0 8px 8px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.live__repartition thead th:nth-child(n+2) { text-align: right; }

.live__repartition tbody tr { border-top: 1px solid var(--paper-deep); }

.live__repartition tbody th,
.live__repartition tbody td {
    padding: 9px 8px;
    font-size: 14px;
    vertical-align: middle;
}

.live__repartition tbody th {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
}

.live__repartition tbody td { text-align: right; font-family: var(--font-mono); }

.live__repartition td.est-vide { color: var(--ink-mute); opacity: .5; font-family: inherit; }

/* La case du premier : la même couleur que la prime « 1er » ailleurs sur la
   régie, pour qu'on reconnaisse la même idée d'un écran à l'autre. */
.live__repartition td.est-premier {
    font-weight: 700;
    color: var(--teal);
}

/* Le total, en bout de ligne : plus appuyé que les autres colonnes, c'est
   lui qu'on regarde en premier même si les autres expliquent d'où il vient. */
.live__repartition__total {
    font-weight: 800;
    color: var(--ink);
}

/* La phrase qui explique le « ×2 » avant qu'on ait à deviner pourquoi une
   case ne montre pas le total qu'elle a rapporté. */
.live__repartition-note {
    margin: -6px 0 12px;
    font-size: 12px;
    color: var(--ink-mute);
}

/* Le rang, avec son disque pour les trois premiers. */
.live__final__rang {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 7px;
    text-align: right;
}

.live__final__rang b { font-size: 13px; }

.live__final__disque { display: flex; flex: 0 0 auto; }

@media (max-width: 620px) {
    .live__final thead th:nth-child(2),
    .live__final thead th:nth-child(3),
    .live__final thead th:nth-child(4),
    .live__final tbody td:nth-child(2),
    .live__final tbody td:nth-child(3),
    .live__final tbody td:nth-child(4) { display: none; }
}


/* ---------- La boule à facettes qui tourne --------------------------------
   Pour le diamant, ce sont les miroirs qui tournent, pas l'image entière :
   l'ombre reste en place, et chaque facette s'assombrit en y entrant.
   -------------------------------------------------------------------- */

.annonce[data-vinyle="diamant"] .annonce__disque {
    animation: disque-arrive .78s cubic-bezier(.16, 1.02, .3, 1.26) backwards;
}

.annonce[data-vinyle="diamant"] .vnl__facettes {
    transform-origin: 50px 50px;
    animation: disque-tourne 2.4s .8s linear infinite;
}

/* Même principe sur les pièces du compte, qui tournent aussi. */
.mes-stats__disque .vnl--diamant .vnl__facettes {
    transform-origin: 50px 50px;
    animation: piece-tourne 9s linear infinite;
}

.mes-stats__piece:has(.vnl--diamant) .mes-stats__disque { animation: none; }

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


/* Les scintillements de la boule à facettes.

   Ils ne brillent que sur les disques animés : posé dans une page, un vinyle
   qui clignote attire l'œil pour rien. */
.vnl__eclat {
    opacity: 0;

    /* Sans ces deux lignes, « scale » part du coin haut-gauche du SVG et
       chaque éclat traverse le disque en s'agrandissant. « fill-box » le
       ramène à sa propre boîte, et il grandit sur place. */
    transform-box: fill-box;
    transform-origin: center;
}

.annonce[data-vinyle="diamant"] .vnl__eclat,
.mes-stats__disque .vnl--diamant .vnl__eclat {
    animation: vnl-scintille 1.4s ease-in-out infinite;
}

/* Un éclat bref et net, séparé par un long temps mort : c'est l'irrégularité
   qui fait croire au reflet, pas la pulsation. */
@keyframes vnl-scintille {
    0%, 62%, 100% { opacity: 0; transform: scale(.4); }
    72%           { opacity: .95; transform: scale(1.4); }
    84%           { opacity: .35; transform: scale(1); }
}

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


/* ---------- Ce qui a été gagné en direct -----------------------------------
   Les points sont déjà dans le total ; cette liste dit d'où ils viennent.
   -------------------------------------------------------------------- */

.mes-stats__titre {
    margin: 26px 0 10px;
    font-family: var(--font-display);
    font-size: 19px;
}

.mes-live { margin: 0; padding: 0; list-style: none; }

.mes-live li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 4px;
    border-bottom: 1px solid var(--paper-deep);
}

.mes-live__disque { display: flex; flex: 0 0 auto; }

.mes-live__quoi { flex: 1; min-width: 0; }

.mes-live__quoi b {
    display: block;
    font-size: 15px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mes-live__quoi small {
    display: block;
    margin-top: 1px;
    font-size: 11.5px;
    color: var(--ink-mute);
}

.mes-live__pts { font-weight: 700; color: var(--teal); }


/* Ce qu'il reste de parties aujourd'hui. Rouge à zéro : le bouton ne
   marchera pas, autant le dire avant le clic. */
.live__quota {
    margin: 20px 0 0;
    font-size: 12px;
    color: var(--ink-mute);
}

.live__quota[data-vide="1"] {
    font-weight: 600;
    color: var(--red-deep);
}


/* Le bouton éteint quand il n'y a plus de partie : il garde sa forme mais
   ne réagit plus, ce qui se comprend sans explication. */
.live__lancer:disabled {
    border-color: var(--ink-mute);
    background: var(--paper-deep);
    color: var(--ink-mute);
    font-size: 19px;
    box-shadow: none;
    cursor: not-allowed;
}

.live__lancer:disabled:hover { transform: none; background: var(--paper-deep); }


/* ---------- La page des outils ---------------------------------------------
   Des blocs séparés, un par domaine. Rien d'ici n'est utilisé en direct : la
   page peut être dense sans gêner.
   -------------------------------------------------------------------- */

.dev__titre { font-family: var(--font-display); font-size: 30px; margin: 0 0 6px; }

.dev__bloc {
    margin: 22px 0;
    padding: 18px 20px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
}

.dev__bloc h2 {
    margin: 0 0 4px;
    font-family: var(--font-display);
    font-size: 19px;
}

.dev__aide { margin: 0 0 14px; font-size: 13.5px; color: var(--ink-mute); }

.dev__actions { display: flex; gap: 8px; flex-wrap: wrap; }

.dev__note { margin: 12px 0 0; font-size: 12px; color: var(--ink-mute); }

.dev__url { display: block; margin-top: 14px; }

.dev__url span {
    display: block;
    margin-bottom: 4px;
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.dev__url input {
    width: 100%;
    padding: 9px 12px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper);
    font-family: var(--font-mono);
    font-size: 12.5px;
    cursor: pointer;
}

/* La liste des albums au repos. */
.dev-repos { margin: 14px 0 0; padding: 0; list-style: none; }

.dev-repos li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 0;
    border-bottom: 1px solid var(--paper-deep);
}

.dev-repos__mode {
    flex: 0 0 auto;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .06em;
    background: var(--paper-deep);
    color: var(--ink-mute);
}

.dev-repos__mode[data-ton="easy"]   { background: rgba(23,148,139,.16); color: #12796f; }
.dev-repos__mode[data-ton="medium"] { background: rgba(201,162,39,.18); color: #8a6d10; }
.dev-repos__mode[data-ton="hard"]   { background: rgba(217,59,43,.16); color: #a8321f; }

.dev-repos__quoi { flex: 1; min-width: 0; }

.dev-repos__quoi b {
    display: block;
    font-size: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dev-repos__quoi small { font-size: 11.5px; color: var(--ink-mute); }

.dev-repos__reste { flex: 0 0 auto; font-size: 12px; color: var(--ink-mute); }


/* L'état d'un module, avant d'agir dessus : quatre chiffres alignés, qu'on
   lit d'un coup d'œil sans ouvrir de fenêtre. */
.dev__etat {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 10px;
    margin: 0 0 16px;
    padding: 12px 14px;
    border-radius: 11px;
    background: var(--paper);
    list-style: none;
}

.dev__etat li { display: flex; flex-direction: column; gap: 2px; }

.dev__etat span {
    font-size: 10.5px;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.dev__etat b { font-family: var(--font-display); font-size: 20px; }


/* Un réglage chiffré, avec son bouton : le champ et l'action se lisent
   ensemble plutôt que d'être séparés par la largeur du bloc. */
.dev__champ {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    margin: 0 0 16px;
    flex-wrap: wrap;
}

.dev__champ span {
    display: block;
    width: 100%;
    margin-bottom: 4px;
    font-size: 11px;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.dev__champ input {
    width: 110px;
    padding: 8px 12px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper);
    font-family: var(--font-mono);
    font-size: 14px;
}


/* Le bloc des scores : un liseré rouge pour qu'on le distingue des réglages
   ordinaires. Ce qu'on y efface ne revient pas. */
.dev__bloc--risque { border-color: var(--red); }

.dev__bloc--risque h2 { color: var(--red-deep); }


/* L'état du catalogue, niveau par niveau. Un tableau plutôt qu'une phrase :
   six chiffres se comparent d'un coup d'œil, une phrase se relit. */
.dev__cata {
    width: 100%;
    margin: 0 0 16px;
    border-collapse: collapse;
    text-align: left;
}

.dev__cata thead th {
    padding: 0 8px 7px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.dev__cata thead th:nth-child(n+2) { text-align: right; }

.dev__cata tbody tr { border-top: 1px solid var(--paper-deep); }

.dev__cata tbody th,
.dev__cata tbody td { padding: 8px; font-size: 13.5px; }

.dev__cata tbody th { font-weight: 700; }
.dev__cata tbody td { text-align: right; }

.dev__cata tbody th[data-ton="easy"]   { color: #12796f; }
.dev__cata tbody th[data-ton="medium"] { color: #8a6d10; }
.dev__cata tbody th[data-ton="hard"]   { color: #a8321f; }

/* Une journée prête se voit du premier coup : c'est l'information qu'on
   cherche en ouvrant la page. */
.dev__cata td[data-ok="1"] { color: var(--teal); font-weight: 600; }
.dev__cata td[data-ok=""] { color: var(--ink-mute); }


/* =============================================================================
   LA NAVIGATION MOBILE

   Une barre de cinq emplacements en bas de l'écran, et un tiroir. Le pouce
   atteint le bas sans changer de prise ; une barre en haut oblige à
   repositionner la main à chaque geste.
   ========================================================================== */

/* Sur grand écran, rien de tout cela n'existe : la navigation du haut suffit
   et la barre ne ferait que manger de la place. */
.mob,
.mob-tiroir { display: none; }

@media (max-width: 860px) {

    .mob {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 60;
        display: grid;
        grid-template-columns: repeat(5, 1fr);
        border-top: 2px solid var(--ink);
        background: var(--paper-hi);

        /* La barre du système, sur les téléphones qui en ont une. */
        padding-bottom: env(safe-area-inset-bottom, 0);
        box-shadow: 0 -6px 22px rgba(23, 18, 15, .12);
    }

    .mob__slot {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 3px;
        padding: 9px 4px 8px;
        border: 0;
        background: none;
        color: var(--ink-2);
        font-family: inherit;
        font-size: 10px;
        font-weight: 600;
        text-decoration: none;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }

    .mob__slot span {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        max-width: 100%;
    }

    /* Un emplacement vide garde sa place : les boutons ne se déplacent pas
       d'une page à l'autre, la main les retrouve au même endroit. */
    .mob__slot--vide { pointer-events: none; }

    .mob__slot:active { background: var(--paper-deep); }

    .mob__slot[aria-current="page"] { color: var(--red); }

    .mob__slot--menu { border-left: 1px dashed var(--ink-mute); }

    /* Le contenu ne doit pas passer sous la barre. */
    .pub-main { padding-bottom: calc(86px + env(safe-area-inset-bottom, 0)); }

    /* ---------- Le tiroir ------------------------------------------------- */

    .mob-tiroir {
        position: fixed;
        inset: 0;
        z-index: 70;
        display: block;
    }

    .mob-tiroir__voile {
        position: absolute;
        inset: 0;
        background: rgba(23, 18, 15, .5);
        opacity: 0;
        transition: opacity .28s var(--ease);
    }

    .mob-tiroir.est-ouvert .mob-tiroir__voile { opacity: 1; }

    /* Il vient de la gauche, même si le bouton est à droite : c'est le sens
       habituel d'un menu, et le panneau ne masque pas le pouce qui vient de
       l'ouvrir. */
    .mob-tiroir__panneau {
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
        width: min(310px, 84vw);
        display: flex;
        flex-direction: column;
        background: var(--paper-hi);
        border-right: 2px solid var(--ink);
        transform: translateX(-100%);
        transition: transform .28s var(--ease);
        overflow-y: auto;
    }

    .mob-tiroir.est-ouvert .mob-tiroir__panneau { transform: translateX(0); }

    .mob-tiroir__tete {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 16px 18px;
        border-bottom: 2px dashed var(--ink-mute);
    }

    .mob-tiroir__titre { font-family: var(--font-display); font-size: 18px; }

    .mob-tiroir__croix {
        border: 0;
        background: none;
        font-size: 26px;
        line-height: 1;
        color: var(--ink-2);
        cursor: pointer;
    }

    .mob-tiroir__moi {
        display: flex;
        align-items: center;
        gap: 11px;
        padding: 14px 18px;
        border-bottom: 1px solid var(--paper-deep);
        text-decoration: none;
        color: inherit;
    }

    .mob-tiroir__moi img {
        width: 42px;
        height: 42px;
        border-radius: 50%;
        object-fit: cover;
        border: 2px solid var(--ink);
    }

    .mob-tiroir__moi b { display: block; font-size: 15px; }
    .mob-tiroir__moi small { font-size: 12px; color: var(--ink-mute); }

    .mob-tiroir__liens { flex: 1; padding: 8px 0; }

    .mob-tiroir__liens a,
    .mob-tiroir__pied a {
        display: flex;
        align-items: center;
        gap: 11px;
        padding: 13px 18px;
        color: var(--ink);
        text-decoration: none;
        font-size: 15px;
    }

    .mob-tiroir__liens a:active { background: var(--paper-deep); }

    .mob-tiroir__pied {
        border-top: 2px dashed var(--ink-mute);
        padding: 6px 0 calc(10px + env(safe-area-inset-bottom, 0));
    }

    .mob-tiroir__pied a { font-size: 14px; color: var(--ink-2); }

    /* Le corps ne défile plus derrière le tiroir : sans cela, la page
       glisse sous le panneau et on perd sa position. */
    body.mob-fige { overflow: hidden; }
}


/* =============================================================================
   L'ADAPTATION MOBILE

   La barre du bas remplace l'en-tête : celui-ci disparaît, et tout ce qui
   comptait sur sa largeur se réorganise.
   ========================================================================== */

@media (max-width: 860px) {

    /* ---------- L'en-tête ------------------------------------------------- */

    /* Il ne sert plus à rien : le logo, le butin et le compte sont dans le
       tiroir, et la navigation en bas. */
    .pub-header { display: none; }

    .pub-main { padding-top: 18px; }

    .pub-footer { display: none; }

    /* ---------- 10Cover ---------------------------------------------------- */

    /* Les trois cartes de difficulté l'une sous l'autre : côte à côte sur un
       téléphone, la pochette devient illisible. */
    .dcj-niveaux { grid-template-columns: 1fr; gap: 12px; }

    .dcj-niveau { padding: 14px 16px; }

    /* La pochette prend la largeur, moins les marges. */
    .dcj-cover { width: min(100%, 78vw); max-width: 78vw; }

    .dcj-champs { grid-template-columns: 1fr; gap: 10px; }

    .dcj-accueil h1 { font-size: clamp(34px, 11vw, 52px); }

    .dcj-liens { flex-direction: column; gap: 8px; }
    .dcj-liens a { width: 100%; text-align: center; }

    /* ---------- Le classement et les albums passés ------------------------- */

    .dcl-chiffres { grid-template-columns: repeat(2, 1fr); }

    /* Les onglets du classement se serrent plutôt que de déborder. */
    .dcl-onglets { flex-wrap: wrap; }
    .dcl-onglets button { flex: 1 1 auto; font-size: 12.5px; }

    /* La ligne d'un album passé se replie : la pochette et le nom en haut,
       les chiffres en dessous. */
    .dcp-album {
        grid-template-columns: 44px 1fr;
        grid-template-areas:
            'cover quoi'
            'chiffres chiffres';
        gap: 4px 12px;
        padding: 12px 14px;
    }

    .dcp-album__cover { grid-area: cover; }
    .dcp-album__quoi { grid-area: quoi; }

    .dcp-album__niveau,
    .dcp-album__chiffres,
    .dcp-album__mien { grid-area: chiffres; justify-self: start; }

    .dcp-album__chiffres { font-size: 11px; }

    /* ---------- Le compte -------------------------------------------------- */

    .mes-stats__butin {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 16px;
        transform: none;
        padding-left: 20px;
    }

    .mes-stats__disque { left: -20px; }
    .mes-stats__disque svg { width: 62px; height: 62px; }

    .mes-stats__piece { min-height: 58px; padding: 6px 8px; }
    .mes-stats__piece b { font-size: 22px; }
    .mes-stats__piece small { font-size: 9.5px; padding-left: 10px; }

    .mes-stats .dcl-chiffres { grid-template-columns: repeat(2, 1fr); }

    .mes-live li { gap: 10px; padding: 10px 2px; }
    .mes-live__quoi b { font-size: 14px; }

    /* ---------- Les fenêtres ----------------------------------------------- */

    /* Elles montent du bas plutôt que d'apparaître au centre : c'est le
       geste attendu sur un téléphone, et le pouce atteint les boutons. */
    .modal__box {
        width: 100%;
        max-width: none;
        max-height: 88vh;
        margin: 0;
        border-radius: 18px 18px 0 0;
        align-self: flex-end;
    }

    /*
     * Les fenêtres montent du bas, mais pas le lecteur.
     *
     * Une feuille qui remonte est le bon geste pour un formulaire : on lit du
     * haut vers le bas et le pouce atteint les boutons. Une vidéo, elle, se
     * regarde au milieu — collée en bas, elle laissait un grand vide noir
     * au-dessus.
     */
    .modal:not(.player) { align-items: flex-end; }

    .modal.player {
        align-items: center;
        padding: 12px;
    }

    .modal.player .player__box {
        width: 100%;
        max-width: none;

        /* La hauteur disponible moins la place des commandes : la vidéo garde
           ses proportions sans pousser le reste hors de l'écran. */
        max-height: 90vh;
        align-self: center;
    }

    /* ---------- Les animations --------------------------------------------- */

    /* La scène de récompense tient dans la largeur : le disque et la pochette
       débordaient et provoquaient un défilement horizontal. */
    .dcj-sacre__scene { padding: 0 16px; }

    /* La pièce et la pochette tiennent dans la largeur : elles débordaient
       et provoquaient un défilement latéral. */
    .dcj-sacre__piece svg { width: min(46vw, 190px); height: auto; }
    .dcj-sacre__pochette { width: min(52vw, 220px); }

    .dcj-sacre__texte b { font-size: clamp(24px, 7vw, 36px); }
    .dcj-sacre__texte small { font-size: 12.5px; }
    .dcj-sacre__bonus { font-size: 11.5px; }

    /* Rien ne doit pouvoir élargir la page : une animation qui dépasse crée
       une barre de défilement latérale dont on ne se débarrasse plus. */
    body { overflow-x: hidden; }
}

/* Sur les écrans très étroits, les trois pièces du butin se serrent trop :
   deux par ligne se lisent mieux qu'une rangée illisible. */
@media (max-width: 430px) {
    .mes-stats__butin { grid-template-columns: repeat(2, minmax(0, 1fr)); }

    .mob__slot span { font-size: 9px; }
}


/* ---------- Le résumé de la page des outils --------------------------------
   Quatre cartes en tête : ce qu'on regarde en arrivant, avant de chercher un
   bouton.
   -------------------------------------------------------------------- */

.dev__resume {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 12px;
    margin: 0 0 22px;
}

.dev__carte {
    padding: 14px 16px;
    border: var(--border);
    border-radius: 13px;
    background: var(--paper-hi);
}

.dev__carte b {
    display: block;
    font-family: var(--font-display);
    font-size: 30px;
    line-height: 1;
}

.dev__carte small {
    display: block;
    margin-top: 3px;
    font-size: 11px;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

/* Les journées couvertes passent au vert quand demain est prêt : c'est la
   seule carte dont la valeur seule ne dit pas si tout va bien. */
.dev__carte[data-ok="1"] { border-color: var(--teal); }
.dev__carte[data-ok="1"] b { color: var(--teal); }
.dev__carte[data-ok="0"] b { color: var(--red-deep); }

/* Un intertitre dans un bloc : sépare deux familles d'actions sans ouvrir un
   bloc de plus. */
.dev__sous {
    margin: 22px 0 10px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.dev__sous:first-of-type { margin-top: 14px; }


/* Une entrée pas encore ouverte : visible mais inerte, comme sur grand
   écran. La masquer laisserait croire qu'elle n'existe pas. */
.mob-tiroir__liens a[data-bientot] {
    opacity: .5;
    pointer-events: none;
}

.mob-tiroir__bientot {
    margin-left: auto;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--paper-deep);
    font-size: 10px;
    font-style: normal;
    letter-spacing: .04em;
}


/* Le badge du direct, dans la liste des albums passés. Une manche jouée à
   l'antenne ne se compare pas à un défi ouvert toute la journée. */
.dcp-album__live {
    flex: 0 0 auto;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--red);
    color: var(--paper-hi);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .06em;
}

@media (max-width: 620px) {
    .dcp-album__live { grid-area: chiffres; justify-self: start; }
}


/* =============================================================================
   LE MOBILE DES AUTRES PAGES

   L'accueil, le classement d'albums, la roulette et la fiche d'album. Elles
   sont dans le menu au même titre que 10Cover : les laisser en version bureau
   revenait à n'avoir fait le travail qu'à moitié.
   ========================================================================== */

@media (max-width: 860px) {

    /* ---------- L'accueil --------------------------------------------------- */

    /* Le téléviseur occupe toute la largeur : à taille fixe, il débordait et
       poussait une barre de défilement latérale. */
    .landing { padding: 8px 0 0; }

    /* Le cadre suit son contenu : à cent pour cent, il laissait une bande
       rouge vide à droite de l'écran. */
    .landing__tv { width: fit-content; max-width: 100%; }

    /* Pas de remplissage ici : le cadre tient son ratio 16/9 et le lecteur
       s'y place en absolu. Un padding ne l'aurait pas déplacé, mais aurait
       faussé la hauteur calculée. */
    .landing__frame { border-radius: 14px; }

    /* Les boutons et le bloc lecteur passent l'un sous l'autre. */
    .landing__actions {
        flex-direction: column;
        align-items: stretch;
        gap: 9px;
    }

    .landing__actions .btn { width: 100%; text-align: center; }

    .landing__player { flex-wrap: wrap; gap: 10px; }

    /* Les molettes ne servent qu'au décor : elles mangeraient de la place
       utile sur un écran étroit. */
    .landing__knob { display: none; }

    /* ---------- Le classement d'albums -------------------------------------- */

    .pub-hero { padding: 20px 0 14px; text-align: left; }

    .pub-hero h1 { font-size: clamp(30px, 9vw, 44px); }

    /* Une seule colonne : deux fiches côte à côte sur 390 pixels ne laissent
       lire ni le titre ni l'artiste. */
    .grid,
    .grid--lists { grid-template-columns: 1fr; gap: 12px; }

    .listcard { padding: 14px 16px; }

    .listcard h3 { font-size: 17px; }

    /* La barre de rang se replie : le nom au-dessus, les chiffres dessous. */
    .rankbar {
        flex-wrap: wrap;
        gap: 6px 10px;
        padding: 11px 14px;
    }

    .rankbar__stats {
        width: 100%;
        justify-content: flex-start;
        font-size: 11.5px;
    }

    .rankbar__chevron { margin-left: auto; }

    /* ---------- La roulette -------------------------------------------------- */

    /* La roue tient dans la largeur, moins une marge : elle est ronde, donc
       c'est le côté le plus court qui commande. */
    .wheel__ring,
    .wheel__halo {
        width: min(88vw, 420px);
        height: min(88vw, 420px);
    }

    /* La carte suit la roue au lieu de la contraindre : c'est un simple
       conteneur, il n'a pas à imposer sa largeur. */
    .wheelcard { width: auto; max-width: 96vw; }

    .wheel__carte { font-size: 13px; }

    /* La flèche suit la roue plutôt que de rester à sa taille de bureau. */
    .wheel__pointer { transform: scale(.8); }

    /* ---------- La fiche d'un album ------------------------------------------ */

    /* La pochette et le texte l'un sous l'autre. */
    .fiche__tete {
        grid-template-columns: 1fr;
        gap: 14px;
        text-align: center;
    }

    .fiche__pochette {
        width: min(64vw, 260px);
        margin: 0 auto;
    }

    .fiche__titre { font-size: clamp(24px, 7vw, 34px); }

    .fiche__faits {
        justify-content: center;
        flex-wrap: wrap;
        gap: 8px 14px;
    }

    .fiche__liens {
        flex-direction: column;
        gap: 8px;
    }

    .fiche__liens .btn { width: 100%; text-align: center; }

    /* La liste des pistes : le numéro, le titre, la durée, sans colonne
       intermédiaire qui n'aurait plus la place. */
    .fiche__pistes li {
        grid-template-columns: 26px 1fr auto;
        padding: 9px 2px;
        font-size: 14px;
    }

    .fiche__duree { font-size: 11.5px; }
}


/* ---------- Le journal des parties -----------------------------------------
   Une zone qui défile dans la fenêtre, avec un en-tête par journée.
   -------------------------------------------------------------------- */

.dev-journal {
    max-height: 58vh;
    overflow-y: auto;
    margin: 6px 0 0;

    /* La barre de défilement ne colle pas au texte : sans cette marge, les
       chiffres de droite passent dessous. */
    padding-right: 6px;
}

.dev-journal__jour + .dev-journal__jour { margin-top: 18px; }

.dev-journal__jour h3 {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin: 0 0 6px;
    padding-bottom: 5px;
    border-bottom: 2px dashed var(--ink-mute);
    font-size: 13px;
    text-transform: capitalize;
}

.dev-journal__jour h3 b { font-size: 12px; color: var(--teal); }

.dev-journal__jour ul { margin: 0; padding: 0; list-style: none; }

.dev-journal__jour li {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 2px;
    border-bottom: 1px solid var(--paper-deep);
}

.dev-journal__niveau {
    flex: 0 0 auto;
    width: 62px;
    padding: 2px 0;
    border-radius: 999px;
    text-align: center;
    font-size: 10px;
    font-weight: 700;
    background: var(--paper-deep);
}

.dev-journal__niveau[data-ton="easy"]   { color: #12796f; }
.dev-journal__niveau[data-ton="medium"] { color: #8a6d10; }
.dev-journal__niveau[data-ton="hard"]   { color: #a8321f; }

.dev-journal__qui { flex: 1; min-width: 0; }

.dev-journal__qui b {
    display: block;
    font-size: 13.5px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dev-journal__qui small {
    display: block;
    font-size: 11px;
    color: var(--ink-mute);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dev-journal__parfait { flex: 0 0 auto; color: var(--gold, #c9a227); }

.dev-journal__pts {
    flex: 0 0 auto;
    min-width: 46px;
    text-align: right;
    font-weight: 600;
}

.dev-journal__pied {
    margin: 10px 0 0;
    font-size: 12px;
    color: var(--ink-mute);
    text-align: center;
}

/* ---------- Le tableau simple du quotidien --------------------------------- */

.dev-journal__table {
    width: 100%;
    margin-bottom: 22px;
    border-collapse: collapse;
    font-size: 13px;
}

.dev-journal__table th {
    padding: 6px 8px;
    border-bottom: 2px solid var(--ink);
    text-align: left;
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--ink-mute);
    white-space: nowrap;
}

.dev-journal__table td {
    padding: 8px;
    border-bottom: 1px solid var(--paper-deep);
    vertical-align: middle;
}

.dev-journal__table td small {
    display: block;
    color: var(--ink-mute);
    font-size: 11px;
}

.dev-journal__ligne--repliable { cursor: pointer; }
.dev-journal__ligne--repliable:hover { background: var(--paper-deep); }
.dev-journal__ligne--repliable:focus-visible { outline: 2px solid var(--teal); outline-offset: -2px; }

.dev-journal__absent {
    color: var(--ink-mute);
    font-style: italic;
}

/* ---------- La fenêtre de détail, à deux onglets ---------------------------

   « Chronologie » raconte la partie dans l'ordre où elle s'est jouée ;
   « Détail » regroupe la même matière par catégorie. Deux lectures d'une
   même trace plutôt qu'un choix à faire entre les deux.
   ---------------------------------------------------------------------- */

.dev-journal__onglets {
    display: flex;
    gap: 8px;
    margin: -4px 0 16px;
    border-bottom: 2px solid var(--paper-deep);
}

.dev-journal__onglets button {
    padding: 8px 4px;
    border: none;
    border-bottom: 3px solid transparent;
    background: none;
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 700;
    color: var(--ink-mute);
    cursor: pointer;
}

.dev-journal__onglets button.est-actif {
    border-bottom-color: var(--teal);
    color: var(--ink);
}

/* La chronologie : un événement par ligne, dans l'ordre où il est arrivé. */
.dev-journal__chrono {
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: chrono;
}

.dev-journal__chrono li {
    position: relative;
    padding: 6px 0 6px 26px;
    font-size: 13.5px;
    border-bottom: 1px solid var(--paper-deep);
}

.dev-journal__chrono li::before {
    counter-increment: chrono;
    content: counter(chrono);
    position: absolute;
    left: 0;
    top: 7px;
    width: 18px;
    height: 18px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--paper-deep);
    font-size: 10px;
    font-weight: 700;
    color: var(--ink-mute);
}

.dev-journal__chrono li.est-juste { color: var(--teal); font-weight: 700; }
.dev-journal__chrono li.est-passe { color: var(--ink-mute); font-style: italic; }

.dev-journal__chrono li.est-eclaircir {
    font-style: italic;
    color: var(--gold, #c9a227);
}

/* Le détail par catégorie. */
.dev-journal__champ {
    margin-bottom: 16px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--paper-deep);
}

.dev-journal__champ:last-child { border-bottom: none; margin-bottom: 0; }

.dev-journal__champ > b {
    display: block;
    margin-bottom: 4px;
    font-family: var(--font-display);
    font-size: 15px;
}

.dev-journal__essais-txt {
    margin: 0 0 4px;
    font-size: 13px;
    color: var(--ink-mute);
}

.dev-journal__resultat {
    margin: 0;
    font-size: 13.5px;
    font-weight: 600;
}

.dev-journal__resultat.est-juste { color: var(--teal); }
.dev-journal__resultat.est-passe { color: var(--ink-mute); font-style: italic; font-weight: 400; }

/* =============================================================================
   L'ADAPTATION MOBILE DES AUTRES PAGES

   L'accueil, le classement d'albums, la fiche et la roulette. Elles étaient
   restées en plan : lisibles mais serrées, avec des grilles calées sur des
   largeurs de bureau.
   ========================================================================== */

@media (max-width: 860px) {

    /* ---------- L'accueil --------------------------------------------------- */

    .landing { padding: 20px 0 12px; gap: 14px; }

    /*
     * C'est l'écran qui grandit, pas le cadre.
     *
     * Le cadre s'ajuste à son contenu ; l'élargir de force laissait l'image
     * dans un coin, au milieu d'un aplat rouge. Sa largeur est fixée en
     * « vw » pour le bureau, ce qui le rétrécissait justement là où il y a
     * le moins de place.
     */
    .landing__screen { width: min(62vw, 240px); }

    .landing__name { font-size: clamp(30px, 10vw, 46px); }

    .landing__lede { font-size: 14.5px; }

    .landing__actions,
    .landing__more { width: 100%; }

    .landing__actions .btn,
    .landing__more .btn { flex: 1 1 auto; justify-content: center; }

    /* Les compteurs passent en colonnes égales plutôt qu'en ligne serrée. */
    .landing__counts {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 10px;
        width: 100%;
        text-align: center;
    }

    /* ---------- Le classement d'albums -------------------------------------- */

    /* Une carte par ligne : à 268 px minimum, deux colonnes ne tenaient pas
       et la grille retombait déjà sur une, mais avec des marges perdues. */
    .grid--lists { grid-template-columns: 1fr; gap: 12px; }
    .grid--albums { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 12px; }
    .grid--stats { grid-template-columns: repeat(2, 1fr); gap: 12px; }

    .listcard { padding: 14px 16px; }

    .page-head { flex-direction: column; align-items: flex-start; gap: 10px; }

    /* ---------- La fiche d'un album ------------------------------------------ */

    /* La pochette au-dessus du texte : deux colonnes de 260 px ne laissaient
       plus rien au titre. */
    .fiche__tete {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 16px;
        text-align: center;
    }

    .fiche__pochette { width: min(72vw, 280px); }

    .fiche__titre { font-size: clamp(24px, 7vw, 34px); }

    .fiche__faits,
    .fiche__liens { justify-content: center; flex-wrap: wrap; }

    .fiche__liens .btn { flex: 1 1 auto; justify-content: center; }

    .fiche__pistes li { font-size: 13.5px; }

    /* ---------- La roulette --------------------------------------------------- */

    /* La roue tient dans la largeur, en gardant son carré. Pas de plafond en
       pixels : sur un écran étroit c'est « vw » qui borne, et un chiffre fixe
       empêchait l'incrustation de profiter de la place. */
    .overlay-body .wheel__stage.wheel__stage {
        width: min(92vw, 70vh);
        margin: 0 auto;
    }

    .wheel__carte { font-size: 12px; }

    /* La scène d'annonce suit la même règle. */
    .overlay__stage { max-width: 92vw; }
    .overlay__disc svg { width: min(52vw, 220px); height: auto; }
}

/* Sur les écrans très étroits, deux colonnes de pochettes valent mieux que
   trois illisibles. */
@media (max-width: 430px) {
    .grid--albums { grid-template-columns: repeat(2, 1fr); }
    .landing__counts { grid-template-columns: repeat(3, 1fr); font-size: 12px; }
}


/* La pochette au bilan de manche : c'est elle qu'on commente à l'antenne,
   entre deux tours. */
.live__bilan-cover {
    display: block;
    width: min(220px, 46vw);
    margin: 14px auto 20px;
    border: var(--border);
    border-radius: 12px;
    box-shadow: 5px 5px 0 var(--ink);
}




/* ---------- Les trois pochettes de fin de partie ----------------------------
   Côte à côte, avec leur niveau dessous : le récapitulatif qu'on montre à
   l'antenne avant le classement.
   -------------------------------------------------------------------- */

.live__pochettes {
    display: flex;
    justify-content: center;
    gap: 16px;
    margin: 16px 0 24px;
    flex-wrap: wrap;
}

.live__pochettes figure { margin: 0; text-align: center; }

/* Trois de front, quelle que soit la largeur : à 230 px elles passaient à la
   ligne dès que la fenêtre se resserrait, et le récapitulatif perdait sa
   lecture d'un coup d'œil. */
.live__pochettes { flex-wrap: nowrap; }

.live__pochettes figure { flex: 0 1 210px; min-width: 0; }

.live__pochettes img,
.live__pochettes__vide {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    border: var(--border);
    border-radius: 10px;
    object-fit: cover;
    background: var(--paper-deep);
    box-shadow: 4px 4px 0 var(--ink);
}

.live__pochettes figcaption { margin-top: 10px; }

.live__pochettes__niveau {
    display: inline-block;
    margin-bottom: 5px;
    padding: 3px 12px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .05em;
    background: var(--paper-deep);
}

.live__pochettes__niveau[data-ton="easy"]   { color: #12796f; }
.live__pochettes__niveau[data-ton="medium"] { color: #8a6d10; }
.live__pochettes__niveau[data-ton="hard"]   { color: #a8321f; }

.live__pochettes figcaption b {
    display: block;
    font-size: 14.5px;
    line-height: 1.25;
}

.live__pochettes figcaption small {
    display: block;
    margin-top: 2px;
    font-size: 12px;
    color: var(--ink-mute);
}

@media (max-width: 620px) {
    .live__pochettes { gap: 10px; }
    .live__pochettes figure { width: min(140px, 30vw); }
    .live__pochettes figcaption b { font-size: 12.5px; }
}


/* ---------- L'accueil du direct --------------------------------------------
   Les galettes côte à côte, le reste en dessous. Le conteneur portait une
   disposition en colonne : y poser deux galettes mettait le texte à côté
   d'elles plutôt qu'en dessous.
   -------------------------------------------------------------------- */

.live__accueil {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
}

.live__galettes {
    display: flex;
    gap: 34px;
    flex-wrap: wrap;
    justify-content: center;
}

.live__galette { text-align: center; }

.live__galette__num {
    display: block;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-mute);
    text-align: center;
}

/* Une partie close reste visible mais se distingue : on n'y joue plus, on la
   relit. */
.live__galette[data-etat="finie"] svg { opacity: .55; }

/* Le bouton d'une partie close est plus large que « Jouer » : il porte une
   phrase, pas un mot. */
.live__lancer--revoir {
    width: 150px;
    height: 150px;
    font-size: 14px;
    line-height: 1.25;
    padding: 0 14px;
}

.live__lancer--revoir { font-size: 15px; }

@media (max-width: 620px) {
    .live__accueil { gap: 20px; }
}


/* ---------- D'où viennent les disques ---------------------------------------
   Dans la fiche d'un vinyle, sous la règle : lesquels on a déjà, et sur quel
   album. La règle dit comment les gagner, cette liste ce qu'on en a fait.
   -------------------------------------------------------------------- */

.gemme-vue__ou {
    width: 100%;
    margin-top: 18px;
    padding-top: 14px;
    border-top: 1px dashed var(--ink-mute);
    text-align: left;
}

.gemme-vue__ou h4 {
    margin: 0 0 8px;
    font-size: 10.5px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.gemme-vue__ou ul { margin: 0; padding: 0; list-style: none; }

.gemme-vue__ou li {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
}

.gemme-vue__ou img {
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: 6px;
    border: var(--border);
    object-fit: cover;
}

.gemme-vue__ou li span { flex: 1; min-width: 0; }

.gemme-vue__ou b {
    display: block;
    font-size: 13px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.gemme-vue__ou small {
    display: block;
    font-size: 11px;
    color: var(--ink-mute);
    text-transform: capitalize;
}

.gemme-vue__ou em {
    flex: 0 0 auto;
    font-style: normal;
    font-weight: 700;
    font-size: 13px;
    color: var(--teal);
}


/* Le lien de relecture, sous la galette : discret, il ne rivalise pas avec
   le bouton de jeu. */
.live__revoir {
    border: var(--border);
    border-radius: 999px;
    padding: 8px 18px;
    background: var(--paper-hi);
    font-family: inherit;
    font-size: 13.5px;
    font-weight: 600;
    cursor: pointer;
}

.live__revoir:hover { background: var(--paper-deep); }

/* Un bilan de partie dans la fenêtre des résultats. */
.live-resultat + .live-resultat {
    margin-top: 26px;
    padding-top: 22px;
    border-top: 2px dashed var(--ink-mute);
}

.live-resultat h3 {
    margin: 0 0 12px;
    font-size: 12px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.live-resultat .live__pochettes { margin: 0 0 16px; }
.live-resultat .live__pochettes figure { flex: 0 1 130px; }
.live-resultat .live__pochettes figcaption b { font-size: 12.5px; }

/* Le choix du jeu, en tête du classement. */
/* Les deux jeux, centrés comme les onglets qui les suivent. */
.dcl-jeux {
    display: flex;
    gap: 8px;
    margin: 0 0 18px;
    justify-content: center;
}

.dcl-jeux button {
    border: var(--border);
    border-radius: 999px;
    padding: 8px 22px;
    background: var(--paper-hi);
    font-family: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
}

.dcl-jeux button.is-actif {
    background: var(--ink);
    color: var(--paper-hi);
}


/* =============================================================================
   L'ATELIER DE STORIES

   Deux colonnes : les réglages à gauche, l'aperçu à droite. L'aperçu est une
   vraie image de 1080 × 1920, réduite à l'écran par une mise à l'échelle —
   ce qu'on voit est exactement ce qui sera exporté.
   ========================================================================== */

.story__atelier {
    display: grid;
    grid-template-columns: minmax(300px, 380px) 1fr;
    gap: 28px;
    align-items: start;
}

.story__reglages { display: flex; flex-direction: column; gap: 16px; }

.story__bloc {
    padding: 16px 18px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
}

.story__bloc h2 {
    margin: 0 0 12px;
    font-family: var(--font-display);
    font-size: 16px;
}

.story__aide { margin: 6px 0 10px; font-size: 12px; color: var(--ink-mute); }

.story__champ {
    width: 100%;
    margin: 6px 0 12px;
    padding: 8px 12px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper);
    font-family: inherit;
    font-size: 13.5px;
}

textarea.story__champ { resize: vertical; line-height: 1.5; }

.story__paire { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

.story__ligne { display: block; margin: 12px 0; }

.story__ligne > span {
    display: block;
    margin-bottom: 6px;
    font-size: 11px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.story__ligne input[type="range"] { width: 100%; }

.story__bascule {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 10px 0 2px;
    font-size: 13.5px;
    cursor: pointer;
}

/* Les groupes de boutons : un seul actif, comme des onglets. */
.story__choix { display: flex; gap: 6px; flex-wrap: wrap; }

.story__choix button {
    flex: 1 1 auto;
    padding: 7px 12px;
    border: var(--border);
    border-radius: 999px;
    background: var(--paper);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
}

.story__choix button.is-actif { background: var(--ink); color: var(--paper-hi); }

.story__teintes { display: flex; gap: 8px; }

.story__teintes button {
    width: 30px;
    height: 30px;
    border: 2px solid var(--ink);
    border-radius: 50%;
    background: var(--t);
    cursor: pointer;
}

.story__teintes button.is-actif { box-shadow: 0 0 0 3px var(--paper), 0 0 0 5px var(--ink); }

/* Les résultats de recherche : une vignette et deux lignes. */
.story__trouves {
    margin: 0;
    padding: 0;
    list-style: none;
    max-height: 210px;
    overflow-y: auto;
}

.story__trouves li {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px;
    border-radius: 9px;
    cursor: pointer;
}

.story__trouves li:hover { background: var(--paper-deep); }

.story__trouves li.est-choisi {
    background: var(--ink);
    color: var(--paper-hi);
}

.story__trouves img {
    width: 42px;
    height: 42px;
    border-radius: 6px;
    object-fit: cover;
    flex: 0 0 auto;
}

.story__trouves b { display: block; font-size: 13px; }
.story__trouves small { font-size: 11px; opacity: .75; }

.story__vide { padding: 8px; font-size: 12.5px; color: var(--ink-mute); }

.story__actions { display: flex; gap: 8px; }

/* ---------- L'aperçu -------------------------------------------------------
   La vue fait ses 1080 × 1920 réels, ramenés à l'écran par « scale ». Rendre
   un aperçu plus petit puis l'exporter en grand aurait donné deux mises en
   page différentes.
   -------------------------------------------------------------------- */

.story__scene { position: sticky; top: 20px; }

.story__cadre {
    width: 324px;
    height: 576px;
    margin: 0 auto;
    border: 3px solid var(--ink);
    border-radius: 18px;
    overflow: hidden;
    box-shadow: 8px 8px 0 var(--ink);
}

.story__vue {
    width: 1080px;
    height: 1920px;
    transform: scale(0.3);
    transform-origin: top left;
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    font-family: var(--font-sans);
    color: var(--ink);
    background: var(--paper);
}

.story__format {
    margin: 12px 0 0;
    text-align: center;
    font-size: 11px;
    color: var(--ink-mute);
}

/* Les fonds. */
.story__vue[data-fond="uni"] { background: var(--paper); }

.story__vue[data-fond="degrade"] {
    background: linear-gradient(160deg, var(--paper-hi), var(--paper-deep));
}

.story__vue[data-fond="sombre"] { background: var(--ink); color: var(--paper-hi); }

.story__vue[data-fond="soleil"]::before {
    content: '';
    position: absolute;
    inset: -20%;
    background: repeating-conic-gradient(
        from 0deg at 50% 42%,
        var(--story-teinte, #d93b2b) 0deg 4deg,
        transparent 4deg 8deg
    );
    opacity: .14;
}

/* La teinte pilote le soleil, les accents et la bande du bas. */
.story__vue[data-teinte="rouge"]  { --story-teinte: #d93b2b; }
.story__vue[data-teinte="teal"]   { --story-teinte: #1a9c8b; }
.story__vue[data-teinte="or"]     { --story-teinte: #c9a227; }
.story__vue[data-teinte="encre"]  { --story-teinte: #17120f; }
.story__vue[data-teinte="creme"]  { --story-teinte: #e8dcc4; }

.story__grain {
    position: absolute;
    inset: 0;
    opacity: .5;
    pointer-events: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='.16'/%3E%3C/svg%3E");
}

.story__tete {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 24px;
    padding: 70px 80px 0;
}

.story__logo img { width: 96px; height: 96px; border-radius: 22px; display: block; }

.story__chaine {
    font-family: var(--font-mono);
    font-size: 30px;
    letter-spacing: .04em;
    opacity: .8;
}

.story__corps {
    position: relative;
    z-index: 2;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 34px;
    padding: 0 80px;
    justify-content: center;
    text-align: center;
    align-items: center;
}

.story__vue[data-place="haut"] .story__corps { justify-content: flex-start; padding-top: 90px; }
.story__vue[data-place="bas"] .story__corps { justify-content: flex-end; padding-bottom: 180px; }

.story__surtitre {
    margin: 0;
    font-family: var(--font-mono);
    font-size: 34px;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--story-teinte);
}

.story__titre {
    margin: 0;
    font-family: var(--font-display);
    font-size: 128px;
    line-height: .95;
    letter-spacing: -.02em;
}

.story__punch {
    margin: 0;
    font-size: 46px;
    line-height: 1.3;
    max-width: 820px;
}

.story__texte {
    margin: 0;
    font-size: 32px;
    line-height: 1.55;
    max-width: 780px;
    opacity: .82;
}

.story__quand {
    margin: 0;
    padding: 16px 40px;
    border-radius: 999px;
    background: var(--story-teinte);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 32px;
    text-transform: capitalize;
}

.story__vue[data-teinte="creme"] .story__quand { color: var(--ink); }

/* Le visuel, dans son cadre. */
.story__media { position: relative; max-width: 100%; }

.story__media img { width: 100%; display: block; }

.story__vue[data-cadre="carte"] .story__media img {
    border: 6px solid var(--ink);
    border-radius: 20px;
    box-shadow: 22px 22px 0 var(--ink);
}

.story__vue[data-cadre="polaroid"] .story__media {
    padding: 34px 34px 96px;
    background: #fdfaf3;
    box-shadow: 18px 18px 0 rgba(23, 18, 15, .28);
}

.story__vue[data-cadre="rond"] .story__media img {
    border-radius: 50%;
    border: 8px solid var(--ink);
}

.story__media__nom {
    display: block;
    margin-top: 26px;
    text-align: center;
}

.story__media__nom b { display: block; font-size: 40px; line-height: 1.2; }
.story__media__nom small { font-size: 28px; opacity: .7; }

.story__vue[data-cadre="polaroid"] .story__media__nom {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 22px;
    margin: 0;
    color: var(--ink);
}

/* Le repère du sticker de lien : visible ici, absent de l'export. */
.story__lien {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    z-index: 3;
    text-align: center;
}

.story__lien__cadre {
    display: block;
    width: 520px;
    height: 130px;
    border: 5px dashed var(--story-teinte);
    border-radius: 26px;
    opacity: .8;
}

.story__lien small {
    display: block;
    margin-top: 14px;
    font-family: var(--font-mono);
    font-size: 26px;
    color: var(--story-teinte);
}

.story__stries {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 46px;
    z-index: 2;
    background: repeating-linear-gradient(
        90deg,
        var(--story-teinte) 0 30px,
        var(--paper-hi) 30px 60px
    );
}

@media (max-width: 1000px) {
    .story__atelier { grid-template-columns: 1fr; }
    .story__scene { position: static; }
}





/* ---------- Le tableau de contrôle ------------------------------------------
   Quatre rangées, trois cases. Ce qui manque se voit sans avoir à lire.
   -------------------------------------------------------------------- */

.dev-pret {
    width: 100%;
    border-collapse: collapse;
    text-align: left;
}

.dev-pret thead th {
    padding: 0 10px 8px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.dev-pret tbody tr { border-top: 1px solid var(--paper-deep); }

.dev-pret tbody th {
    width: 210px;
    padding: 12px 10px;
    font-size: 13px;
    font-weight: 700;
}

.dev-pret td {
    padding: 10px;
    vertical-align: top;
}

/* Les états, chacun sa lecture. Un manque se voit en rouge ; une manche du
   direct pas encore lancée reste neutre, elle n'a rien d'anormal. */
.dev-pret td[data-etat="charge"] { background: rgba(26, 156, 139, .08); }
.dev-pret td[data-etat="encours"] { background: rgba(201, 162, 39, .14); }
.dev-pret td[data-etat="joue"] { background: rgba(26, 156, 139, .14); }

.dev-pret td[data-etat="manque"] { background: rgba(217, 59, 43, .1); }
.dev-pret td[data-etat="avenir"] { opacity: .5; }

.dev-pret__vide {
    font-size: 11.5px;
    font-style: italic;
    color: var(--ink-mute);
}

.dev-pret td[data-etat="manque"] .dev-pret__vide {
    font-style: normal;
    font-weight: 600;
    color: var(--red-deep);
}

/* L'album couvert : une étiquette, pas un titre. */
.dev-pret__album {
    display: inline-block;
    padding: 3px 9px;
    border-radius: 7px;
    background: var(--paper-deep);
    font-size: 11.5px;
    color: var(--ink-mute);
    cursor: pointer;
    user-select: none;
}

.dev-pret__album.est-vu {
    padding: 0;
    background: none;
    color: var(--ink);
    cursor: default;
}

.dev-pret__album b { display: block; font-size: 13px; line-height: 1.25; }
.dev-pret__album small { font-size: 11px; color: var(--ink-mute); }

.dev-pret__joueurs {
    display: block;
    margin-top: 5px;
    font-size: 10.5px;
    color: var(--ink-mute);
}

@media (max-width: 700px) {
    .dev-pret tbody th { width: auto; font-size: 11.5px; }
    .dev-pret td { padding: 8px 5px; }
}



/* ---------- L'accueil pendant un direct -------------------------------------
   Le lecteur prend toute la place. Le téléviseur, le nom et le bouton
   servaient à annoncer une chaîne hors ligne : pendant le direct, ils
   répètent ce qu'on a déjà sous les yeux.
   -------------------------------------------------------------------- */

.landing[data-live="1"] .landing__tv,
.landing[data-live="1"] .landing__name,
.landing[data-live="1"] .landing__actions { display: none; }

.landing[data-live="1"] { padding-top: 18px; }

/* Le lecteur monte et s'élargit : c'est lui qu'on vient voir. */
.landing[data-live="1"] .landing__player {
    width: min(100%, 1000px);
    margin: 0 auto;
}

/* Le titre du direct : centré s'il tient, défilant seulement s'il déborde.
   Faire défiler un titre court donnait un mouvement gratuit qui fatiguait
   l'œil. */
.landing__playerhead b {
    flex: 1;
    min-width: 0;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
}

.landing__playerhead b.est-long {
    text-align: left;
    animation: marquee 24s linear infinite;
}

.landing__player:hover .landing__playerhead b.est-long {
    animation-play-state: paused;
}

@media (prefers-reduced-motion: reduce) {
    .landing__playerhead b.est-long {
        animation: none;
        text-overflow: ellipsis;
    }
}


/* =============================================================================
   LA BULLE DE SONDAGE

   Un point flottant collé à un bord. On la déplace en hauteur, elle se range
   du côté le plus proche — au milieu, elle masquerait les colonnes qu'on est
   en train de remplir.
   ========================================================================== */

.sondage {
    position: fixed;

    /* Assez bas pour ne pas recouvrir la barre d'actions de la page : elle
       porte « Titres », « Post Instagram » et « Supprimer ». */
    top: 210px;

    /*
     * Au-dessus de tout, lecteur compris.
     *
     * Le lecteur de musique monte à 960 et recouvrait la bulle : on ne
     * pouvait plus lancer un sondage pendant qu'un morceau tournait, ce qui
     * est justement le moment où l'on veut demander l'avis du chat.
     */
    z-index: 1000;
    display: flex;
    align-items: flex-start;
    gap: 10px;
}

.sondage[data-cote="droite"] { right: 18px; flex-direction: row-reverse; }
.sondage[data-cote="gauche"] { left: 18px; }

.sondage__bulle {
    position: relative;
    flex: 0 0 auto;
    width: 46px;
    height: 46px;
    display: grid;
    place-items: center;
    border: var(--border);
    border-radius: 50%;
    background: var(--paper-hi);
    box-shadow: 3px 3px 0 var(--ink);
    /* Un curseur ordinaire : la bulle est d'abord un bouton. La main ne
       s'affiche que lorsqu'on la tient vraiment. */
    cursor: pointer;
    touch-action: none;
}

.sondage.est-saisi .sondage__bulle { cursor: grabbing; }

/* Pendant le geste, elle suit le pointeur sans transition : une animation
   la ferait traîner derrière la souris. */
.sondage.est-saisi { transition: none; }

.sondage.est-ouvert .sondage__bulle {
    background: var(--ink);
    color: var(--paper-hi);
}

/* Le compteur de participants, sur la bulle : on suit le sondage même quand
   le panneau est replié. */
.sondage__pastille {
    position: absolute;
    top: -5px;
    right: -5px;
    min-width: 20px;
    padding: 1px 5px;
    border-radius: 999px;
    background: var(--red);
    color: var(--paper-hi);
    font-family: var(--font-mono);
    font-size: 10.5px;
    font-weight: 700;
}

.sondage__panneau {
    width: 230px;
    padding: 13px 15px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
    box-shadow: 5px 5px 0 var(--ink);
}

.sondage__tete { margin-bottom: 11px; }
.sondage__tete b { display: block; font-size: 14px; }

.sondage__tete small {
    display: block;
    margin-top: 2px;
    font-size: 10.5px;
    line-height: 1.35;
    color: var(--ink-mute);
}

.sondage__ligne {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}

.sondage__lettre {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    display: grid;
    place-items: center;
    border-radius: 6px;
    border: 1.5px solid var(--ink);
    font-size: 11px;
    font-weight: 800;
    color: var(--ink);
}

.sondage__piste {
    flex: 1;
    height: 9px;
    border-radius: 999px;
    background: var(--paper-deep);
    overflow: hidden;
}

/* La jauge s'anime : on voit le sondage bouger pendant qu'on parle. */
.sondage__jauge {
    display: block;
    height: 100%;
    width: 0;
    transition: width .35s var(--ease);
}

.sondage__pc {
    flex: 0 0 auto;
    width: 38px;
    text-align: right;
    font-size: 11px;
    color: var(--ink-2);
}

.sondage__pied {
    margin: 10px 0 0;
    padding-top: 9px;
    border-top: 1px dashed var(--ink-mute);
    font-size: 11.5px;
    color: var(--ink-mute);
    text-align: center;
}

@media (max-width: 860px) {
    .sondage { top: auto; bottom: 100px; }
    .sondage__panneau { width: min(230px, 62vw); }
}


/* =============================================================================
   LE SUIVI DES PARTIES

   Un écran pour un dock d'OBS : il prend toute la fenêtre, quelle qu'en soit
   la taille, et reste lisible très étroit — c'est ainsi qu'on range un dock.
   ========================================================================== */

.flux {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    background: var(--paper);
    font-family: var(--font-sans);
    color: var(--ink);
}

.flux__tete {
    flex: 0 0 auto;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 16px;
    border-bottom: 2px solid var(--ink);
    background: var(--paper-hi);
}

.flux__titre {
    font-family: var(--font-display);
    font-size: 15px;
}

.flux__compte {
    font-size: 12px;
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--ink);
    color: var(--paper-hi);
}

.flux__liste {
    flex: 1;
    margin: 0;
    padding: 0;
    list-style: none;
    overflow-y: auto;
}

.flux__ligne {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 16px;
    border-bottom: 1px solid var(--paper-deep);

    /* La ligne arrive par le haut : on voit qu'elle vient de s'ajouter sans
       avoir à comparer avec l'état précédent. */
    animation: flux-entre .3s var(--ease) both;
}

@keyframes flux-entre {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: none; }
}

.flux__heure {
    flex: 0 0 auto;
    font-size: 11px;
    color: var(--ink-mute);
}

/* Le portrait du joueur, ou son initiale : la place est la même dans les
   deux cas, les noms restent alignés. */
.flux__avatar {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    border: 1.5px solid var(--ink);
    background: var(--paper-deep);
    overflow: hidden;
    font-size: 11px;
    font-weight: 700;
    color: var(--ink-2);
}

.flux__avatar img { width: 100%; height: 100%; object-fit: cover; }

.flux__qui {
    flex: 1;
    min-width: 0;
    font-size: 13.5px;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.flux__niveau {
    flex: 0 0 auto;
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--paper-deep);
    font-size: 10.5px;
    font-weight: 700;
}

.flux__ligne[data-ton="easy"] .flux__niveau   { color: #12796f; }
.flux__ligne[data-ton="medium"] .flux__niveau { color: #8a6d10; }
.flux__ligne[data-ton="hard"] .flux__niveau   { color: #a8321f; }

.flux__points {
    flex: 0 0 auto;
    min-width: 48px;
    text-align: right;
    font-size: 13px;
    font-weight: 700;
    color: var(--teal);
}

/* La place du disque est réservée même vide : sans elle, les lignes sans
   vinyle décaleraient leur colonne de points. */
.flux__disque {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    display: grid;
    place-items: center;
}

.flux__disque svg { width: 100%; height: 100%; }

.flux__vide {
    margin: 0;
    padding: 26px 16px;
    text-align: center;
    font-size: 13px;
    color: var(--ink-mute);
}

/* Très étroit, l'heure et le niveau s'effacent : le joueur et ses points
   suffisent à suivre. */
@media (max-width: 320px) {
    .flux__heure, .flux__niveau { display: none; }
}


/* =============================================================================
   LES EMOTES DU CHAT

   Un coin de l'incrustation où elles apparaissent, montent ou descendent, et
   s'effacent. La zone occupe un quart de l'écran : elles se dispersent
   dedans plutôt que de s'empiler sur le coin exact.
   ========================================================================== */

.emotes {
    position: fixed;
    width: 34vw;
    height: 40vh;
    overflow: hidden;
    pointer-events: none;
    z-index: 40;
}

.emotes[data-coin="HG"] { top: 0; left: 0; }
.emotes[data-coin="HD"] { top: 0; right: 0; }
.emotes[data-coin="BG"] { bottom: 0; left: 0; }
.emotes[data-coin="BD"] { bottom: 0; right: 0; }

.emotes__une {
    position: absolute;
    display: block;

    /*
     * Une course régulière, sans à-coup.
     *
     * Une courbe qui freine en fin de trajet donnait l'impression que
     * l'emote s'arrêtait avant de disparaître. Le déplacement est presque
     * linéaire ; le fondu, lui, garde sa propre douceur.
     */
    animation-timing-function: cubic-bezier(.33, .18, .58, 1), ease-in-out;
    animation-fill-mode: both;

    /* Une ombre portée légère : sur un fond clair de stream, une emote sans
       relief se confond avec l'image. */
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .35));
}


/* En bas, elles montent : elles partent du bord et s'élèvent dans la zone. */
@keyframes emote-monte {
    from {
        bottom: -60px;
        opacity: 0;
        transform: translateX(0) scale(.7);
    }
    18% { opacity: 1; }
    75% { opacity: 1; }
    to {
        bottom: 100%;
        opacity: 0;
        transform: translateX(var(--derive, 0)) scale(1);
    }
}

/* En haut, l'inverse : elles descendent depuis le bord supérieur. */
@keyframes emote-descend {
    from {
        top: -60px;
        opacity: 0;
        transform: translateX(0) scale(.7);
    }
    18% { opacity: 1; }
    75% { opacity: 1; }
    to {
        top: 100%;
        opacity: 0;
        transform: translateX(var(--derive, 0)) scale(1);
    }
}


/* ---------- Les incrustations, dans la page DEV -----------------------------
   Une par bloc, avec son adresse et ses options. On les colle dans OBS sans
   avoir à se souvenir des paramètres.
   -------------------------------------------------------------------- */

.dev__obs {
    margin: 0 0 14px;
    padding: 12px 14px;
    border: var(--border);
    border-radius: 12px;
    background: var(--paper);
}

.dev__obs b { display: block; font-size: 14px; }

.dev__obs > small {
    display: block;
    margin: 2px 0 9px;
    font-size: 12px;
    color: var(--ink-mute);
}

.dev__obs input {
    width: 100%;
    padding: 7px 11px;
    border: var(--border);
    border-radius: 9px;
    background: var(--paper-hi);
    font-size: 12.5px;
    cursor: pointer;
}

.dev__opts {
    margin: 10px 0 0;
    padding: 9px 0 0;
    border-top: 1px dashed var(--ink-mute);
    list-style: none;
}

.dev__opts li { padding: 2px 0; }

/* Chaque option est un interrupteur : on la voit s'allumer, et l'adresse
   au-dessus change en même temps. */
.dev__opts button {
    display: flex;
    align-items: baseline;
    gap: 9px;
    width: 100%;
    padding: 4px 6px;
    border: 0;
    border-radius: 7px;
    background: none;
    font-family: inherit;
    font-size: 12px;
    text-align: left;
    cursor: pointer;
}

.dev__opts button:hover { background: var(--paper-deep); }

.dev__opts button.est-actif code {
    background: var(--ink);
    color: var(--paper-hi);
}

.dev__opts button.est-actif span { color: var(--ink); }

.dev__opts code {
    flex: 0 0 auto;
    padding: 1px 7px;
    border-radius: 6px;
    background: var(--paper-deep);
    font-family: var(--font-mono);
    font-size: 11px;
}

.dev__opts span { color: var(--ink-mute); }


/* L'intertitre d'un groupe : le défi du jour, ou une partie du direct. */
.dcp-groupe {
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 14px 0 4px;
    padding: 0 2px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.dcp-groupe:first-of-type { margin-top: 6px; }

/* Les colonnes de la ligne, chacune à sa place. */
.dcp-album__niveau,
.dcp-album__chiffres,
.dcp-album__mien { justify-self: start; }

.dcp-album__chiffres {
    font-size: 11.5px;

    /* Sur une seule ligne : coupé en deux, le chiffre se lit moins bien que
       la colonne voisine et rompt l'alignement. */
    white-space: nowrap;
}

@media (max-width: 620px) {
    /* (règle reprise plus bas, en deux lignes) */
}


/*
 * Un seul mouvement, du début à la fin.
 *
 * La version d'avant faisait tout en trois temps — surgir, attendre, partir —
 * et la pause du milieu se voyait comme un à-coup. Ici la course est
 * continue : c'est l'opacité, sur sa propre piste, qui fait apparaître et
 * disparaître.
 */
@keyframes emote-monte {
    from { transform: translateY(34px) scale(.72); }
    to   { transform: translateY(-104px) scale(1.02); }
}

/* En haut, exactement l'inverse : elles descendent. */
@keyframes emote-descend {
    from { transform: translateY(-34px) scale(.72); }
    to   { transform: translateY(104px) scale(1.02); }
}

/* Le fondu tourne en parallèle du déplacement : deux animations sur le même
   élément, chacune avec sa propre courbe. */
@keyframes emote-fondu {
    0%   { opacity: 0; }
    14%  { opacity: 1; }
    68%  { opacity: 1; }
    100% { opacity: 0; }
}


/* Ma colonne dans les albums passés : le score marqué, et le disque décroché
   s'il y en a un. Deux informations distinctes, plus un mot fourre-tout. */
/* Le cadre coloré appartenait à l'ancienne pastille, qui portait un mot.
   Maintenant qu'on affiche un score et un disque, il enferme deux
   informations qui n'ont pas à l'être. */
.dcp-album__mien {
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    font-size: 12px;
    color: inherit;
}

.dcp-album__mien b { font-family: var(--font-mono); font-weight: 700; }

.dcp-album__mien em {
    font-style: normal;
    color: var(--ink-mute);
}

.dcp-album__mien svg { display: block; }



/* Le halo n'a plus d'usage : les faisceaux du fond portent la lumière. */
.wheel__halo { display: none; }



/* ---------- L'ombre sous la roue --------------------------------------------
   Elle assombrit ce qui passe derrière : sur une incrustation transparente,
   une roue claire posée sur une image claire perd son contour.
   -------------------------------------------------------------------- */

/*
 * L'ombre, entre la roue et sa lumière.
 *
 * Large, pour creuser un fond sombre tout autour : c'est ce contraste qui
 * détache la roue d'une image claire. Le halo passe dessous — la lumière
 * vient de derrière l'ombre, pas devant.
 */
/*
 * Une lueur, plus une ombre.
 *
 * Assombrir le pourtour détachait bien la roue, mais salissait l'image
 * derrière d'un cerne noir. Une lumière chaude fait le même travail — dire
 * où s'arrête la roue — en ajoutant au lieu de retrancher.
 */
.overlay-body .wheel__stage::before {
    content: '';
    position: absolute;
    inset: -22%;
    z-index: -2;
    border-radius: 50%;
    pointer-events: none;

    /*
     * Un blanc chaud, franc près du bord.
     *
     * Une lueur ambrée disparaissait dans les rayons, eux-mêmes orangés :
     * deux teintes voisines ne se distinguent pas. Le blanc, lui, tranche
     * quelle que soit la couleur du rayon qui passe derrière.
     */
    background: radial-gradient(circle at 50% 50%,
        rgba(255, 252, 240, .92) 41%,
        rgba(255, 240, 200, .62) 47%,
        rgba(255, 210, 130, .30) 55%,
        rgba(255, 170,  90, .10) 66%,
        rgba(255, 170,  90, 0)   78%
    );

    /* Sans mode de fusion : la lueur est assez claire pour se détacher
       seule, et la fusion coûtait une recomposition à chaque image. */

    /* Elle respire : la roue paraît allumée plutôt que posée sur un fond. */
    animation: roue-lueur 5s ease-in-out infinite;
}

@keyframes roue-lueur {
    0%, 100% { transform: scale(1);     opacity: .85; }
    50%      { transform: scale(1.035); opacity: 1; }
}

/* Pendant la rotation elle bat plus vite ; au résultat, elle éclate. */
.overlay-body .wheel__stage.is-spinning::before { animation-duration: 1.4s; }

.overlay-body .wheel__stage.is-won::before {
    animation-duration: .9s;
    filter: brightness(1.3);
}



/* =============================================================================
   LE TITRE DE LA ROULETTE

   Au-dessus de la roue, dans l'incrustation. Il doit se lire de loin et sur
   n'importe quel fond : d'où la taille, le contour sombre et le halo chaud.
   ========================================================================== */

/*
 * Il paraît et disparaît avec la roue.
 *
 * Laissé en permanence, il annonçait une roulette qui ne tourne pas. Le
 * sélecteur frère le lie à l'état de l'incrustation, sans avoir à le placer
 * dedans — un ancêtre transformé y piégerait son positionnement.
 */
.wheeltitre {
    opacity: 0;
    transform: translateX(-50%) translateY(-14px);
    transition: opacity .45s var(--ease), transform .55s var(--ease);
    position: fixed;
    top: 2.5vh;
    left: 50%;
    z-index: 6;
    display: grid;
    justify-items: center;
    gap: 0;
    pointer-events: none;
    text-align: center;
    line-height: 1;
    white-space: nowrap;
}

/* Une nappe sombre derrière le bloc entier : elle éteint les rayons juste
   sous le texte, sans dessiner de cadre. */
/*
 * Bien plus grande que le texte.
 *
 * Serrée sur lui, elle s'arrêtait net à quelques pixels des lettres et son
 * bord se voyait comme un rectangle sombre. En débordant largement, elle a
 * la place de s'éteindre.
 */
.wheeltitre::before {
    content: '';
    position: absolute;
    inset: -190% -85%;
    z-index: -1;
    pointer-events: none;
    /* Assez pour asseoir le texte, pas au point de creuser un trou noir
       dans le décor : les ombres portées de la lettre font le reste. */
    background: radial-gradient(ellipse at 50% 50%,
        rgba(10, 8, 6, .44) 12%,
        rgba(10, 8, 6, .32) 28%,
        rgba(10, 8, 6, .17) 42%,
        rgba(10, 8, 6, .06) 56%,
        rgba(10, 8, 6, 0)   70%
    );
}

/* Le petit mot d'attaque, posé sur le grand : il tient la ligne sans lui
   voler de place. */
.wheeltitre__sur {
    font-family: var(--font-display);
    font-size: clamp(14px, 2.4vh, 26px);
    font-weight: 700;
    letter-spacing: .24em;
    text-transform: uppercase;
    color: rgba(255, 226, 160, .95);
    margin-bottom: -.1em;

    text-shadow:
        0 2px 0 #12100e,
        0 3px 12px rgba(0, 0, 0, .9),
        0 0 18px rgba(255, 170, 70, .6);
}

/* Le mot porteur : c'est lui qu'on lit de loin. */
.wheeltitre__gros {
    font-family: var(--font-display);
    font-size: clamp(38px, 9vh, 104px);
    font-weight: 800;
    letter-spacing: -.02em;
    color: var(--paper-hi);

    /*
     * Un relief sous la lettre, puis deux halos.
     *
     * Le décalage vertical net imite l'épaisseur du lettrage peint qu'on
     * trouve sur les enseignes ; les halos, eux, l'allument.
     */
    /*
     * Beaucoup d'ombre.
     *
     * Le motif derrière est vif et bariolé : sans une masse sombre sous la
     * lettre, elle se perd dès qu'un rayon clair passe dessous. Les couches
     * nettes donnent l'épaisseur, les floues détachent du fond.
     */
    text-shadow:
        0 3px 0 #12100e,
        0 6px 0 #12100e,
        0 9px 0 rgba(18, 16, 14, .8),
        0 4px 18px rgba(0, 0, 0, .95),
        0 8px 34px rgba(0, 0, 0, .85),
        0 0 26px rgba(255, 190, 100, .7),
        0 0 62px rgba(255, 130, 50, .45);

    animation: titre-respire 5s ease-in-out infinite;
}

/* La mention, tenue par deux filets. */
.wheeltitre__sous {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: .35em;

    font-family: var(--font-mono);
    font-size: clamp(11px, 1.8vh, 19px);
    font-weight: 500;
    letter-spacing: .3em;
    text-transform: uppercase;
    color: rgba(255, 240, 214, .92);

    text-shadow:
        0 2px 0 #12100e,
        0 3px 14px rgba(0, 0, 0, .92),
        0 0 14px rgba(255, 170, 70, .5);
}

/* Les filets s'éteignent vers l'extérieur : ils encadrent sans enfermer. */
.wheeltitre__sous i {
    display: block;
    width: clamp(28px, 6vh, 72px);
    height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg,
        rgba(255, 190, 100, 0), rgba(255, 190, 100, .9));
    box-shadow: 0 0 10px rgba(255, 170, 70, .6);
}

.wheeltitre__sous i:last-child {
    background: linear-gradient(90deg,
        rgba(255, 190, 100, .9), rgba(255, 190, 100, 0));
}

@keyframes titre-respire {
    0%, 100% { opacity: .93; }
    50%      { opacity: 1; }
}

.overlay.is-visible ~ .wheeltitre {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* Hors incrustation, il n'a pas lieu d'être : la console a déjà son titre. */
body:not(.overlay-body) .wheeltitre { display: none; }


/* Le portrait, dans la colonne du nom : même taille des deux côtés, et une
   place réservée pour que les noms restent alignés sans lui. */
.dcl-nom {
    display: flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
}

.dcl-avatar {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 1.5px solid var(--ink);
    background: var(--paper-deep);
    object-fit: cover;
    display: block;
}

@media (max-width: 700px) {
    .dcl-avatar { width: 22px; height: 22px; }
}


/* ---------- Le rappel du soir, dans le compte ------------------------------- */

/*
 * Le rappel du soir n'a de sens que sur un téléphone.
 *
 * Sur ordinateur, une notification de navigateur arrive quand le site est
 * fermé depuis longtemps et n'a plus grand rapport avec le jeu du jour.
 */
.rappel { display: none; }

@media (max-width: 860px) {

.rappel {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin: 18px 0;
    padding: 14px 16px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
}

.rappel__quoi b { display: block; font-size: 14.5px; }

.rappel__quoi small {
    display: block;
    margin-top: 3px;
    max-width: 46ch;
    font-size: 12px;
    line-height: 1.45;
    color: var(--ink-mute);
}

/* Actif : une pastille verte, pour qu'on le voie sans lire le bouton. */
.rappel[data-etat="actif"] { border-color: var(--teal); }

.rappel[data-etat="actif"] .rappel__quoi b::after {
    content: '';
    display: inline-block;
    width: 7px;
    height: 7px;
    margin-left: 7px;
    border-radius: 50%;
    background: var(--teal);
    vertical-align: middle;
}

}

@media (max-width: 620px) {
    .rappel { flex-direction: column; align-items: stretch; }
    .rappel .btn { width: 100%; }
}


/* =============================================================================
   LE TOUCHER

   Un doigt couvre environ neuf millimètres : en dessous de 38 pixels, on vise
   à côté. Les liens gardent leur taille apparente ; c'est leur zone sensible
   qui grandit, par du remplissage et des marges négatives qui l'annulent.
   ========================================================================== */

@media (hover: none) and (pointer: coarse) {

    /* Le fil d'Ariane : des mots courts, donc des cibles minuscules. */
    .fil a,
    .fil span {
        display: inline-block;
        padding: 9px 4px;
        margin: -9px 0;
    }

    /* Les liens sous le jeu sont maintenant des boutons : ils ont déjà leur
       propre remplissage, en ajouter décalerait leur cadre. */
    .dcl-liens a {
        display: inline-block;
        padding: 10px 6px;
        margin: -10px 0;
    }

    /* Les boutons gardent une hauteur franche partout. */
    .btn,
    .btn--sm {
        min-height: 42px;
        padding-top: 9px;
        padding-bottom: 9px;
    }

    /* Les bascules Daily / Live : deux cibles voisines, il leur faut de la
       place pour qu'on ne prenne pas l'une pour l'autre. */
    .dcl-bascule button,
    .dcj-bascule button,
    .dcl-onglets button,
    .dcl-jeux button {
        min-height: 44px;
        padding-left: 20px;
        padding-right: 20px;
    }

    /* Les lignes de classement et d'album : la ligne entière devient la
       cible, plutôt que le seul texte. */
    .dcp-album,
    .dcl-table li a {
        min-height: 56px;
    }

    /* Rien ne se sélectionne par accident pendant qu'on fait défiler. */
    .dcj-vinyle,
    .dcp-album,
    .mob__slot {
        -webkit-tap-highlight-color: rgba(23, 18, 15, .08);
        -webkit-touch-callout: none;
    }
}


/* =============================================================================
   L'EN-TÊTE SUR MOBILE

   Sur un téléphone, la bande « en ligne / hors ligne » mangeait une ligne
   entière pour une information qu'on ne vient pas chercher. Elle disparaît ;
   la place revient au butin du joueur et à sa bulle de compte, qui eux
   servent à chaque partie.
   ========================================================================== */

@media (max-width: 860px) {

    .livebar { display: none; }

    /* L'en-tête se resserre : la marque à gauche, le butin au milieu, le
       compte à droite. */
    .pub-header {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr) auto;
        align-items: center;
        gap: 8px;
        padding: 8px 12px;
    }

    /*
     * L'en-tête reste en haut.
     *
     * Sur un téléphone, remonter chercher son butin après avoir fait défiler
     * une longue liste demande un aller-retour : il vaut mieux qu'il ne parte
     * jamais.
     */
    /*
     * Fixe, et non collant.
     *
     * « overflow-x: clip » sur le corps empêche « sticky » de fonctionner :
     * l'élément se comporte alors comme s'il défilait normalement. Une
     * position fixe s'en affranchit, au prix d'une marge à rendre au contenu
     * puisqu'il ne pousse plus rien.
     */
    .pub-header {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        z-index: 60;
    }

    /* La hauteur de l'en-tête, rendue au contenu. */
    body { padding-top: 58px; }

    /* Une cible d'ancre ne doit pas se cacher dessous. */
    :target { scroll-margin-top: 66px; }

    /* La marque se réduit au logo : le nom du site est déjà dans l'onglet, et
       la place revient au butin. */
    .brand span { display: none; }
    .brand img { width: 36px; height: 36px; }

    /* Le butin prend la place libérée, sans jamais pousser le reste. */
    .pub-butin-zone {
        display: block;
        min-width: 0;
        justify-self: center;
    }

    .pub-butin {
        display: flex;
        align-items: center;
        gap: 6px;
        padding: 4px 8px;
    }

    /* Les points restent dans la pastille, à gauche des vinyles : c'est le
       chiffre qu'on suit d'une partie à l'autre. */
    .pub-butin__points {
        display: flex;
        padding-right: 7px;
        margin-right: 3px;
        border-right: 1px solid rgba(251, 244, 230, .25);
    }

    .pub-butin__points b { font-size: 16px; }
    .pub-butin__points small { font-size: 10px; }

    .pub-butin__prix { padding: 2px 6px; gap: 4px; }
    .pub-butin__prix svg { width: 22px; height: 22px; }
    .pub-butin__prix b { font-size: 13px; }

    /*
     * Le portrait ne s'ouvre pas.
     *
     * Son menu ne contenait que « Mon compte » et « Se déconnecter », déjà
     * présents dans le tiroir du bas. Le rendre inerte évite qu'un pouce qui
     * vise le butin ouvre un menu par mégarde.
     */
    .pub-compte { justify-self: end; }

    /*
     * Inerte de bout en bout.
     *
     * « pointer-events » suffit à bloquer le clic, mais le bouton gardait ses
     * effets de survol et d'appui — d'où le léger sursaut au toucher. On
     * neutralise aussi l'apparence et la sélection.
     */
    .pub-moi,
    .pub-moi:hover,
    .pub-moi:active,
    .pub-moi:focus,
    .pub-moi[aria-expanded="true"] {
        pointer-events: none;
        cursor: default;
        transform: none !important;
        box-shadow: none !important;
        background: transparent !important;
        border-color: transparent !important;
        outline: none !important;
        -webkit-tap-highlight-color: transparent;
        user-select: none;
    }

    .pub-compte__menu { display: none !important; }
    .pub-moi b,
    .pub-moi svg { display: none; }

    .pub-moi {
        padding: 3px;
        border-radius: 50%;
    }

    .pub-moi img {
        width: 34px;
        height: 34px;
        margin: 0;
    }

    /* Le menu déroulant du compte s'aligne sur le bord droit. */
    .pub-compte__menu { right: 0; left: auto; }

    .burger { display: none; }

    /*
     * L'en-tête tient sur une seule ligne.
     *
     * « display: contents » sortait le menu de son enveloppe et faisait
     * surgir tout le bureau ; il suffit d'interdire le retour à la ligne.
     */
    .pub-header { flex-wrap: nowrap; }
}


/* =============================================================================
   LE CLASSEMENT D'ALBUMS SUR MOBILE

   L'en-tête prenait la moitié de l'écran avant le premier album, et chaque
   carte en prenait un tiers. Sur un téléphone, on veut voir la liste.
   ========================================================================== */

@media (max-width: 860px) {

    /* L'en-tête se resserre : titre plus petit, texte d'intro réduit à
       l'essentiel. */
    .page-head { margin-bottom: 14px; }

    .page-head h1,
    .pub-hero h1 { font-size: clamp(22px, 6.4vw, 30px); margin-bottom: 4px; }

    /* Le texte d'intro se lit en entier : le couper laissait une phrase en
       suspens, ce qui intrigue plus que ça n'informe. */
    .lede { font-size: 13px; line-height: 1.45; }

    /*
     * La carte d'un album : tout à côté de la vignette.
     *
     * Empilée, chacune prenait trois cents pixels de haut pour trois lignes
     * de texte. En grille, la pochette tient la hauteur et le reste se range
     * à sa droite.
     */
    .listcard {
        display: grid;
        grid-template-columns: 58px minmax(0, 1fr);
        align-items: center;
        gap: 4px 12px;
        padding: 10px 12px;
    }

    /* Le style en attribut met « flex » sur ce bloc : il faut « important »
       pour l'effacer, sans quoi la grille de la carte ne prend pas. */
    .listcard__tete { display: contents !important; }

    .listcard .crt--sm {
        width: 58px;
        height: 58px;
        margin: 0;
        grid-row: span 3;
    }

    .listcard__quoi { min-width: 0; }

    .listcard h3 {
        font-size: 15px;
        line-height: 1.2;
        margin: 0;
    }

    .listcard .meta { font-size: 11.5px; margin-top: 2px; }

    /* La barre et le pied se rangent sous le titre, dans sa colonne. */
    .listcard .progress { height: 5px; margin: 0; }

    .listcard .foot { margin: 0; font-size: 11px; }

    /* Le grand classement, plus haut : lui aussi se resserre. */
    .rankbar { padding: 11px 13px; }
    .rankbar__title b { font-size: 14.5px; }
    .rankbar__title small { font-size: 11.5px; }

    .rankbar__stats { display: none; }

    .rankbar__stats--jamais {
        display: flex;
        align-items: center;
        gap: 8px;
        font-size: 11px;
    }

    .score-chip { font-size: 12px; padding: 2px 8px; }

    /* Le chevron disparaît : la carte entière est déjà cliquable, et il
       volait de la place au titre. */
    .rankbar__chevron { display: none; }
}


/* =============================================================================
   LES ALBUMS PASSÉS SUR MOBILE

   Cinq colonnes ne tiennent pas dans 375 pixels : les cellules se
   chevauchaient, le niveau passant par-dessus le nombre de joueurs. En deux
   lignes, chacune a la place qu'il lui faut.
   ========================================================================== */

@media (max-width: 860px) {

    .dcp-album {
        display: grid;
        grid-template-columns: 46px minmax(0, 1fr) auto;
        grid-template-areas:
            'pochette titre  niveau'
            'pochette chiffres mien';
        align-items: center;
        gap: 3px 11px;
        padding: 9px 8px;
    }

    .dcp-album > :first-child { grid-area: pochette; }

    .dcp-album__quoi,
    .dcp-album > div:nth-child(2) { grid-area: titre; min-width: 0; }

    .dcp-album__niveau { grid-area: niveau; justify-self: end; }

    .dcp-album__chiffres {
        grid-area: chiffres;
        font-size: 11px;
        white-space: normal;
    }

    .dcp-album__mien { grid-area: mien; justify-self: end; font-size: 11px; }

    .dcp-album__mien b { font-size: 12px; }

    /* La pochette tient les deux lignes. */
    .dcp-album img,
    .dcp-album .crt {
        width: 46px;
        height: 46px;
    }

    /* Les intertitres de groupe se resserrent aussi. */
    .dcp-groupe { margin: 12px 0 3px; font-size: 10px; }
    .dcp-jour { margin-top: 16px; }
}


/* ---------- Les pièces du compte, sur mobile --------------------------------
   À 96 pixels débordant de 38 vers la gauche, elles mordaient sur la carte
   voisine. Plus petites et moins sorties, elles restent des médailles sans
   écraser le chiffre qu'elles accompagnent.
   -------------------------------------------------------------------- */

@media (max-width: 860px) {

    .mes-stats__piece { padding-left: 42px; }

    .mes-stats__disque {
        width: 62px;
        height: 62px;
        left: -16px;
    }

    .mes-stats__piece b { font-size: 20px; }
    .mes-stats__piece small { font-size: 10.5px; }
}


/* ---------- Les chiffres d'un album ----------------------------------------
   Le bouton n'existe que sur mobile : sur grand écran, la liste tient à côté
   de la pochette et n'a pas besoin d'être ouverte.
   -------------------------------------------------------------------- */

.fiche__voirfaits { display: none; }

@media (max-width: 860px) {

    .fiche__voirfaits {
        display: inline-flex;
        align-items: center;
        gap: 8px;
        padding: 10px 16px;
        border: var(--border);
        border-radius: 999px;
        background: var(--paper-hi);
        box-shadow: var(--lift-sm);
        font: inherit;
        font-size: 13.5px;
        font-weight: 600;
        cursor: pointer;
    }

    /* Dans la fenêtre, la liste s'étale sur deux colonnes : elle a la place,
       et l'œil compare plus vite. */
    .modal--faits .fiche__faits {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 10px 14px;
        margin: 0;
        padding: 0;
        list-style: none;
    }

    .modal--faits .fiche__faits li {
        padding: 7px 10px;
        border-radius: 10px;
        background: var(--paper);
    }

    .modal--faits .fiche__faits small {
        display: block;
        font-size: 10.5px;
        color: var(--ink-mute);
    }

    .modal--faits .fiche__faits b { font-size: 15px; }
}


/* =============================================================================
   LES RANGS EN CARTES, SUR MOBILE

   Empilés, les cinq rangs demandaient un long défilement vertical et on
   perdait de vue celui qu'on venait de quitter. En cartes côte à côte, chaque
   rang tient un écran et on passe de l'un à l'autre d'un geste — le même que
   pour changer de photo.
   ========================================================================== */

@media (max-width: 860px) {

    .tiers {
        display: flex;
        gap: 14px;

        /* Le défilement s'arrête sur une carte, jamais entre deux. */
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        scroll-padding: 0 14px;

        /* Une carte à la fois : sans cela, un geste un peu vif en franchit
           deux ou trois et on perd le fil. */
        overscroll-behavior-x: contain;

        /* Les cartes débordent du cadre de la page : les marges négatives
           rendent la largeur pleine, le remplissage garde la première et la
           dernière à distance du bord. */
        margin-inline: -16px;
        padding: 4px 16px 16px;

        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    .tiers::-webkit-scrollbar { display: none; }

    .tier--albums {
        flex: 0 0 86%;
        scroll-snap-align: center;

        /* Le défilement s'arrête obligatoirement sur chaque carte. */
        scroll-snap-stop: always;
        display: flex;
        flex-direction: column;
        min-width: 0;

        border: var(--border);
        border-radius: 16px;
        background: var(--paper-hi);
        box-shadow: var(--lift);
        overflow: hidden;
    }

    /* L'étiquette passe en bandeau, en haut de la carte. */
    .tier--albums .tier__label {
        width: auto;
        min-height: 0;
        padding: 10px 14px;
        border-radius: 0;
        border-bottom: var(--border);
    }

    .tier--albums .tier__letter { font-size: 22px !important; }

    /* La zone des albums défile verticalement dans sa carte : un rang chargé
       ne doit pas étirer la carte au-delà de l'écran. */
    .tier--albums .tier__drop {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 10px;
        padding: 12px;
        min-height: 180px;
        max-height: 58vh;
        overflow-y: auto;
        align-content: start;
    }

    /* Un repère sous les cartes : on sait qu'il y en a d'autres à côté. */
    .tiers-guide {
        display: flex;
        justify-content: center;
        gap: 6px;
        margin: -6px 0 18px;
    }

    .tiers-guide i {
        width: 6px;
        height: 6px;
        border-radius: 50%;
        background: var(--ink);
        opacity: .22;
        transition: opacity .2s var(--ease), transform .2s var(--ease);
    }

    .tiers-guide i.est-vu { opacity: 1; transform: scale(1.3); }
}


/* ---------- La pastille du grand classement --------------------------------

/* Ces deux-là n'existent que sur mobile : sur le bureau, la note garde sa
   ligne sous le texte et la carte s'ouvre par son chevron. */
.cover-note,
.acard__lien,
.rankbar__pastille { display: none; }

/* =============================================================================
   TOUT CE QUI SUIT NE CONCERNE QUE LE MOBILE

   Ces règles étaient écrites hors de toute condition de largeur et
   changeaient donc aussi l'affichage sur ordinateur, où rien ne le
   demandait. Elles sont enfermées ici : le bureau retrouve exactement ce
   qu'il avait.
   ========================================================================== */

@media (max-width: 860px) {
       Dans l'angle de la carte : un chiffre y est lu d'un coup d'œil, là où une
       phrase demande qu'on la parcoure.
       -------------------------------------------------------------------- */

    .rankbar { position: relative; }

    .rankbar__pastille {
        display: block;
        position: absolute;
        top: -9px;
        right: -7px;

        min-width: 30px;
        padding: 3px 8px;
        border: var(--border);
        border-radius: 999px;
        background: var(--red);
        box-shadow: var(--lift-sm);

        font-family: var(--font-mono);
        font-size: 13px;
        font-weight: 700;
        text-align: center;
        color: var(--paper-hi);
    }

    /* Le titre et sa description à côté de l'icône, pas dessous. */
    .rankbar__title {
        display: grid;
        grid-template-columns: 26px minmax(0, 1fr);
        align-items: center;
        gap: 12px;
    }

    /* L'icône tient dans sa colonne : à sa taille d'origine, elle poussait le
       texte hors du cadre. */
    .rankbar__title > svg {
        width: 26px;
        height: 26px;
    }

    .rankbar__title > span { min-width: 0; }
    .rankbar__title b { display: block; }
    .rankbar__title small { display: block; color: var(--ink-mute); }


    /* =============================================================================
       L'EN-TÊTE D'UNE FICHE D'ALBUM

       La pochette tenait cent vingt pixels et poussait le titre dessous. Réduite,
       elle laisse la place au nom de l'album et à l'artiste, qui sont ce qu'on
       vient lire.
       ========================================================================== */

    /* La largeur de bureau n'a rien à faire dans le bloc mobile : elle y
       luttait contre la règle qui la réduit. Le style en attribut de la
       vue s'en charge côté bureau. */

    /* La note et son rang, détachés du texte. */
    .scorebtn--static {
        display: flex;
        align-items: center;
        gap: 10px;
    }

    .scorebtn__rang {
        display: grid;
        place-items: center;
        width: 34px;
        height: 34px;
        border: var(--border);
        border-radius: 10px;

        /* La couleur vient du rang théorique, la lettre du rang réel : le fond
           dit ce que vaut la note, le signe dit où l'album est rangé. */
        background: var(--teinte, var(--paper-deep));
        color: var(--encre, var(--ink));

        font-family: var(--font-display);
        font-size: 17px;
        font-weight: 800;
    }


        .editor-head {
            display: grid;
            grid-template-columns: 76px minmax(0, 1fr);
            align-items: center;
            gap: 12px;
    }

        /*
         * Le sélecteur est doublé pour l'emporter.
         *
         * Trois règles plus haut fixent la largeur de « .editor-head .crt » ; à
         * spécificité égale, c'est la dernière qui gagne, et elles viennent après
         * une classe seule.
         */
        /* « !important » est nécessaire : la largeur d'origine est écrite en
       attribut « style », qu'aucun sélecteur ne peut surcharger autrement.
       C'est le prix à payer pour laisser le bureau intact. */
    .editor-head .editor-head__pochette { width: 76px !important; }

        /* Sans cela, « min-width: 220px » force le texte à passer à la ligne dès
           que l'écran est étroit. */
        .editor-head .info { min-width: 0; flex: initial; }

        /*
         * Le titre défile s'il déborde.
         *
         * Le couper priverait du nom de l'album ; le laisser passer à la ligne
         * doublerait la hauteur de l'en-tête. Le faire glisser montre tout sans
         * rien prendre.
         */
        .editor-head__titre {
            font-size: 19px;
            margin: 0;
            overflow: hidden;
            white-space: nowrap;
        }

        .editor-head__titre span { display: inline-block; }

        .editor-head__titre span.defile {
            animation: titre-glisse 12s linear infinite;
            padding-right: 40px;
        }

        .editor-head .meta { font-size: 12px; }

        /* La note passe sous le texte, sur toute la largeur. */
        .scorebtn--static {
            grid-column: 1 / -1;
            justify-content: flex-start;
            margin-top: 2px;
        }

    @keyframes titre-glisse {
        0%, 12%   { transform: translateX(0); }
        88%, 100% { transform: translateX(calc(-100% + 84vw)); }
    }


}

/* Cette section était restée hors de toute condition de largeur : ses
   règles écrasaient les cartes du grand classement sur ordinateur. */
@media (max-width: 860px) {

/* =============================================================================
   LES ALBUMS DU GRAND CLASSEMENT, SUR MOBILE

   En grille de deux, chaque album voyait son titre coupé au tiers. Un par
   ligne, la pochette à gauche et le texte à sa droite, tout tient et se lit.
   ========================================================================== */


    .tier--albums .tier__drop {
        grid-template-columns: 1fr;
        gap: 8px;

        /*
         * La hauteur restante, et pas plus.
         *
         * On retranche l'en-tête fixe, la barre du bas, la fiche de l'album
         * et le bandeau du rang : ce qui reste est ce que la liste peut
         * occuper sans pousser la page au-delà de l'écran.
         */
        max-height: calc(100vh - 340px);
        min-height: 120px;
    }

    .acard {
        display: grid;
        grid-template-columns: 46px minmax(0, 1fr) auto;
        align-items: center;
        gap: 11px;
        width: auto;
        padding: 7px 10px;
    }

    .acard .crt {
        width: 46px;
        height: 46px;
        margin: 0;
    }

    /* Le titre et l'artiste prennent la largeur restante, sans coupure. */
    .acard b {
        font-size: 13.5px;
        line-height: 1.25;
        margin: 0;
        white-space: normal;
        overflow: visible;
        text-overflow: clip;
    }

    .acard small {
        grid-column: 2;
        font-size: 11px;
        color: var(--ink-mute);
        white-space: normal;
    }

    /* Le lien d'ouverture passe à droite, sur les deux lignes. */
    .acard__open {
        position: static;
        grid-column: 3;
        grid-row: 1 / -1;
        opacity: 1;
    }

    .acard__score { top: 2px; right: 2px; }
}




/* La note sur la pochette n'existe que sur mobile : ailleurs, elle garde
   sa ligne sous le titre. */
@media (max-width: 860px) {
    /* ---------- La note, sur la pochette ----------------------------------------
       Dans l'angle de l'image : lue en même temps qu'elle, sans prendre de ligne.
       -------------------------------------------------------------------- */

    /*
     * La note se pose sur la carte, pas sur la pochette.
     *
     * Accrochée à la pochette, elle obligeait à lui retirer son « overflow »
     * — et la pochette débordait alors de son cadre arrondi. Dans le coin de
     * la carte, elle ne demande rien à personne.
     */
    .editor-head { position: relative; }

    .cover-note {
        display: block;
        position: absolute;
        top: 8px;
        right: 8px;
        z-index: 2;

        min-width: 30px;
        padding: 2px 7px;
        border: var(--border);
        border-radius: 999px;
        background: var(--teinte, var(--gold));
        color: var(--encre, var(--ink));
        box-shadow: var(--lift-sm);

        font-family: var(--font-mono);
        font-size: 12.5px;
        font-weight: 700;
        text-align: center;
    }

        .cover-note { font-size: 11px; min-width: 26px; padding: 1px 6px; }


    /* ---------- La carte d'album, cliquable en entier --------------------------- */

    .acard { position: relative; }

    /* Le lien recouvre la carte sans l'englober : le dessin reste libre, et
       n'importe quel point mène à l'album. */
    .acard__lien {
        display: block;
        position: absolute;
        inset: 0;
        z-index: 1;
        border-radius: inherit;
    }
}


/* La note centrée sous la pochette est propre au mobile : sur ordinateur,
   la carte garde son format d'origine. */
@media (max-width: 860px) {

/* La note sous la pochette, centrée : elle appartient à l'image plutôt qu'au
   texte, et se compare d'une carte à l'autre. */
.acard__score {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    top: auto;
    right: auto;

    min-width: 28px;
    padding: 1px 7px;
    border: 1.5px solid var(--ink);
    border-radius: 999px;
    box-shadow: 0 2px 0 var(--ink);

    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 700;
    text-align: center;
}

    /* La pochette porte la note sur son bord bas. */
    .acard .crt { position: relative; overflow: visible; }
    .acard__score { bottom: -7px; }
}




/* =============================================================================
   LES CARTES DE TITRE S'ADAPTENT À LEUR TEXTE

   À largeur fixe, un titre un peu long se coupait au tiers — « Titre num… »
   n'apprend rien. Elles prennent maintenant la place qu'il leur faut, dans
   une limite raisonnable pour que la colonne en montre plusieurs.

   Les cartes d'album du grand classement gardent leur format : elles portent
   une pochette carrée, dont la taille fait justement leur régularité.
   ========================================================================== */

/*
 * On distingue par le conteneur, pas par la classe du rang.
 *
 * « tier--albums » marque tous les rangs, des deux pages : c'est
 * l'identifiant de la liste qui dit si l'on range des titres ou des albums.
 * « #pub-tiers » est la fiche d'un album, « #pub-ranking-tiers » le grand
 * classement.
 */
/*
 * Toutes de la même largeur, et le titre entier.
 *
 * Des cartes de tailles inégales donnaient un rang en dents de scie. Elles
 * reprennent une largeur commune ; c'est le titre qui s'adapte, en passant
 * sur une seconde ligne au lieu d'être coupé.
 */
#pub-tiers .tier__drop {
display: grid;
grid-template-columns: repeat(auto-fill, var(--card-w));
justify-content: start;

/*
 * Les cartes d'une même ligne se calent sur la plus haute.
 *
 * « start » les laissait à leur hauteur propre : un titre sur deux lignes
 * voisinait avec un titre sur une, et le bas des cartes formait un
 * escalier.
 */
align-items: stretch;
}

#pub-tiers .card {
width: var(--card-w);
min-width: 0;
max-width: none;

/* La carte occupe la hauteur que la grille lui donne, et pousse sa
   dernière ligne — durée et bouton — contre le bas. */
display: flex;
flex-direction: column;
height: 100%;
}

/* Ce qui suit le titre se colle en bas, quelle que soit la hauteur. */
#pub-tiers .card > :last-child { margin-top: auto; }

/*
 * Le titre sur deux lignes au plus.
 *
 * Entier tant qu'il tient en deux lignes, tronqué au-delà — sans quoi un
 * titre à rallonge étirerait sa carte et romprait l'alignement du rang.
 */
#pub-tiers .card b {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
white-space: normal;
line-height: 1.25;

/* Plus de hauteur réservée : c'est la grille qui égalise, et un titre
   court n'a plus besoin de réserver une ligne vide. */
}


/* ---------- Une seule note à la fois ---------------------------------------
   Sur mobile, la note est sur la pochette ; le bloc sous le titre ferait
   double emploi et prendrait une ligne pour rien.
   -------------------------------------------------------------------- */

@media (max-width: 860px) {

    .editor-head .scorebtn--static { display: none; }

    /* Le titre reste dans son cadre : il défile s'il déborde, plutôt que de
       sortir de la carte. */
    .editor-head__titre {
        overflow: hidden;
        max-width: 100%;
    }
}


/* =============================================================================
   LES CARTES DE TITRE, SUR MOBILE

   Une seule ligne, en trois blocs : le numéro, les informations, le bouton.
   Le bloc du milieu tient deux lignes — le titre, puis la durée alignée à
   droite sous lui.
   ========================================================================== */

@media (max-width: 860px) {

    #pub-tiers .tier__drop {
        display: flex;
        flex-direction: column;
        gap: 8px;
    }

    #pub-tiers .card.card {
        display: grid;
        grid-template-columns: 38px minmax(0, 1fr) 34px;
        grid-template-rows: auto auto;
        align-items: center;
        gap: 0 10px;

        width: 100%;
        min-width: 0;
        max-width: none;
        padding: 8px 10px;
        height: auto;
        overflow: visible;
    }

    /* Les trois blocs sont des enfants directs de la grille. */
    #pub-tiers .card__top { display: contents; }

    /*
     * Le numéro, aussi haut que les deux lignes voisines.
     *
     * Un carré de la hauteur du bloc d'information : c'est ce qui donne à la
     * ligne son équilibre, plutôt qu'une pastille flottant au milieu.
     */
    #pub-tiers .card__num {
        grid-column: 1;
        grid-row: 1 / -1;
        align-self: stretch;

        display: grid;
        place-items: center;
        min-width: 38px;
        width: 38px;
        height: auto;
        min-height: 38px;
        border-radius: 9px;
        font-size: 14px;
    }

    /* Le titre, première ligne du bloc du milieu. */
    /* Le sélecteur est doublé : une règle plus haut met « white-space:
       normal » sur ce titre, et à spécificité égale c'est la dernière qui
       gagne. */
    #pub-tiers .card__title.card__title {
        grid-column: 2;
        grid-row: 1;

        /* Une seule ligne : la durée occupe la seconde, et deux lignes de
           titre feraient grandir la carte au-delà de ses voisines. */
        display: block;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;

        font-size: 13px;
        line-height: 1.3;
    }

    /*
     * Le pied s'efface devant la grille.
     *
     * Il contient la durée et le bouton ; tant qu'il existe, ses deux enfants
     * restent enfermés dedans et ne peuvent pas se placer dans des colonnes
     * différentes. « contents » le fait disparaître en tant que boîte.
     */
    #pub-tiers .card__foot {
        display: contents;
    }

    /* La durée, seconde ligne du bloc du milieu, poussée à droite. */
    #pub-tiers .card__foot > .mono {
        grid-column: 2;
        grid-row: 2;
        justify-self: end;
        margin-top: 1px;
        font-size: 10.5px;
        line-height: 1.2;
    }

    /* Le bouton au bout, sur les deux lignes. */
    #pub-tiers .card__links {
        grid-column: 3;
        grid-row: 1 / -1;
        justify-self: end;
        align-self: center;
    }
}

/* =============================================================================
   LES RANGS DU GRAND CLASSEMENT, SUR MOBILE

   Mêmes colonnes que sur la fiche d'un album : hauteur pleine, défilement
   interne, et des cartes en ligne plutôt qu'en vignettes.
   ========================================================================== */

@media (max-width: 860px) {

    /* La colonne garde sa hauteur même presque vide : une carte qui flotte
       dans un grand cadre reste plus lisible qu'un cadre qui change de taille
       d'un rang à l'autre. */
    #pub-ranking-tiers .tier__drop {
        display: flex;
        flex-direction: column;
        gap: 8px;
        max-height: none;
        min-height: 0;
        overflow-y: auto;
    }

    /*
     * La carte d'album, en ligne.
     *
     * La pochette à gauche, le titre et l'artiste à sa droite. C'est la même
     * lecture que les cartes de piste, ce qui évite d'avoir à s'habituer à
     * deux dispositions dans la même application.
     */
    #pub-ranking-tiers .acard {
        display: grid;
        grid-template-columns: 44px minmax(0, 1fr);
        align-items: center;
        gap: 0 10px;

        width: 100%;
        padding: 7px 10px;
    }

    /* La pochette se réduit : à sa taille de bureau elle mangeait la ligne. */
    #pub-ranking-tiers .acard .crt {
        grid-column: 1;
        grid-row: 1 / -1;
        width: 44px;
        height: 44px;
        margin: 0;
    }

    #pub-ranking-tiers .acard b {
        grid-column: 2;
        grid-row: 1;

        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;

        font-size: 13px;
        line-height: 1.3;
        margin: 0;
    }

    /* L'artiste, sous le titre et aligné à droite comme la durée d'une
       piste : les deux pages se lisent de la même façon. */
    #pub-ranking-tiers .acard small {
        grid-column: 2;
        grid-row: 2;
        justify-self: end;

        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 100%;

        font-size: 10.5px;
        line-height: 1.2;
        color: var(--ink-mute);
    }

    /* Le chevron disparaît : la carte entière est déjà un lien. */
    #pub-ranking-tiers .acard__open { display: none; }

    /* La note reste dans l'angle de la pochette. */
    #pub-ranking-tiers .acard__score {
        top: auto;
        bottom: -5px;
        left: 50%;
        right: auto;
        transform: translateX(-50%);
        font-size: 10px;
        padding: 0 5px;
        min-width: 24px;
    }
}


/* =============================================================================
   UNE PAGE DE RANGS TIENT DANS L'ÉCRAN

   La fiche d'un album et le grand classement ne défilent pas : ce sont leurs
   colonnes qui défilent, comme une pile de cartes qu'on feuillette. Le repère
   sous les colonnes reste donc toujours visible.

   La classe est posée par le script, et seulement sur ces deux pages : les
   autres gardent leur défilement.
   ========================================================================== */

@media (max-width: 860px) {

    body.fiche-fixe {
        overflow: hidden;
        height: 100vh;
    }

    /* On retranche l'en-tête fixe : le reste est ce que le contenu occupe. */
    body.fiche-fixe .pub-main {
        height: calc(100vh - 58px);
        overflow: hidden;
    }

    /* Les sections internes ne débordent pas non plus. */
    body.fiche-fixe .pub-main > section,
    body.fiche-fixe .dcl {
        max-height: 100%;
        overflow: hidden;
    }
}


/* ---------- L'en-tête du grand classement, sur mobile -----------------------
   L'icône tenait un quart de l'écran et poussait le texte hors du cadre. Elle
   se réduit au format des autres vignettes de la page.
   -------------------------------------------------------------------- */

@media (max-width: 860px) {

    /* L'en-tête du grand classement est un « editor-head », comme celui d'un
       album : il hérite donc de sa grille. Seule sa vignette diffère. */
    #pub-ranking .crt {
        /* Le style en attribut fixe 96 pixels ; « important » est le seul
           moyen de le réduire sans toucher au bureau. */
        width: 46px !important;
        height: 46px;
        margin: 0;
    }

    #pub-ranking .wordmark {
        font-size: 17px;
        line-height: 1.15;
        margin: 0;
    }

    #pub-ranking .meta {
        font-size: 11px;
        line-height: 1.35;
        margin-top: 2px;
    }
}


/* =============================================================================
   LES LISTES DE TITRES, SUR MOBILE

   Elles étaient dessinées pour un grand écran : hauteur de ligne large,
   corps de texte généreux. Sur un téléphone, une liste de douze titres
   demandait trois écrans de défilement.

   Vaut pour la fiche d'un album de classement comme pour celle d'un défi
   10Cover : mêmes réglages, une seule règle.
   ========================================================================== */

@media (max-width: 860px) {

    .fiche__pistes h2 {
        font-size: 15px;
        margin-bottom: 8px;
    }

    .fiche__pistes ol {
        display: flex;
        flex-direction: column;
        gap: 4px;
        margin: 0;
        padding: 0;
    }

    .fiche__pistes li {
        display: grid;
        grid-template-columns: 30px minmax(0, 1fr) auto;
        align-items: center;
        gap: 0 9px;

        padding: 6px 8px;
        min-height: 0;
        font-size: 12.5px;
        line-height: 1.3;
    }

    /* Le bouton d'écoute tient la première colonne, à la place du numéro. */
    .fiche__pistes .fiche__ecoute {
        grid-column: 1;
        width: 30px;
        height: 30px;
        min-width: 30px;
        padding: 0;
    }

    /*
     * Le titre prend la largeur restante, sur une ligne.
     *
     * Le sélecteur est doublé : la règle de bureau porte la même classe, et
     * à spécificité égale c'est la dernière qui gagne — or elle vient avant.
     */
    .fiche__pistes .fiche__titre.fiche__titre {
        grid-column: 2;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        font-size: 12.5px;
        line-height: 1.3;
    }

    /* La durée au bout, en petit. */
    .fiche__pistes .fiche__duree {
        grid-column: 3;
        font-size: 10.5px;
        white-space: nowrap;
    }

    /* Le bouton d'écoute se resserre lui aussi. */
    .fiche__pistes .fiche__ecoute.fiche__ecoute {
        width: 30px;
        height: 30px;
        min-width: 30px;
        padding: 0;
    }

    .fiche__pistes .fiche__ecoute svg {
        width: 13px;
        height: 13px;
    }
}


/* ---------- Les données d'un album, en grille ------------------------------
   Quatre lignes l'une sous l'autre pour quatre chiffres courts : autant les
   ranger deux par deux, la page y gagne la moitié de sa hauteur.
   -------------------------------------------------------------------- */

@media (max-width: 860px) {

    .fiche__faits {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 8px;
        margin: 0 0 14px;
        padding: 0;
        list-style: none;
    }

    .fiche__faits li {
        display: block;
        padding: 7px 9px;
        border-radius: 9px;
        background: var(--paper);
        border: 1px solid var(--paper-deep);
    }

    .fiche__faits small {
        display: block;
        font-size: 10px;
        line-height: 1.2;
        color: var(--ink-mute);
    }

    .fiche__faits b {
        display: block;
        margin-top: 1px;
        font-size: 14px;
        line-height: 1.2;
    }
}
/* =============================================================================
   LE SUIVI DES POINTS

   Un instrument de contrôle, pas une page de présentation : des tableaux
   denses, des chiffres alignés, et une seule couleur d'alerte pour ce qui
   mérite un coup d'œil.
   ========================================================================== */

.aud-cartes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 14px;
    margin: 18px 0;
}

.aud-carte {
    padding: 14px 16px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
}

.aud-carte h2 {
    margin: 0 0 10px;
    font-size: 15px;
}

.aud-carte dl { margin: 0; }

.aud-carte dl > div {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 5px 0;
    border-bottom: 1px solid var(--paper-deep);
}

.aud-carte dl > div:last-child { border-bottom: 0; }

.aud-carte dt {
    font-size: 12.5px;
    color: var(--ink-mute);
}

.aud-carte dd {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
}

/* Le verdict, en une ligne : ce qu'on vient lire en premier. */
.aud-verdict {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 12px;
    padding: 12px 16px;
    border: var(--border);
    border-radius: 12px;
    margin-bottom: 8px;
}

.aud-verdict b { font-size: 15px; }
.aud-verdict span { font-size: 13px; color: var(--ink-2); }

.aud-verdict.est-bon {
    background: rgba(23, 148, 139, .1);
    border-color: var(--teal);
}

.aud-verdict.est-douteux {
    background: rgba(217, 59, 43, .1);
    border-color: var(--red);
}

/* ---------- Les sondes ---------------------------------------------------- */

.aud-sondes {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.aud-sonde {
    border: var(--border);
    border-radius: 12px;
    background: var(--paper-hi);
    overflow: hidden;
}

/* Une sonde sans résultat s'efface : c'est le cas normal, il ne doit pas
   attirer l'œil autant qu'une anomalie. */
.aud-sonde.est-vide { opacity: .58; }

.aud-sonde summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 14px;
    cursor: pointer;
    font-size: 13.5px;
    font-weight: 600;
    list-style: none;
}

.aud-sonde summary::-webkit-details-marker { display: none; }

.aud-pastille {
    min-width: 30px;
    padding: 1px 8px;
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: 11.5px;
    text-align: center;
}

.aud-pastille--vert  { background: rgba(23, 148, 139, .18); color: var(--teal); }
.aud-pastille--rouge { background: var(--red); color: var(--paper-hi); }
.aud-pastille--gris  { background: var(--paper-deep); color: var(--ink-mute); }

.aud-note {
    margin: 0;
    padding: 0 14px 12px;
    font-size: 12px;
    color: var(--ink-mute);
}

.aud-carte .aud-note { padding: 10px 0 0; }

/* ---------- Les tableaux -------------------------------------------------- */

/*
 * Le défilement latéral est dans la zone, pas dans la page.
 *
 * Un tableau de dix colonnes ne tient pas toujours : il vaut mieux qu'il
 * défile chez lui plutôt que d'élargir toute la page.
 */
.aud-table-zone {
    overflow-x: auto;
    border: var(--border);
    border-radius: 12px;
    background: var(--paper-hi);
    margin-bottom: 18px;
}

.aud-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12.5px;
}

.aud-table th,
.aud-table td {
    padding: 7px 10px;
    text-align: left;
    white-space: nowrap;
    border-bottom: 1px solid var(--paper-deep);
}

.aud-table th {
    position: sticky;
    top: 0;
    background: var(--paper);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.aud-table tbody tr:last-child td { border-bottom: 0; }

.aud-table tbody tr:hover { background: rgba(23, 18, 15, .035); }

/* La seule couleur d'alerte du tableau : une ligne qui mérite un examen. */
.aud-table tr.est-douteux { background: rgba(217, 59, 43, .09); }
.aud-table tr.est-douteux:hover { background: rgba(217, 59, 43, .14); }

.aud-table .est-douteux { color: var(--red); font-weight: 700; }

/* Ce qu'il fallait trouver, en retrait : c'est une référence, pas une
   donnée du joueur. */
.aud-attendu { color: var(--ink-mute); font-style: italic; }

/* ---------- La recherche -------------------------------------------------- */

.aud-rech {
    display: flex;
    gap: 10px;
    margin: 16px 0 20px;
}

.aud-rech input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 10px 14px;
    border: var(--border);
    border-radius: 999px;
    background: var(--paper-hi);
    font: inherit;
    font-size: 14px;
}

@media (max-width: 860px) {
    .aud-rech { flex-direction: column; }
    .aud-rech .btn { width: 100%; }
    .aud-table { font-size: 11.5px; }
    .aud-table th, .aud-table td { padding: 6px 8px; }
}


/* =============================================================================
   LE GESTIONNAIRE DE COMMANDES
   ========================================================================== */

.cmd-liste {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 18px 0;
}

.cmd {
    padding: 13px 16px;
    border: var(--border);
    border-radius: 13px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
}

/* Une commande hors service reste lisible mais s'efface : elle existe, elle
   ne répond simplement pas. */
.cmd.est-eteinte { opacity: .5; }

.cmd__tete {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 7px;
}

.cmd__nom {
    font-family: var(--font-mono);
    font-size: 15px;
    font-weight: 700;
}

.cmd__alias code {
    font-size: 11.5px;
    padding: 1px 6px;
    border-radius: 6px;
    background: var(--paper-deep);
    color: var(--ink-mute);
    margin-right: 3px;
}

.cmd-etiquette {
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--paper-deep);
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--ink-mute);
}

.cmd-etiquette--acces {
    background: rgba(23, 148, 139, .16);
    color: var(--teal);
}

.cmd__reponse {
    margin: 0;
    font-size: 13.5px;
    line-height: 1.45;
    word-break: break-word;
}

.cmd__note {
    margin: 6px 0 0;
    font-size: 12px;
    font-style: italic;
    color: var(--ink-mute);
}

.cmd__pied {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-top: 11px;
    padding-top: 10px;
    border-top: 1px solid var(--paper-deep);
    font-size: 11.5px;
    color: var(--ink-mute);
}

.cmd__boutons { display: flex; gap: 6px; }

/* La suppression se distingue : c'est la seule action sans retour. */
.cmd__suppr:hover { color: var(--red); border-color: var(--red); }

/* ---------- Les variables -------------------------------------------------- */

.cmd-vars {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 7px;
    margin: 14px 0 22px;
}

.cmd-var {
    display: flex;
    align-items: baseline;
    gap: 9px;
    padding: 7px 11px;
    border: 1px solid var(--paper-deep);
    border-radius: 9px;
    background: var(--paper-hi);
    text-align: left;
}

.cmd-var code {
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
    color: var(--red);
}

.cmd-var span {
    font-size: 11.5px;
    line-height: 1.35;
    color: var(--ink-mute);
}

/* Cliquables dans l'éditeur : elles s'insèrent au curseur. */
.cmd-vars--cliquables .cmd-var {
    cursor: pointer;
    font: inherit;
    transition: border-color .15s, transform .12s;
}

.cmd-vars--cliquables .cmd-var:hover {
    border-color: var(--ink);
    transform: translateY(-1px);
}

/* ---------- L'éditeur ------------------------------------------------------ */

.cmd-form { max-width: 760px; }

.cmd-form__grille {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 14px;
    margin-bottom: 14px;
}

.champ-bloc {
    display: block;
    margin-bottom: 14px;
}

.champ-bloc > span {
    display: block;
    margin-bottom: 5px;
    font-size: 12.5px;
    font-weight: 600;
}

.champ-bloc input,
.champ-bloc select,
.champ-bloc textarea {
    width: 100%;
    padding: 9px 12px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper-hi);
    font: inherit;
    font-size: 13.5px;
}

.champ-bloc textarea {
    resize: vertical;
    line-height: 1.5;
}

.champ-bloc small {
    display: block;
    margin-top: 4px;
    font-size: 11.5px;
    color: var(--ink-mute);
}

/* Le point d'exclamation, collé au champ : il fait partie de l'usage, pas du
   nom qu'on enregistre. */
.champ-prefixe {
    display: flex;
    align-items: stretch;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper-hi);
    overflow: hidden;
}

.champ-prefixe b {
    display: grid;
    place-items: center;
    padding: 0 11px;
    background: var(--paper-deep);
    font-family: var(--font-mono);
    font-size: 15px;
}

.champ-prefixe input {
    border: 0;
    border-radius: 0;
    background: transparent;
}

.champ-bascule {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 18px;
    font-size: 13.5px;
    cursor: pointer;
}

.cmd-apercu {
    padding: 12px 15px;
    border: 1px dashed var(--ink-mute);
    border-radius: 11px;
    background: var(--paper);
    margin-bottom: 14px;
}

.cmd-apercu__tete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 7px;
}

.cmd-apercu__tete b { font-size: 12px; color: var(--ink-mute); }

.cmd-apercu__texte {
    margin: 0;
    font-size: 13.5px;
    line-height: 1.5;
    word-break: break-word;
}

.cmd-form__pied {
    display: flex;
    gap: 9px;
    padding-top: 6px;
}

@media (max-width: 860px) {
    .cmd-form__grille { grid-template-columns: 1fr; }
    .cmd-vars { grid-template-columns: 1fr; }
    .cmd__pied { flex-direction: column; align-items: flex-start; }
    .cmd__boutons { width: 100%; flex-wrap: wrap; }
}


/* ---------- Le détail d'une partie, dans le suivi --------------------------- */

.aud-parties {
    display: flex;
    flex-direction: column;
    gap: 7px;
    margin-bottom: 20px;
}

.aud-partie {
    border: var(--border);
    border-radius: 11px;
    background: var(--paper-hi);
    overflow: hidden;
}

.aud-partie.est-douteuse { border-color: var(--red); }

.aud-partie summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 9px 13px;
    cursor: pointer;
    font-size: 12.5px;
    list-style: none;
}

.aud-partie summary::-webkit-details-marker { display: none; }

.aud-partie__quand { color: var(--ink-mute); font-size: 11.5px; }

.aud-partie__niveau {
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--paper-deep);
    font-size: 11px;
}

/* L'album prend la place restante et pousse le score au bout. */
.aud-partie__album {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
}

/* Les trois champs d'un coup d'œil : A, L, D ou un point. */
.aud-partie__champs {
    letter-spacing: .18em;
    font-size: 13px;
    color: var(--teal);
}

.aud-partie__score { font-size: 12.5px; }

/* La colonne du champ, qui coiffe ses essais. */
.aud-champ {
    vertical-align: top;
    background: var(--paper);
    border-right: 1px solid var(--paper-deep);
}

.aud-champ b { display: block; font-size: 12.5px; }

.aud-champ small {
    display: block;
    margin-top: 2px;
    font-size: 10.5px;
    color: var(--ink-mute);
}

/* L'essai qui a payé : c'est lui qu'on cherche en relisant une partie. */
.aud-table tr.est-juste { background: rgba(23, 148, 139, .08); }
.aud-table tr.est-juste:hover { background: rgba(23, 148, 139, .13); }


/* =============================================================================
   LES CASES DE QUESTION, DANS 10COVER

   Trois cases fermées, une seule ouverte à la fois. Le joueur ne peut répondre
   qu'à une question à la fois : l'interface le dit.
   ========================================================================== */

.dcj-case {
    border: var(--border);
    border-radius: 13px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    overflow: hidden;
    transition: box-shadow .18s var(--ease), transform .18s var(--ease);
}

.dcj-case.est-ouverte {
    box-shadow: var(--lift);
    border-color: var(--ink);
}

/* La tête : le nom de la case et ce qu'elle rapporte. */
.dcj-case__tete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 13px 15px;
    border: 0;
    background: transparent;
    font: inherit;
    cursor: pointer;
    text-align: left;
}

.dcj-case__tete:disabled { cursor: default; }

.dcj-case__tete b {
    font-family: var(--font-display);
    font-size: 16px;
}

/* Ce que la case vaut : en vert tant qu'on peut la gagner. */
.dcj-case__vaut {
    padding: 2px 10px;
    border-radius: 999px;
    background: rgba(23, 148, 139, .15);
    color: var(--teal);
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 700;
}

/* Trouvée : la case s'apaise et affiche ce qu'elle a rapporté. */
.dcj-case[data-etat="trouve"] {
    border-color: var(--teal);
    background: rgba(23, 148, 139, .07);
}

.dcj-case[data-etat="trouve"] .dcj-case__vaut {
    background: var(--teal);
    color: var(--paper-hi);
}

/* Ratée : elle s'efface, sans disparaître — on veut voir la réponse. */
.dcj-case[data-etat="rate"] { opacity: .62; }

.dcj-case[data-etat="rate"] .dcj-case__vaut {
    background: var(--paper-deep);
    color: var(--ink-mute);
}

.dcj-case__reponse {
    margin: 0;
    padding: 0 15px 13px;
    font-size: 13.5px;
    color: var(--ink-2);
}

/*
 * Le corps se déplie.
 *
 * « grid-template-rows » de 0 à 1 fraction : c'est la seule façon d'animer une
 * hauteur qu'on ne connaît pas à l'avance.
 */
.dcj-case__corps {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows .22s var(--ease);
}

.dcj-case.est-ouverte .dcj-case__corps { grid-template-rows: 1fr; }

/* L'unique enfant porte le rognage : c'est lui qui se replie. */
.dcj-case__dedans {
    min-height: 0;
    overflow: hidden;
}

.dcj-case__question {
    margin: 0;
    padding: 0 15px 10px;
    font-size: 14px;
    font-weight: 600;
}

.dcj-case__form {
    display: flex;
    gap: 8px;
    padding: 0 15px 13px;
}

.dcj-case__form input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 10px 13px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper);
    font: inherit;
    font-size: 15px;
}

.dcj-case__indice,
.dcj-case__restants {
    margin: 0;
    padding: 0 15px 11px;
    font-size: 12px;
    color: var(--ink-mute);
}

.dcj-case__indice { color: var(--gold); font-weight: 600; }

/* ---------- Le bonus, près du bouton --------------------------------------- */

.dcj-bonus {
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1.1;
}

.dcj-bonus b {
    font-family: var(--font-mono);
    font-size: 17px;
    color: var(--teal);
}

.dcj-bonus b.est-nul { color: var(--ink-mute); }

.dcj-bonus small {
    font-size: 10px;
    color: var(--ink-mute);
    white-space: nowrap;
}

/* ---------- Le score acquis ------------------------------------------------ */

.dcj-total {
    display: flex;
    align-items: baseline;
    gap: 7px;
    margin: 0;
}

.dcj-total b {
    font-family: var(--font-display);
    font-size: 24px;
}

.dcj-total small { font-size: 12px; color: var(--ink-mute); }

.dcj-total em {
    font-size: 11.5px;
    font-style: normal;
    color: var(--ink-mute);
    opacity: .8;
}

@media (max-width: 860px) {
    .dcj-case__tete { padding: 11px 13px; }
    .dcj-case__tete b { font-size: 15px; }
    .dcj-case__form { flex-direction: column; }
    .dcj-case__form .btn { width: 100%; }
    .dcj-total b { font-size: 20px; }
    .dcj-bonus small { font-size: 9px; }
}


/* =============================================================================
   LES ESSAIS PASSÉS, SOUS LE CHAMP

   Numérotés, dans l'ordre, avec leur verdict. Ils remplacent les
   notifications : l'information reste sous les yeux au lieu de passer.
   ========================================================================== */

.dcj-essais {
    display: flex;
    flex-direction: column;
    gap: 5px;
    margin: 0;
    padding: 0 15px 13px;
    list-style: none;
}

.dcj-essais li {
    display: flex;
    align-items: baseline;
    gap: 9px;
    padding: 6px 10px;
    border-radius: 8px;
    background: var(--paper);
    font-size: 13px;
}

.dcj-essais li.est-bon {
    background: rgba(23, 148, 139, .14);
}

.dcj-essais__rang {
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-size: 10.5px;
    color: var(--ink-mute);
}

/* Ce qui a été tapé prend la place restante et pousse le verdict au bout. */
.dcj-essais li b {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dcj-essais__verdict {
    flex: 0 0 auto;
    font-size: 11px;
    color: var(--ink-mute);
}

.dcj-essais__verdict.est-bon { color: var(--teal); font-weight: 700; }

/* Le sens, pour l'année : c'est un indice, pas un constat d'échec. */
.dcj-essais__verdict.est-sens {
    color: var(--gold);
    font-weight: 600;
}

/* ---------- Le refus, sans notification ------------------------------------ */

/*
 * Le champ tremble et rougit une fois.
 *
 * Trois allers-retours courts : assez pour être vu, trop bref pour gêner celui
 * qui tape déjà sa réponse suivante.
 */
@keyframes dcj-rate {
    0%, 100% { transform: translateX(0); }
    15%      { transform: translateX(-7px); }
    30%      { transform: translateX(6px); }
    45%      { transform: translateX(-4px); }
    60%      { transform: translateX(3px); }
    75%      { transform: translateX(-2px); }
}

.dcj-case__form input.est-rate {
    animation: dcj-rate .42s var(--ease);
    border-color: var(--red);
    background: rgba(217, 59, 43, .09);
}

/* Le retour au calme est progressif : la secousse s'arrête net, la couleur
   s'efface. */
.dcj-case__form input {
    transition: border-color .35s var(--ease), background .35s var(--ease);
}

@media (max-width: 860px) {
    .dcj-essais { padding: 0 13px 11px; }
    .dcj-essais li { font-size: 12.5px; padding: 5px 9px; gap: 7px; }
    .dcj-essais__rang { font-size: 10px; }
}

/* Ceux qui préfèrent éviter les mouvements gardent le changement de couleur. */
@media (prefers-reduced-motion: reduce) {
    .dcj-case__form input.est-rate { animation: none; }
    .dcj-case__corps { transition: none; }
}


/* =============================================================================
   LES PHASES DU DIRECT

   Le compte à rebours sous l'image, et l'annonce qui marque le changement
   d'étape.
   ========================================================================== */

.live-minuteur {
    display: grid;
    justify-items: center;
    gap: 3px;
    margin: 14px auto 6px;
    max-width: 260px;
}

.live-minuteur b {
    font-family: var(--font-display);
    font-size: 40px;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.live-minuteur small {
    font-size: 12px;
    color: var(--ink-mute);
    letter-spacing: .04em;
}

.live-minuteur__barre {
    width: 100%;
    height: 5px;
    margin-top: 5px;
    border-radius: 999px;
    background: var(--paper-deep);
    overflow: hidden;
}

.live-minuteur__barre i {
    display: block;
    height: 100%;
    width: 100%;
    border-radius: 999px;
    background: var(--teal);

    /* Une seconde tout juste : la barre descend au même rythme que le
       chiffre, sans le devancer ni le suivre. */
    transition: width 1s linear;
}

/* Les cinq dernières secondes : le chiffre rougit et bat. */
.live-minuteur.est-urgent b { color: var(--red); animation: live-bat 1s infinite; }
.live-minuteur.est-urgent .live-minuteur__barre i { background: var(--red); }

@keyframes live-bat {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.12); }
}

/* ---------- Les compteurs sur les cases ------------------------------------ */

.live__trouveurs {
    display: block;
    margin-top: 3px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--ink-mute);
}

/* Dès que quelqu'un a trouvé, le compte se voit : c'est la pression. */
.live__trouveurs.est-vif { color: var(--teal); font-weight: 700; }

/*
 * Un champ verrouillé par l'admin.
 *
 * Le chat ne marque plus dessus : le dire évite de se demander pourquoi le
 * compteur s'est arrêté.
 */
.live__champs li.est-verrouille { opacity: .72; }

.live__champs li.est-verrouille .live__trouveurs::after {
    content: ' · verrouillé';
    color: var(--ink-mute);
    font-weight: 400;
}

@media (max-width: 860px) {
    .live-minuteur b { font-size: 32px; }
    .live-etape { padding: 10px 18px; margin: 10px auto; }
    .live-etape b { font-size: 17px; }
    .live-etape small { font-size: 11.5px; }
}

@media (prefers-reduced-motion: reduce) {
    .live-minuteur.est-urgent b { animation: none; }
    .live-etape.est-entree,
    .live-etape.est-partie { animation-duration: .01s; }
}


/* =============================================================================
   LES CASES DE LA RÉGIE

   Mêmes gestes que le jeu quotidien : une case ouverte à la fois, sa question
   dedans. S'y ajoute le compte de ceux qui ont trouvé dans le chat.
   ========================================================================== */

.live-cases {
    display: flex;
    flex-direction: column;
    gap: 9px;
    margin: 14px 0;
}

.live-case {
    border: var(--border);
    border-radius: 13px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    overflow: hidden;
}

.live-case.est-ouverte { border-color: var(--ink); box-shadow: var(--lift); }

.live-case__tete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 12px 15px;
    border: 0;
    background: transparent;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.live-case__tete:disabled { cursor: default; }

.live-case__tete b {
    font-family: var(--font-display);
    font-size: 16px;
}

/* Le compte du chat : discret tant que personne n'a trouvé, net ensuite. */
.live-case__chat {
    font-family: var(--font-mono);
    font-size: 11.5px;
    color: var(--ink-mute);
}

.live-case__chat.est-vif { color: var(--teal); font-weight: 700; }

.live-case.est-trouve {
    border-color: var(--teal);
    background: rgba(23, 148, 139, .07);
}

.live-case.est-passe,
.live-case.est-close { opacity: .66; }

.live-case__reponse {
    margin: 0;
    padding: 0 15px 12px;
    font-size: 13.5px;
    color: var(--ink-2);
}

/* Le dépliage, comme dans le jeu : une grille qui passe de 0 à 1 fraction. */
.live-case__corps {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows .2s var(--ease);
}

.live-case.est-ouverte .live-case__corps { grid-template-rows: 1fr; }

.live-case__dedans { min-height: 0; overflow: hidden; }

.live-case__question {
    margin: 0;
    padding: 0 15px 9px;
    font-size: 14px;
    font-weight: 600;
}

.live-case__form {
    display: flex;
    gap: 8px;
    padding: 0 15px 11px;
}

.live-case__form input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 10px 13px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper);
    font: inherit;
    font-size: 15px;
}

.live-case__essais {
    margin: 0;
    padding: 0 15px 12px;
    font-size: 12px;
    color: var(--ink-mute);
}

/* Un champ que l'animateur a trouvé : le chat n'y marque plus. */
.live-case.est-verrouille .live-case__chat::after {
    content: ' · verrouillé';
    color: var(--ink-mute);
    font-weight: 400;
}

.live-outils {
    display: flex;
    gap: 8px;
    justify-content: center;
}

@media (max-width: 860px) {
    .live-case__form { flex-direction: column; }
    .live-case__form .btn { width: 100%; }
    .live-outils { flex-direction: column; }
    .live-outils .btn { width: 100%; }
}


/* =============================================================================
   LES PRODUITS DE LA BOUTIQUE, EN SVG

   Un dessin plat, aux couleurs du site, qui flotte doucement — sans moteur
   3D à charger, sans rien à calculer image par image.
   ========================================================================== */

.prod3d {
    display: grid;
    place-items: center;
    height: 150px;
}

.prod3d__svg {
    display: block;
    filter: drop-shadow(0 10px 14px rgba(23, 18, 15, .22));

    /*
     * Le flottement : une légère translation verticale, doublée d'un tangage
     * très doux — le mouvement qu'on voit sur les icônes de boutique des
     * jeux actuels, sans qu'il attire l'œil plus qu'un produit ne le
     * mérite.
     */
    animation: prod3d-flotte 3.6s ease-in-out infinite;
}

/* Chaque objet flotte à son propre rythme : les deux cartes d'une même
   rangée ne doivent pas monter et descendre en cadence, ce qui donnerait un
   effet mécanique plutôt que vivant. */
.prod3d--jeton .prod3d__svg { animation-duration: 3.1s; animation-delay: -.6s; }

@keyframes prod3d-flotte {
    0%, 100% { transform: translateY(0) rotate(-2deg); }
    50%      { transform: translateY(-9px) rotate(2deg); }
}

.prod3d--ticket .prod3d__svg { width: 168px; height: auto; }
.prod3d--jeton .prod3d__svg { width: 108px; height: auto; }

@media (max-width: 860px) {
    .prod3d { height: 128px; }
    .prod3d--ticket .prod3d__svg { width: 144px; }
    .prod3d--jeton .prod3d__svg { width: 92px; }
}

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


/* =============================================================================
   LA BOUTIQUE
   ========================================================================== */

.boutique-bourse {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin: 18px 0 24px;
}

.boutique-bourse__poste {
    display: flex;
    align-items: baseline;
    gap: 6px;
    padding: 8px 14px;
    border: var(--border);
    border-radius: 999px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
}

.boutique-bourse__poste b { font-size: 17px; }
.boutique-bourse__poste small { font-size: 11.5px; color: var(--ink-mute); }

.boutique-grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 16px;
}

.boutique-carte {
    display: flex;
    flex-direction: column;
    padding: 16px;
    border: var(--border);
    border-radius: 16px;
    background: var(--paper-hi);
    box-shadow: var(--lift);
}

/* Un produit annoncé mais pas en vente s'efface, sans disparaître : c'est
   justement ce qu'on veut montrer. */
.boutique-carte.est-indisponible { opacity: .62; }

.boutique-carte__texte { margin-top: 10px; }

.boutique-carte__texte h2 {
    margin: 0 0 5px;
    font-size: 18px;
}

.boutique-carte__texte p {
    margin: 0;
    font-size: 13px;
    line-height: 1.45;
    color: var(--ink-2);
}

.boutique-carte__prix {
    display: flex;
    align-items: baseline;
    gap: 7px;
    margin: 13px 0 0;
}

.boutique-carte__prix b {
    font-family: var(--font-display);
    font-size: 26px;
}

.boutique-carte__prix small { font-size: 12px; color: var(--ink-mute); }

.boutique-carte__notes {
    margin: 10px 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.boutique-carte__notes li {
    font-size: 11.5px;
    color: var(--ink-mute);
}

.boutique-carte__notes li::before { content: '· '; }

.boutique-carte__notes li.est-acquis { color: var(--teal); font-weight: 600; }

/* Le pied se colle en bas : les cartes d'une même ligne alignent leurs
   boutons, quelle que soit la longueur du descriptif. */
.boutique-carte__pied {
    margin-top: auto;
    padding-top: 14px;
}

.boutique-carte__pied .btn { width: 100%; }

.boutique-etiquette {
    display: block;
    padding: 9px;
    border-radius: 999px;
    background: var(--paper-deep);
    color: var(--ink-mute);
    font-size: 12.5px;
    font-weight: 600;
    text-align: center;
}

/* ---------- Les achats passés ---------------------------------------------- */

.boutique-achats {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.boutique-achat {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 14px;
    border: 1px solid var(--paper-deep);
    border-radius: 10px;
    background: var(--paper-hi);
    font-size: 13px;
}

.boutique-achat small { font-size: 11px; color: var(--ink-mute); }

/* ---------- La console ------------------------------------------------------ */

.boutadm {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin-top: 18px;
}

.boutadm-produit {
    padding: 16px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
}

.boutadm-produit__tete {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 12px;
}

.boutadm-produit__tete b { font-size: 17px; }

.boutadm-produit__tete code {
    padding: 1px 7px;
    border-radius: 6px;
    background: var(--paper-deep);
    font-size: 11.5px;
    color: var(--ink-mute);
}

.boutadm-ventes {
    margin-left: auto;
    font-size: 11.5px;
    color: var(--ink-mute);
}

.boutadm-produit__grille {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 12px;
}

.boutadm-produit__pied {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-top: 4px;
}

.boutadm-etat { font-size: 12px; color: var(--ink-mute); }
.boutadm-etat.est-bon { color: var(--teal); font-weight: 600; }
.boutadm-etat.est-rate { color: var(--red); font-weight: 600; }

@media (max-width: 860px) {
    .boutique-grille { grid-template-columns: 1fr; }
    .boutadm-produit__grille { grid-template-columns: 1fr; }
    .boutique-achat { flex-direction: column; align-items: flex-start; gap: 3px; }
}


/* =============================================================================
   L'INVENTAIRE
   ========================================================================== */

.inv-grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 14px;
}

.inv-objet {
    position: relative;
    padding: 14px;
    border: var(--border);
    border-radius: 15px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
}

.inv-objet__texte { margin-top: 8px; }

.inv-objet__texte h3 { margin: 0 0 4px; font-size: 16px; }

.inv-objet__texte p {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.4;
    color: var(--ink-2);
}

/* Le nombre, dans l'angle : c'est ce qu'on cherche sur une page d'inventaire. */
.inv-objet__combien {
    position: absolute;
    top: -9px;
    right: -7px;

    min-width: 36px;
    padding: 4px 10px;
    border: var(--border);
    border-radius: 999px;
    background: var(--ink);
    color: var(--paper-hi);
    box-shadow: var(--lift-sm);

    font-size: 14px;
    text-align: center;
}

.inv-etat {
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--paper-deep);
    font-size: 11px;
    color: var(--ink-mute);
}

.boutique-achat.est-annule { opacity: .55; }



@media (max-width: 860px) {
    .inv-grille { grid-template-columns: 1fr; }
    .inv-objet__combien { top: -7px; right: -5px; font-size: 13px; }
}


/* =============================================================================
   LES CATÉGORIES DE CLASSEMENT
   ========================================================================== */

.cat-etat { font-size: 12px; color: var(--ink-mute); }
.cat-etat.est-bon { color: var(--teal); font-weight: 600; }
.cat-etat.est-rate { color: var(--red); font-weight: 600; }

/* ---------- Le choix sur une tier list -------------------------------------- */

.cat-choix {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 9px;
    margin-top: 10px;
}

.cat-choix > span {
    font-size: 12px;
    font-weight: 600;
    color: var(--ink-mute);
}

.cat-choix em {
    font-size: 11.5px;
    font-style: normal;
    color: var(--ink-mute);
}

.cat-choix em.est-bon { color: var(--teal); }
.cat-choix em.est-rate { color: var(--red); }

/* ---------- L'interrupteur général de l'échange ----------------------------- */

.bout-interrupteur {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 14px;

    padding: 14px 18px;
    margin: 18px 0 20px;
    border: var(--border);
    border-radius: 14px;

    /* Fermé, le bandeau est rouge : c'est un état qu'on ne doit pas oublier
       d'avoir laissé en place. */
    background: rgba(217, 59, 43, .1);
    border-color: var(--red);
}

.bout-interrupteur.est-ouvert {
    background: rgba(23, 148, 139, .1);
    border-color: var(--teal);
}

.bout-interrupteur__texte b {
    display: block;
    font-size: 16px;
}

.bout-interrupteur__texte small {
    font-size: 12.5px;
    color: var(--ink-2);
}

.bout-interrupteur .champ-bascule { margin: 0; }

@media (max-width: 860px) {
    .bout-interrupteur { flex-direction: column; align-items: flex-start; }
}


/* =============================================================================
   10COVER — TROIS ONGLETS, UNE SAISIE

   Le bouton et son prix sur une ligne, les trois champs sur la suivante, la
   saisie dessous. Elle ne bouge jamais : on enchaîne les réponses sans aller
   la rechercher des yeux.
   ========================================================================== */

.dcj-barre {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 16px 0 12px;
}

.dcj-barre .btn { flex: 0 0 auto; white-space: nowrap; }

.dcj-barre .dcj-nettete__barre { flex: 1 1 auto; }

/*
 * La barre avait sa largeur qui s'effondrait à zéro : dans une colonne
 * flexible centrée, un enfant sans largeur propre se réduit à la taille de
 * son contenu plutôt que de remplir la colonne — et le contenu d'une barre
 * de progression vide, c'est rien. Lui donner sa pleine largeur rend enfin
 * à « flex: 1 1 auto » l'espace qu'il est censé se répartir.
 */
#live-barre { width: 100%; }

.dcj-barre__dit {
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-size: 11.5px;
    color: var(--ink-mute);
    white-space: nowrap;
}

/* ---------- Les trois onglets ----------------------------------------------- */

.dcj-onglets {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    margin-bottom: 14px;
}

.dcj-onglet {
    display: grid;
    justify-items: center;
    gap: 3px;

    padding: 11px 6px;
    border: var(--border);
    border-radius: 12px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);

    font: inherit;
    cursor: pointer;
    transition: transform .14s var(--ease), box-shadow .14s var(--ease);
}

.dcj-onglet:hover:not(:disabled) { transform: translateY(-2px); }

/* L'onglet visé porte la couleur de l'encre : c'est là que va la saisie. */
.dcj-onglet.est-actif {
    background: var(--ink);
    color: var(--paper-hi);
    box-shadow: var(--lift);
}

.dcj-onglet.est-actif .dcj-onglet__vaut { color: var(--gold); }

.dcj-onglet__logo {
    display: grid;
    place-items: center;
    opacity: .85;
}

.dcj-onglet b {
    font-family: var(--font-display);
    font-size: 14px;
}

.dcj-onglet__vaut {
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 700;
    color: var(--teal);
}

/* Trouvé : l'onglet s'éteint en vert, il n'y a plus rien à y faire. */
.dcj-onglet[data-etat="trouve"] {
    background: rgba(23, 148, 139, .14);
    border-color: var(--teal);
    opacity: .78;
}

.dcj-onglet[data-etat="rate"] { opacity: .5; }

.dcj-onglet:disabled { cursor: default; }

/* ---------- La saisie, fixe --------------------------------------------------- */

.dcj-saisie {
    padding: 14px 16px;
    border: var(--border);
    border-radius: 14px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);
    margin-bottom: 14px;
}

.dcj-saisie__question {
    margin: 0 0 9px;
    font-size: 14.5px;
    font-weight: 600;
}

.dcj-saisie__ligne {
    display: flex;
    gap: 8px;
}

.dcj-saisie__ligne input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 11px 14px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper);
    font: inherit;
    font-size: 16px;

    /* Le refus se voit sans que rien ne bouge autour. */
    transition: border-color .3s var(--ease), background .3s var(--ease);
}

.dcj-saisie__ligne input.est-rate {
    animation: dcj-rate .42s var(--ease);
    border-color: var(--red);
    background: rgba(217, 59, 43, .09);
}

.dcj-saisie__pied {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin: 9px 0 0;
    font-size: 11.5px;
    color: var(--ink-mute);
}

/*
 * L'abandon : un lien, pas un bouton.
 *
 * Il renonce à des points ; le présenter comme « Valider » inviterait à
 * cliquer dessus par symétrie.
 */
.dcj-abandon {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: 11.5px;
    color: var(--ink-mute);
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

.dcj-abandon:hover { color: var(--red); }

.dcj-essais-zone { margin-bottom: 14px; }

/* Les essais reprennent la mise en forme déjà posée, sans le cadre de case. */
.dcj-essais-zone .dcj-essais { padding: 0; }

@media (max-width: 860px) {
    .dcj-barre { flex-wrap: wrap; }
    .dcj-barre .btn { width: 100%; }
    .dcj-barre .dcj-nettete__barre { order: 3; }

    .dcj-onglet { padding: 9px 4px; }
    .dcj-onglet b { font-size: 12.5px; }
    .dcj-onglet__vaut { font-size: 11px; }

    .dcj-saisie__ligne { flex-wrap: wrap; }
    .dcj-saisie__ligne input { flex: 1 1 100%; }
    .dcj-saisie__ligne .btn { flex: 1 1 100%; }
}


/* ---------- Un champ réglé, consulté ---------------------------------------- */

/*
 * Ce que le champ a donné, sous ses essais.
 *
 * On clique sur un onglet éteint pour relire ce qu'on avait tenté ; sans cette
 * ligne, on verrait ses erreurs sans jamais savoir ce qu'il fallait trouver.
 */
.dcj-clos__mot {
    margin: 9px 0 0;
    padding: 8px 12px;
    border-radius: 9px;
    background: var(--paper-deep);
    font-size: 13px;
    font-weight: 600;
    color: var(--ink-2);
}

.dcj-clos__mot.est-trouve {
    background: rgba(23, 148, 139, .15);
    color: var(--teal);
}

/* Un onglet réglé reste cliquable : le curseur doit le dire. */
.dcj-onglet[data-etat="trouve"],
.dcj-onglet[data-etat="rate"] { cursor: pointer; }

.dcj-onglet[data-etat="trouve"]:hover,
.dcj-onglet[data-etat="rate"]:hover { opacity: 1; }

/* Consulté, il se souligne sans reprendre la couleur d'encre : il est regardé,
   pas actif. */
.dcj-onglet.est-actif[data-etat="trouve"],
.dcj-onglet.est-actif[data-etat="rate"] {
    background: var(--paper-hi);
    color: var(--ink);
    outline: 2px solid var(--ink);
    outline-offset: -2px;
    opacity: 1;
}


/* =============================================================================
   10COVER — REPÈRE UNIQUE ET MISE EN PAGE RESSERRÉE
   ========================================================================== */

/*
 * Deux pastilles de même taille, côte à côte.
 *
 * Une seule pastille partagée obligeait le score à se décaler chaque fois que
 * le genre changeait de longueur. Séparées et de largeur égale, elles restent
 * en place quoi qu'il arrive.
 */
.dcj-reperes {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 150px));
    justify-content: center;
    gap: 8px;
    margin: 10px auto 14px;
}

.dcj-pastille {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;

    padding: 6px 14px;
    border: var(--border);
    border-radius: 999px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);

    overflow: hidden;
}

.dcj-pastille small {
    font-size: 9.5px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.dcj-pastille b {
    font-family: var(--font-display);
    font-size: 15px;
    line-height: 1.1;

    /* Un genre à rallonge se coupe plutôt que d'élargir la pastille. */
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
 * Une seule pastille visible occupe sa place, pas toute la ligne.
 *
 * Sans cela, le score s'étirerait sur deux colonnes quand le genre manque.
 */
.dcj-guide[hidden] ~ .dcj-pastille { grid-column: 2; }

/* ---------- Mobile : tout se resserre --------------------------------------- */

@media (max-width: 860px) {
    .dcj-reperes {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 6px;
        margin: 8px auto 11px;
    }

    .dcj-pastille { padding: 5px 11px; }
    .dcj-pastille small { font-size: 8.5px; }
    .dcj-pastille b { font-size: 13.5px; }

    /*
     * La ligne du bouton tient sur une seule.
     *
     * Elle passait à la ligne dès que le prix s'affichait, ce qui poussait
     * tout le jeu vers le bas.
     */
    .dcj-barre {
        flex-wrap: nowrap;
        gap: 8px;
        margin: 10px 0 9px;
    }

    .dcj-barre .btn {
        width: auto;
        padding: 7px 12px;
        font-size: 12.5px;
    }

    .dcj-barre .dcj-nettete__barre { order: 0; height: 4px; }

    .dcj-barre__dit { font-size: 10.5px; }

    /* Les onglets : plus bas, textes plus courts. */
    .dcj-onglets { gap: 6px; margin-bottom: 10px; }

    .dcj-onglet { padding: 7px 3px; gap: 1px; border-radius: 10px; }
    .dcj-onglet b { font-size: 11.5px; }
    .dcj-onglet__vaut { font-size: 10.5px; }
    .dcj-onglet__logo svg { width: 15px; height: 15px; }

    /* La saisie : moins de marge, un champ plus court. */
    .dcj-saisie { padding: 11px 12px; margin-bottom: 10px; }

    .dcj-saisie__question { font-size: 13px; margin-bottom: 7px; }

    .dcj-saisie__ligne { flex-wrap: nowrap; gap: 6px; }

    .dcj-saisie__ligne input {
        flex: 1 1 auto;
        padding: 9px 11px;
        font-size: 15px;
    }

    .dcj-saisie__ligne .btn {
        flex: 0 0 auto;
        width: auto;
        padding: 9px 14px;
        font-size: 13px;
    }

    .dcj-saisie__pied { margin-top: 7px; font-size: 10.5px; }
    .dcj-abandon { font-size: 10.5px; }

    .dcj-essais-zone { margin-bottom: 10px; }
}


/* ---------- Les onglets de la régie ----------------------------------------- */

/*
 * Ils reprennent ceux du jeu quotidien, avec une ligne de plus : le compte de
 * ceux qui ont trouvé dans le chat.
 */
.live-onglet { padding-bottom: 8px; }

.live-onglet__chat {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--ink-mute);
}

.live-onglet__chat.est-vif { color: var(--teal); font-weight: 700; }

.live-onglet.est-actif .live-onglet__chat { color: rgba(239, 226, 204, .7); }

.live-onglet.est-actif .live-onglet__chat.est-vif { color: var(--teal); }

/* Un champ verrouillé par l'animateur : le chat n'y marque plus. */
.live-onglet.est-verrouille .live-onglet__chat::after {
    content: ' · verrouillé';
    font-weight: 400;
    opacity: .8;
}

@media (max-width: 860px) {
    .live-onglet__chat { font-size: 9px; }
}


/* =============================================================================
   LES INTERRUPTEURS À PASTILLE

   Un rail et une pastille qui glisse : l'état se lit sans lire, ce qu'une case
   à cocher ne fait pas.
   ========================================================================== */

.pill {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    cursor: pointer;
    user-select: none;
}

/* La case reste là pour le clavier et les lecteurs d'écran ; elle ne se voit
   simplement pas. */
.pill input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.pill__piste {
    position: relative;
    width: 42px;
    height: 24px;
    border-radius: 999px;
    background: var(--paper-deep);
    border: 1.5px solid var(--ink);
    transition: background .2s var(--ease);
    flex: 0 0 auto;
}

.pill__piste i {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 17px;
    height: 17px;
    border-radius: 50%;
    background: var(--ink);
    transition: transform .2s var(--ease), background .2s var(--ease);
}

.pill input:checked + .pill__piste { background: var(--teal); }
.pill input:checked + .pill__piste i {
    transform: translateX(18px);
    background: var(--paper-hi);
}

/* Le focus se voit : on doit pouvoir basculer au clavier sans deviner où on
   se trouve. */
.pill input:focus-visible + .pill__piste {
    outline: 2px solid var(--red);
    outline-offset: 2px;
}

.pill__mot { font-size: 13px; font-weight: 600; }

.pill--petit .pill__piste { width: 34px; height: 20px; }
.pill--petit .pill__piste i { width: 13px; height: 13px; }
.pill--petit input:checked + .pill__piste i { transform: translateX(14px); }
.pill--petit .pill__mot { font-size: 12px; }

/* =============================================================================
   LES CARTES D'OBJET, EN CONSOLE
   ========================================================================== */

.objets {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 16px;
    margin-top: 18px;
}

.objet {
    /* La perspective vit ici : posée sur la carte qui tourne, elle tournerait
       avec elle et l'effet s'annulerait. */
    perspective: 1400px;

    /*
     * La hauteur suit le contenu.
     *
     * Une hauteur imposée laissait du vide sous les cartes courtes. Les deux
     * faces se superposent par « grid » : la carte prend celle de la plus
     * haute, et le retournement ne change rien à la place occupée.
     */
    display: grid;
}

.objet.est-eteint .objet__face--avant { opacity: .66; }

/* La carte glissée s'efface : on voit où elle vient se poser. */
.objet.est-glissee { opacity: .35; }

.objet.est-cible .objet__face--avant { outline: 2px dashed var(--red); }

.objet__pivot {
    display: grid;
    transform-style: preserve-3d;
    transition: transform .45s var(--ease);
}

/* Les deux faces occupent la même case de la grille : elles se superposent
   sans être sorties du flux, donc elles comptent dans la hauteur. */
.objet__face {
    grid-area: 1 / 1;
}

.objet.est-retournee .objet__pivot { transform: rotateY(180deg); }

.objet__face {
    display: flex;
    flex-direction: column;
    gap: 11px;

    padding: 16px;
    border: var(--border);
    border-radius: 17px;
    background: var(--paper-hi);
    box-shadow: var(--lift);

    backface-visibility: hidden;
}

.objet__face--arriere { transform: rotateY(180deg); }

/* La poignée : trois traits, en haut à gauche. */
.objet__poignee {
    position: absolute;
    top: 11px;
    left: 13px;
    display: grid;
    gap: 3px;
    cursor: grab;
    padding: 4px;
}

.objet__poignee i {
    display: block;
    width: 15px;
    height: 2px;
    border-radius: 999px;
    background: var(--ink-mute);
}

.objet__poignee:active { cursor: grabbing; }

.objet__dessin {
    display: grid;
    place-items: center;
    min-height: 140px;
}

.objet__tete {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: 8px;
    text-align: center;
}

.objet__tete b {
    font-family: var(--font-display);
    font-size: 18px;
}

.objet__tete code {
    padding: 1px 7px;
    border-radius: 6px;
    background: var(--paper-deep);
    font-size: 11px;
    color: var(--ink-mute);
}

/* Les quatre réglages, deux par deux. */
.objet__reglages {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 9px;
}

.objet__champ { display: block; }

.objet__champ span {
    display: block;
    margin-bottom: 3px;
    font-size: 11px;
    font-weight: 600;
    color: var(--ink-mute);
}

.objet__champ input,
.objet__champ select {
    width: 100%;
    padding: 7px 10px;
    border: var(--border);
    border-radius: 9px;
    background: var(--paper);
    font: inherit;
    font-size: 13px;
}

.objet__pied {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 9px;

    /* Le pied se colle en bas : les cartes d'une ligne alignent leurs boutons
       quelle que soit la hauteur du dessin. */
    margin-top: auto;
    padding-top: 10px;
    border-top: 1px solid var(--paper-deep);
}

.objet__ventes { font-size: 11px; color: var(--ink-mute); }

.objet__lien {
    margin-left: auto;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: 12px;
    color: var(--ink-mute);
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

.objet__lien:hover { color: var(--ink); }

.objet__etat {
    position: absolute;
    bottom: 13px;
    left: 16px;
    font-size: 11.5px;
    color: var(--ink-mute);
}

.objet__etat.est-bon { color: var(--teal); font-weight: 600; }
.objet__etat.est-rate { color: var(--red); font-weight: 600; }

/* ---------- Le dos ---------------------------------------------------------- */

.objet__face--arriere b {
    font-family: var(--font-display);
    font-size: 17px;
}

.objet__aide {
    margin: -4px 0 0;
    font-size: 12px;
    color: var(--ink-mute);
}

.objet__face--arriere textarea {
    flex: 1 1 auto;
    width: 100%;
    padding: 11px 13px;
    border: var(--border);
    border-radius: 11px;
    background: var(--paper);
    font: inherit;
    font-size: 13.5px;
    line-height: 1.5;
    resize: none;
}

/* ---------- Les dessins, à leur taille --------------------------------------- */

/*
 * Chaque objet a son format.
 *
 * Un billet est large et plat, un jeton rond et épais : les mettre au même
 * gabarit les rendrait interchangeables, alors qu'on veut les reconnaître d'un
 * coup d'œil.
 */
.objet .prod3d { height: 140px; }


@media (max-width: 860px) {
    .objets { grid-template-columns: 1fr; }
    .objet { min-height: 440px; }
    .objet__reglages { grid-template-columns: 1fr 1fr; }
    .objet__poignee { display: none; }
}

/* Une carte qui tourne sans fin gêne certaines personnes : le retournement
   reste, il est simplement instantané. */
@media (prefers-reduced-motion: reduce) {
    .objet__pivot { transition: none; }
}


/* =============================================================================
   LES REPÈRES DE LA RÉGIE

   Genre, temps, et ce que vaut une bonne réponse. Tous de même taille, sur une
   ligne, au-dessus du jeu.
   ========================================================================== */

.live-reperes {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;

    /* De l'air sous la pochette : les repères y étaient collés, à moitié
       dessus. */
    margin: 16px auto 14px;
}

.live-reperes .dcj-pastille {
    min-width: 108px;
    flex: 0 1 auto;
}

/* La pastille du temps porte sa jauge, qui descend avec le chiffre. */
.live-pastille--temps { position: relative; padding-bottom: 9px; }

.live-pastille__jauge {
    position: absolute;
    left: 12px;
    right: 12px;
    bottom: 5px;
    height: 3px;
    border-radius: 999px;
    background: var(--paper-deep);
    overflow: hidden;
}

.live-pastille__jauge span {
    display: block;
    height: 100%;
    width: 100%;
    border-radius: 999px;
    background: var(--teal);
    transition: width 1s linear;
}

/* Les cinq dernières secondes : le chiffre rougit et bat. */
.live-minuteur.est-urgent b,
#live-minuteur.est-urgent b { color: var(--red); animation: live-bat 1s infinite; }

#live-minuteur.est-urgent .live-pastille__jauge span { background: var(--red); }

/* La prime de premier, une fois prise : elle s'éteint. */
#live-prime.est-pris { opacity: .55; }
#live-prime.est-pris b { text-decoration: line-through; }

/* L'animateur ne marque pas de point : sa pastille reste sobre. */
#live-noiz b { color: var(--ink-mute); }

/* ---------- L'annonce de phase, en grand ------------------------------------

   Dans l'esprit du titre qui lance la roulette à l'écran : un mot qui
   s'impose au centre, pas un badge qu'il faut chercher des yeux. Sans fond
   opaque — la pochette reste visible derrière, seulement assombrie sous le
   texte, ce qui garde le jeu en contexte.
   ---------------------------------------------------------------------- */

/* ---------- L'annonce de phase, en haut de la colonne technique ------------

   Dans le flux normal, au-dessus de tout le reste — pas une apparition
   brève : elle reste affichée tant que la phase dure. Couleurs pleines de
   la charte plutôt que le halo sombre pensé pour un titre posé sur une
   image : ici elle vit sur le papier clair de la page, à côté de la
   pochette plutôt que par-dessus elle, et n'a donc plus besoin de
   contraste artificiel pour se détacher.
   ---------------------------------------------------------------------- */

.live-annonce {
    display: grid;
    justify-items: center;
    gap: .2em;
    margin: 0 0 20px;

    text-align: center;
    line-height: 1;

    opacity: 0;
}

.live-annonce__gros {
    font-family: var(--font-display);
    font-size: clamp(28px, 3.2vw, 44px);
    font-weight: 800;
    letter-spacing: -.01em;
    color: var(--ink);
}

.live-annonce__sous {
    display: flex;
    align-items: center;
    gap: 8px;

    font-family: var(--font-mono);
    font-size: clamp(10px, 1.1vw, 13px);
    font-weight: 600;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ink-mute);
}

.live-annonce__sous i {
    display: block;
    width: clamp(20px, 3vw, 44px);
    height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, rgba(233, 167, 44, 0), var(--gold));
    box-shadow: none;
}

.live-annonce__sous i:last-child {
    background: linear-gradient(90deg, var(--gold), rgba(233, 167, 44, 0));
}

.live-annonce.est-entree {
    animation: live-annonce-entre .4s var(--ease) forwards;
}

.live-annonce.est-partie {
    animation: live-annonce-part .5s var(--ease) forwards;
}

@keyframes live-annonce-entre {
    from { opacity: 0; transform: translateY(-6px) scale(.95); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes live-annonce-part {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(-4px); }
}

@media (prefers-reduced-motion: reduce) {
    .live-annonce.est-entree, .live-annonce.est-partie { animation-duration: .01s; }
}

/* Le score de l'animateur — un repère discret, pas un chiffre en avant. */
.live__score-admin {
    margin: 0 0 16px;
    font-size: 13px;
    color: var(--ink-mute);
}

.live__score-admin b {
    font-family: var(--font-display);
    font-size: 17px;
    color: var(--ink);
}

/* ---------- Le gros minuteur circulaire de la phase « chat » ---------------

   Le bouton de netteté et les trois cases n'ont pas leur place tant que
   l'animateur n'a rien à faire : cet anneau prend leur emplacement, pour
   qu'on garde un seul repère à l'œil plutôt que plusieurs qui ne servent à
   rien encore.
   ---------------------------------------------------------------------- */

.live-gros-minuteur {
    position: relative;
    display: grid;
    place-items: center;
    width: 152px;
    height: 152px;
    margin: 10px auto;
}

.live-gros-minuteur__anneaux {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    transform: rotate(-90deg);
}

.live-gros-minuteur__fond {
    fill: none;
    stroke: var(--paper-deep);
    stroke-width: 10;
}

.live-gros-minuteur__anneau {
    fill: none;
    stroke: var(--teal);
    stroke-width: 10;
    stroke-linecap: round;
    stroke-dasharray: 376.99;
    stroke-dashoffset: 0;
    transition: stroke-dashoffset 1s linear, stroke .2s var(--ease);
}

.live-gros-minuteur.est-urgent .live-gros-minuteur__anneau {
    stroke: var(--red);
}

.live-gros-minuteur__texte {
    display: grid;
    justify-items: center;
    gap: 2px;
}

.live-gros-minuteur__texte b {
    font-family: var(--font-display);
    font-size: 46px;
    line-height: 1;
    color: var(--ink);
}

.live-gros-minuteur.est-urgent .live-gros-minuteur__texte b {
    color: var(--red);
    animation: live-bat 1s infinite;
}

.live-gros-minuteur__texte small {
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--ink-mute);
}

@media (max-width: 860px) {
    .live-gros-minuteur { width: 124px; height: 124px; }
    .live-gros-minuteur__texte b { font-size: 36px; }
}

/*
 * Vide plutôt qu'absente : hors des phases chronométrées, la boîte reste en
 * place — seul son contenu s'efface. La retirer du tout au tout aurait fait
 * bouger ce qui l'entoure à chaque changement de phase.
 */
.live-gros-minuteur.est-vide .live-gros-minuteur__anneau {
    stroke: var(--paper-deep);
    stroke-dashoffset: 0;
}

.live-gros-minuteur.est-vide .live-gros-minuteur__texte { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
    .live-gros-minuteur__anneau { transition-duration: .1s; }
    .live-gros-minuteur.est-urgent .live-gros-minuteur__texte b { animation: none; }
}

@media (max-width: 860px) {
    .live-reperes { gap: 6px; margin: 12px auto 10px; }
    .live-reperes .dcj-pastille { min-width: 0; flex: 1 1 88px; }
}


/* =============================================================================
   LES CARTES D'OBJET — CORRECTIFS
   ========================================================================== */

/* Les trois interrupteurs, l'un sous l'autre. */
.objet__bascules {
    display: flex;
    flex-direction: column;
    gap: 7px;
}

/* Le champ qui prend la ligne entière. */
.objet__champ--large { grid-column: 1 / -1; }

/*
 * Une carte modifiée mais pas enregistrée.
 *
 * Le liseré et le bouton qui bat disent qu'il reste quelque chose à faire :
 * sans eux, on quitte la page en croyant avoir enregistré.
 */
.objet.est-modifiee .objet__face--avant,
.objet.est-modifiee .objet__face--arriere {
    border-color: var(--gold);
    box-shadow: var(--lift), 0 0 0 3px rgba(201, 162, 39, .25);
}

.objet.est-modifiee .objet__garder {
    animation: objet-rappel 1.6s ease-in-out infinite;
}

@keyframes objet-rappel {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.05); }
}

.objet.est-modifiee .objet__etat::before {
    content: 'non enregistré';
    color: var(--gold);
    font-weight: 600;
}

/*
 * Le trait de dépôt.
 *
 * Il se pose du côté où la carte arrivera : surligner la carte survolée ne
 * disait pas si l'on passe avant ou après elle.
 */
.objet.est-avant::before,
.objet.est-apres::after {
    content: '';
    position: absolute;
    top: 6px;
    bottom: 6px;
    width: 5px;
    border-radius: 999px;
    background: var(--red);
    z-index: 3;
}

.objet.est-avant::before { left: -10px; }
.objet.est-apres::after { right: -10px; }

.objet { position: relative; }

/* La carte en cours de déplacement : visible mais en retrait, pour qu'on
   suive des yeux ce qu'on déplace. */
.objet.est-glissee { opacity: .5; }
.objet.est-glissee .objet__face--avant { border-style: dashed; }

@media (max-width: 860px) {
    /* En une colonne, le trait se met au-dessus ou au-dessous. */
    .objet.est-avant::before,
    .objet.est-apres::after {
        top: auto;
        bottom: auto;
        left: 6px;
        right: 6px;
        width: auto;
        height: 5px;
    }

    .objet.est-avant::before { top: -9px; }
    .objet.est-apres::after { bottom: -9px; }
}

@media (prefers-reduced-motion: reduce) {
    .objet.est-modifiee .objet__garder { animation: none; }
}


/* =============================================================================
   LE DÉPLACEMENT DES CARTES

   La carte suit vraiment le doigt, et un emplacement vide s'ouvre là où elle
   se posera.
   ========================================================================== */

/* Pendant un déplacement, rien ne se sélectionne : le texte surligné en
   travers gênerait le geste. */
body.objets-en-cours { user-select: none; cursor: grabbing; }

.objet.est-en-main {
    position: fixed;
    z-index: 200;
    margin: 0;
    pointer-events: none;

    /* Légèrement plus grande et inclinée : on la sent soulevée. */
    transform: rotate(-1.6deg) scale(1.03);
    transform-origin: center;
}

.objet.est-en-main .objet__face--avant {
    box-shadow: 0 22px 46px rgba(23, 18, 15, .38);
    border-color: var(--ink);
}

/*
 * L'emplacement d'accueil.
 *
 * Un cadre en pointillé, de la taille exacte de la carte : on voit où elle
 * atterrira avant de lâcher.
 */
.objet-fantome {
    border: 2px dashed var(--red);
    border-radius: 17px;
    background: rgba(217, 59, 43, .06);

    /* Il grandit depuis rien : l'ouverture se voit au lieu d'apparaître. */
    animation: fantome-ouvre .16s var(--ease);
}

@keyframes fantome-ouvre {
    from { opacity: 0; transform: scale(.97); }
    to   { opacity: 1; transform: scale(1); }
}

/* La poignée se prend : le curseur le dit avant qu'on essaie. */
.objet__poignee { touch-action: none; }

@media (prefers-reduced-motion: reduce) {
    .objet-fantome { animation: none; }
    .objet.est-en-main { transform: none; }
}


/* =============================================================================
   LA FENÊTRE DES CATÉGORIES
   ========================================================================== */

.modale {
    position: fixed;
    inset: 0;
    z-index: 300;
    display: grid;
    place-items: center;
    padding: 20px;
}

.modale__fond {
    position: absolute;
    inset: 0;
    background: rgba(23, 18, 15, .55);
    animation: modale-fond .18s var(--ease);
}

@keyframes modale-fond { from { opacity: 0; } to { opacity: 1; } }

.modale__panneau {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 460px;
    max-height: 84vh;
    overflow-y: auto;

    padding: 22px;
    border: var(--border);
    border-radius: 18px;
    background: var(--paper-hi);
    box-shadow: var(--lift);

    animation: modale-entre .2s var(--ease);
}

@keyframes modale-entre {
    from { opacity: 0; transform: translateY(10px) scale(.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

.modale__tete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 6px;
}

.modale__tete h2 { margin: 0; font-size: 19px; }

.modale__fermer {
    width: 30px;
    height: 30px;
    border: var(--border);
    border-radius: 50%;
    background: var(--paper);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}

/* ---------- Créer ------------------------------------------------------- */

.cat-neuve {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 10px;
    padding: 14px;
    margin: 14px 0 18px;

    border: 1px dashed var(--paper-deep);
    border-radius: 13px;
    background: var(--paper);
}

.cat-neuve__champ {
    flex: 1 1 160px;
    display: block;
}

.cat-neuve__champ span {
    display: block;
    margin-bottom: 4px;
    font-size: 11px;
    font-weight: 600;
    color: var(--ink-mute);
}

.cat-neuve__champ input {
    width: 100%;
    padding: 9px 12px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper-hi);
    font: inherit;
    font-size: 13.5px;
}

.cat-neuve__creer {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}

/* ---------- Les lignes --------------------------------------------------- */

.cat-liste {
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.cat-ligne {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 11px;
    border: 1px solid var(--paper-deep);
    border-radius: 11px;
    background: var(--paper);
}

.cat-ligne__poignee {
    display: grid;
    gap: 3px;
    padding: 4px;
    cursor: grab;
    touch-action: none;
}

.cat-ligne__poignee i {
    display: block;
    width: 14px;
    height: 2px;
    border-radius: 999px;
    background: var(--ink-mute);
}

/*
 * L'étoile qui fait d'une catégorie celle par défaut.
 *
 * Pleine et fixe pour celle qui l'est déjà — cliquer dessus ne changerait
 * rien, alors elle n'écoute pas le clic. Vide et grise pour les autres, elle
 * se colore à l'approche de la souris pour dire qu'un clic fera quelque
 * chose.
 */
.cat-ligne__etoile {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border: 0;
    background: transparent;
    font-size: 17px;
    line-height: 1;
    color: var(--ink-mute);
    cursor: pointer;
}

.cat-ligne__etoile:disabled { cursor: default; }

.cat-ligne__etoile.est-defaut { color: var(--gold); }

.cat-ligne__etoile:not(:disabled):hover { color: var(--gold); }

.cat-ligne__textes {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.cat-ligne__nom {
    border: 0;
    background: transparent;
    font: inherit;
    font-weight: 700;
    font-size: 14px;
    padding: 2px 0;
}

.cat-ligne__descriptif {
    border: 0;
    background: transparent;
    font: inherit;
    font-size: 12px;
    color: var(--ink-mute);
    padding: 1px 0;
}

.cat-ligne__nom:focus,
.cat-ligne__descriptif:focus {
    outline: none;
    border-bottom: 1px solid var(--red);
}

.cat-ligne__suppr {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--ink-mute);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}

.cat-ligne__suppr:hover { background: rgba(217, 59, 43, .12); color: var(--red); }

/* ---------- Le déplacement, comme dans l'échange -------------------------- */

.cat-ligne.est-en-main {
    position: fixed;
    z-index: 320;
    pointer-events: none;
    box-shadow: 0 16px 34px rgba(23, 18, 15, .32);
    transform: rotate(-1deg);
}

.cat-ligne-fantome {
    border: 2px dashed var(--red);
    border-radius: 11px;
    background: rgba(217, 59, 43, .06);
}

@media (max-width: 860px) {
    .modale__panneau { padding: 18px; max-height: 90vh; }
    .cat-neuve { flex-direction: column; align-items: stretch; }
    .cat-neuve__creer { width: 100%; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
    .modale__fond, .modale__panneau { animation: none; }
}

/* =============================================================================
   LE SÉLECTEUR FAIT MAISON (.mini-select)

   Reprend l'habillage du site plutôt que le rendu natif du navigateur, qui
   diffère d'un système à l'autre.
   ========================================================================== */

/*
 * Le <select> d'origine, posé automatiquement sur tout sélecteur du site.
 *
 * Il reste dans la page, fonctionnel : un clavier peut encore l'atteindre au
 * tabulateur et le faire fonctionner normalement, et le code déjà écrit qui
 * lit sa valeur continue de marcher sans y toucher. Seul l'œil ne le voit
 * plus — masqué comme on masque un texte réservé aux lecteurs d'écran,
 * jamais avec « display:none », qui le retirerait aussi du clavier.
 */
.mini-select__natif {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.mini-select {
    position: relative;
    display: inline-block;
}

.mini-select__tete {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border: var(--border);
    border-radius: 10px;
    background: var(--paper-hi);
    font: inherit;
    font-size: 13.5px;
    cursor: pointer;
    min-width: 160px;
}

.mini-select__tete svg {
    margin-left: auto;
    flex: 0 0 auto;
    transition: transform .15s var(--ease);
}

.mini-select.est-ouvert .mini-select__tete svg { transform: rotate(180deg); }

.mini-select.est-ouvert .mini-select__tete {
    border-color: var(--ink);
}

.mini-select__val {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mini-select__menu {
    position: absolute;
    z-index: 60;
    top: calc(100% + 5px);
    left: 0;
    min-width: 100%;

    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 5px;

    border: var(--border);
    border-radius: 11px;
    background: var(--paper-hi);
    box-shadow: var(--lift);

    max-height: 220px;
    overflow-y: auto;

    animation: mini-select-ouvre .12s var(--ease);
}

@keyframes mini-select-ouvre {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}

.mini-select__opt {
    padding: 7px 10px;
    border: 0;
    border-radius: 7px;
    background: transparent;
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mini-select__opt:hover { background: var(--paper); }

.mini-select__opt.est-choisie {
    background: var(--ink);
    color: var(--paper-hi);
    font-weight: 600;
}

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

/* =============================================================================
   LES CARTES DE CATÉGORIE

   La page d'accueil des classements : une carte par catégorie, cliquable
   entière, qui mène à son grand classement et à ses albums.
   ========================================================================== */

.cat-cartes {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 16px;
    margin-top: 18px;
}

.cat-carte {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 18px;

    border: var(--border);
    border-radius: 16px;
    background: var(--paper-hi);
    box-shadow: var(--lift-sm);

    text-decoration: none;
    color: inherit;
    transition: transform .14s var(--ease), box-shadow .14s var(--ease);
}

.cat-carte:hover {
    transform: translateY(-3px);
    box-shadow: var(--lift);
}

.cat-carte.est-eteinte { opacity: .58; }

.cat-carte__tete {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
}

.cat-carte__tete h2 {
    margin: 0;
    font-size: 19px;
}

.cat-carte__etoile {
    flex: 0 0 auto;
    font-size: 15px;
    color: var(--gold);
}

.cat-carte__descriptif {
    margin: 0;
    font-size: 13px;
    line-height: 1.45;
    color: var(--ink-2);

    /* Deux lignes maximum : une carte ne doit pas s'étirer selon la longueur
       du descriptif, sans quoi la grille perd son alignement. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.cat-carte__pied {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-top: auto;
    padding-top: 10px;
    border-top: 1px solid var(--paper-deep);
}

.cat-carte__pied b {
    font-family: var(--font-display);
    font-size: 20px;
}

/* Le séparateur de la fraction, discret : c'est les deux chiffres qui
   comptent, pas le trait entre eux. */
.cat-carte__pied b i {
    margin: 0 1px;
    font-style: normal;
    color: var(--ink-mute);
    font-weight: 400;
}

.cat-carte__pied span {
    font-size: 12px;
    color: var(--ink-mute);
}

.cat-carte__vide {
    font-size: 12.5px;
    font-style: italic;
    color: var(--ink-mute);
}

@media (max-width: 860px) {
    .cat-cartes { grid-template-columns: 1fr 1fr; gap: 11px; }
    .cat-carte { padding: 14px; }
    .cat-carte__tete h2 { font-size: 16px; }
}

@media (max-width: 480px) {
    .cat-cartes { grid-template-columns: 1fr; }
}


/* ---------- 10Cover LIVE : netteté et minuteur côte à côte -----------------

   Deux colonnes pour gagner de la hauteur. À gauche, le bouton « Plus net »
   et un disque dont la résolution suit la netteté de l'image ; à droite, le
   minuteur et le bouton pour passer la phase. Les deux sont centrés dans leur
   colonne.
   ---------------------------------------------------------------------- */

.live-duo {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: stretch;
    width: 100%;
    margin: 6px 0 10px;
    padding: 10px 12px;
    background: var(--paper-hi);
    border: var(--border);
    border-radius: var(--radius);
}

.live-duo__col {
    display: grid;
    justify-items: center;
    align-items: center;
    /* Le contenu en haut occupe la place, le bouton se pose en bas : les deux
       boutons sont ainsi sur la même ligne, d'une colonne à l'autre. */
    grid-template-rows: 1fr auto;
    gap: 8px;
    min-width: 0;
    padding: 0 8px;
}

.live-duo__col--temps { border-left: 2px dashed var(--paper-deep); }

.live-duo .live-gros-minuteur { width: 124px; height: 124px; margin: 0; }
.live-duo .live-gros-minuteur__texte { max-width: 84px; gap: 3px; }
.live-duo .live-gros-minuteur__texte b { font-size: 34px; }
.live-duo .live-gros-minuteur__texte small {
    max-width: 100%;
    font-size: 10px;
    letter-spacing: .04em;
    line-height: 1.1;
    text-align: center;
    overflow-wrap: anywhere;
}

.live-duo__net,
.live-duo__passer {
    width: 100%;
    max-width: 210px;
    justify-content: center;
    text-align: center;
    white-space: normal;
}

/* Armé : le second clic confirme. */
.live-duo__passer.est-arme {
    background: var(--red);
    border-color: var(--red-deep);
    color: #fff;
}

.live-pixels {
    display: grid;
    justify-items: center;
    gap: 4px;
}

.live-pixels canvas {
    width: 104px;
    height: 104px;
    border-radius: 14px;
    border: var(--border);
    background: var(--paper-deep);
    transition: box-shadow .3s var(--ease);
}

/* Un éclat sur le cadre à chaque cran de netteté gagné. */
.live-pixels.est-eclat canvas { animation: live-eclat .7s var(--ease); }

@keyframes live-eclat {
    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(31, 158, 146, .7); }
    35%  { transform: scale(1.07); box-shadow: 0 0 0 8px rgba(31, 158, 146, 0); }
    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(31, 158, 146, 0); }
}

.live-pixels[data-cran="3"] canvas { border-color: var(--teal); }

@media (prefers-reduced-motion: reduce) {
    .live-pixels.est-eclat canvas { animation: none; }
}
