@import 'tailwindcss';
@import './themes.css';
@import './theme-herbier.css';
@import './theme-vitrail.css';
@import './theme-explorateur.css';

@source '../views';
@source '../js';

@theme {
    --font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif;
}

:root {
    --ygg-primary: #1f6f54;
    --ygg-accent: #e8b04b;
    --ygg-bg: #f7f5ef;

    /* Arrondi des visuels de cartes, partout ou une carte est montree.
       Exprime en pourcentage pour rester proportionnel de la vignette au
       plein ecran. Les deux valeurs (horizontale / verticale) sont dans
       le rapport du format de carte : les coins restent ainsi des arcs
       de cercle, comme sur une vraie carte a jouer. */
    --carte-radius: 6% / 4.3%;
}

/* Toute image de carte affichee dans l'appli porte le meme arrondi */
.carte-image {
    border-radius: var(--carte-radius);
    overflow: hidden;
}

html,
body {
    height: 100%;
}

body {
    margin: 0;
    font-family: var(--font-sans);
    /* Fond neutre du "bureau" derriere la fenetre mobile */
    background: #1c1b1a;
}

/* ------------------------------------------------------------------ */
/* Harmonisation entre navigateurs : chaque regle repond a un ecart    */
/* constate entre Chrome, Firefox et Safari                            */
/* ------------------------------------------------------------------ */

html {
    /* Safari iOS grossit les textes de lui-meme en paysage : le plan
       plein ecran tournait, la typographie sautait */
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

/* Chrome Android pose un voile bleu sur chaque toucher : sur un ecran
   fait de grandes touches (quiz, plan), il clignote en permanence */
html {
    -webkit-tap-highlight-color: transparent;
}

/* Safari dessine les champs de recherche a sa facon : coins arrondis
   forces, loupe et croix maison. Les notres reprennent le dessin des
   autres champs, identique partout */
input[type='search'] {
    -webkit-appearance: none;
    appearance: none;
}

input[type='search']::-webkit-search-decoration,
input[type='search']::-webkit-search-cancel-button,
input[type='search']::-webkit-search-results-button,
input[type='search']::-webkit-search-results-decoration {
    -webkit-appearance: none;
    display: none;
}

/* ------------------------------------------------------------------ */
/* La scene : plein ecran pour tous, apercu mobile pour l'organisation */
/* ------------------------------------------------------------------ */

.desktop-stage {
    /* Repli pour les navigateurs sans dvh (vieux Safari, vieux Firefox) :
       sans lui, la page s'effondrait a zero de haut */
    height: 100vh;
    height: 100dvh;
    display: flex;
    align-items: center;
    justify-content: center;
}

/*
 * Sur telephone, l'application occupe tout l'ecran. La largeur etait
 * plafonnee a 430px en toutes circonstances : un appareil dont la
 * fenetre depasse cette valeur (affichage regle en petit, navigateur en
 * mode ordinateur) se retrouvait avec deux bandes noires sur les cotes.
 * Le plafond n'a de sens qu'au bureau, ou il dessine la fenetre mobile.
 */
.phone-frame {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100vh;
    height: 100dvh;
    background: var(--ygg-bg);
    color: #1f2937;
    overflow: hidden;
}

/*
 * L'apercu en fenetre de telephone est reserve aux comptes d'organisation
 * (.stage-apercu, pose par App.vue) : il sert a controler ce que voient
 * les visiteurs, pas a consulter l'appli. La condition de hauteur ecarte
 * les telephones en paysage : plus larges que 768px mais bien trop bas,
 * ils se retrouvaient enfermes dans l'apercu avec le contenu ecrase.
 */
@media (min-width: 768px) and (min-height: 500px) {
    .stage-apercu .phone-frame {
        max-width: 430px;
        height: min(880px, calc(100vh - 48px));
        height: min(880px, calc(100dvh - 48px));
        border-radius: 36px;
        border: 10px solid #000;
        box-shadow: 0 24px 80px rgba(0, 0, 0, 0.55);
    }
}

@media (min-width: 768px) {
    /*
     * Pour tout le monde d'autre, l'appli remplit l'ecran. Sur tablette
     * et au bureau, le contenu ne s'etire pas pour autant sur toute la
     * largeur : les listes restent dans une bande centrale lisible, et
     * la barre du bas garde ses onglets groupes au centre plutot que
     * disperses aux deux bouts d'un grand ecran. Les ecrans qui vivent
     * en pleine largeur (plan, scan, quiz) portent .ecran-large.
     */
    .desktop-stage:not(.stage-apercu) .app-header {
        padding-inline: max(16px, calc((100% - 900px) / 2));
    }

    .desktop-stage:not(.stage-apercu) .bottom-nav {
        padding-inline: max(0px, calc((100% - 640px) / 2));
    }

    .desktop-stage:not(.stage-apercu) .app-main > * {
        width: 100%;
        max-width: 900px;
        margin-inline: auto;
    }

    .desktop-stage:not(.stage-apercu) .app-main > .ecran-large {
        max-width: none;
    }

    /* Espace organisateur : pleine largeur au bureau. Gerer 120 cartes ou
       poser des points sur un plan dans une fenetre de telephone n'a
       aucun sens. Sur mobile, rien ne change. */
    .stage-admin {
        align-items: stretch;
    }

    .phone-frame.frame-admin {
        max-width: none;
        width: 100%;
        height: 100vh;
        height: 100dvh;
        border: 0;
        border-radius: 0;
        box-shadow: none;
    }

    /* Menu a gauche, travail a droite : la disposition de base empile
       en colonne pour le mobile, on la remet en ligne ici */
    .frame-admin .admin-layout {
        display: flex;
        flex-direction: row;
        height: 100%;
        min-height: 0;
    }

    .frame-admin .admin-sidebar {
        display: flex;
        flex-direction: column;
        width: 268px;
        flex-shrink: 0;
        background: #1c2b22;
        color: #e8efe9;
        border-right: 1px solid rgba(255, 255, 255, 0.08);
    }

    .frame-admin .admin-work-header,
    .frame-admin .admin-home-menu {
        display: none;
    }

    /* Le contenu reste lisible : on ne l'etire pas sur toute la largeur */
    .frame-admin .app-main > div {
        max-width: 1100px;
        margin: 0 auto;
    }

    /* Les cartes s'affichent en grille plutot qu'en liste etroite */
    .frame-admin .admin-cards-grid {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
        gap: 8px;
        align-items: start;
    }
}

.font-display {
    font-weight: 700;
}

/* ------------------------------------------------------------------ */
/* Structure de l'appli                                                */
/* ------------------------------------------------------------------ */

/* Les habillages debordent volontairement de l'en-tete et de la barre du
   bas (le cordage d'Explorateur, par exemple). Sans plan declare, ces
   debordements passaient derriere le contenu des que celui-ci portait
   une position, donc a certaines pages seulement et selon le
   defilement. Ces deux bandeaux sont maintenant toujours au-dessus. */
.app-header {
    position: relative;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 12px 16px;
    background: var(--ygg-primary);
    color: #fff;
    flex-shrink: 0;
}

.app-main {
    flex: 1;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}

/* Barre du bas : cibles tactiles 48px minimum */
.bottom-nav {
    position: relative;
    z-index: 10;
    display: flex;
    align-items: stretch;
    justify-content: space-around;
    border-top: 1px solid #e5e7eb;
    background: #fff;
    padding-bottom: env(safe-area-inset-bottom);
    flex-shrink: 0;
}

.nav-tab {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-width: 64px;
    min-height: 56px;
    color: #9ca3af;
}

.nav-tab-active {
    color: var(--ygg-primary);
    font-weight: 600;
}

/* Le bouton SCAN : central, sureleve, le geste unique du festival */
.scan-button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 62px;
    height: 62px;
    margin-top: -31px; /* la moitie du bouton flotte au-dessus de la barre */
    border-radius: 9999px;
    background: var(--ygg-primary);
    color: #fff;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
    border: 4px solid #fff;
    z-index: 5;
}

