  /* ---- Mode VN (roman visuel) v1 — décors & sprites en PLACEHOLDER (CSS), à remplacer par des assets ---- */
  #vn { position:fixed; inset:38px 0 0 0; z-index:80; display:none; overflow:hidden; user-select:none; }
  body.vn-open #vn { display:block; }
  body.vn-open #log, body.vn-open #inbar, body.vn-open .sidebar { visibility:hidden; }
  #vn-bg { position:absolute; inset:0; background:linear-gradient(160deg,#243049,#0e1320 58%,#1a1030); }
  /* VN6 : CROSSFADE entre deux calques d'image superposes (background-image n'est pas animable :
     on fond l'OPACITE des calques). Le degrade placeholder du conteneur transparait quand le
     calque visible n'a pas d'image. L'overlay ::after (lisibilite) reste au-dessus des calques. */
  .vn-bg-layer { position:absolute; inset:0; background-size:cover; background-position:center;
    opacity:0; transition:opacity .8s ease; }
  .vn-bg-layer.on { opacity:1; }
  #vn-bg::after { content:""; position:absolute; inset:0;
    background:radial-gradient(120% 80% at 50% -10%, rgba(130,160,230,.16), transparent 60%); }
  /* Decor IMAGE (VN1, resolu par ambiance.py) : le halo placeholder laisse place a un leger
     assombrissement bas -> la boite de dialogue et le tag de lieu restent lisibles. */
  #vn-bg.img::after { background:linear-gradient(180deg, rgba(6,8,14,.30) 0%, transparent 26%,
    transparent 55%, rgba(6,8,14,.42) 100%); }
  #vn-loc { position:absolute; top:14px; left:0; right:0; padding:0 150px; text-align:center;
    color:#cdd6e6; font-size:12px; letter-spacing:.18em; text-transform:uppercase; opacity:.6;
    text-shadow:0 1px 4px #000; pointer-events:none; transition:opacity .35s; }
  #vn-loc.fade { opacity:0; }
  /* v21 : EFFETS D'ÉCRAN des scènes scriptées (overlay #vn-fx + classes sur la scène) */
  #vn-fx { position:absolute; inset:0; z-index:6; pointer-events:none; opacity:0; }
  #vn-fx.fx-flash { background:#fff; opacity:0; animation:fxFlash var(--fxd,500ms) ease-out; }
  #vn-fx.fx-fondu_noir { background:#000; opacity:0; animation:fxFade var(--fxd,600ms) ease-in-out; }
  #vn-fx.fx-fondu_blanc { background:#fff; opacity:0; animation:fxFade var(--fxd,600ms) ease-in-out; }
  #vn-fx.fx-teinte { background:var(--fxc,#c0392b); opacity:0; animation:fxTint var(--fxd,600ms) ease-in-out; }
  #vn-fx.fx-vignette { background:radial-gradient(ellipse at center, transparent 42%, #000 122%);
    opacity:0; animation:fxTint var(--fxd,600ms) ease-in-out; }
  #vn-fx.fx-onde { background:radial-gradient(circle at center, rgba(230,240,255,.55) 0%, transparent 42%);
    opacity:0; animation:fxWave var(--fxd,600ms) ease-out; }
  #vn-fx.fx-letterbox::before, #vn-fx.fx-letterbox::after { content:""; position:absolute; left:0; right:0;
    height:0; background:#000; animation:fxBar var(--fxd,600ms) ease-in-out; }
  #vn-fx.fx-letterbox::before { top:0; } #vn-fx.fx-letterbox::after { bottom:0; }
  @keyframes fxFlash { 0%{opacity:0} 12%{opacity:var(--fxo,.7)} 100%{opacity:0} }
  @keyframes fxFade { 0%{opacity:0} 42%{opacity:1} 60%{opacity:1} 100%{opacity:0} }
  @keyframes fxTint { 0%{opacity:0} 25%{opacity:var(--fxo,.5)} 75%{opacity:var(--fxo,.5)} 100%{opacity:0} }
  @keyframes fxWave { 0%{opacity:var(--fxo,.6); transform:scale(.2)} 100%{opacity:0; transform:scale(1.7)} }
  @keyframes fxBar { 0%{height:0} 24%{height:12%} 78%{height:12%} 100%{height:0} }
  #vn.fx-shake { animation:fxShake var(--fxd,500ms) linear; }
  @keyframes fxShake { 0%,100%{transform:translate(0,0)} 20%{transform:translate(calc(var(--fxa,6px)*-1),var(--fxa,6px))}
    40%{transform:translate(var(--fxa,6px),calc(var(--fxa,6px)*-1))} 60%{transform:translate(calc(var(--fxa,6px)*-.6),0)}
    80%{transform:translate(var(--fxa,6px),var(--fxa,6px))} }
  #vn.fx-glitch { animation:fxGlitch var(--fxd,500ms) steps(3); }
  @keyframes fxGlitch { 0%{filter:none;transform:translate(0)} 20%{filter:hue-rotate(90deg) saturate(2);transform:translate(-5px,2px)}
    45%{filter:invert(.12);transform:translate(5px,-3px)} 70%{filter:hue-rotate(-80deg);transform:translate(-3px,1px)}
    100%{filter:none;transform:translate(0)} }
  #vn-bg.fx-zoom { animation:fxZoom var(--fxd,600ms) ease-out forwards; }
  @keyframes fxZoom { from{transform:scale(1)} to{transform:scale(1.12)} }
  /* v21 : boutons de CHOIX (au-dessus de la bulle ; le prompt de réponse est masqué) */
  #vn-choices { position:absolute; left:0; right:0; bottom:150px; z-index:6; display:none;
    flex-direction:column; align-items:center; gap:10px; padding:0 20px; }
  .vn-choice { min-width:min(440px,82%); max-width:82%; padding:12px 18px; border-radius:10px;
    border:1px solid rgba(200,215,240,.34); background:rgba(12,16,26,.82); color:#e6ecf7; font:inherit;
    font-size:15px; cursor:pointer; text-align:center; transition:transform .14s, border-color .14s, background .14s; }
  .vn-choice:hover:not([disabled]) { border-color:#c9a24a; background:rgba(32,28,16,.9); transform:translateY(-1px); }
  .vn-choice[disabled] { opacity:.5; cursor:default; }
  @media (prefers-reduced-motion:reduce) {
    #vn-fx, #vn.fx-shake, #vn.fx-glitch, #vn-bg.fx-zoom { animation-duration:1ms !important; }
  }
  /* v20.9 : horloge du monde (sous le lieu, discrète) */
  #vn-clock { position:absolute; top:33px; left:0; right:0; padding:0 150px; text-align:center;
    color:#e0c069; font-size:11px; letter-spacing:.08em; opacity:.72; text-shadow:0 1px 4px #000;
    pointer-events:none; }
  /* VN6 : controles de lecture (auto / vitesse / fin) — coin oppose au bouton Quitter */
  #vn-ctl { position:absolute; top:12px; left:14px; z-index:2; display:flex; gap:6px; }
  #vn-ctl button { background:rgba(0,0,0,.45); color:#cdd6e6; border:1px solid var(--line);
    border-radius:8px; padding:5px 10px; cursor:pointer; font:inherit; font-size:13px; }
  #vn-ctl button.on { border-color:#8ab8e8; color:#fff; box-shadow:0 0 10px rgba(138,184,232,.35); }
  /* vitesse : 3 chevrons, 1/2/3 allumes selon le niveau */
  #vn-speed .ar { opacity:.22; transition:opacity .15s; letter-spacing:1px; }
  #vn-speed .ar.lit { opacity:1; color:#8ab8e8; text-shadow:0 0 6px rgba(138,184,232,.6); }
  /* 📜 backlog : les 20 dernieres bulles lues, par-dessus la scene, sous les controles */
  #vn-log { position:absolute; inset:52px 16px 180px; z-index:3; display:none;
    justify-content:center; align-items:flex-start; }
  #vn-log-list { width:min(760px, 100%); max-height:100%; overflow-y:auto;
    background:rgba(10,12,18,.93); border:1px solid var(--line); border-radius:12px;
    padding:14px 16px; display:flex; flex-direction:column; gap:12px; }
  .vn-log-item .w { display:inline-block; font-size:11px; font-weight:600; padding:2px 8px;
    border-radius:6px; margin-bottom:3px; color:#fff; text-shadow:0 1px 2px rgba(0,0,0,.5); }
  .vn-log-item .tx { font-size:13px; line-height:1.5; white-space:pre-wrap; color:#dde3ee; }
  .vn-log-item.dice .tx { color:#e8d78a; }
  .vn-log-item.user .tx { color:#c3d6c3; font-style:italic; }
  .vn-log-item .vn-rb { margin-top:5px; }
  .vn-log-ch { border-top:1px solid var(--line); margin-top:6px; padding-top:8px; }
  .vn-log-ch .tt { font-size:12px; font-weight:600; color:#e8d78a; margin-bottom:4px; }
  #vn-stage { position:absolute; inset:0 0 176px 0; display:flex; align-items:flex-end; justify-content:center;
    gap:2.4%; padding:0 4%; pointer-events:none; }   /* paire RESSERRÉE vers le centre (VN7.2) ; bas = hauteur de bulle */
  .vn-sprite { position:relative; width:min(340px,30vw); height:90%; border-radius:130px 130px 16px 16px;
    background:linear-gradient(180deg, var(--sc,#888) 0%, rgba(10,12,20,.4) 74%, rgba(10,12,20,.7) 100%);
    box-shadow:inset 0 0 40px rgba(0,0,0,.5); opacity:.4; filter:grayscale(.55) brightness(.7);
    /* transform COMPOSÉ par variables : --fx/--fy = glissement (entrée + FLIP de recentrage), --fsc = échelle
       (actif / sortie). Anime le recentrage SANS écraser le lift de l'actif — aucun mouvement ne « saute ». */
    transform:translateX(var(--fx,0)) translateY(var(--fy,0)) scale(var(--fsc,1));
    transition:opacity .8s ease, transform .8s ease, filter .35s, box-shadow .35s; }
  /* VN7.2 : scene dynamique — 2 emplacements RAPPROCHES du centre (petite marge de securite,
     jamais de chevauchement en taille normale). PLANS : le locuteur ACTIF passe au plan 2
     (devant), l'autre au plan 1 — un tres gros sprite peut deborder, l'actif reste devant. */
  .vn-sprite { z-index:1; }
  .vn-sprite.active { z-index:2; }
  .vn-sprite.l { order:0; }
  .vn-sprite.r { order:1; }
  /* entrée : glissement COURT (220px) + fondu — jamais de grand écart vers les bords de l'écran */
  .vn-sprite.enter.l { --fx:-220px; opacity:0; }
  .vn-sprite.enter.r { --fx:220px; opacity:0; }
  .vn-sprite.out { opacity:0 !important; z-index:0; --fy:6%; --fsc:.98; }
  .vn-sprite.active { opacity:1; filter:none; --fy:-2%; --fsc:1.04;
    box-shadow:inset 0 0 40px rgba(0,0,0,.4), 0 0 34px var(--sc); }
  .vn-sprite .head { position:absolute; top:7%; left:50%; transform:translateX(-50%); width:46%; aspect-ratio:1;
    border-radius:50%; background:rgba(255,255,255,.28); box-shadow:inset 0 6px 20px rgba(0,0,0,.35); }
  .vn-sprite .nm { position:absolute; bottom:12px; left:0; right:0; text-align:center; font-weight:bold;
    color:#fff; text-shadow:0 2px 6px #000; font-size:15px; }
  /* VN7 : VRAI sprite (art) — l'image remplace la silhouette, meme gabarit de scene.
     Inactif : attenue mais bien PRESENT (moins fantomatique que la silhouette). */
  .vn-sprite.art { background:none; box-shadow:none; border-radius:0; width:auto;
    opacity:.62; filter:grayscale(.3) brightness(.78); }
  .vn-sprite.art img { height:100%; width:auto; max-width:min(600px,42vw); object-fit:contain;   /* PC : sprites ~+50% (mobile réduit plus bas) */
    object-position:bottom; display:block; filter:drop-shadow(0 6px 18px rgba(0,0,0,.55)); }
  .vn-sprite.art.active { opacity:1; box-shadow:none; filter:drop-shadow(0 0 22px var(--sc)); }
  /* transition IRIS (asset fade converti en voile alpha) : cligne au CHANGEMENT DE LIEU */
  #vn-veil { position:absolute; inset:-55%; z-index:1; background-size:100% 100%;
    opacity:0; pointer-events:none; }
  #vn-veil.blink { animation:vn-blink 1.05s ease-in-out; }
  @keyframes vn-blink { 0%{opacity:0} 40%{opacity:.97} 60%{opacity:.97} 100%{opacity:0} }
  /* ---- GABARIT bulle VN : taille FIXE, prête à recevoir une IMAGE (via --vn-bubble). Narration et dialogue
         partagent la MÊME bulle ; seul l'encart du nom au-dessus change. Le texte est PAGINÉ pour toujours tenir. ---- */
  /* PAS d'overflow:hidden ici : l'encart du nom depasse AU-DESSUS de la bulle par design
     (top negatif) — c'est #vn-text qui clippe le texte pagine. */
  #vn-box { position:absolute; left:50%; bottom:22px; transform:translateX(-50%); width:min(880px,94%);
    height:176px; box-sizing:border-box; z-index:4; display:flex; flex-direction:column;   /* DEVANT les sprites (z≤2) */
    background:var(--vn-bubble, linear-gradient(180deg, rgba(16,20,32,.62), rgba(9,12,20,.68)));  /* nettement transparent (façon VN) */
    background-size:cover; background-position:center;
    border:1px solid rgba(140,180,240,.5); border-radius:16px; padding:18px 28px 14px;
    box-shadow:0 8px 40px rgba(0,0,0,.55), inset 0 0 30px rgba(60,100,180,.12);
    backdrop-filter:blur(4px); cursor:pointer; }
  #vn-name { position:absolute; top:-16px; left:22px; padding:3px 16px; border-radius:8px; font-weight:bold;
    font-size:15px; color:#fff; background:#3a4a66; box-shadow:0 2px 10px rgba(0,0,0,.5);
    border:1px solid rgba(255,255,255,.28); text-shadow:0 1px 3px rgba(0,0,0,.5); }
  #vn-name.hidden { display:none; }
  #vn-text { flex:1; min-height:0; overflow:hidden; font-size:calc(19px * var(--vn-scale, 1)); line-height:1.72; letter-spacing:.03em;
    color:#eef2f8; white-space:pre-wrap; font-family:var(--vn-font, inherit); }   /* AÉRÉ : interligne + interlettrage (toutes polices).
    Taille pilotée par --vn-scale (réglage « Taille du texte » du compte) — la bulle est fixe, la pagination re-mesure.
    Police VN choisie (compte) — la pagination re-mesure après chargement, donc rien ne déborde. */
  #vn-text.pop { animation:vnPop .18s ease; }   /* VN6 : apparition douce de chaque page */
  @keyframes vnPop { from { opacity:0; transform:translateY(3px); } to { opacity:1; } }
  #vn-text.narr { font-style:italic; color:#dce3ee; }
  #vn-text.user { color:#dbe7d5; }                              /* replique du joueur (relecture) */
  #vn-text.dice { font-family:ui-monospace,monospace; font-size:calc(16px * var(--vn-scale, 1)); color:#e8d78a; }   /* ligne de des */
  #vn-hint { align-self:flex-end; margin-top:4px; font-size:12px; color:#8fa0bd; opacity:.85; pointer-events:none; }
  #vn-exit { position:absolute; top:12px; right:14px; z-index:2; background:rgba(0,0,0,.45); color:#cdd6e6;
    border:1px solid var(--line); border-radius:8px; padding:5px 12px; cursor:pointer; font:inherit; }
  #vn-reply { position:absolute; left:50%; bottom:22px; transform:translateX(-50%); width:min(880px,94%);
    display:none; gap:8px; z-index:4; }
  #vn.await #vn-reply { display:flex; }
  #vn.await #vn-box { display:none; }
  #vn-reply input { flex:1; background:rgba(12,16,26,.92); color:#eef2f8; border:1px solid rgba(140,180,240,.5);
    border-radius:10px; padding:12px 14px; font:inherit; font-size:16px; }
  #vn-reply button { background:#3a4a66; color:#fff; border:none; border-radius:10px; padding:0 18px; cursor:pointer; font:inherit; }
  /* ---- PC HAUTE RÉSOLUTION : la scène s'ADAPTE — grand écran = bulle + police + sprites plus
     grands (sinon une bulle de 880px et 19px de texte semblent minuscules sur du 1440p/4K). Le
     gabarit de base garde sa hauteur FIXE (contrat image) ; on ne fait que le monter par paliers. ---- */
  @media (min-width:1500px){
    #vn-box { width:min(1120px,82%); height:224px; padding:22px 36px 16px; }
    #vn-stage { inset:0 0 224px 0; }                 /* sprites remontés au niveau de la bulle plus haute */
    #vn-text { font-size:calc(23px * var(--vn-scale, 1)); line-height:1.72; }
    #vn-name { font-size:17px; top:-18px; }
    #vn-hint { font-size:13px; }
    #vn-loc { font-size:13px; letter-spacing:.2em; }
    #vn-clock { font-size:12px; }
    #vn-reply { width:min(1120px,82%); }
    #vn-reply input { font-size:18px; padding:14px 18px; }
    .vn-sprite.art img { max-width:min(700px,40vw); }
    .vn-sprite { height:92%; }
  }
  @media (min-width:2100px){
    #vn-box { width:min(1400px,72%); height:272px; padding:28px 44px 20px; }
    #vn-stage { inset:0 0 272px 0; }
    #vn-text { font-size:calc(28px * var(--vn-scale, 1)); line-height:1.75; }
    #vn-name { font-size:20px; top:-21px; padding:4px 20px; }
    #vn-hint { font-size:15px; }
    #vn-loc { font-size:15px; }
    #vn-clock { font-size:13px; }
    #vn-reply { width:min(1400px,72%); }
    #vn-reply input { font-size:21px; padding:16px 20px; }
    .vn-sprite.art img { max-width:min(840px,38vw); }
  }
  @media (min-width:3200px){   /* 4K (3840px+) : sinon la bulle de 1400px et 28px de texte redeviennent petits */
    #vn-box { width:min(2050px,62%); height:348px; padding:36px 56px 26px; }
    #vn-stage { inset:0 0 348px 0; }
    #vn-text { font-size:calc(37px * var(--vn-scale, 1)); line-height:1.75; }
    #vn-name { font-size:27px; top:-27px; padding:6px 28px; }
    #vn-hint { font-size:20px; }
    #vn-loc { font-size:20px; }
    #vn-clock { font-size:17px; }
    #vn-reply { width:min(2050px,62%); }
    #vn-reply input { font-size:27px; padding:20px 26px; }
    .vn-sprite.art img { max-width:min(1180px,34vw); }
  }
  /* ---- TELEPHONE (<=760px) : le VN prend TOUT l'ecran (il couvre le topbar, ✕ pour sortir),
     UN seul sprite (gere en JS, vnStageMax), plus GRAND et centre ; controles compacts qui ne
     chevauchent plus Quitter ; bulle adaptee ; decor en cover centre (crop lateral assume). ---- */
  @media (max-width:760px){
    #vn { inset:0; }
    #vn-ctl { gap:4px; left:8px; top:8px; max-width:calc(100% - 70px); flex-wrap:wrap; }
    #vn-ctl button { padding:4px 8px; font-size:12px; }
    #vn-exit { top:8px; right:8px; font-size:0; padding:6px 10px; }
    #vn-exit::before { content:"✕"; font-size:15px; }
    #vn-loc { top:44px; padding:0 56px; font-size:10.5px; letter-spacing:.12em; }
    #vn-stage { inset:0 0 190px 0; }                 /* remonté au niveau de la bulle plus haute */
    .vn-sprite { width:min(260px,58vw); height:64%; }
    .vn-sprite.art img { max-width:80vw; }
    .vn-sprite.enter.l { --fx:-70vw; }
    .vn-sprite.enter.r { --fx:70vw; }
    #vn-box { height:184px; padding:14px 17px 12px; bottom:calc(8px + env(safe-area-inset-bottom, 0px)); }
    #vn-text { font-size:calc(16px * var(--vn-scale, 1)); line-height:1.62; }
    #vn-text.dice { font-size:calc(13.5px * var(--vn-scale, 1)); }
    #vn-name { left:12px; top:-14px; font-size:13.5px; padding:2px 12px; }
    #vn-log { inset:44px 8px 175px; }
    #vn-log-list { padding:10px 12px; }
    #vn-reply { bottom:calc(8px + env(safe-area-inset-bottom, 0px)); width:calc(100% - 16px); }
  }
  /* VN6 : accessibilite — pas d'animations si l'OS demande la reduction de mouvement */
  @media (prefers-reduced-motion: reduce){
    .vn-bg-layer, #vn-loc { transition:none; }
    #vn-text.pop { animation:none; }
    #vn-veil.blink { animation:none; }
    .vn-sprite { transition:filter .25s, box-shadow .25s; }
  }

  /* ===== SKIN « Cristal » — bulle de dialogue VN (cadran façon JRPG cyan). Le FOND reste piloté par
     --vn-bubble (déjà personnalisable : image / monde plus tard) ; on n'ajoute QUE le cadre orné + la
     plaque de nom, theme-aware (prend var(--accent)). Toujours 100 % CSS, aucun asset. ===== */
  [data-skin="cristal"] #vn-box {
    border:1px solid color-mix(in srgb, var(--accent) 70%, rgba(140,180,240,.5)); border-radius:13px;
    box-shadow:0 8px 40px rgba(0,0,0,.55), 0 0 24px -5px var(--accent),
      inset 0 0 34px -8px color-mix(in srgb, var(--accent) 34%, transparent); }
  [data-skin="cristal"] #vn-box::before {   /* double liseré d'accent, en retrait du bord */
    content:""; position:absolute; inset:5px; pointer-events:none; border-radius:9px;
    border:1px solid color-mix(in srgb, var(--accent) 62%, transparent);
    box-shadow:inset 0 0 26px -13px var(--accent); }
  [data-skin="cristal"] #vn-box::after {    /* équerres de coin (à droite) */
    content:""; position:absolute; inset:4px; pointer-events:none;
    background:
      linear-gradient(var(--accent),var(--accent)) 100% 0 / 26px 2px no-repeat,
      linear-gradient(var(--accent),var(--accent)) 100% 0 / 2px 26px no-repeat,
      linear-gradient(var(--accent),var(--accent)) 100% 100% / 26px 2px no-repeat,
      linear-gradient(var(--accent),var(--accent)) 100% 100% / 2px 26px no-repeat;
    filter:drop-shadow(0 0 3px var(--accent)); }
  [data-skin="cristal"] #vn-name {          /* PLAQUE de nom biseautée + glow (élément signature) */
    background:linear-gradient(120deg, color-mix(in srgb, var(--accent) 52%, var(--panel)), color-mix(in srgb, var(--accent) 22%, var(--panel)));
    border:1px solid color-mix(in srgb, var(--accent) 78%, transparent); border-radius:0; padding-right:26px;
    clip-path:polygon(0 0, 100% 0, calc(100% - 13px) 100%, 0 100%);
    box-shadow:0 2px 10px rgba(0,0,0,.5), 0 0 13px -3px var(--accent); }
