/*
 * nedvriend.css : identité visuelle Nedvriend
 * Habillage propre à « l'académie des enquêteurs ».
 *
 * Ce fichier :
 *   1. surcharge les tokens sémantiques de main.css avec la palette Nedvriend
 *      (ambiance bureau d'enquête la nuit : ardoise froide, laiton du badge,
 *      kraft des chemises de dossier) ;
 *   2. ajoute les tokens propres à Nedvriend (kraft, encre, statuts) ;
 *   3. définit les composants spécifiques : hero, Ned, bulle-fiche, dossiers
 *      d'affaires, liste des épreuves ;
 *   4. garde la compatibilité avec les classes du squelette (.carte, .pastille,
 *      .feedback, .grille-cartes, formulaires).
 *
 * À charger APRÈS main.css.
 * Ton bienveillant : jamais de rouge agressif dans les feedbacks. Réussi
 * (vert), en chemin (ambre), à découvrir (gris).
 * Nedvriend : Edulutic SRL
 */

/* ===== Surcharge des tokens : thème « bureau d'enquête » ===== */
:root {
    --fond:           #0b1017;
    --surface:        #121a24;
    --surface-2:      #1b2635;
    --voile:          rgba(7, 11, 17, 0.65);
    --texte:          #e8e4d6;
    --texte-doux:     #9aa7b8;
    --accent:         #cfa338;   /* laiton du badge */
    --accent-clair:   #eccc6f;
    --sur-accent:     #0b1017;   /* nuit, posée sur le laiton */
    --bordure:        rgba(255, 255, 255, 0.08);
    --bordure-accent: rgba(207, 163, 56, 0.25);
    --halo-accent:    rgba(207, 163, 56, 0.45);
    --ombre:          rgba(0, 0, 0, 0.5);

    /* Tokens propres à Nedvriend */
    --kraft:      #dcc9a3;   /* chemise de dossier */
    --kraft-doux: #bfa87c;
    --encre:      #2b2416;   /* écriture sur kraft */

    /* Statuts bienveillants (règle du squelette, conservée) */
    --reussi:      #2e9d6e;
    --en-chemin:   #d9a13b;
    --a-decouvrir: #8a93a0;

    /* Couleur d'affaire : l'académie (a00). Les enquêtes suivantes
       ajouteront la leur (a01, a02…) sur le même modèle. */
    --a0: #2d9d78;
}

/* ===== Fond d'ambiance : lampe de bureau sur la nuit ===== */
body {
    background:
        radial-gradient(1100px 560px at 50% -10%, var(--surface-2), transparent 60%),
        linear-gradient(180deg, var(--surface) 0%, var(--fond) 100%);
}

/* ===== En-tête : marque et navigation ===== */
.marque { font-size: 2.2rem; }
.entete__nav { display: inline-flex; gap: 18px; margin-left: auto; align-items: center; flex-wrap: wrap; }
.entete__nav a {
    color: var(--texte-doux);
    text-decoration: none;
    font-size: 0.92rem;
    padding: 7px 14px;
    border: 1px solid transparent;
    border-radius: 999px;
    transition: color 0.15s ease, border-color 0.15s ease;
}
.entete__nav a:hover { color: var(--accent-clair); border-color: var(--bordure-accent); }

/* ===== Hero ===== */
.hero { padding: 40px 0 24px; }
/* La mascotte se CENTRE verticalement sur le bloc de texte : avec les poses
   en buste (2026-07-29), la tête arrive ainsi au niveau de la bulle de
   consigne, quel que soit le format de l'illustration. */
.hero__scene { display: flex; align-items: center; gap: 20px; }
.hero__texte h1 { font-size: 2rem; margin-bottom: 6px; }
.hero__texte .sous-titre { color: var(--texte-doux); }

/* ================= Ned, ton coéquipier d'enquête =================
   Composant <x-ned pose="…" taille="sm|md|lg">, même contrat que le socle.
   Chaque pose porte une micro-animation ; prefers-reduced-motion les
   désactive toutes. */
.ned {
    flex: 0 0 auto;
    position: relative;
    width: clamp(90px, 11vw, 112px);
    filter: drop-shadow(0 0 22px rgba(207, 163, 56, 0.3));
    animation: ned-flotte 5s ease-in-out infinite;
}
.ned svg,
.ned__img { display: block; width: 100%; height: auto; }

/* Badge de repli d'une mascotte sans illustration dédiée (ex. Noor tant
   que ses poses ne sont pas dessinées) : couleur + initiale, jamais le
   visage d'une autre mascotte. */
.ned__img--repli {
    aspect-ratio: 591 / 1181;
    border-radius: 999px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-family: var(--police-titre, serif);
    font-weight: 700;
    font-size: clamp(1.4rem, 6vw, 2.6rem);
}

.ned--sm { width: clamp(48px, 7vw, 64px); }
.ned--md { width: clamp(88px, 11vw, 112px); }
.ned--lg { width: clamp(132px, 20vw, 200px); }

.ned[data-pose="court"]                              { animation: ned-court 2.6s ease-in-out infinite; }
.ned[data-pose="hourra"],
.ned[data-pose="rire"],
.ned[data-pose="fier"]                               { animation: ned-bounce 1.6s ease-in-out infinite; transform-origin: 50% 100%; }
.ned[data-pose="idee"]                               { animation: ned-pulse 2s ease-in-out infinite; }
.ned[data-pose="reflechit"],
.ned[data-pose="question"],
.ned[data-pose="enquete"],
.ned[data-pose="mystere"]                            { animation: ned-balance 4s ease-in-out infinite; transform-origin: 50% 100%; }
.ned[data-pose="crie"],
.ned[data-pose="micro"]                              { animation: ned-shake 0.5s ease-in-out 1; transform-origin: 50% 100%; }

@keyframes ned-flotte {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-8px); }
}
@keyframes ned-court {
    0%, 100% { transform: translateX(-6px); }
    50%      { transform: translateX(6px); }
}
@keyframes ned-bounce {
    0%, 100% { transform: translateY(0); }
    30%      { transform: translateY(-12px); }
    55%      { transform: translateY(0); }
    70%      { transform: translateY(-5px); }
}
@keyframes ned-pulse {
    0%, 100% { transform: scale(1); filter: drop-shadow(0 0 16px rgba(207, 163, 56, 0.28)); }
    50%      { transform: scale(1.045); filter: drop-shadow(0 0 30px rgba(236, 204, 111, 0.55)); }
}
@keyframes ned-balance {
    0%, 100% { transform: rotate(-2.5deg); }
    50%      { transform: rotate(2.5deg); }
}
@keyframes ned-shake {
    0%, 100% { transform: translateX(0); }
    20%      { transform: translateX(-5px); }
    40%      { transform: translateX(5px); }
    60%      { transform: translateX(-3px); }
    80%      { transform: translateX(3px); }
}

/* Bulle compacte rendue PAR le composant : fiche kraft du dossier. */
.ned .ned-bulle {
    margin-top: 10px;
    background: var(--kraft);
    color: var(--encre);
    font-family: var(--serif);
    font-size: 0.98rem;
    line-height: 1.45;
    padding: 12px 14px;
    border-radius: var(--rayon);
    box-shadow: 0 8px 22px var(--ombre);
}

@media (prefers-reduced-motion: reduce) {
    .ned,
    .ned[data-pose] { animation: none !important; }
}

/* Bulle de dialogue : fiche kraft glissée dans le dossier. */
.bulle {
    position: relative;
    margin-top: clamp(8px, 1.5vw, 24px);
    background: var(--kraft);
    color: var(--encre);
    font-family: var(--serif);
    font-size: 1.05rem;
    line-height: 1.5;
    padding: 18px 20px;
    border-radius: var(--rayon);
    box-shadow: 0 10px 30px var(--ombre);
}
.bulle::after {
    content: "";
    position: absolute;
    left: -14px; top: 30px;
    border: 8px solid transparent;
    border-right-color: var(--kraft);
}

/* ===== Dossiers d'affaires (grille des enquêtes) ===== */
.dossiers {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 22px;
}
.dossier {
    --teinte: var(--a0);
    position: relative;
    border-radius: var(--rayon);
    padding: 26px 20px 20px;
    min-height: 190px;
    display: flex;
    flex-direction: column;
    background:
        linear-gradient(160deg, rgba(255, 255, 255, 0.06), rgba(0, 0, 0, 0.18)),
        var(--surface-2);
    border: 1px solid var(--bordure);
    border-left: 5px solid var(--teinte);
    color: var(--texte);
    overflow: hidden;
    transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
/* Onglet de chemise kraft en haut du dossier */
.dossier::before {
    content: "";
    position: absolute;
    top: 0; left: 18px;
    width: 92px; height: 10px;
    border-radius: 0 0 8px 8px;
    background: linear-gradient(180deg, var(--kraft), var(--kraft-doux));
    opacity: 0.85;
}
.dossier__numero {
    font-family: var(--serif);
    font-size: 0.82rem;
    letter-spacing: 0.14em;
    color: var(--teinte);
    text-transform: uppercase;
}
.dossier__titre { font-family: var(--serif); font-size: 1.3rem; margin: 6px 0 2px; }
.dossier__ville { font-size: 0.85rem; color: var(--texte-doux); }
.dossier__etat { margin-top: auto; padding-top: 12px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

/* Tampon d'état posé de biais, façon encre de commissariat */
.tampon {
    display: inline-block;
    font-family: var(--serif);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    padding: 4px 10px;
    border: 2px solid currentColor;
    border-radius: 6px;
    transform: rotate(-4deg);
    opacity: 0.95;
}
.tampon--reussi      { color: var(--reussi); }
.tampon--en-chemin   { color: var(--en-chemin); }
.tampon--a-decouvrir { color: var(--a-decouvrir); transform: rotate(-2deg); }

/* Dossier ACCESSIBLE : lumineux, cliquable, léger flottement */
.dossier--dispo { cursor: pointer; animation: flotte-carte 3.4s ease-in-out infinite; }
@keyframes flotte-carte {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-7px); }
}
.dossier--dispo:hover,
.dossier--dispo:focus-within {
    animation: none;
    transform: translateY(-6px);
    box-shadow: 0 18px 40px rgba(207, 163, 56, 0.22);
    border-color: var(--accent);
}
/* Dossier VERROUILLÉ : grisé, jamais culpabilisant */
.dossier--bloque { filter: grayscale(0.75) brightness(0.72); }
/* Les étapes MISSION de la piste (affaires classées) ont le même rang
   visuel que les dossiers d'enquête (décision Djess 2026-07-31 : « il est
   tout aussi riche ») : seule l'étiquette « Mission » les distingue, et
   elles ne bloquent jamais la suite (règle des classées, inchangée). */