/* ------------------------------------------------------------------ */
/* Composants                                                          */
/* ------------------------------------------------------------------ */

.tap-target {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 48px;
    min-height: 48px;
}

.chip {
    flex-shrink: 0;
    padding: 8px 14px;
    border-radius: 9999px;
    border: 1px solid #d1d5db;
    background: #fff;
    font-size: 13px;
    font-weight: 500;
    white-space: nowrap;
}

.chip-active {
    background: var(--ygg-primary);
    border-color: var(--ygg-primary);
    color: #fff;
}

/* Pastille de rarete : la couleur officielle du referentiel */
.rarete-pastille {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 9999px;
    vertical-align: baseline;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15);
}

.section-title {
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #6b7280;
    margin-bottom: 8px;
}

.btn-primary {
    display: block;
    width: 100%;
    padding: 14px;
    border-radius: 14px;
    background: var(--ygg-primary);
    color: #fff;
    font-weight: 600;
    text-align: center;
}

.btn-primary:disabled {
    opacity: 0.6;
}

/* Feuilles montantes (fiches courtes, selecteurs) */
.sheet-backdrop {
    position: absolute;
    inset: 0;
    z-index: 40;
    display: flex;
    align-items: flex-end;
    background: rgba(0, 0, 0, 0.45);
}

.sheet {
    width: 100%;
    background: #fff;
    color: #1f2937;
    border-radius: 20px 20px 0 0;
    padding: 20px 16px calc(20px + env(safe-area-inset-bottom));
}

/* Apercu visiteur depuis l'administration : le rendu reel, dans une
   fenetre de telephone, pour juger avant de publier */
.apercu-backdrop {
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.65);
}

.apercu-cadre {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    max-height: 100%;
}

.apercu-phone {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    width: 340px;
    max-width: 88vw;
    height: 600px;
    max-height: 70vh;
    border-radius: 28px;
    background: var(--ygg-bg);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}

.apercu-legende {
    font-size: 12px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.75);
}

/* Scanner */
.scan-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.scan-window {
    width: 220px;
    height: 220px;
    border-radius: 24px;
    border: 3px solid rgba(255, 255, 255, 0.9);
    box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.45);
}

/* ------------------------------------------------------------------ */
/* Espace organisation                                                  */
/* ------------------------------------------------------------------ */

.admin-layout {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

.admin-work {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    min-height: 0;
}

/* Sur mobile la barre laterale n'a pas sa place : le tableau de bord
   sert de menu, comme sur n'importe quelle application */
.admin-sidebar {
    display: none;
}

.admin-sidebar-head {
    padding: 16px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.admin-sidebar-nav {
    flex: 1;
    overflow-y: auto;
    padding: 8px 10px 16px;
}

.admin-sidebar-title {
    padding: 14px 10px 6px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.45;
}

.admin-sidebar-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px;
    border-radius: 10px;
    font-size: 14px;
    color: rgba(232, 239, 233, 0.85);
}

.admin-sidebar-link:hover {
    background: rgba(255, 255, 255, 0.06);
}

.admin-sidebar-link-active {
    background: var(--ygg-primary);
    color: #fff;
    font-weight: 600;
}

.admin-sidebar-back {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 20px;
    font-size: 13px;
    color: rgba(232, 239, 233, 0.7);
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}

/* Plan interactif */
.map-viewport {
    height: 100%;
    overflow: auto;
    border-radius: 12px;
}

.map-pin {
    position: absolute;
    width: 22px;
    height: 22px;
    border-radius: 9999px;
    border: 2.5px solid #fff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
    transform: translate(-50%, -50%);
    cursor: pointer;
    /* La zone de touche elargie ci-dessous deborde du disque */
    overflow: visible;
}

/*
 * Le disque reste a 22px pour ne pas noyer le plan, mais le doigt vise
 * 34px : sur le terrain, une pastille de 22px se rate une fois sur deux,
 * et le visiteur qui cherche les toilettes ou les secours ouvre la fiche
 * du stand d'a cote.
 *
 * Le debordement s'arrete a 6px, et pas plus. Les pastilles sont des
 * freres absolus sans z-index : le halo invisible d'une pastille tardive
 * se pose par-dessus le disque visible de ses voisines. Sur un plan de
 * 40 stands dans une fenetre de telephone, des points a 25px les uns des
 * autres sont la norme ; a 44px, le halo de la buvette mangeait la
 * moitie du disque de l'infirmerie et ouvrait la mauvaise fiche, soit
 * exactement le probleme que cette zone elargie devait supprimer.
 */
.map-pin::after {
    content: '';
    position: absolute;
    inset: -6px;
    border-radius: 9999px;
}

/*
 * Editeur de plan de l'organisation : aucune zone elargie.
 *
 * La-bas chaque puce arrete le pointeur pour se laisser glisser, donc le
 * halo devient une zone morte : poser un nouveau point a 8px d'un stand
 * existant ne fait rien du tout, sans le moindre message, et l'orga
 * croit l'editeur casse. Elle vise a la souris sur un grand ecran, le
 * disque de 22px lui suffit.
 */
.map-pin-edit::after {
    content: none;
}

/*
 * Apercu du plan de site dans l'espace organisation.
 *
 * Le meme dessin que sur le telephone d'un visiteur, mais pose sur un
 * grand ecran. La hauteur est fixe, et non proportionnelle au terrain :
 * un terrain tres large donnait sinon un cadre haut de 80 pixels ou plus
 * rien ne se lisait, et un terrain profond poussait tout le reste de la
 * page hors de vue. Elle est genereuse au bureau, parce que c'est
 * justement pour regarder les emplacements que l'organisation ouvre cet
 * ecran.
 *
 * Ni ombre ni degrade : c'est un plan de site, pas une illustration.
 */
.plan-apercu {
    display: block;
    width: 100%;
    height: 320px;
    border-radius: 12px;
    border: 1px solid #d1d5db;
    background: #fff;
}

@media (min-width: 768px) {
    .plan-apercu {
        height: 560px;
    }
}

/* "Vous etes ici" : le point bleu, promis uniquement en plein air */
.map-me {
    position: absolute;
    width: 18px;
    height: 18px;
    border-radius: 9999px;
    background: #2563eb;
    border: 3px solid #fff;
    box-shadow: 0 0 0 6px rgba(37, 99, 235, 0.25);
    transform: translate(-50%, -50%);
    animation: pulse-me 2s ease-out infinite;
}

@keyframes pulse-me {
    0% { box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.35); }
    70% { box-shadow: 0 0 0 12px rgba(37, 99, 235, 0); }
    100% { box-shadow: 0 0 0 4px rgba(37, 99, 235, 0); }
}

/*
 * Le plan de site dessine par l'organisation (source Merlin).
 *
 * C'est un plan de site, pas une carte de jeu : pas d'ombre, pas de
 * degrade, pas d'animation. Le seul confort ajoute est de pouvoir
 * regarder de plus pres, parce que sur un terrain de 120 metres tenu
 * dans une main les noms de stands font trois pixels.
 */
.plan-merlin {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 12px;
    border: 1px solid #d1d5db;
    background: #fff;
    /* Le pincement et le glissement appartiennent au plan : sans cela, le
       navigateur zoome la page entiere et le visiteur perd la barre de
       navigation du bas au milieu de sa recherche */
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
}

/* Le nom d'un stand ne se selectionne pas : un appui un peu long sur un
   telephone ouvrait la loupe de copie du systeme au lieu de la fiche */
.plan-texte {
    pointer-events: none;
    -webkit-user-select: none;
    user-select: none;
}

.plan-vignette {
    cursor: pointer;
}

/* La goutte des animations : une ombre discrete la decolle du fond,
   sans quoi elle se confond avec les blocs qu'elle survole */
.plan-puce path {
    filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.35));
}

/* Le nom d'une scene est un repere, pas une etiquette : petites capitales
   larges, dans la police d'affichage du projet */
.plan-nom-scene {
    font-weight: 800;
    letter-spacing: 0.04em;
    pointer-events: none;
    user-select: none;
}

/*
 * Le plan en plein ecran : il recouvre toute la fenetre, en-tete et barre
 * de navigation compris, et tourne librement avec le telephone. Le fond
 * opaque compte : sans lui, l'ecran d'en dessous transparait pendant le
 * glissement. Les marges de securite respectent l'encoche des telephones.
 */
.plan-plein-ecran {
    position: fixed;
    inset: 0;
    z-index: 70;
    background: var(--ygg-bg);
    padding: max(env(safe-area-inset-top), 12px) max(env(safe-area-inset-right), 12px)
        max(env(safe-area-inset-bottom), 12px) max(env(safe-area-inset-left), 12px);
}

.plan-commandes {
    position: absolute;
    right: 24px;
    bottom: 24px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    transition: bottom 0.15s ease;
}

/* La fiche d'un emplacement s'ouvre en bas du plan et recouvrait les
   commandes de zoom : le visiteur qui venait de toucher un stand ne
   pouvait plus ni s'approcher ni revenir au plan entier. Elles remontent
   au-dessus de la fiche tant qu'elle est ouverte. */
.plan-commandes-remontees {
    bottom: 200px;
}

/* 44px : la taille minimale d'une cible tactile, sur un ecran ou le
   pouce vise a cote d'un plan que l'on vient de faire glisser */
.plan-commande {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 12px;
    border: 1px solid #d1d5db;
    background: #fff;
    color: #374151;
}

/* Affiche du festival : mise en valeur sobre */
.poster-frame {
    border-radius: 14px;
    border: 1px solid #e5e7eb;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}

/* Didacticiel : plein ecran dans la fenetre mobile, sobre et clair */
.onboarding {
    position: absolute;
    inset: 0;
    z-index: 50;
    display: flex;
    flex-direction: column;
    background: var(--ygg-bg);
    color: #1f2937;
}

.onboarding-skip {
    align-self: flex-end;
    margin: 12px 16px 0;
    padding: 8px 12px;
    font-size: 14px;
    color: #6b7280;
    text-decoration: underline;
}

.onboarding-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 88px;
    height: 88px;
    margin-bottom: 20px;
    border-radius: 9999px;
    color: #fff;
    background: var(--ygg-primary);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
}

/* Bibliotheque : les vraies cartes, les manquantes en dos estompe */
.collection-card {
    position: relative;
    aspect-ratio: 180 / 251;
    border-radius: var(--carte-radius);
    overflow: hidden;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
}

.collection-card img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--carte-radius);
}

/* Cartes manquantes : le dos garde ses vraies couleurs, legerement
   assombri pour faire ressortir le grand ? dore */
.collection-card-locked img {
    filter: brightness(0.8);
}

.collection-card-num {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 44px;
    font-weight: 800;
    color: #e2c56d;
    text-shadow:
        0 2px 6px rgba(0, 0, 0, 0.75),
        0 0 14px rgba(226, 197, 109, 0.5);
}

/* Visionneuse plein ecran : zoom et deplacement dans la carte */
.card-viewer {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: flex;
    flex-direction: column;
    background: rgba(8, 8, 12, 0.96);
    color: #fff;
    touch-action: none;
}

.card-viewer-close {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 2;
    color: #fff;
}

.card-viewer-stage {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    cursor: grab;
}

.card-viewer-image {
    max-width: 92%;
    max-height: 86%;
    user-select: none;
    transition: transform 0.08s linear;
    will-change: transform;
    border-radius: var(--carte-radius);
}

/* Carte paysage : remise a l'horizontale, dimensionnee sur la largeur d'ecran */
.card-viewer-image.card-viewer-paysage {
    max-height: none;
    max-width: none;
    height: min(92vw, 60vh);
}

.card-viewer-caption {
    padding: 10px 16px calc(16px + env(safe-area-inset-bottom));
    text-align: center;
    max-height: 46%;
    overflow-y: auto;
}

/* Credits d'une carte : un nom que l'on touche, une fiche qui se deplie */
.credit {
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.07);
    overflow: hidden;
    text-align: left;
}

.credit-tete {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 12px;
    font-size: 14px;
    color: #fff;
}

.credit-tete-figee {
    cursor: default;
}

.credit-portrait {
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    border-radius: 9999px;
    object-fit: cover;
}

.credit-corps {
    padding: 0 12px 12px;
    color: #fff;
}

.credit-signature {
    display: block;
    max-height: 56px;
    margin-top: 10px;
    /* Une signature est presque toujours noire sur blanc : sur fond
       sombre, on l'inverse plutot que de la poser dans un cadre blanc */
    filter: invert(1) brightness(1.6);
    opacity: 0.85;
}

.credit-lien {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 11px;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.14);
    font-size: 12px;
    font-weight: 600;
    color: #fff;
}