/* ===== Piste d'enquêteur (accueil, 2026-07-24) : chemin d'étapes façon
   Duolingo, sans streak ni classement — juste la progression PERSONNELLE. ===== */
/* Dossiers CÔTE À CÔTE (retour de Djess du 2026-07-24 : le zigzag vertical
   étirait trop la page), reliés par un trait horizontal ; retour à la
   ligne naturel sur petit écran. */
.piste { display: flex; flex-wrap: wrap; align-items: center; padding: 16px 0 8px; }
.piste__lien {
    flex: 0 0 auto;
    width: 56px;
    height: 4px;
    background: linear-gradient(90deg, var(--bordure-accent), transparent);
}
.piste__etape {
    display: flex;
    width: min(300px, 100%);
    margin: 14px 0;
}
/* Les étapes de la piste réutilisent le composant .dossier tel quel
   (ce sont des affaires). */
.piste__dossier { width: 100%; margin: 0; }

/* Collection de badges d'enquêteur : personnelle, jamais comparée. */
.badges-collection { display: flex; flex-wrap: wrap; gap: 10px; }
.badge-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid var(--bordure-accent);
    background: rgba(207, 163, 56, 0.08);
    font-size: 0.9rem;
}
.badge-chip__emoji { font-size: 1.25rem; }

/* Badges PAS ENCORE gagnés : discrets, avec leur barre de progression. */
.badge-chip--attente {
    opacity: 0.85;
    border-style: dashed;
    background: rgba(255, 255, 255, 0.03);
}
.badge-chip__barre {
    display: block;
    width: min(120px, 40vw);
    height: 6px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.1);
    overflow: hidden;
    margin-top: 3px;
}
.badge-chip__remplissage {
    display: block;
    height: 100%;
    background: linear-gradient(90deg, var(--accent), var(--accent-clair));
}

/* ===== Mot cliquable pendant une lecture (2026-07-24, inspiré de
   WonderLang) : la traduction se lit au clic/focus, aucun JS. ===== */
.mot-annote {
    background: none;
    border: none;
    font: inherit;
    color: inherit;
    padding: 0;
    cursor: pointer;
    text-decoration: underline dotted;
    text-underline-offset: 3px;
    position: relative;
}
.mot-annote:hover, .mot-annote:focus { color: var(--accent-clair); }
.mot-annote:focus::after {
    content: attr(data-traduction);
    position: absolute;
    left: 50%;
    bottom: 100%;
    transform: translateX(-50%);
    margin-bottom: 6px;
    padding: 4px 10px;
    border-radius: 8px;
    background: var(--surface-2);
    border: 1px solid var(--bordure-accent);
    color: var(--texte);
    font-size: 0.82rem;
    white-space: nowrap;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
    z-index: 5;
}

/* ===== Mini-dossiers de la salle d'entraînement ===== */
/* Un module d'entraînement groupé par affaire (2026-07-24) : même motif de
   chemise kraft que .dossier, mais un CONTENEUR (pas une carte cliquable),
   pour que le lien avec l'affaire saute aux yeux sans se perdre dans le
   texte discret d'un simple <h3>. */
.mini-dossier {
    position: relative;
    border-radius: var(--rayon);
    padding: 24px 20px 20px;
    margin: 24px 0;
    background:
        linear-gradient(160deg, rgba(255, 255, 255, 0.045), rgba(0, 0, 0, 0.16)),
        var(--surface-2);
    border: 1px solid var(--bordure);
    border-left: 5px solid var(--bordure-accent);
    overflow: hidden;
}
.mini-dossier::before {
    content: "";
    position: absolute;
    top: 0; left: 18px;
    width: 92px; height: 10px;
    border-radius: 0 0 8px 8px;
    background: linear-gradient(180deg, var(--kraft), var(--kraft-doux));
    opacity: 0.85;
}
.mini-dossier--necessaire { border-left-color: var(--accent); }
.mini-dossier__entete {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin: 6px 0 16px;
    font-family: var(--serif);
    font-size: 1.15rem;
}
.mini-dossier--necessaire .mini-dossier__entete { color: var(--accent-clair); }
.mini-dossier .grille-cartes { margin: 0; }

/* Entonnoir de la salle d'entraînement (2026-07-24) : niveau 1, une
   affaire = un .dossier cliquable (bouton, pas un lien). */
.entonnoir__affaire {
    font: inherit;
    text-align: left;
    cursor: pointer;
    width: 100%;
}
.entonnoir__affaire--ouverte {
    border-color: var(--accent);
    box-shadow: 0 18px 40px rgba(207, 163, 56, 0.22);
}

/* ===== Liste des épreuves d'une affaire ===== */
.epreuves { list-style: none; display: flex; flex-direction: column; gap: 8px; }
.epreuve {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 10px 14px;
    border-radius: 12px;
    border: 1px solid var(--bordure);
    background: rgba(255, 255, 255, 0.03);
    transition: border-color 0.15s ease, background 0.15s ease;
}
.epreuve--active {
    border-color: var(--bordure-accent);
    background: linear-gradient(160deg, rgba(207, 163, 56, 0.10), rgba(0, 0, 0, 0.1));
}
.epreuve__numero {
    flex: 0 0 auto;
    width: 34px; height: 34px;
    border-radius: 50%;
    display: grid; place-items: center;
    font-family: var(--serif); font-weight: 700;
    background: rgba(255, 255, 255, 0.06);
    color: var(--texte-doux);
    border: 1px solid var(--bordure);
}
.epreuve--active .epreuve__numero {
    background: linear-gradient(160deg, var(--accent-clair), var(--accent));
    color: var(--sur-accent);
    border-color: transparent;
    box-shadow: 0 0 14px var(--halo-accent);
}
.epreuve--faite .epreuve__numero {
    background: rgba(46, 157, 110, 0.18);
    color: var(--reussi);
    border-color: rgba(46, 157, 110, 0.4);
}
.epreuve__bouton {
    flex: 1 1 auto;
    text-align: left;
    background: none; border: none; cursor: pointer;
    color: var(--texte);
    font-size: 0.98rem;
    font-family: var(--sans);
    padding: 4px 0;
}
.epreuve__bouton:hover { color: var(--accent-clair); }
.epreuve__palier {
    font-family: var(--serif);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-size: 0.8rem;
    color: var(--texte-doux);
    margin: 14px 0 6px;
}

/* ===== Progression (dossier et épreuves) : toujours visible ===== */
.progression {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 12px 0 4px;
    max-width: 560px;
}
.progression__barre {
    flex: 1 1 auto;
    height: 12px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid var(--bordure-accent);
    overflow: hidden;
}
.progression__remplissage {
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--accent), var(--accent-clair));
    box-shadow: 0 0 12px var(--halo-accent);
    transition: width 0.5s ease;
}
.progression__texte {
    flex: 0 0 auto;
    font-family: var(--serif);
    font-size: 0.9rem;
    color: var(--accent-clair);
    white-space: nowrap;
}
.progression--etapes { margin-bottom: 14px; }

/* ===== Memory des nombres (chambre des souvenirs) ===== */
.memoire-vies { font-size: 1.3rem; letter-spacing: 6px; margin: 10px 0 16px; }
.memoire-grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
    gap: 12px;
    margin: 16px 0;
}
.memoire-carte {
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px;
    border-radius: 10px;
    border: 1px solid var(--bordure);
    background: linear-gradient(160deg, var(--kraft), var(--kraft-doux));
    color: var(--encre);
    font-family: var(--serif);
    font-size: 0.95rem;
    line-height: 1.1;
    font-weight: 700;
    text-align: center;
    cursor: pointer;
    /* Les mots néerlandais des nombres peuvent être longs
       (« zevenennegentig ») : jamais de débordement hors de la tuile. */
    overflow: hidden;
    overflow-wrap: break-word;
    hyphens: auto;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.memoire-carte:hover:not(:disabled) { transform: translateY(-3px); box-shadow: 0 10px 20px rgba(0, 0, 0, 0.25); }
.memoire-carte--retournee { background: var(--surface-2); color: var(--texte); border-color: var(--accent); }
.memoire-carte--trouvee {
    background: rgba(46, 157, 110, 0.16);
    color: #7fe0bd;
    border-color: var(--reussi);
    cursor: default;
}
.memoire-carte:disabled { cursor: default; }

/* ===== Le mot mystère (pendu) : pas de pendaison dessinée (univers
   bienveillant, CLAUDE.md § IDENTITÉ DU PRODUIT) — les essais restants se
   lisent en loupes 🔍 qui s'éteignent, pas en gibet. ===== */
.mot-mystere {
    font-family: var(--serif);
    font-size: 2rem;
    letter-spacing: 0.35em;
    text-align: center;
    margin: 18px 0;
    color: var(--accent-clair);
}
.clavier-pendu { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
/* Chaque lettre est PARFAITEMENT centrée dans son cercle : bouton carré,
   centrage flex sur les deux axes, ligne compacte (Djess 2026-07-26). */
.clavier-pendu .bouton {
    width: 44px;
    height: 44px;
    min-width: 44px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}
.clavier-pendu .bouton:disabled { opacity: 0.35; cursor: default; }

/* Fil d'Ariane au-dessus de l'épreuve */
.fil-ariane { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 4px 0 2px; }
.lien-discret {
    background: none; border: none; cursor: pointer;
    color: var(--accent-clair);
    font: inherit; font-size: 0.92rem;
    padding: 4px 0;
}
.lien-discret:hover { text-decoration: underline; }

/* Navigation d'étapes (précédent / suivant) */
.nav-etapes {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    margin-top: 16px;
}
.nav-etapes .bouton[disabled] { opacity: 0.35; cursor: not-allowed; transform: none; }

/* Sous-dossier cliquable (bouton stylé en dossier) */
button.sous-dossier { font: inherit; text-align: left; }

/* Réplique : locuteur et lecteur sur une même ligne */
.replique { display: flex; align-items: center; gap: 12px; margin: 8px 0; }
.replique strong { flex: 0 0 90px; }
.replique audio { height: 40px; }

/* ===== Scène en bulles de chat (2026-07-24, inspiré de Night Zookeeper) :
   une réplique = un message, le côté alterne à chaque changement de
   locuteur, comme une vraie conversation plutôt qu'une liste de lignes.
   Avatar en badge de repli (couleur dérivée du nom + initiale) tant
   qu'aucun portrait illustré n'existe pour ce personnage — même logique
   que <x-ned>, jamais un visage générique unique pour tout le monde. ===== */
/* Colonne de conversation RESSERRÉE (retour de Djess du 2026-07-24 : les
   bulles collées aux deux bords d'une carte large, « trop excentré ») :
   la scène garde une largeur de fil de discussion, l'alternance
   gauche/droite reste lisible sans grand vide au milieu. */
.chat-scene {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 12px 0;
    max-width: 560px;
}
.chat-ligne { display: flex; align-items: flex-end; gap: 10px; max-width: 92%; }
.chat-ligne--gauche { align-self: flex-start; }
.chat-ligne--droite { align-self: flex-end; flex-direction: row-reverse; }
.chat-avatar {
    flex: 0 0 auto;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--serif);
    font-weight: 700;
    font-size: 0.9rem;
    color: #fff;
    border: 2px solid var(--bordure-accent);
}
.chat-avatar--portrait { overflow: hidden; background: var(--surface-2); }
.chat-avatar--portrait img { width: 100%; height: 100%; object-fit: cover; display: block; }
.chat-bulle {
    /* min-width : sans lui, une bulle sans texte long (juste un lecteur
       audio) rétrécit au contenu le plus étroit et le lecteur natif se
       tronque (barre de progression invisible, juste ▬ ⋮). */
    min-width: min(240px, 100%);
    max-width: 100%;
    padding: 10px 14px;
    border-radius: 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: var(--surface-2);
    border: 1px solid var(--bordure);
}
.chat-ligne--gauche .chat-bulle { border-bottom-left-radius: 4px; }
.chat-ligne--droite .chat-bulle {
    border-bottom-right-radius: 4px;
    background: linear-gradient(160deg, rgba(207, 163, 56, 0.12), var(--surface-2));
    border-color: var(--bordure-accent);
}
.chat-bulle__locuteur {
    font-family: var(--serif);
    font-size: 0.78rem;
    color: var(--accent-clair);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.chat-bulle audio { height: 38px; width: 100%; }
.chat-bulle__traduction { font-size: 0.85rem; }

/* ===== Vignettes d'activité façon épisode (2026-07-24, inspiré de Night
   Zookeeper) : un bandeau « affiche » en tête de carte, en attendant une
   vraie illustration — juste l'emoji existant mis en scène, rien de neuf
   à produire. ===== */
.vignette { padding-top: 0; overflow: hidden; }
/* ===== La filature (2026-07-24) : reskin non-violent d'un « combat »
   façon WonderLang — une course-poursuite, jamais une attaque. ===== */
.filature { margin: 8px 0 16px; }
/* L'avatar de grade de l'élève en poursuivant (à la place de l'emoji). */
.filature__avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--accent);
    background: var(--surface-2);
    display: block;
}
.filature__piste {
    position: relative;
    height: 48px;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--surface-2), var(--surface));
    border: 1px solid var(--bordure);
    margin-bottom: 6px;
    overflow: hidden;
}
.filature__poursuivant {
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    font-size: 1.7rem;
    transition: left 0.4s ease;
}
.filature__suspect {
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 1.7rem;
}

.vignette__art {
    width: calc(100% + 40px);
    margin: 0 -20px 14px;
    aspect-ratio: 16 / 9;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2.6rem;
    background:
        radial-gradient(circle at 50% 42%, rgba(207, 163, 56, 0.35), transparent 70%),
        linear-gradient(160deg, var(--surface-2), var(--fond));
    border-bottom: 1px solid var(--bordure-accent);
    overflow: hidden;
}
/* Illustration du poste (déposée par Djess) : remplit le bandeau, l'emoji
   en repli garde le fond dégradé. */
.vignette__art img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Remise en ordre : la phrase en construction */
.construction-phrase {
    min-height: 52px;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 12px 16px;
    margin: 10px 0;
    border: 1px dashed var(--bordure-accent);
    border-radius: 12px;
    font-family: var(--serif);
    font-size: 1.15rem;
    background: rgba(255, 255, 255, 0.03);
}

/* Choix de paire (discrimination) : deux grands mots cliquables */
.paire-choix { display: flex; justify-content: center; gap: 16px; margin: 14px 0; flex-wrap: wrap; }
.paire-choix__mot {
    display: inline-flex; align-items: center; gap: 8px;
    font-family: var(--serif); font-size: 1.3rem;
    padding: 14px 26px;
    border-radius: 14px;
    border: 1px solid var(--bordure);
    background: rgba(255, 255, 255, 0.04);
    cursor: pointer;
    margin: 0;
    transition: border-color 0.15s ease, background 0.15s ease;
}
.paire-choix__mot:hover { border-color: var(--bordure-accent); }
.paire-choix__mot--choisi {
    border-color: var(--accent);
    background: rgba(207, 163, 56, 0.12);
    box-shadow: 0 0 12px rgba(207, 163, 56, 0.2);
}
.paire-choix__mot input { width: auto; }

/* ===== Flashcards (salle d'entraînement) ===== */
.flashcard {
    max-width: 460px;
    margin: 16px auto;
    padding: 34px 26px;
    text-align: center;
    border-radius: 18px;
    border: 1px solid var(--bordure-accent);
    background:
        radial-gradient(240px 120px at 50% 0%, rgba(207, 163, 56, 0.10), transparent),
        var(--surface-2);
    box-shadow: 0 14px 40px var(--ombre);
}
.flashcard__mot { font-family: var(--serif); font-size: 1.7rem; margin-bottom: 12px; }
.flashcard__traduction { font-family: var(--serif); font-size: 1.6rem; color: var(--kraft); margin-bottom: 12px; }
.flashcard__boutons { display: flex; justify-content: center; gap: 14px; margin-top: 6px; flex-wrap: wrap; }
.flashcard audio { height: 38px; max-width: 100%; }

/* Carte à deux faces (2026-07-24, demande de Djess : « il faut qu'elles se
   retournent vraiment ») : vraie rotation 3D en CSS, déclenchée par le
   basculement de classe au rendu Livewire (l'état reste côté serveur).
   Les deux faces s'empilent sur la même cellule de grille (hauteur = la
   plus grande), la face cachée est ignorée des clics. */
.flashcard-flip { perspective: 1100px; max-width: 460px; margin: 16px auto; }
.flashcard-flip__inner {
    display: grid;
    transform-style: preserve-3d;
    transition: transform 0.55s ease;
}
.flashcard-flip__inner--retournee { transform: rotateY(180deg); }
.flashcard-flip__face {
    grid-area: 1 / 1;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    margin: 0;
    max-width: none;
    pointer-events: none;
}
.flashcard-flip__face--dos { transform: rotateY(180deg); }
.flashcard-flip__inner:not(.flashcard-flip__inner--retournee) > .flashcard-flip__face:not(.flashcard-flip__face--dos),
.flashcard-flip__inner--retournee > .flashcard-flip__face--dos { pointer-events: auto; }
/* Confort : la rotation se coupe pour qui préfère éviter les animations. */
@media (prefers-reduced-motion: reduce) {
    .flashcard-flip__inner { transition: none; }
}

/* Filtre des jeux par dossier */
.filtre-dossiers { display: flex; gap: 10px; flex-wrap: wrap; margin: 10px 0 16px; }
.filtre-dossiers .pastille { cursor: pointer; font: inherit; font-size: 0.85rem; }