/* ------------------------------------------------------------------ */
/* Revelation de carte : dos presente, retournement, effets par rarete */
/* ------------------------------------------------------------------ */

/* Contenue dans la fenetre mobile : en plein ecran sur telephone,
   et sans deborder du cadre sur ordinateur */
.reveal-screen {
    position: absolute;
    inset: 0;
    z-index: 50;

    /*
     * Les teintes derivees de la rarete, avec un REPLI : Safari avant
     * 16.2 et Firefox avant 113 ne connaissent pas color-mix et jetaient
     * toute declaration qui l'utilisait. Halo, brume, feuilles et anneaux
     * disparaissaient alors de la revelation, qui semblait cassee sur ces
     * telephones. Le repli sert la teinte pleine (les degrades gardent
     * leurs transparences), et les rayons s'effacent : des rayons pleine
     * couleur hurleraient.
     */
    --rarity-eclat: var(--rarity);
    --rarity-halo-doux: var(--rarity);
    --rarity-halo-fort: var(--rarity);
    --rarity-rayon: transparent;
    --rarity-brume: var(--rarity);
    --rarity-voile: var(--rarity);
    --rarity-feuille: var(--rarity);
    --rarity-anneau: var(--rarity);
    /* Les rayons debordent volontairement : ils sont coupes ici */
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: radial-gradient(ellipse at 50% 40%, rgba(40, 40, 60, 0.95) 0%, rgba(8, 8, 14, 0.98) 70%);
}

.reveal-title {
    font-size: 18px;
    font-weight: 700;
    color: var(--rarity);
    opacity: 0;
    transform: translateY(6px);
    transition: opacity 0.4s ease, transform 0.4s ease;
}

.reveal-title-visible {
    opacity: 1;
    transform: translateY(0);
}

.reveal-stage {
    position: relative;
    width: min(62vw, 260px);
    aspect-ratio: 180 / 251;
    perspective: 900px;
}

/* Enveloppe portant le halo et le rebond.
   Un filtre CSS pose sur un element en preserve-3d aplatit sa
   perspective : le halo doit donc vivre a l'exterieur du retournement,
   sinon la carte ne se retourne jamais. */
.reveal-halo {
    width: 100%;
    height: 100%;
}

/* Cartes concues a l'horizontale : le dos se presente a la verticale
   comme les autres, puis la carte bascule une fois retournee. Le pivot
   part apres le retournement, pour que les deux mouvements se lisent. */
.reveal-paysage .reveal-halo {
    transition: transform 0.55s cubic-bezier(0.3, 1.3, 0.5, 1) 0.85s;
}

/* Le pivot redresse aussi le visuel : les cartes paysage sont stockees
   couchees dans un fichier portrait, la meme rotation les remet donc
   dans leur sens de lecture. */
.reveal-paysage.reveal-flipped .reveal-halo {
    transform: rotate(-90deg) scale(0.92);
}

/* Retournement 3D : dos -> face */
.reveal-flip {
    position: relative;
    width: 100%;
    height: 100%;
    transform-style: preserve-3d;
    transition: transform 0.8s cubic-bezier(0.3, 1.4, 0.4, 1);
}

.reveal-flipped .reveal-flip {
    transform: rotateY(180deg);
}

.reveal-face {
    position: absolute;
    inset: 0;
    backface-visibility: hidden;
    border-radius: var(--carte-radius);
    overflow: hidden;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
}

.reveal-face img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--carte-radius);
}

/* Le dos officiel, presente pendant le suspense */
.reveal-back {
    animation: reveal-waiting 1.4s ease-in-out infinite alternate;
}

.reveal-front {
    transform: rotateY(180deg);
}

/* Reflet diagonal qui balaie la carte revelee */
.reveal-shine {
    position: absolute;
    inset: 0;
    background: linear-gradient(
        115deg,
        transparent 30%,
        rgba(255, 255, 255, 0.45) 48%,
        rgba(255, 255, 255, 0.15) 52%,
        transparent 65%
    );
    transform: translateX(-130%);
    pointer-events: none;
}

.reveal-flipped .reveal-shine {
    animation: reveal-shine-sweep 1.1s ease-out 0.75s;
}

@keyframes reveal-shine-sweep {
    from { transform: translateX(-130%); }
    to { transform: translateX(130%); }
}