/* ===== Volet latéral « Relire les fiches » ===== */
.volet {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: min(420px, 92vw);
    z-index: 50;
    display: flex;
    flex-direction: column;
    background:
        linear-gradient(160deg, rgba(255, 255, 255, 0.04), rgba(0, 0, 0, 0.2)),
        var(--surface-2);
    border-left: 1px solid var(--bordure-accent);
    box-shadow: -18px 0 50px var(--ombre);
    animation: volet-glisse 0.25s ease-out;
}
@keyframes volet-glisse {
    from { transform: translateX(40px); opacity: 0; }
    to   { transform: translateX(0); opacity: 1; }
}
.volet__entete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 18px 10px;
    border-bottom: 1px solid var(--bordure);
}
.volet__entete h3 { color: var(--accent-clair); font-size: 1.1rem; }
.volet__fermer {
    background: none;
    border: 1px solid var(--bordure);
    border-radius: 50%;
    width: 34px; height: 34px;
    color: var(--texte-doux);
    font-size: 1rem;
    cursor: pointer;
}
.volet__fermer:hover { color: var(--accent-clair); border-color: var(--bordure-accent); }
.volet__corps {
    overflow-y: auto;
    padding: 14px 18px 24px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.volet .bulle::after { display: none; }

/* ===== Le badge d'enquêteur (remise au serment) ===== */
.badge-carte { border-color: var(--bordure-accent); text-align: center; }
.badge-visuel {
    display: inline-flex;
    flex-direction: column;
    gap: 4px;
    margin: 14px auto;
    padding: 22px 30px;
    border-radius: 16px;
    border: 2px solid var(--accent);
    background:
        radial-gradient(120px 60px at 50% 0%, rgba(236, 204, 111, 0.18), transparent),
        var(--surface-2);
    box-shadow: 0 0 30px var(--halo-accent);
    animation: badge-remise 0.9s ease-out;
}
@keyframes badge-remise {
    0%   { transform: scale(0.6) rotate(-6deg); opacity: 0; }
    60%  { transform: scale(1.06) rotate(1.5deg); }
    100% { transform: scale(1) rotate(0); opacity: 1; }
}
.badge-visuel__numero { font-family: var(--serif); letter-spacing: 0.2em; color: var(--accent-clair); font-size: 0.85rem; }
.badge-visuel__nom { font-family: var(--serif); font-size: 1.5rem; }
.badge-visuel__schuilnaam { color: var(--texte-doux); font-style: italic; }
.badge-visuel__grade { margin-top: 6px; color: var(--accent-clair); font-size: 0.9rem; letter-spacing: 0.08em; text-transform: uppercase; }

/* Bouton dictaphone en cours d'enregistrement */
.dictaphone--actif { box-shadow: 0 0 0 4px rgba(217, 74, 59, 0.4); animation: dictaphone-pulse 1.2s ease-in-out infinite; }
@keyframes dictaphone-pulse { 0%, 100% { box-shadow: 0 0 0 4px rgba(217, 74, 59, 0.4); } 50% { box-shadow: 0 0 0 8px rgba(217, 74, 59, 0.18); } }
@media (prefers-reduced-motion: reduce) { .dictaphone--actif { animation: none; } }

/* ===== Compatibilité avec le squelette existant ===== */
.contenu { width: 100%; max-width: var(--max); margin: 0 auto; padding: 8px 20px 30px; }

.carte {
    background:
        linear-gradient(160deg, rgba(255, 255, 255, 0.04), rgba(0, 0, 0, 0.12)),
        var(--surface);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    padding: 18px 20px;
    margin: 14px 0;
}
.grille-cartes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.grille-cartes .carte { margin: 0; }

/* ===== Aération générale (Djess 2026-07-26 : « l'app doit être aérée ») =====
   Le reset global `* { margin: 0 }` colle les cartes à leur titre. On rend
   aux titres de CONTENU (hors cartes) l'air qui manque, et on décolle les
   grilles de cartes/dossiers de ce qui les précède. */
.contenu h1 { margin-bottom: 16px; }
.contenu h2 { margin: 30px 0 16px; }
.contenu h3 { margin: 22px 0 12px; }
.contenu > h1:first-child,
.contenu > h2:first-child { margin-top: 0; }
/* Dans une carte, titres et sous-titres respirent AUSSI (retour Djess
   2026-08-06) ; seul le titre qui OUVRE la carte reste collé en haut. */
.contenu .carte h2 { margin: 26px 0 12px; }
.contenu .carte h3 { margin: 24px 0 10px; }
.contenu .carte h4 { margin: 18px 0 8px; }
.contenu .carte > h2:first-child,
.contenu .carte > h3:first-child,
.contenu .carte > h4:first-child { margin-top: 0; }
/* Le reset global `* { margin: 0 }` collait aussi les paragraphes (lignes
   de pastilles, textes d'aide) à ce qui les entoure. */
.contenu .carte p { margin: 10px 0; }
.grille-cartes,
.dossiers { margin-top: 12px; margin-bottom: 22px; }

.discret { color: var(--texte-doux); font-size: 0.92rem; }

.pastille {
    display: inline-block;
    font-size: 0.78rem;
    letter-spacing: 0.06em;
    padding: 3px 10px;
    border-radius: 999px;
    border: 1px solid currentColor;
    /* Couleur par défaut : sans elle, un <button class="pastille"> hérite
       de la couleur de texte système du navigateur (souvent noire) au lieu
       du thème sombre — illisible sur le fond de la salle d'entraînement
       (filtre par dossier, .filtre-dossiers). */
    color: var(--texte-doux);
    background: none;
}
.pastille.reussi      { color: #7fe0bd; background: rgba(46, 157, 110, 0.14); }
.pastille.en-chemin   { color: #ecc86f; background: rgba(217, 161, 59, 0.12); }
.pastille.a-decouvrir { color: var(--a-decouvrir); background: rgba(138, 147, 160, 0.12); }

/* Feedback bienveillant : ambre doux par défaut, vert quand c'est réussi. */
.feedback {
    margin-top: 14px;
    padding: 14px 16px;
    border-radius: 12px;
    background: rgba(217, 161, 59, 0.10);
    border: 1px solid rgba(217, 161, 59, 0.35);
    color: var(--texte);
}
.feedback.positif {
    background: rgba(46, 157, 110, 0.12);
    border-color: rgba(46, 157, 110, 0.4);
}

/* Bouton secondaire : contour discret sur la nuit. */
.bouton.secondaire {
    background: transparent;
    color: var(--accent-clair);
    border: 1px solid var(--bordure-accent);
    box-shadow: none;
}
.bouton.secondaire:hover { border-color: var(--accent); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3); }

/* Formulaires sur fond nuit */
label { display: block; margin: 10px 0 4px; color: var(--texte-doux); font-size: 0.92rem; }
input, textarea, select {
    width: 100%;
    max-width: 420px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid var(--bordure);
    background: rgba(255, 255, 255, 0.05);
    color: var(--texte);
    font: inherit;
}
textarea { max-width: 100%; min-height: 130px; }
input:focus, textarea:focus, select:focus {
    outline: none;
    border-color: var(--bordure-accent);
    box-shadow: 0 0 0 3px rgba(207, 163, 56, 0.15);
}

/* ===== Séquence pédagogique des modules d'entraînement (2026-07-24) :
   découverte -> quiz -> écoute -> pendu (vocabulaire), synthèse -> simple
   -> complexe (grammaire). ===== */
.sequence-etapes {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 10px 0 18px;
}
.sequence-etapes__etape {
    padding: 5px 12px;
    border-radius: 999px;
    border: 1px solid var(--bordure);
    color: var(--texte-doux);
    font-size: 0.82rem;
    white-space: nowrap;
}
.sequence-etapes__etape--faite {
    border-color: var(--reussi);
    color: #7fe0bd;
}
.sequence-etapes__etape--active {
    border-color: var(--accent);
    background: rgba(207, 163, 56, 0.12);
    color: var(--accent-clair);
    font-weight: 700;
}

/* Découverte : réutilise .flashcard (jeu « Flashcards », même identité
   visuelle) — recto NL, verso FR, révélé au clic. */

/* QCM séquentiel (écoute, exercice complexe) : boutons regroupés SERRÉS
   contre le libellé (accessibilité dys, CLAUDE.md, retour de Djess sur
   « les boutons trop loin des mots »). */
.qcm-choix {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 14px 0 4px;
}
.qcm-choix .bouton { min-width: 90px; }

/* Synthèse de grammaire mise en scène « rapport d'enquête » (police,
   dossier officiel) : contenu rédigé par Claude, mis en page par Djess. */
.rapport-enquete {
    max-width: 720px;
    margin: 16px 0;
    padding: 22px 24px;
    border-radius: 14px;
    border: 1px solid var(--bordure-accent);
    background: linear-gradient(180deg, var(--surface-2), var(--surface));
}
.rapport-enquete__tampon {
    display: inline-block;
    margin: 0 0 16px;
    padding: 4px 14px;
    border: 2px solid var(--accent);
    border-radius: 6px;
    color: var(--accent-clair);
    font-family: var(--serif);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.85rem;
    transform: rotate(-2deg);
}
.rapport-enquete__bloc { margin-bottom: 20px; }
.rapport-enquete__bloc h2 { font-size: 1.05rem; margin-bottom: 8px; }
.rapport-enquete__tableau-scroll { overflow-x: auto; }
.rapport-enquete__tableau {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.92rem;
}
.rapport-enquete__tableau th, .rapport-enquete__tableau td {
    padding: 8px 10px;
    border-bottom: 1px solid var(--bordure);
    text-align: left;
    white-space: nowrap;
}
.rapport-enquete__tableau th { color: var(--texte-doux); font-weight: 600; }
.rapport-enquete__exemples { list-style: none; padding: 0; margin: 0; }
.rapport-enquete__exemples li { margin: 8px 0; }
fieldset { border: 1px solid var(--bordure); border-radius: 12px; padding: 12px 16px; margin: 10px 0; }
legend { padding: 0 8px; color: var(--texte); }
fieldset label { margin: 6px 0; color: var(--texte); }
audio { max-width: 100%; }

/* Case à cocher/bouton radio : jamais étirée à 100 % (elle héritait de la
   règle générale des champs texte, ce qui l'affichait comme une longue
   barre vide au lieu d'un simple rond) ; son étiquette reste collée
   juste à côté, jamais loin dans un flux séparé — repéré via une capture
   montrant des options illisibles pour un enfant dys. */
input[type="radio"], input[type="checkbox"] { width: auto; max-width: none; }
label:has(> input[type="radio"]), label:has(> input[type="checkbox"]) {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* ===== Responsive ===== */
@media (max-width: 860px) {
    .dossiers, .grille-cartes { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
    .dossiers, .grille-cartes { grid-template-columns: 1fr; }
    .hero__scene { flex-direction: column; align-items: center; text-align: center; }
    .bulle::after { display: none; }
}

/* ===== Épreuve 4 : fiches du dossier ===== */
/* Téléphone lisible sur la fiche beige (le .discret clair ne l'était pas). */
.bulle .fiche-tel { color: #4a3113; font-weight: 600; margin-bottom: 0; }
/* Fiche cliquable (sélection des recrues arrivées en retard). */
button.fiche-cliquable { display: block; width: 100%; text-align: left; font: inherit; cursor: pointer; border: 2px solid transparent; }
button.fiche-cliquable:hover { border-color: rgba(184, 134, 11, .5); }
.fiche-choisie { border-color: #b8860b !important; box-shadow: 0 0 0 3px rgba(184, 134, 11, .35); }

/* Les options des menus deroulants s'affichent sur le panneau BLANC natif
   du navigateur : texte sombre force, sinon illisible. */
select option { color: #1c2431; background-color: #ffffff; }

/* Epreuves listees dans les sous-dossiers du sommaire (relecture libre). */
.sous-dossier__epreuves { list-style: none; margin: 10px 0 0; padding: 0; text-align: left; width: 100%; }
.sous-dossier__epreuves li { margin: 4px 0; }

/* ===== Stand de l'academie : celebration et defi du jour ===== */
.tampon-goedzo {
    display: inline-block; font-weight: 800; font-size: 1.5rem; letter-spacing: 1px;
    color: #3fae6a; border: 3px solid #3fae6a; border-radius: 10px; padding: 4px 16px;
    transform: rotate(-6deg); animation: tampon-pop .4s ease-out;
}
@keyframes tampon-pop {
    0% { transform: scale(2.2) rotate(-6deg); opacity: 0; }
    70% { transform: scale(.95) rotate(-6deg); opacity: 1; }
    100% { transform: scale(1) rotate(-6deg); }
}
@media (prefers-reduced-motion: reduce) {
    .tampon-goedzo { animation: none; }
}

/* ===== Rapport de mission (2026-07-24, fin de partie façon jeu vidéo) :
   la fin d'une partie est un rapport officiel, tamponné, avec le compteur
   d'XP animé (effets.js) et le prochain insigne en ligne de mire. ===== */
.rapport-mission {
    margin: 14px 0;
    padding: 20px 22px;
    border-radius: 14px;
    border: 1px solid var(--bordure-accent);
    background: linear-gradient(180deg, var(--surface-2), var(--surface));
}
.rapport-mission--sans-faute {
    border-color: var(--reussi);
    box-shadow: 0 0 24px rgba(46, 157, 110, 0.18);
}
.rapport-mission__entete {
    font-family: var(--serif);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.85rem;
    color: var(--texte-doux);
    margin-bottom: 10px;
}
.rapport-mission__score { font-size: 1.15rem; }
/* KLAAR ! (mission accomplie sans le sans-faute) : ambre, jamais un rouge
   d'échec — on ne perd jamais rien. */
.rapport-mission:not(.rapport-mission--sans-faute) .tampon-goedzo {
    color: var(--en-chemin);
    border-color: var(--en-chemin);
}
.rapport-mission__suivant {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px dashed var(--bordure);
}

/* ===== La salle des pièces à conviction : vitrine personnelle. Les
   pièces manquantes restent en silhouette « ? » avec leur indice — une
   piste, jamais un manque reproché. ===== */
.vitrine {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 14px;
    margin: 18px 0;
}
.vitrine__piece {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 18px 12px 14px;
    border-radius: 14px;
    border: 1px solid var(--bordure-accent);
    background:
        linear-gradient(180deg, rgba(207, 163, 56, 0.07), transparent 55%),
        var(--surface-2);
    text-align: center;
}
.vitrine__piece--manquante {
    border-style: dashed;
    border-color: var(--bordure);
    filter: saturate(0.4);
}
.vitrine__objet {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--bordure);
    font-size: 2.1rem;
    font-family: var(--serif);
    color: var(--texte-doux);
    overflow: hidden;
}
.vitrine__objet img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vitrine__nom { font-family: var(--serif); font-size: 0.95rem; }
.vitrine__indice { font-size: 0.8rem; }

/* ===== De achtervolging : le mini-jeu « vidéo » du stand (2026-07-24).
   Couloir de l'école en dégradés (les illustrations de Djess pourront
   remplacer le décor), trois portes-mots, l'avatar de l'élève qui court.
   AUCUN chrono : le décor ne défile qu'entre deux vagues, la scène
   attend le choix. ===== */
.arcade {
    position: relative;
    height: clamp(280px, 46vw, 380px);
    border-radius: 16px;
    overflow: hidden;
    border: 1px solid var(--bordure-accent);
    background: linear-gradient(180deg, #1c2a3d 0%, #16202e 55%, #10161f 100%);
    margin: 10px 0 6px;
}
.arcade__decor {
    position: absolute;
    inset: 0 0 22%;
    background:
        repeating-linear-gradient(90deg,
            transparent 0 120px, rgba(207, 163, 56, 0.10) 120px 126px,
            transparent 126px 250px),
        repeating-linear-gradient(90deg,
            transparent 0 56px, rgba(255, 255, 255, 0.035) 56px 58px,
            transparent 58px 110px);
}
.arcade__sol {
    position: absolute;
    inset: 78% 0 0;
    background:
        repeating-linear-gradient(90deg,
            rgba(255, 255, 255, 0.05) 0 44px, transparent 44px 88px),
        linear-gradient(180deg, #2a2317, #1a150d);
}
/* Défilement bref entre deux vagues (jamais pendant le choix). */
.arcade--defile .arcade__decor { animation: arcade-defile 0.7s linear; }
.arcade--defile .arcade__sol { animation: arcade-defile-sol 0.7s linear; }
@keyframes arcade-defile { from { background-position-x: 0, 0; } to { background-position-x: -250px, -110px; } }
@keyframes arcade-defile-sol { from { background-position-x: 0; } to { background-position-x: -88px; } }

.arcade__consigne {
    position: relative;
    z-index: 2;
    text-align: center;
    margin: 14px auto 0;
    padding: 6px 16px;
    width: fit-content;
    max-width: 90%;
    border-radius: 999px;
    background: rgba(11, 16, 23, 0.8);
    border: 1px solid var(--bordure-accent);
    color: var(--accent-clair);
}
.arcade__portes {
    position: absolute;
    z-index: 2;
    left: 0;
    right: 0;
    top: 26%;
    /* Trois colonnes ÉGALES, porte centrée dans sa colonne : les centres
       tombent exactement sur 1/6, 1/2, 5/6 de la largeur, quelle que soit la
       largeur des portes — l'avatar s'y aligne pile (Djess 2026-07-26). */
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    justify-items: center;
    align-items: end;
}
.arcade__porte {
    position: relative;
    width: clamp(84px, 14vw, 120px);
    height: clamp(120px, 20vw, 170px);
    border: 2px solid var(--kraft-doux);
    border-bottom: none;
    border-radius: 10px 10px 0 0;
    background: linear-gradient(160deg, var(--kraft), var(--kraft-doux));
    color: var(--encre);
    font-family: var(--serif);
    font-weight: 700;
    font-size: clamp(0.85rem, 1.8vw, 1.05rem);
    cursor: pointer;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 12px 6px 0;
    overflow: hidden;
    overflow-wrap: break-word;
    transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}
.arcade__porte-battant {
    position: absolute;
    inset: 34% 18% 0;
    border-radius: 6px 6px 0 0;
    background: linear-gradient(160deg, #7a5c33, #5d4526);
    border: 1px solid rgba(0, 0, 0, 0.25);
}
.arcade__porte-mot { position: relative; z-index: 1; }
.arcade__porte:hover,
.arcade__porte--visee {
    transform: translateY(-4px);
    border-color: var(--accent);
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.35), 0 0 14px var(--halo-accent);
}
.arcade__avatar {
    position: absolute;
    z-index: 3;
    bottom: 4%;
    left: 50%;
    transform: translateX(-50%);
    font-size: 2.2rem;
    transition: left 0.25s ease;
}
.arcade__avatar img {
    height: clamp(64px, 11vw, 92px);
    width: auto;
    display: block;
    filter: drop-shadow(0 6px 8px rgba(0, 0, 0, 0.45));
}
/* Position de l'avatar selon la voie visée (flèches ← →) : alignée sur les
   centres des trois colonnes de portes (1/6, 1/2, 5/6). */
.arcade--voie-0 .arcade__avatar { left: 16.666%; }
.arcade--voie-1 .arcade__avatar { left: 50%; }
.arcade--voie-2 .arcade__avatar { left: 83.333%; }
/* Course (bonne porte) et trébuchement cartoon (mauvaise) : jamais une
   chute dramatique, on se rattrape toujours. */
.arcade__avatar--course { animation: arcade-course 0.7s ease; }
.arcade__avatar--trebuche { animation: arcade-trebuche 0.7s ease; }
@keyframes arcade-course {
    0% { bottom: 4%; }
    40% { bottom: 30%; opacity: 1; }
    70% { bottom: 44%; opacity: 0; }
    100% { bottom: 4%; opacity: 1; }
}
@keyframes arcade-trebuche {
    0%, 100% { transform: translateX(-50%) rotate(0); }
    25% { transform: translateX(-54%) rotate(-10deg); }
    50% { transform: translateX(-46%) rotate(8deg); }
    75% { transform: translateX(-51%) rotate(-4deg); }
}
@media (prefers-reduced-motion: reduce) {
    .arcade--defile .arcade__decor,
    .arcade--defile .arcade__sol,
    .arcade__avatar--course,
    .arcade__avatar--trebuche { animation: none; }
    .arcade__avatar { transition: none; }
}

/* ============================================================
   Le canon à mots (2026-07-26) : jeu ZÉRO PRESSION. Les bulles-réponses
   dérivent doucement dans le ciel (canon.js), le canon pivote vers la
   bulle visée, on tire à son rythme. Aucun chrono, rien qui monte ou
   descend vers une limite. prefers-reduced-motion fige tout.
============================================================ */
.canon {
    position: relative;
    height: clamp(300px, 48vw, 420px);
    border-radius: 16px;
    overflow: hidden;
    border: 1px solid var(--bordure-accent);
    background: linear-gradient(180deg, #16263c 0%, #1b3450 55%, #24425f 100%);
    margin: 10px 0 6px;
}
/* Ciel décoratif : quelques « étoiles/indices » discrets, immobiles. */
.canon__ciel {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(1.5px 1.5px at 20% 30%, rgba(255, 255, 255, 0.35) 50%, transparent 51%),
        radial-gradient(1.5px 1.5px at 70% 18%, rgba(255, 255, 255, 0.25) 50%, transparent 51%),
        radial-gradient(2px 2px at 45% 60%, rgba(207, 163, 56, 0.30) 50%, transparent 51%),
        radial-gradient(1.5px 1.5px at 85% 48%, rgba(255, 255, 255, 0.20) 50%, transparent 51%);
}
.canon__consigne {
    position: relative;
    z-index: 3;
    text-align: center;
    margin: 14px auto 0;
    padding: 6px 16px;
    width: fit-content;
    max-width: 92%;
    border-radius: 999px;
    background: rgba(11, 16, 23, 0.82);
    border: 1px solid var(--bordure-accent);
    color: var(--accent-clair);
}
.canon__ecoute {
    border: none;
    background: transparent;
    cursor: pointer;
    font-size: 1.1rem;
    line-height: 1;
    padding: 0 2px;
}
/* Le champ de dérive : les bulles y sont positionnées en absolu par
   canon.js. Repli sans JS (et mouvement réduit) : simple flex centré. */
.canon__champ {
    position: relative;
    z-index: 2;
    height: 58%;
    margin: 10px 10px 0;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-content: center;
    justify-content: center;
}
.canon__bulle {
    z-index: 2;
    border-radius: 999px;
    border: 2px solid var(--kraft-doux);
    background: radial-gradient(circle at 32% 28%, rgba(255, 255, 255, 0.85), var(--kraft) 60%, var(--kraft-doux));
    color: var(--encre);
    font-family: var(--serif);
    font-weight: 700;
    font-size: clamp(0.82rem, 1.7vw, 1.02rem);
    padding: 12px 16px;
    cursor: pointer;
    box-shadow: inset 0 -3px 6px rgba(0, 0, 0, 0.12), 0 4px 10px rgba(0, 0, 0, 0.25);
    transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}
.canon__bulle:hover,
.canon__bulle--visee {
    transform: scale(1.06);
    border-color: var(--accent);
    box-shadow: 0 0 16px var(--halo-accent), 0 6px 14px rgba(0, 0, 0, 0.3);
}
/* Le canon : un tube qui pivote vers la bulle visée (angle posé par canon.js
   dans --canon-angle), planté sur un socle au bas-centre. */
.canon__tube {
    position: absolute;
    z-index: 4;
    left: 50%;
    bottom: 14px;
    width: clamp(16px, 3vw, 22px);
    height: clamp(58px, 12vw, 84px);
    border-radius: 8px 8px 3px 3px;
    background: linear-gradient(90deg, #3f3016, #8a6a3c 45%, #d8b878 50%, #8a6a3c 55%, #3f3016);
    border: 1px solid rgba(0, 0, 0, 0.35);
    transform-origin: bottom center;
    transform: translateX(-50%) rotate(var(--canon-angle, 0deg));
    transition: transform 0.12s ease-out;
}
.canon__socle {
    position: absolute;
    z-index: 3;
    left: 50%;
    bottom: 2px;
    transform: translateX(-50%);
    font-size: 1.6rem;
    line-height: 1;
}
/* Bille tirée (canon.js, Web Animations API) et éclat/rebond au point d'impact. */
.canon__bille {
    position: absolute;
    z-index: 5;
    top: 0;
    left: 0;
    width: 12px;
    height: 12px;
    margin: -6px 0 0 -6px;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 30%, #fff, var(--accent) 70%);
    box-shadow: 0 0 8px var(--halo-accent);
    pointer-events: none;
}
.canon__eclat {
    position: absolute;
    z-index: 5;
    width: 60px;
    height: 60px;
    margin: -30px 0 0 -30px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(207, 163, 56, 0.85) 0%, rgba(207, 163, 56, 0.25) 45%, transparent 70%);
    pointer-events: none;
    animation: canon-eclat 0.55s ease-out forwards;
}
.canon__eclat--rebond {
    background: radial-gradient(circle, rgba(120, 160, 200, 0.55) 0%, rgba(120, 160, 200, 0.15) 50%, transparent 72%);
    animation: canon-rebond 0.55s ease-out forwards;
}
@keyframes canon-eclat {
    0% { transform: scale(0.3); opacity: 0.95; }
    100% { transform: scale(1.5); opacity: 0; }
}
@keyframes canon-rebond {
    0% { transform: scale(0.5); opacity: 0.8; }
    40% { transform: scale(1.1); opacity: 0.5; }
    100% { transform: scale(0.8); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .canon__bulle,
    .canon__tube { transition: none; }
    .canon__bulle:hover,
    .canon__bulle--visee { transform: none; }
    .canon__eclat,
    .canon__eclat--rebond { animation: none; display: none; }
}

/* Image agrandissable au clic (lightbox image-zoom.js) : affichée plus
   petite, un indice « à la loupe » invite à cliquer pour la voir en grand. */
.img-zoomable {
    cursor: zoom-in;
    max-width: min(100%, 300px);
    height: auto;
    display: block;
    margin: 8px auto 4px;
    border-radius: 8px;
    transition: filter 0.15s ease;
}
.img-zoomable:hover { filter: brightness(1.05); }
.img-zoomable-legende { text-align: center; margin-top: 0; }
.zoom-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 3vmin;
    background: rgba(6, 9, 14, 0.9);
    cursor: zoom-out;
}
.zoom-overlay img {
    max-width: 96vw;
    max-height: 94vh;
    width: auto;
    height: auto;
    border-radius: 10px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
}

/* Défis opt-in (chrono, mode défi) et sablier décoratif. */
.defis-optin { display: flex; gap: 10px; flex-wrap: wrap; margin: 6px 0 10px; }
.chrono-badge {
    width: fit-content;
    margin: 4px 0 10px;
    padding: 5px 14px;
    border-radius: 999px;
    border: 1px solid var(--bordure-accent);
    background: rgba(207, 163, 56, 0.10);
    color: var(--accent-clair);
    font-variant-numeric: tabular-nums;
}
.chrono-badge--ecoule { border-color: var(--bordure); color: var(--texte-doux); background: none; }

/* Bouton son de l'en-tête (injecté par effets.js) */
.entete__son {
    background: none;
    border: 1px solid var(--bordure);
    border-radius: 999px;
    padding: 4px 10px;
    cursor: pointer;
    font-size: 1rem;
}
.entete__son:hover { border-color: var(--bordure-accent); }

/* Illustration du grade à côté du nom (à la place de l'emoji) :
   médaillon rond, aligné sur la ligne de texte. */
.grade-ligne { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.grade-illustration {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--bordure-accent);
    background: var(--surface-2);
}

/* Choix du personnage de grade (garçon / fille) : deux médaillons
   cliquables au premier passage, un lien discret pour changer ensuite. */
.choix-avatar { display: flex; align-items: center; gap: 10px; margin: 8px 0 4px; }
.choix-avatar__option {
    padding: 0;
    border: 2px solid var(--bordure);
    border-radius: 50%;
    background: var(--surface-2);
    cursor: pointer;
    width: 56px;
    height: 56px;
    overflow: hidden;
    transition: border-color 0.15s ease, transform 0.15s ease;
}
.choix-avatar__option:hover { border-color: var(--accent); transform: translateY(-2px); }
.choix-avatar__option img { width: 100%; height: 100%; object-fit: cover; display: block; }
.choix-avatar__changer { margin-top: 2px; }

/* Illustration de titre de section (remplace l'emoji, ex. la piste) :
   calée sur la hauteur de la ligne. */
.titre-illustration {
    height: 1.5em;
    width: auto;
    vertical-align: -0.35em;
    margin-right: 4px;
}

/* Le bureau du commissariat en toile de fond de l'accueil (illustration
   de Djess, 2026-07-24) : voile nuit pour garder le texte lisible. */
.hero--commissariat {
    background:
        linear-gradient(180deg, rgba(11, 16, 23, 0.68), rgba(11, 16, 23, 0.88)),
        url('/assets/illustrations/commissariat.png') center / cover no-repeat;
    border-radius: 16px;
    padding: 22px 20px;
    border: 1px solid var(--bordure-accent);
}

/* Les deux mascottes côte à côte à l'accueil (Noor à gauche de Ned) :
   serrées comme des coéquipiers, jamais dispersées. Les deux PNG n'ont
   pas le même ratio (Noor 433x577, Ned 480x520) : on aligne sur la
   HAUTEUR (silhouettes égales), pas sur la largeur du composant. */
.hero__mascottes {
    display: flex;
    align-items: flex-end;
    gap: 0;
    flex: 0 0 auto;
}
.hero__mascottes .ned { width: auto; }
.hero__mascottes .ned__img { height: clamp(120px, 16vw, 168px); width: auto; }
/* Les PNG portent des marges transparentes autour des personnages : un
   chevauchement négatif les met vraiment épaule contre épaule. */
.hero__mascottes .ned + .ned { margin-left: clamp(-124px, -13vw, -64px); }

/* Bouton « Se déconnecter » : sobre, aligné sur les liens de navigation. */
.entete__deconnexion {
    background: none;
    border: 1px solid var(--bordure);
    border-radius: 999px;
    padding: 5px 12px;
    cursor: pointer;
    font: inherit;
    font-size: 0.92rem;
    color: var(--texte-doux);
}
.entete__deconnexion:hover { border-color: var(--bordure-accent); color: var(--texte); }
/* « ← Retour » de l'en-tête : même gabarit qu'un lien de nav (bouton -> JS). */
.entete__retour {
    background: none;
    border: 1px solid var(--bordure);
    border-radius: 999px;
    padding: 5px 12px;
    cursor: pointer;
    font: inherit;
    font-size: 0.92rem;
    color: var(--texte-doux);
}
.entete__retour:hover { border-color: var(--bordure-accent); color: var(--texte); }
/* Lien de retour DANS une page (ex. quitter un jeu) : discret mais visible. */
.lien-retour {
    display: inline-block;
    margin-bottom: 10px;
    color: var(--accent-clair, #d9a441);
    text-decoration: none;
    font-size: 0.95rem;
}
.lien-retour:hover { text-decoration: underline; }
.defi-jour { border-left: 4px solid var(--bordure-accent, #cfa338); }

/* ================= Exercice « tri » : classement en colonnes =================
   (2026-07-30, demande Djess : « de vraies colonnes où on peut glisser les
   mots ».) Glisser-déposer via tri-colonnes.js ; repli tactile : toucher
   l'étiquette puis la colonne. */
.tri-grille {
    display: grid;
    grid-template-columns: repeat(var(--tri-colonnes, 2), minmax(130px, 1fr));
    gap: 12px;
    margin-top: 12px;
}
@media (max-width: 640px) {
    .tri-grille { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
}
.tri-zone {
    border: 2px dashed rgba(128, 128, 128, 0.45);
    border-radius: 10px;
    padding: 10px;
    min-height: 64px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-content: flex-start;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
.tri-zone--reserve { background: rgba(128, 128, 128, 0.06); }
.tri-zone--colonne { flex-direction: column; align-items: stretch; }
.tri-zone--survol { border-color: var(--accent, #cfa338); background: rgba(207, 163, 56, 0.08); }
.tri-zone__titre {
    margin: 0 0 6px;
    font-weight: 700;
    text-align: center;
    border-bottom: 1px solid rgba(128, 128, 128, 0.3);
    padding-bottom: 6px;
}
.tri-mot {
    display: inline-block;
    padding: 6px 12px;
    border-radius: 8px;
    background: #eef3f7;
    color: #1b2a44;
    font-weight: 600;
    cursor: grab;
    user-select: none;
    text-align: center;
}
.tri-mot:active { cursor: grabbing; }
.tri-mot--choisi { outline: 3px solid var(--accent, #cfa338); }
.tri-mot--juste { background: #d9f2e0; }
.tri-mot--arevoir { background: #fbe8cc; }

/* Flèche de CHRONOLOGIE entre les évènements posés d'une remise en ordre de
   vocabulaire (« le temps qui passe », Djess 2026-07-30). */
.ordre-fleche { color: var(--accent, #cfa338); font-weight: 700; font-size: 1.1em; }

/* ================= Exercice « etiketten » : le plan à étiqueter ========== */
/* Le conteneur reçoit son RATIO et sa largeur en style inline (calculés au
   serveur depuis les dimensions du fichier) : l'image le remplit à 100 %,
   les zones en % restent donc exactement alignées, et le plafond de hauteur
   (68vh, dans le calc de largeur) garde l'image ET la banque d'étiquettes
   ensemble à l'écran (retours Djess 2026-07-31). */
.etiket-plan { position: relative; margin: 0 auto; }
.etiket-plan img { width: 100%; height: 100%; display: block; border-radius: 8px; }
.etiket-zone {
    position: absolute;
    border: 2px dashed rgba(27, 42, 68, 0.55);
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.75);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: clamp(0.6rem, 1.6vw, 0.9rem);
    color: #1b2a44;
    padding: 2px;
    text-align: center;
    cursor: pointer;
}
.etiket-zone--juste { border-color: #1b7a3d; background: rgba(217, 242, 224, 0.9); border-style: solid; }
.etiket-zone--arevoir { border-color: #c8862a; background: rgba(251, 232, 204, 0.9); border-style: solid; }
/* Une étiquette POSÉE épouse exactement sa case (sinon le pion de la banque
   déborde et recouvre les cases voisines, retour Djess 2026-07-31). */
.etiket-zone .tri-mot {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 2px;
    margin: 0;
    border-radius: 4px;
    font-size: clamp(0.55rem, 1.5vw, 0.85rem);
    line-height: 1.05;
    white-space: nowrap;
    overflow: hidden;
}

/* Texte à LIRE d'une épreuve (le briefje du témoin, une consigne de tri) :
   mis en évidence comme une pièce du dossier (2026-08-02). */
.citation-dossier {
    background: #fbf3dd; color: #4a3a1a;
    border-left: 5px solid #cfa338; border-radius: 8px;
    margin: 0 auto 14px; max-width: 640px; padding: 14px 18px;
    font-size: 1.08rem; line-height: 1.6; font-style: italic;
}
:root[data-theme="dark"] .citation-dossier { background: #3a3524; color: #f0e6cf; }

/* Désignation « qcm_multi » : les lettres A-F à cliquer (escaperoom c02). */
.keuze-lettres { display: flex; flex-wrap: wrap; gap: 10px; }
.keuze-lettre {
    width: 48px; height: 48px; border-radius: 10px;
    border: 2px solid #1b2a44; background: #eef3f7; color: #1b2a44;
    font-size: 1.3rem; font-weight: 700; cursor: pointer;
}
.keuze-lettre:hover, .keuze-lettre:focus-visible { border-color: #cfa338; background: #fbf3dd; }
.keuze-lettre--choisi { background: #cfa338; color: #1b2a44; border-color: #cfa338; }

/* ====== Escaperoom (c02) : la fouille cliquable et les molettes ========= */
.zoekplaat { position: relative; max-width: 680px; margin: 0 auto; cursor: zoom-in; }
.zoekplaat img { width: 100%; height: auto; display: block; border-radius: 8px; user-select: none; }
.zoekplaat__eclat {
    position: absolute;
    width: 26px; height: 26px;
    margin: -13px 0 0 -13px;
    border: 3px solid #cfa338;
    border-radius: 50%;
    pointer-events: none;
    animation: zoek-eclat 0.7s ease-out forwards;
}
@keyframes zoek-eclat { from { transform: scale(0.4); opacity: 1; } to { transform: scale(1.6); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .zoekplaat__eclat { animation: none; opacity: 0.7; } }
.zoekplaat__lijst { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: 6px 16px; font-weight: 600; }
/* Poursuite (c03) : la piste du fuyard tracée sur le plan de ville. */
.poursuite-trace { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.poursuite-teller { font-weight: 700; }
.poursuite-carnet { background: #fbf3dd; border: 1px dashed #cfa338; border-radius: 8px; padding: 8px 14px; margin-bottom: 10px; color: #4a3113; }
.poursuite-carnet .discret { color: #7a561a; font-weight: 600; }
.poursuite-carnet ul { margin: 4px 0 0; padding-left: 20px; }
.poursuite-carnet li { color: #4a3113; }
:root[data-theme="dark"] .poursuite-carnet { background: #3a3524; color: #f2e7c9; }
:root[data-theme="dark"] .poursuite-carnet .discret { color: #e0c884; }
:root[data-theme="dark"] .poursuite-carnet li { color: #f2e7c9; }
/* Checkpoint de lecture (arrivée sur un lieu : témoignage + question). */
.poursuite-checkpoint { border: 2px solid #cfa338; }
.poursuite-vraag { font-weight: 700; margin: 10px 0 6px; }
.poursuite-opties { display: flex; flex-direction: column; gap: 8px; }
.poursuite-opties .bouton { text-align: left; }
/* Aide de lecture : mot cliquable qui révèle sa traduction (après une
   mauvaise réponse au checkpoint). Le mot reste dans le fil du texte. */
.mot-klikbaar {
    font: inherit; color: inherit; background: transparent; cursor: pointer;
    border: 0; padding: 0; border-bottom: 2px dotted #b8860b;
    line-height: inherit;
}
.mot-klikbaar:hover { background: rgba(184, 134, 11, .15); }
.mot-klikbaar--open { border-bottom-style: solid; }
.mot-klikbaar--open::after {
    content: ' (' attr(data-vertaling) ')';
    font-style: italic; font-weight: 600; color: #7a561a;
}
:root[data-theme="dark"] .mot-klikbaar--open::after { color: #e0c884; }
/* Fil d'Ariane du dossier Conjugaison : boutons retour espacés, jamais collés. */
.conjug-fil { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-bottom: 12px; }
/* QCM façon quiz : une question à la fois, barre de progression, grandes
   cartes colorées d'options (2026-08-03, demande Djess). */
.eval-progressie { margin: 6px 0 14px; }
.eval-progressie__barre { height: 10px; border-radius: 6px; background: rgba(184, 134, 11, .18); overflow: hidden; }
.eval-progressie__vulling { height: 100%; background: #b8860b; border-radius: 6px; transition: width .25s ease; }
.eval-progressie__tekst { display: block; margin-top: 4px; font-size: .85rem; opacity: .8; }
.eval-vraag-titel { font-size: 1.35rem; font-weight: 700; text-align: center; margin: 10px 0 16px; text-wrap: balance; }
.eval-kaarten { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
@media (max-width: 520px) { .eval-kaarten { grid-template-columns: 1fr; } }
.eval-kaart {
    min-height: 84px; border: 0; border-radius: 12px; cursor: pointer;
    color: #fff; font-size: 1.1rem; font-weight: 600; padding: 14px 16px;
    display: flex; align-items: center; justify-content: center; text-align: center;
    box-shadow: 0 2px 0 rgba(0, 0, 0, .25); transition: transform .08s ease, filter .15s ease;
}
.eval-kaart:hover { filter: brightness(1.08); }
.eval-kaart:active { transform: translateY(1px); }
.eval-kaart--0 { background: #2f6db0; }   /* bleu */
.eval-kaart--1 { background: #2a8f7f; }   /* vert */
.eval-kaart--2 { background: #d19a2a; }   /* orange */
.eval-kaart--3 { background: #c0556f; }   /* rose */
.eval-kaart--gekozen { outline: 4px solid #fff; outline-offset: -4px; filter: brightness(1.12); }
/* Feedback formatif (entraînement) : anneau vert/rouge sur la carte choisie. */
.eval-kaart--juste { outline: 5px solid #1b7a3d; outline-offset: -5px; }
.eval-kaart--fout { outline: 5px solid #c0392b; outline-offset: -5px; }
.eval-kaart--juste::after { content: ' ✓'; font-weight: 800; }
.eval-kaart--fout::after { content: ' ✗'; font-weight: 800; }
.eval-kaart:disabled { cursor: default; opacity: .9; }
.eval-navigatie { display: flex; justify-content: space-between; gap: 10px; margin-top: 16px; }
.eval-navigatie .bouton { margin: 0; }
.eval-recap { list-style: none; padding-left: 0; margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.eval-recap li { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
/* Couverture référentiel des thèmes (tableau de bord prof). */
.theme-couverture { border-top: 1px solid rgba(184, 134, 11, .3); padding-top: 10px; margin-top: 10px; }
.theme-couverture:first-of-type { border-top: 0; }
.couverture-savoirs { margin: 2px 0 0; padding-left: 4px; list-style: none; }
.couverture-savoirs li { margin-bottom: 4px; }
.couverture-savoirs .pastille { margin-right: 4px; }
/* Inventaire d'outils à glisser sur leur cible (escaperoom, 2026-08-02). */
.zoek-inventaris { margin: 10px 0; }
.zoek-inventaris__rij { display: flex; flex-wrap: wrap; gap: 10px; }
.zoek-outil {
    background: #fbf3dd; border: 2px solid #cfa338; border-radius: 8px;
    padding: 8px 14px; font-weight: 600; color: #4a3a1a; cursor: grab;
    user-select: none;
}
.zoek-outil:active { cursor: grabbing; }
.zoek-outil--arme { outline: 3px solid var(--accent, #cfa338); box-shadow: 0 0 0 4px rgba(207, 163, 56, 0.3); }
.molettes { display: flex; justify-content: center; gap: 14px; }
.molette { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.molette__cijfer {
    font-size: 2rem; font-weight: 700; font-family: Consolas, monospace;
    background: #1b2a44; color: #f7d774;
    border-radius: 8px; padding: 6px 14px; min-width: 52px; text-align: center;
}
.molette__bouton { font-size: 1rem; padding: 4px 12px; border-radius: 6px; border: 1px solid #1b2a44; background: #eef3f7; cursor: pointer; }
.molette__bouton:hover, .molette__bouton:focus-visible { background: #f7d774; }
.code-cijfer { display: inline-block; min-width: 1.6em; text-align: center; font-family: Consolas, monospace; font-size: 1.2em; background: #eef3f7; border-radius: 4px; margin: 0 2px; }

/* ============ Exercice « route » : Stuur Ned door de stad! =============== */
.route-plan { width: min(560px, 100%); height: auto; display: block; margin: 0 auto; }
.route-ned { transition: transform 0.55s ease; }
@media (prefers-reduced-motion: reduce) { .route-ned { transition: none; } }
.route-doel { animation: route-pulse 1.6s ease-in-out infinite; }
@keyframes route-pulse { 0%, 100% { stroke-opacity: 1; } 50% { stroke-opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) { .route-doel { animation: none; } }
.route-opdrachten { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: 8px 18px; }
.route-opdrachten code { background: #eef3f7; color: #1b2a44; padding: 3px 10px; border-radius: 6px; font-weight: 600; }
.route-journal { list-style: none; padding: 8px 0 0; margin: 0; font-size: 0.92rem; }
.route-journal li { padding: 2px 0; }
.route-formulaire { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 12px; }
.route-formulaire input { flex: 1 1 240px; }

/* ================= Exercice « klok » : l'horloge à régler ================= */
.klok-item { padding: 12px 0; border-bottom: 1px solid rgba(128, 128, 128, 0.2); }
.klok-item--juste .klok-cadran circle:first-of-type { stroke: #1b7a3d; }
.klok-item--arevoir .klok-cadran circle:first-of-type { stroke: #c8862a; }
.klok-cadran { width: min(220px, 70vw); height: auto; display: block; margin: 0 auto; }
.klok-digitaal {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 1.4rem;
    background: #10192b;
    color: #7ef29a;
    border-radius: 8px;
    padding: 6px 12px;
}
.klok-digitaal input { background: transparent; border: none; color: inherit; }

/* ====== Suivi des compétences (prof) : grilles emoji façon Narralis ====== */
/* Légende des statuts, en chips discrètes au-dessus des grilles. */
.legende-suivi { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 0.92rem; margin: 6px 0 2px; }
.legende-suivi span { background: var(--surface-2); border: 1px solid var(--bordure); border-radius: 999px; padding: 3px 12px; }

/* Zone défilante : la grille peut être large (codes) et haute (élèves). */
.grille-suivi-zone { overflow: auto; max-height: 65vh; border: 1px solid var(--bordure); border-radius: 10px; }
table.grille-suivi { border-collapse: separate; border-spacing: 0; width: 100%; }
table.grille-suivi th, table.grille-suivi td { padding: 14px 16px; line-height: 1.6; vertical-align: middle; text-align: center; border-bottom: 1px solid var(--bordure); white-space: nowrap; }
table.grille-suivi th:first-child, table.grille-suivi td:first-child { text-align: left; }
/* En-tête ET première colonne collants : on garde codes + prénoms en vue. */
table.grille-suivi thead th { position: sticky; top: 0; background: var(--surface-2); z-index: 3; }
table.grille-suivi th:first-child, table.grille-suivi td:first-child { position: sticky; left: 0; background: var(--surface-2); z-index: 2; }
table.grille-suivi thead th:first-child { z-index: 4; }
table.grille-suivi tbody tr:hover td { background: var(--surface-2); }
.cellule-suivi { font-size: 1.05rem; cursor: help; }
.cellule-suivi .lien-discret { margin-left: 2px; }

/* ======= Tableaux de données (.tableau) : aération demandée par Djess ======= */
.tableau { width: 100%; border-collapse: collapse; }
.tableau th, .tableau td { padding: 13px 14px; text-align: left; line-height: 1.6; vertical-align: middle; border-bottom: 1px solid var(--bordure); }
.tableau th { color: var(--texte-doux); font-weight: 600; }

/* Aération des grilles de suivi (retour Djess 2026-08-06). */
.legende-suivi { margin: 8px 0 12px; }
.grille-suivi-zone { margin: 10px 0 14px; }

/* Correspondance programmes (SeGEC / CPEONS) sous chaque point du référentiel. */
.correspondance-programmes { display: block; margin: 2px 0 6px 4px; padding-left: 10px; border-left: 2px solid var(--bordure-accent); font-size: 0.85rem; color: var(--texte-doux); }
.correspondance-programmes span { display: block; }

/* Nuance de mot du volet Oral : le mot exact, son audio, son conseil. */
.oral-nuance { background: var(--surface-2); border: 1px solid var(--bordure-accent); border-radius: 10px; padding: 10px 14px; line-height: 1.7; }

/* ===== Le tableau des indices : étiquettes flottantes (refonte
   2026-08-08, demande de Djess, façon Quizlet Match). L''arène est la
   zone de vol ; le JS (etiquettes-flottantes.js) déplace les étiquettes
   via transform, le CSS borne leur TAILLE pour que mots et phrases ne
   débordent jamais (max-width + retour à la ligne + petite taille de
   police sur les libellés longs). ===== */
.arene-etiquettes {
    position: relative;
    overflow: hidden;
    height: min(62vh, 480px);
    margin: 10px 0;
    border: 1px solid var(--bordure-accent);
    border-radius: 14px;
    background: radial-gradient(circle at 50% 30%, rgba(207, 163, 56, 0.10), transparent 65%);
}
.etiquette {
    position: absolute;
    top: 0;
    left: 0;
    max-width: min(200px, 44vw);
    padding: 8px 14px;
    border: 1px solid var(--bordure-accent);
    border-radius: 999px;
    background: rgba(207, 163, 56, 0.12);
    color: inherit;
    font: inherit;
    font-size: 0.95rem;
    line-height: 1.3;
    text-align: center;
    overflow-wrap: anywhere;
    cursor: pointer;
    will-change: transform;
}
.etiquette--fr { border-style: dashed; background: rgba(255, 255, 255, 0.06); }
/* Libellé long (phrase, mot composé) : police réduite, jamais de débord. */
.etiquette--longue { font-size: 0.8rem; max-width: min(230px, 60vw); border-radius: 14px; }
.etiquette--choisie {
    border-color: var(--accent);
    background: rgba(207, 163, 56, 0.30);
    box-shadow: 0 0 0 3px var(--halo-accent);
}
/* Paire fausse : l''arène tremble un instant (signal doux, rien de perdu). */
.arene-etiquettes--secousse { animation: arene-secousse 0.3s ease; }
@keyframes arene-secousse {
    25% { transform: translateX(-5px); }
    75% { transform: translateX(5px); }
}
/* Mouvement réduit (préférence système) : aucune étiquette ne vole, la
   grille reste posée et le jeu se joue exactement pareil. */
@media (prefers-reduced-motion: reduce) {
    .arene-etiquettes { height: auto; display: flex; flex-wrap: wrap; gap: 10px; padding: 14px; }
    .etiquette { position: static; }
    .arene-etiquettes--secousse { animation: none; }
}

/* ===== Récapitulatif par épreuve de la fiche élève (2026-08-08, « façon
   Anton ») : lignes AÉRÉES (retour Djess : « c''est trop serré »), état à
   gauche, titre + détail des essais en dessous. ===== */
.recap-dossier { margin: 14px 0 4px; }
.recap-epreuves { list-style: none; padding-left: 6px; margin: 0; }
.recap-epreuves li {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 7px 0;
    line-height: 1.55;
    border-bottom: 1px dashed var(--bordure);
}
.recap-epreuves li:last-child { border-bottom: none; }
.recap-epreuves__etat { flex: 0 0 auto; font-size: 1.05rem; }

/* ===== Couverture référentiel en TABLEAU (2026-08-08, retour Djess :
   « comme Narralis, beaucoup plus clair ») : une ligne par attendu,
   colonnes SeGEC / CPEONS alignées. ===== */
.tableau-attendus td { vertical-align: top; line-height: 1.55; }
.tableau-attendus td:first-child { min-width: 260px; }
.tableau-attendus td:nth-child(2),
.tableau-attendus td:nth-child(3) { min-width: 180px; color: var(--texte-doux, inherit); }

/* ===== Grille de suivi : intitulé VISIBLE sous chaque code (2026-08-08,
   retour Djess : « je ne comprends pas à quoi il correspond ») : le code
   seul ne parle pas, le libellé du référentiel s''affiche en dessous. ===== */
.grille-suivi--intitules th { vertical-align: top; }
.grille-suivi__intitule {
    display: block;
    max-width: 150px;
    margin-top: 3px;
    font-weight: normal;
    font-size: 11px;
    line-height: 1.4;
    white-space: normal;
    color: var(--texte-doux, inherit);
}

/* ===== Import photo des listes de voc (2026-08-08) : les vrais <input
   file> sont masqués, les <label> stylés en boutons les déclenchent
   (accessibles au clavier via focus-within). Sur smartphone, le champ
   `capture` ouvre directement l''appareil photo. ===== */
.champ-fichier-cache {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}
label.bouton { cursor: pointer; display: inline-block; }

/* ===== Mascottes côte à côte (connexion, espace famille) : la MÊME
   HAUTEUR pour Ned et Noor (retour Djess 2026-08-08 : « les personnages
   n''ont pas la même taille ») : leurs illustrations n''ont pas le même
   ratio, une largeur commune donnait des tailles différentes. ===== */
.hero__scene .ned--lg { width: auto; }
.hero__scene .ned--lg .ned__img { height: clamp(150px, 22vw, 230px); width: auto; }

/* ===== Table de classe du prof (2026-08-08) : avec les missions elle est
   LARGE ; elle défile horizontalement (zone dédiée) au lieu de tasser les
   intitulés (retour Djess : « les mots dépassent »). Chaque colonne garde
   une largeur minimale lisible, l''étiquette Enquête/Mission au-dessus du
   titre. ===== */
.tableau-classe th {
    min-width: 118px;
    vertical-align: bottom;
    font-size: 12px;
    line-height: 1.35;
}
.tableau-classe th:first-child { min-width: 90px; }
.tableau-classe td { white-space: nowrap; }
.tableau-classe__type {
    display: block;
    font-weight: normal;
    font-size: 11px;
    color: var(--texte-doux, inherit);
    white-space: nowrap;
}

/* ===== Audit responsive (2026-08-08, demande Djess) ===== */
/* Deux cartes côte à côte qui s''empilent sur téléphone : remplace les
   grid-template inline (le style inline écrasait les media queries). */
.grille-deux { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
/* Liste + détail (relectures prof) : côte à côte sur grand écran, empilés
   dès que l''écran se resserre. */
.grille-maitre-detail { display: grid; grid-template-columns: 1fr 2fr; gap: 16px; align-items: start; }
@media (max-width: 860px) {
    .grille-maitre-detail { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
    .grille-deux { grid-template-columns: 1fr; }
    /* Un tableau plus large que l''écran DÉFILE dans son cadre au lieu de
       déborder de la page (fiche élève, espace parent, listes de voc). */
    .tableau { display: block; overflow-x: auto; }
}
/* Saisie dans un tableau (listes de voc) : le champ remplit sa colonne. */
.tableau input[type="text"] { width: 100%; min-width: 140px; box-sizing: border-box; }
/* Un lecteur audio ne déborde jamais de sa carte. */
audio { max-width: 100%; }

/* ===== Niveau 0 du volet Oral : « J''écoute et je répète » (2026-08-09,
   façon minidialogues des manuels). Une ligne par modèle : le texte, le
   lecteur du modèle, puis le coin « ma voix » (bouton + lecture locale). ===== */
.echo-oral { list-style: none; padding: 0; margin: 10px 0 0; }
.echo-oral__ligne {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 18px;
    padding: 10px 0;
    border-bottom: 1px dashed var(--bordure);
}
.echo-oral__ligne:last-child { border-bottom: none; }
.echo-oral__texte { font-weight: 600; min-width: 150px; }
.echo-oral__moi { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.echo-oral audio { height: 38px; max-width: 100%; }