@supports (color: color-mix(in srgb, red, blue)) {
    .reveal-screen {
        --rarity-eclat: color-mix(in srgb, var(--rarity) 85%, #fff);
        --rarity-halo-doux: color-mix(in srgb, var(--rarity) 55%, transparent);
        --rarity-halo-fort: color-mix(in srgb, var(--rarity) 90%, transparent);
        --rarity-rayon: color-mix(in srgb, var(--rarity) 28%, transparent);
        --rarity-brume: color-mix(in srgb, var(--rarity) 40%, transparent);
        --rarity-voile: color-mix(in srgb, var(--rarity) 50%, transparent);
        --rarity-feuille: color-mix(in srgb, var(--rarity) 75%, #fff 12%);
        --rarity-anneau: color-mix(in srgb, var(--rarity) 42%, transparent);
    }
}

/* Eclat au moment du retournement */
.reveal-flash {
    position: absolute;
    inset: -30%;
    border-radius: 9999px;
    background: radial-gradient(circle, var(--rarity-eclat) 0%, transparent 60%);
    opacity: 0;
    pointer-events: none;
}

.reveal-flipped .reveal-flash {
    animation: reveal-flash-burst 0.7s ease-out;
}

@keyframes reveal-flash-burst {
    0% { opacity: 0; transform: scale(0.4); }
    25% { opacity: 0.9; }
    100% { opacity: 0; transform: scale(1.5); }
}

@keyframes reveal-waiting {
    0% { filter: brightness(0.95); transform: rotate(-1.2deg) translateY(0); }
    100% { filter: brightness(1.12); transform: rotate(1.2deg) translateY(-4px); }
}

/* Halo : present des "rare", plus intense ensuite */
.reveal-flipped.reveal-tier-2 .reveal-halo,
.reveal-flipped.reveal-tier-3 .reveal-halo,
.reveal-flipped.reveal-tier-4 .reveal-halo {
    animation: reveal-glow 2s ease-in-out infinite alternate;
}

@keyframes reveal-glow {
    from { filter: drop-shadow(0 0 12px var(--rarity-halo-doux)); }
    to { filter: drop-shadow(0 0 28px var(--rarity-halo-fort)); }
}

/* Rayons tournants derriere la carte (epique, legendaire).
   Volontairement bien plus grands que l'ecran : cadres sur la carte,
   ils dessinaient un disque et l'effet ressemblait a une bulle. */
.reveal-rays {
    position: absolute;
    inset: -450%;
    background: conic-gradient(
        from 0deg,
        transparent 0deg 12deg, var(--rarity-rayon) 20deg 26deg,
        transparent 34deg 57deg, var(--rarity-rayon) 65deg 71deg,
        transparent 79deg 102deg, var(--rarity-rayon) 110deg 116deg,
        transparent 124deg 147deg, var(--rarity-rayon) 155deg 161deg,
        transparent 169deg 192deg, var(--rarity-rayon) 200deg 206deg,
        transparent 214deg 237deg, var(--rarity-rayon) 245deg 251deg,
        transparent 259deg 282deg, var(--rarity-rayon) 290deg 296deg,
        transparent 304deg 327deg, var(--rarity-rayon) 335deg 341deg,
        transparent 349deg 360deg
    );
    opacity: 0;
    transition: opacity 0.6s ease 0.4s;
    animation: reveal-rays-spin 14s linear infinite;
    pointer-events: none;
}

.reveal-flipped .reveal-rays {
    opacity: 1;
}

@keyframes reveal-rays-spin {
    to { transform: rotate(360deg); }
}

/* Etincelles (legendaire) */
.reveal-spark {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 7px;
    height: 7px;
    border-radius: 9999px;
    background: var(--rarity);
    opacity: 0;
    pointer-events: none;
    transform: rotate(calc(var(--i) * 45deg)) translateY(-10px);
}

.reveal-flipped .reveal-spark {
    animation: reveal-spark-fly 1.6s ease-out infinite;
    animation-delay: calc(0.8s + var(--i) * 0.18s);
}

@keyframes reveal-spark-fly {
    0% {
        opacity: 0;
        transform: rotate(calc(var(--i) * 45deg)) translateY(-10px) scale(1);
    }
    15% { opacity: 1; }
    100% {
        opacity: 0;
        transform: rotate(calc(var(--i) * 45deg)) translateY(-190px) scale(0.2);
    }
}

/* Le legendaire rebondit legerement a l'arrivee */
.reveal-flipped.reveal-tier-4 .reveal-halo {
    animation: reveal-glow 2s ease-in-out infinite alternate, reveal-pop 0.5s ease 0.7s;
}

@keyframes reveal-pop {
    0% { scale: 1; }
    40% { scale: 1.07; }
    100% { scale: 1; }
}

/* La carte se laisse toucher tant qu'elle n'est pas retournee */
.reveal-a-toucher {
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.reveal-a-toucher:focus-visible {
    outline: 3px solid var(--rarity);
    outline-offset: 10px;
    border-radius: 12px;
}

.reveal-invite {
    margin-top: 20px;
    font-size: 15px;
    font-weight: 700;
    color: #fff;
    animation: reveal-invite-respire 1.5s ease-in-out infinite;
}

@keyframes reveal-invite-respire {
    0%, 100% { opacity: 0.6; transform: translateY(0); }
    50% { opacity: 1; transform: translateY(-4px); }
}

/* ------------------------------------------------------------------ */
/* Quiz sur scene                                                      */
/*                                                                     */
/* Deux surfaces : le telephone du joueur, et l'ecran projete derriere */
/* le presentateur. Les quatre couleurs sont communes aux deux, c'est  */
/* ce qui permet de repondre en regardant la scene.                    */
/* ------------------------------------------------------------------ */

/* La pastille qui signale un quiz en cours sur la tuile des quetes */
.quiz-point {
    flex-shrink: 0;
    width: 12px;
    height: 12px;
    border-radius: 9999px;
    background: #fff;
    animation: quiz-battement 1.4s ease-in-out infinite;
}

.quiz-a { --quiz-teinte: #d64545; }
.quiz-b { --quiz-teinte: #2f7dd1; }
.quiz-c { --quiz-teinte: #e8a020; }
.quiz-d { --quiz-teinte: #3f9e6a; }

/* ---- Le telephone du joueur ---- */

.quiz-joueur {
    min-height: 100%;
    display: flex;
    flex-direction: column;
    background: radial-gradient(ellipse at 50% 0%, #1e2b4a 0%, #0d1220 70%);
    color: #fff;
}

.quiz-bandeau {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 16px;
    background: rgba(255, 255, 255, 0.06);
}

.quiz-centre {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 24px;
    text-align: center;
}

.quiz-titre {
    font-size: 22px;
    font-weight: 800;
    line-height: 1.15;
}

.quiz-champ {
    width: 100%;
    margin-top: 8px;
    padding: 14px 16px;
    border-radius: 14px;
    border: 2px solid rgba(255, 255, 255, 0.25);
    background: rgba(255, 255, 255, 0.1);
    color: #fff;
    font-size: 16px;
    text-align: center;
}

.quiz-bouton {
    display: block;
    width: 100%;
    max-width: 320px;
    padding: 16px;
    border-radius: 14px;
    background: var(--ygg-accent);
    color: #21160a;
    font-size: 16px;
    font-weight: 800;
}

/* Le coeur qui bat pendant l'attente */
.quiz-pulse {
    width: 84px;
    height: 84px;
    border-radius: 9999px;
    background: var(--ygg-accent);
    animation: quiz-battement 1.6s ease-in-out infinite;
}

@keyframes quiz-battement {
    0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(232, 176, 75, 0.5); }
    50% { transform: scale(1.08); box-shadow: 0 0 0 26px rgba(232, 176, 75, 0); }
}

.quiz-scene-joueur {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: 16px;
}

.quiz-entete-question {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.quiz-compteur {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.6;
}

.quiz-chrono {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 9999px;
    border: 3px solid var(--ygg-accent);
    font-size: 18px;
    font-weight: 800;
}

.quiz-chrono-urgent {
    border-color: #ff6b6b;
    color: #ff9b9b;
    animation: quiz-battement 0.7s ease-in-out infinite;
}

.quiz-question {
    margin: 14px 0 18px;
    font-size: 19px;
    font-weight: 700;
    line-height: 1.3;
}

/* Le telephone ne repete pas la question : il invite a regarder la scene */
.quiz-consigne {
    margin: 12px 0 14px;
    text-align: center;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    opacity: 0.55;
}

.quiz-grille {
    flex: 1;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    min-height: 300px;
}

.quiz-touche {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    border-radius: 18px;
    background: var(--quiz-teinte);
    color: #fff;
    font-size: 26px;
    font-weight: 900;
    box-shadow: 0 6px 0 rgba(0, 0, 0, 0.28);
    animation: quiz-entree 0.35s cubic-bezier(0.2, 1.3, 0.4, 1) backwards;
    animation-delay: var(--retard);
    transition: transform 0.12s ease, opacity 0.25s ease, box-shadow 0.12s ease;
}

.quiz-touche svg {
    width: 38px;
    height: 38px;
    opacity: 0.9;
}

.quiz-touche:active:not(:disabled) {
    transform: translateY(4px);
    box-shadow: 0 2px 0 rgba(0, 0, 0, 0.28);
}

.quiz-touche-choisie {
    outline: 4px solid #fff;
    outline-offset: -4px;
    animation: quiz-choisie 0.4s ease;
}

.quiz-touche-eteinte {
    opacity: 0.28;
}

@keyframes quiz-entree {
    from { opacity: 0; transform: translateY(18px) scale(0.94); }
    to { opacity: 1; transform: none; }
}

@keyframes quiz-choisie {
    0% { transform: scale(1); }
    45% { transform: scale(1.06); }
    100% { transform: scale(1); }
}

/* Temps ecoule : le titre sursaute une fois, puis se tient tranquille */
.quiz-tremble {
    animation: quiz-tremble 0.55s cubic-bezier(0.36, 0.07, 0.19, 0.97);
}

@keyframes quiz-tremble {
    10%, 90% { transform: translateX(-3px); }
    20%, 80% { transform: translateX(5px); }
    30%, 50%, 70% { transform: translateX(-8px); }
    40%, 60% { transform: translateX(8px); }
}

.quiz-sablier {
    width: 5em;
    height: 5em;
    color: var(--ygg-accent);
    animation: quiz-sablier 2.2s ease-in-out infinite;
}

.quiz-sablier svg { width: 100%; height: 100%; }

@keyframes quiz-sablier {
    0%, 45% { transform: rotate(0deg); }
    55%, 100% { transform: rotate(180deg); }
}

.quiz-temps {
    font-size: 0.8em;
    opacity: 0.7;
    font-variant-numeric: tabular-nums;
}

.quiz-verdict {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 110px;
    height: 110px;
    border-radius: 9999px;
    animation: quiz-verdict 0.5s cubic-bezier(0.2, 1.4, 0.4, 1);
}

.quiz-verdict svg { width: 56px; height: 56px; color: #fff; }
.quiz-juste { background: #3f9e6a; }
.quiz-faux { background: #d64545; }

@keyframes quiz-verdict {
    from { transform: scale(0.4) rotate(-12deg); opacity: 0; }
    to { transform: none; opacity: 1; }
}

.quiz-podium {
    width: 100%;
    max-width: 340px;
    margin-top: 18px;
}

.quiz-podium li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    margin-bottom: 6px;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.08);
    text-align: left;
}

.quiz-podium .quiz-moi {
    background: var(--ygg-accent);
    color: #21160a;
    font-weight: 700;
}

.quiz-rang {
    width: 26px;
    font-weight: 800;
    opacity: 0.7;
}

/* ---- L'ecran de scene ---- */

.quiz-scene {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: #0b1020 center / cover no-repeat;
    color: #fff;
    font-size: clamp(14px, 1.1vw, 20px);
}

.quiz-scene-voile {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse at 50% 0%, rgba(38, 56, 104, 0.75), transparent 65%),
        linear-gradient(180deg, rgba(6, 9, 18, 0.82), rgba(6, 9, 18, 0.94));
}

/* Seuls les blocs de contenu repassent au-dessus du voile. Une regle
   generale sur les enfants directs ecrasait le positionnement absolu de
   la barre de temps et du QR, qui s'etalaient alors en pleine largeur. */
.quiz-scene-centre,
.quiz-scene-jeu {
    position: relative;
    z-index: 1;
}

/*
 * QR insere tel quel dans la page (v-html) : il arrive avec sa taille
 * native, 400 pixels de cote, et recouvrait le formulaire. On le cale
 * sur son cadre.
 */
.qr-mini {
    flex-shrink: 0;
    width: 104px;
    height: 104px;
    padding: 4px;
    border-radius: 10px;
    background: #fff;
}

.qr-mini svg {
    display: block;
    width: 100%;
    height: 100%;
}

/* Incident reseau : un bandeau discret, l'image projetee reste */
.quiz-incident {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    z-index: 3;
    padding: 0.4em 1.4em;
    border-radius: 0 0 12px 12px;
    background: rgba(214, 69, 69, 0.9);
    font-size: 0.9em;
    font-weight: 700;
}

.quiz-jauge {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 10px;
    background: rgba(255, 255, 255, 0.12);
    z-index: 2;
}

.quiz-jauge-remplie {
    height: 100%;
    background: linear-gradient(90deg, var(--ygg-accent), #ff8f4d);
    transition: width 0.15s linear;
}

.quiz-scene-centre,
.quiz-scene-jeu {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 3vh 4vw;
    text-align: center;
}

.quiz-scene-sur {
    font-size: 1.1em;
    font-weight: 700;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--ygg-accent);
}

.quiz-scene-titre {
    margin-top: 0.3em;
    font-size: 3.4em;
    font-weight: 900;
    line-height: 1.05;
}

.quiz-scene-sous { margin-top: 0.6em; font-size: 1.3em; opacity: 0.8; }

/* Rejoindre : le QR et le code cote a cote, lisibles du fond de la salle */
.quiz-rejoindre {
    display: flex;
    align-items: center;
    gap: 1.6em;
    margin-top: 1.6em;
    padding: 1.2em 1.6em;
    border-radius: 24px;
    background: rgba(255, 255, 255, 0.1);
    border: 2px solid rgba(255, 255, 255, 0.2);
}

.quiz-qr {
    width: 11em;
    height: 11em;
    border-radius: 14px;
    background: #fff;
    padding: 0.4em;
}

.quiz-code { text-align: left; }
.quiz-code-label { display: block; font-size: 0.95em; opacity: 0.75; }
.quiz-code strong { display: block; margin-top: 0.1em; font-size: 3.2em; font-weight: 900; letter-spacing: 0.18em; line-height: 1.1; }
.quiz-code-adresse { display: block; margin-top: 0.2em; font-size: 0.9em; opacity: 0.6; }

.quiz-compte { margin-top: 1.4em; font-size: 2.4em; font-weight: 900; }
.quiz-compte span { display: block; font-size: 0.32em; font-weight: 600; opacity: 0.7; }

.quiz-scene-compteur {
    font-size: 1em;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    opacity: 0.6;
}

.quiz-scene-question {
    margin: 0.3em 0 0.5em;
    font-size: 2.6em;
    font-weight: 900;
    line-height: 1.15;
    max-width: 24ch;
    animation: quiz-scene-entree 0.5s cubic-bezier(0.2, 1.2, 0.4, 1);
}

@keyframes quiz-scene-entree {
    from { opacity: 0; transform: translateY(24px); }
    to { opacity: 1; transform: none; }
}

/* Le visuel de la question, centre quoi qu'il arrive */
.quiz-media {
    max-height: 26vh;
    margin: 0 auto 0.6em;
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 14px 40px rgba(0, 0, 0, 0.5);
}

.quiz-media img,
.quiz-media video {
    display: block;
    margin: 0 auto;
    max-height: 26vh;
    max-width: min(60vw, 900px);
}

/*
 * Le QR des retardataires : discret dans son coin. Il doit rester
 * scannable depuis la salle sans jamais disputer la vedette a la
 * question, d'ou la petite taille et la transparence.
 */
.quiz-qr-coin {
    position: absolute;
    top: 1em;
    right: 1em;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 0.5em;
    padding: 0.35em 0.6em 0.35em 0.35em;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.18);
    opacity: 0.75;
}

.quiz-qr-coin img {
    display: block;
    width: 3.4em;
    height: 3.4em;
    border-radius: 6px;
    background: #fff;
    padding: 2px;
}

.quiz-qr-coin span {
    font-size: 0.8em;
    font-weight: 700;
    letter-spacing: 0.14em;
    color: rgba(255, 255, 255, 0.85);
}

.quiz-scene-grille {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1em;
    width: 100%;
    max-width: 1200px;
}

.quiz-scene-reponse {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.7em;
    padding: 1em 1.2em;
    border-radius: 18px;
    background: var(--quiz-teinte);
    text-align: left;
    overflow: hidden;
    animation: quiz-entree 0.45s cubic-bezier(0.2, 1.3, 0.4, 1) backwards;
    animation-delay: var(--retard);
    transition: opacity 0.4s ease, transform 0.4s ease;
}

.quiz-scene-reponse svg { width: 1.6em; height: 1.6em; flex-shrink: 0; opacity: 0.85; }
.quiz-scene-reponse p { font-size: 1.5em; font-weight: 700; line-height: 1.2; }
.quiz-lettre { font-size: 1.5em; font-weight: 900; opacity: 0.55; }

.quiz-gagnante {
    transform: scale(1.04);
    box-shadow: 0 0 0 5px #fff, 0 16px 40px rgba(0, 0, 0, 0.45);
    animation: quiz-gagnante 0.9s ease-in-out infinite alternate;
}

.quiz-perdante { opacity: 0.32; transform: scale(0.97); }

@keyframes quiz-gagnante {
    from { box-shadow: 0 0 0 5px #fff, 0 16px 40px rgba(0, 0, 0, 0.45); }
    to { box-shadow: 0 0 0 5px #fff, 0 16px 60px rgba(255, 255, 255, 0.35); }
}

.quiz-part {
    margin-left: auto;
    font-size: 1.5em;
    font-weight: 900;
}

/* La part de la salle qui a choisi cette reponse */
.quiz-barre {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 6px;
    background: rgba(255, 255, 255, 0.85);
    transition: width 0.8s cubic-bezier(0.2, 1, 0.3, 1);
}

.quiz-explication {
    margin-top: 1.2em;
    font-size: 1.3em;
    opacity: 0.85;
    max-width: 60ch;
}

.quiz-scene-pied {
    margin-top: 1.2em;
    font-size: 1.4em;
    opacity: 0.85;
}

.quiz-scene-pied strong { font-size: 1.3em; }

.quiz-scene-secondes {
    margin-left: 1em;
    padding: 0.2em 0.8em;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.14);
    font-weight: 700;
}

.quiz-scene-podium {
    width: min(880px, 90vw);
    margin-top: 1.4em;
}

.quiz-scene-podium li {
    display: flex;
    align-items: center;
    gap: 1em;
    padding: 0.7em 1.2em;
    margin-bottom: 0.5em;
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.1);
    font-size: 1.6em;
    text-align: left;
    animation: quiz-entree 0.5s cubic-bezier(0.2, 1.3, 0.4, 1) backwards;
    animation-delay: var(--retard);
}

.quiz-scene-podium li:first-child {
    background: linear-gradient(90deg, var(--ygg-accent), #f0c93c);
    color: #21160a;
    font-weight: 800;
}

.quiz-points { font-weight: 900; }

@media (prefers-reduced-motion: reduce) {
    .quiz-touche,
    .quiz-scene-reponse,
    .quiz-scene-question,
    .quiz-scene-podium li,
    .quiz-pulse,
    .quiz-verdict,
    .quiz-gagnante,
    .quiz-chrono-urgent {
        animation: none;
    }
}

/* ------------------------------------------------------------------ */
/* Le decor de la revelation : brume, bulles, feuilles                 */
/* ------------------------------------------------------------------ */

.reveal-decor {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    pointer-events: none;
}

/* Le contenu reste devant le decor */
.reveal-screen > *:not(.reveal-decor) {
    position: relative;
    z-index: 1;
}

/* Brume au sol : discrete pendant le suspense, elle se leve quand la
   carte se retourne */
.reveal-brume {
    position: absolute;
    left: -25%;
    right: -25%;
    bottom: -70px;
    height: 240px;
    background: radial-gradient(ellipse at 50% 100%, var(--rarity-brume) 0%, transparent 70%);
    filter: blur(20px);
    opacity: 0.25;
    transition: opacity 0.9s ease 0.35s;
    animation: reveal-brume-ondule 11s ease-in-out infinite alternate;
}

.reveal-decor-vif .reveal-brume {
    opacity: 0.85;
}

@keyframes reveal-brume-ondule {
    from { transform: translate3d(-4%, 6px, 0) scaleY(0.94); }
    to { transform: translate3d(4%, -6px, 0) scaleY(1.06); }
}

/* Bulles : elles montent en continu, meme avant le retournement */
.reveal-bulle {
    position: absolute;
    bottom: -40px;
    left: var(--x);
    width: var(--taille);
    height: var(--taille);
    border-radius: 9999px;
    background: radial-gradient(circle at 33% 30%,
        rgba(255, 255, 255, 0.9) 0%,
        var(--rarity-voile) 55%,
        transparent 74%);
    box-shadow: inset 0 0 6px rgba(255, 255, 255, 0.35);
    opacity: 0;
    animation: reveal-bulle-monte var(--duree) linear infinite;
    animation-delay: var(--delai);
    will-change: transform, opacity;
}

@keyframes reveal-bulle-monte {
    0% { transform: translate3d(0, 0, 0) scale(0.5); opacity: 0; }
    10% { opacity: 0.7; }
    45% { transform: translate3d(16px, -45vh, 0) scale(1); }
    80% { opacity: 0.45; }
    100% { transform: translate3d(-12px, -106vh, 0) scale(1.15); opacity: 0; }
}

/* Feuilles : elles tombent en tournoyant, a partir de peu commune */
.reveal-feuille {
    position: absolute;
    top: -40px;
    left: var(--x);
    width: var(--taille);
    height: var(--taille);
    border-radius: 0 100% 0 100%;
    background: var(--rarity-feuille);
    opacity: 0;
    animation: reveal-feuille-tombe var(--duree) linear infinite;
    animation-delay: var(--delai);
    will-change: transform, opacity;
}

@keyframes reveal-feuille-tombe {
    0% { transform: translate3d(0, 0, 0) rotate(0deg); opacity: 0; }
    12% { opacity: 0.75; }
    50% { transform: translate3d(-34px, 50vh, 0) rotate(280deg); }
    85% { opacity: 0.55; }
    100% { transform: translate3d(26px, 108vh, 0) rotate(560deg); opacity: 0; }
}

/* Cercle d'invocation : deux anneaux qui tournent en sens contraire */
.reveal-cercle {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 168%;
    aspect-ratio: 1;
    translate: -50% -50%;
    border-radius: 9999px;
    border: 2px dashed var(--rarity-anneau);
    opacity: 0;
    transition: opacity 0.7s ease 0.45s;
    animation: reveal-cercle-tourne 26s linear infinite;
    pointer-events: none;
}

.reveal-cercle-inverse {
    width: 132%;
    border-style: dotted;
    border-width: 3px;
    animation-duration: 18s;
    animation-direction: reverse;
}

.reveal-flipped .reveal-cercle {
    opacity: 1;
}

@keyframes reveal-cercle-tourne {
    to { rotate: 360deg; }
}

/* Certains appareils, et certaines personnes, se passent volontiers de
   tout ce mouvement */
@media (prefers-reduced-motion: reduce) {
    .reveal-bulle,
    .reveal-feuille,
    .reveal-brume,
    .reveal-cercle,
    .reveal-rays,
    .reveal-spark,
    .reveal-back {
        animation: none;
    }

    .reveal-bulle,
    .reveal-feuille {
        display: none;
    }
}

/* ------------------------------------------------------------------ */
/* Le programme dessine : un tableau par scene, l'heure en ordonnee,   */
/* les creneaux a leur place et a leur taille.                          */
/*                                                                      */
/* Repris du site du rassemblement, qui dessine deja son programme      */
/* ainsi : le telephone et le site racontent la meme chose, de la meme  */
/* maniere. Les mesures (64 px par heure, adaptees quand les creneaux   */
/* sont courts) vivent dans resources/js/programme.js.                  */
/* ------------------------------------------------------------------ */

.prg-board {
    position: relative;
    overflow: hidden;
    border-radius: 22px;
    background: linear-gradient(160deg, #17224a, #241433);
    box-shadow: 0 10px 24px rgb(0 0 0 / 18%);
}

.prg-head {
    position: relative;
    z-index: 2;
    padding: 20px 16px 4px;
    text-align: center;
}

.prg-head h2 {
    color: #fff;
    font-size: clamp(1.15rem, 5vw, 1.6rem);
    font-weight: 800;
    letter-spacing: 2px;
    line-height: 1.15;
    text-transform: uppercase;
    text-shadow: 0 4px 18px rgb(0 0 0 / 55%);
}

.prg-head p {
    margin-top: 2px;
    color: var(--ygg-accent);
    font-size: .78rem;
    font-weight: 800;
    letter-spacing: 1.5px;
    text-transform: capitalize;
}

.prg-grid {
    position: relative;
    z-index: 2;
    margin: 18px 12px 22px;
}

/* Le trait d'une heure pleine, et sa demie en pointilles */
.prg-hour {
    position: absolute;
    right: 0;
    left: 0;
    border-top: 1px solid rgb(255 255 255 / 35%);
}

.prg-hour.half { border-top: 1px dashed rgb(255 255 255 / 14%); }

.prg-hour b {
    position: absolute;
    top: -11px;
    left: 2px;
    color: #fff;
    font-size: .85rem;
    font-weight: 800;
    text-shadow: 0 2px 8px rgb(0 0 0 / 60%);
}

/* L'heure qu'il est, en travers du tableau */
.prg-now {
    position: absolute;
    right: 0;
    left: 46px;
    z-index: 3;
    border-top: 2px solid var(--ygg-accent);
}

.prg-now span {
    position: absolute;
    top: -9px;
    right: 0;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--ygg-accent);
    color: #1f2937;
    font-size: .62rem;
    font-weight: 800;
    letter-spacing: .5px;
    text-transform: uppercase;
}

/* Un creneau : un BOUTON, a sa place et a sa taille */
.prg-slot {
    position: absolute;
    right: 4px;
    left: 46px;
    display: flex;
    overflow: hidden;
    flex-direction: column;
    justify-content: center;
    padding: 6px 10px;
    border: 1px solid rgb(255 255 255 / 25%);
    border-radius: 12px;
    box-shadow: 0 8px 20px rgb(0 0 0 / 35%);
    color: #fff;
    text-align: center;
}

.prg-slot.prg-en-cours {
    border-color: var(--ygg-accent);
    box-shadow: 0 0 0 2px var(--ygg-accent), 0 8px 20px rgb(0 0 0 / 35%);
}

.prg-slot b {
    display: -webkit-box;
    overflow: hidden;
    font-size: .92rem;
    font-weight: 800;
    letter-spacing: .3px;
    line-height: 1.2;
    text-shadow: 0 2px 8px rgb(0 0 0 / 40%);
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}

.prg-slot small {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .5px;
    opacity: .95;
}

.prg-slot .who {
    overflow: hidden;
    font-size: .76rem;
    font-weight: 700;
    opacity: .95;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.prg-slot .prg-etoile {
    position: absolute;
    top: 3px;
    right: 6px;
    color: var(--ygg-accent);
    font-size: .8rem;
    line-height: 1;
}

/*
 * Creneaux courts : on retire, dans l'ordre, la troupe puis l'HORAIRE.
 * Le titre garde ses deux lignes le plus longtemps possible : c'est la
 * seule chose qu'on cherche, et l'heure se lit de toute facon sur l'axe
 * a gauche, puisque la tuile est a sa place. Seule une tuile vraiment
 * minuscule se rabat sur une ligne.
 */
.prg-slot.prg-moyen { padding: 4px 8px; }
.prg-slot.prg-moyen b { font-size: .84rem; }
.prg-slot.prg-moyen small { font-size: .68rem; }

.prg-slot.prg-etroit { padding: 2px 8px; }
.prg-slot.prg-etroit b { font-size: .8rem; }

.prg-slot.prg-minus {
    flex-direction: row;
    align-items: center;
    justify-content: center;
    padding: 2px 8px;
}

/*
 * La tuile minuscule (26 px) n'a qu'une ligne de haut. Le titre y est
 * donc pose SUR UNE SEULE LIGNE, avec des points de suspension s'il
 * depasse en largeur : un texte qui se renvoie a la ligne s'y faisait
 * rogner par le milieu, ce qui ne se lit pas du tout.
 */
.prg-slot.prg-minus b {
    display: block;
    overflow: hidden;
    flex: 1;
    min-width: 0;
    font-size: .78rem;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ------------------------------------------------------------------ */
/* Remplacement d'une illustration de carte, par glisser-deposer.      */
/*                                                                      */
/* Le visuel lui-meme est la zone de depot : c'est l'endroit ou l'oeil  */
/* va, et pointer une carte precise parmi 120 demande de viser SON      */
/* image, pas une zone commune.                                         */
/* ------------------------------------------------------------------ */

.carte-depot {
    border-radius: 6px;
    outline: 2px dashed transparent;
    outline-offset: 3px;
    transition: outline-color .15s;
}

.carte-depot:hover,
.carte-depot-survol {
    outline-color: var(--ygg-primary);
}

.carte-depot-occupe { opacity: .5; }

.carte-depot-voile {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    background: rgb(255 255 255 / 75%);
    color: var(--ygg-primary);
    font-size: .7rem;
    font-weight: 800;
}
