/* escape.css -- Annabel's Room: THE ESCAPE ROOM mode layer ("The Vanishing Tutor").
   A full-bleed haunted-study scene that WRAPS the existing question engine -- the
   relocated .qcard becomes the rising "puzzle sheet". Pure CSS/SVG/WebAudio, zero
   image/video assets. Reuses Annabel's dark-theme tokens (--bg0, --cyan, --lime,
   --xp, ...) from annabel.css and adds two driver tokens:
     --warmth  0 -> 1   progressive un-haunting (the room IS the progress bar)
     --crack   0 -> 1   the door seam widening, lock by lock
   Accessibility rails (Lewis, non-negotiable): eerie-fun never frightening, no
   jump-scares, no fade-to-black, all flicker/jitter <=2Hz (seizure-safe), targets
   >=44px, prefers-reduced-motion collapses every sweep to an instant cross-fade,
   audio is behind the existing mute and never required to solve. */

:root{
  --warmth:0;            /* lifted toward 1 as locks clear */
  --crack:0;             /* door seam 0..1 */
  --ghost:#22D3EE;       /* cyan ghost-glow (cold) */
  --slime:#A3E635;       /* lime (cold accent) */
  --gold:#FBBF24;        /* the one warm note */
}

/* ===================== SCENE ROOT ===================== */
/* Hidden until escape starts. When .escape-on is on <body>, the normal room chrome
   is suppressed and this full-bleed scene takes over. */
.escape-root{position:fixed;inset:0;z-index:40;overflow:hidden;display:none;
  /* cold->warm base wash driven by --warmth; stays readable at every step */
  background:
    radial-gradient(120% 90% at 50% 120%,
      color-mix(in srgb, #2A1B12 calc(var(--warmth)*100%), #0E0B22) 0%,
      var(--bg0) 70%),
    linear-gradient(180deg, #0A081A, #0C0A1C 60%, #07060F);
  color:var(--ink);
  font-family:'Inter',system-ui,sans-serif;
}
body.escape-on .escape-root{display:block;}
/* suppress the normal room while in the escape scene (the qcard is relocated into it) */
body.escape-on .topbar,
body.escape-on .hud,
body.escape-on .modes,
body.escape-on .levelbanner,
body.escape-on .helprow,
body.escape-on .reaction,
body.escape-on .pbtoast{display:none!important;}
body.escape-on .app{max-width:none;padding:0;}
body.escape-on{overflow:hidden;}

/* ===================== INTERACTIVE SCROLL LAYER ===================== */
/* The fix for the "scene extends over the page, can't click the controls" bug:
   .escape-root is a viewport-locked, overflow:hidden STAGE that clips the decorative
   atmosphere (vignette/fog/candle/web/caustic/motes -- all pointer-events:none, z 1..6).
   Every INTERACTIVE thing (leave/mute bar, locks, the relocated qcard + keypad + submit,
   the "I'm stuck" help) lives inside .escape-scroll, which scrolls WITHIN the viewport so
   nothing is ever clipped beyond reach -- even when the door+portrait+locks+sheet are
   taller than a phone screen. It sits ABOVE the decorative layers (z-index:10) with
   pointer-events:auto; the atmosphere stays pinned behind it. */
.escape-scroll{position:absolute;inset:0;z-index:10;pointer-events:auto;
  display:flex;flex-direction:column;align-items:stretch;
  overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  /* breathing room so the Submit button never sits flush against the bottom edge / home indicator */
  padding-bottom:calc(env(safe-area-inset-bottom, 0px) + 28px);}

/* a soft vignette + drifting fog at the base (warmth thins the gloom) */
.escape-vignette{position:absolute;inset:0;pointer-events:none;z-index:1;
  background:radial-gradient(110% 80% at 50% 38%, transparent 40%, rgba(2,1,8,.7) 100%);
  opacity:calc(1 - var(--warmth)*.55);transition:opacity 1.2s ease;}
.escape-fog{position:absolute;left:-10%;right:-10%;bottom:-6%;height:42%;pointer-events:none;z-index:2;
  background:radial-gradient(60% 100% at 30% 100%, rgba(34,211,238,.10), transparent 70%),
            radial-gradient(60% 100% at 75% 100%, rgba(163,230,53,.08), transparent 70%);
  filter:blur(8px);opacity:calc(1 - var(--warmth)*.7);
  animation:escFog 14s ease-in-out infinite;transition:opacity 1.2s ease;}
@keyframes escFog{0%,100%{transform:translateX(0);}50%{transform:translateX(3%);}}

/* candle-flicker: a slow radial breathe (>=4s, never a strobe) */
.escape-candle{position:absolute;top:10%;left:8%;width:46vmin;height:46vmin;pointer-events:none;z-index:2;
  background:radial-gradient(circle at 50% 50%, rgba(251,191,36,.16), transparent 62%);
  animation:escFlicker 4.2s ease-in-out infinite;
  opacity:calc(.5 + var(--warmth)*.5);transition:opacity 1.2s ease;}
@keyframes escFlicker{0%,100%{opacity:.55;transform:scale(1);}45%{opacity:.78;transform:scale(1.03);}70%{opacity:.6;}}

/* cobwebs in two corners -> dissolve to gold motes as warmth rises */
.escape-web{position:absolute;width:24vmin;height:24vmin;pointer-events:none;z-index:3;opacity:calc(.5 - var(--warmth)*.5);
  transition:opacity 1.2s ease;}
.escape-web.tl{top:0;left:0;}
.escape-web.tr{top:0;right:0;transform:scaleX(-1);}
.escape-web svg{width:100%;height:100%;stroke:rgba(167,139,250,.45);fill:none;stroke-width:1;}

/* neon EXIT sign -- dead (dim) until the escape, then blooms */
.escape-exit{position:absolute;top:6%;right:7%;z-index:4;font-family:'Space Grotesk',sans-serif;font-weight:700;
  letter-spacing:3px;font-size:clamp(14px,2.4vmin,22px);padding:6px 12px;border-radius:9px;
  border:2px solid rgba(52,211,153,.25);color:rgba(52,211,153,.35);
  text-shadow:none;box-shadow:none;transition:all 1.2s ease;}
body.escape-on .escape-root.escape-exhale .escape-exit{
  color:#8affc0;border-color:#34D399;text-shadow:0 0 14px rgba(52,211,153,.9);
  box-shadow:0 0 24px rgba(52,211,153,.55);animation:escExitBuzz 2.6s ease-in-out infinite;}
@keyframes escExitBuzz{0%,100%{opacity:1;}48%{opacity:.86;}}

/* ===================== TOP BAR (in-scene) ===================== */
.escape-bar{position:relative;z-index:12;display:flex;align-items:center;gap:10px;
  padding:12px 14px;}
.escape-leave{display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:8px 13px;border-radius:12px;
  background:rgba(255,255,255,.07);border:1px solid var(--line);color:var(--muted);cursor:pointer;
  font-family:'Space Grotesk';font-weight:600;font-size:13.5px;}
.escape-leave:active{transform:scale(.96);}
.escape-progress{margin-left:auto;display:flex;align-items:center;gap:8px;}
.escape-locktag{font-family:'Space Grotesk';font-weight:700;font-size:13px;color:var(--ghost);
  background:rgba(34,211,238,.12);border:1px solid rgba(34,211,238,.4);border-radius:10px;padding:6px 11px;letter-spacing:.4px;}
.escape-mute{width:44px;height:44px;min-width:44px;border-radius:12px;border:1px solid var(--line);
  background:rgba(255,255,255,.07);display:grid;place-items:center;cursor:pointer;}
.escape-mute .material-icons-round{font-size:23px;color:var(--ink);}
.escape-mute.muted{background:rgba(251,191,36,.16);border-color:rgba(251,191,36,.5);}
.escape-mute.muted .material-icons-round{color:var(--gold);}

/* ===================== STAGE (door + portrait + locks) ===================== */
.escape-stage{position:relative;z-index:10;display:flex;flex-direction:column;align-items:center;
  padding:2px 14px 8px;}

/* THE DOOR -- a single SVG that deforms via --crack (seam widens, then swings on win) */
.escape-doorwrap{position:relative;width:min(64vmin,360px);height:min(48vmin,270px);
  perspective:1100px;margin:2px auto 6px;}
.escape-door{width:100%;height:100%;transform-style:preserve-3d;transition:transform 1.2s cubic-bezier(.3,.8,.3,1);}
.escape-doorwrap.open .escape-door{transform:rotateY(72deg) translateX(-6%);}
.escape-door svg{width:100%;height:100%;display:block;overflow:visible;}
/* the gold beam that floods through the opening gap (revealed on win) */
.escape-beam{position:absolute;inset:0;z-index:-1;border-radius:18px;opacity:0;pointer-events:none;
  background:radial-gradient(60% 90% at 50% 50%, rgba(251,191,36,.9), rgba(251,146,60,.35) 45%, transparent 75%);
  filter:blur(6px);transition:opacity 1.1s ease;}
.escape-doorwrap.open .escape-beam{opacity:1;}

/* THE LYING PORTRAIT -- rendered SVG/CSS face that lies + glitches */
.escape-portrait{position:relative;z-index:11;width:min(30vmin,150px);margin:-10px auto 2px;}
.escape-portrait .frame{position:relative;border-radius:50%/46%;padding:8px;
  background:linear-gradient(160deg,#3A2A1E,#1d140d);
  box-shadow:0 0 0 3px rgba(120,90,50,.5), 0 10px 30px rgba(0,0,0,.6), inset 0 0 18px rgba(0,0,0,.6);}
.escape-portrait svg{width:100%;height:auto;display:block;border-radius:50%/46%;
  background:radial-gradient(circle at 50% 38%, #241a3a, #0b0818);}
/* the chromatic-aberration glitch: duplicate face layers offset cyan/lime (<=2Hz) */
.escape-portrait.glitch .face-r{transform:translate(2px,0);filter:drop-shadow(2px 0 0 rgba(34,211,238,.7));}
.escape-portrait.glitch .face-b{transform:translate(-2px,0);filter:drop-shadow(-2px 0 0 rgba(163,230,53,.7));}
.escape-portrait.glitch{animation:escGlitch 1.6s steps(2,end) infinite;}   /* ~1.25Hz step, seizure-safe */
@keyframes escGlitch{0%,100%{transform:translate(0,0);}50%{transform:translate(1px,-1px);}}

/* the Potato reveal layer (hidden until capitulation) */
.escape-portrait .potato{position:absolute;inset:8px;border-radius:50%/46%;display:grid;place-items:center;
  font-size:min(16vmin,86px);opacity:0;transform:scale(.7);transition:opacity .6s ease, transform .6s cubic-bezier(.2,1.5,.4,1);
  background:radial-gradient(circle at 50% 40%, #FFE9A8, #caa24a);}
.escape-portrait.revealed .potato{opacity:1;transform:scale(1);}
.escape-portrait.revealed svg{opacity:0;transition:opacity .4s ease;}

/* speech the Portrait dictates (its lies + taunts + capitulation) */
.escape-speech{position:relative;z-index:11;max-width:560px;margin:6px auto 0;text-align:center;
  font-family:'Space Grotesk';font-weight:600;font-size:clamp(14px,2.1vmin,17px);line-height:1.45;
  color:var(--ink);min-height:1.4em;padding:0 10px;}
.escape-speech .liar{color:var(--ghost);}
/* the dictated FAKE target/number visibly glitches + is struck through */
.escape-lie{position:relative;display:inline-block;font-weight:700;color:#ff6b9d;text-decoration:line-through;
  text-decoration-color:rgba(255,107,157,.7);animation:escLieJitter 1.8s steps(3,end) infinite;}
@keyframes escLieJitter{0%,100%{transform:translate(0,0);}33%{transform:translate(.6px,-.4px);}66%{transform:translate(-.6px,.4px);}}
.escape-lie.shattered{animation:none;opacity:0;transition:opacity .35s ease;}
.escape-truth{font-weight:800;color:var(--lime);text-shadow:0 0 10px rgba(163,230,53,.5);}

/* THE LOCK CHAIN -- 6 hex medallions; rail across the top (landscape) / wraps (portrait) */
.escape-locks{position:relative;z-index:11;display:flex;gap:9px;justify-content:center;flex-wrap:wrap;
  margin:8px auto 2px;max-width:560px;}
.escape-lock{width:46px;height:46px;min-width:46px;position:relative;display:grid;place-items:center;
  font-size:20px;border-radius:14px;border:1px solid rgba(167,139,250,.3);
  background:rgba(167,139,250,.06);color:rgba(171,164,214,.5);transition:all .5s ease;}
.escape-lock .num{position:absolute;bottom:-7px;right:-5px;width:18px;height:18px;border-radius:50%;
  font-family:'Space Grotesk';font-weight:700;font-size:11px;display:grid;place-items:center;
  background:#1b1338;border:1px solid var(--line);color:var(--muted);}
.escape-lock.active{border-color:var(--ghost);background:rgba(34,211,238,.14);color:var(--ghost);
  box-shadow:0 0 16px rgba(34,211,238,.5);animation:escLockPulse 2.4s ease-in-out infinite;}
@keyframes escLockPulse{0%,100%{box-shadow:0 0 12px rgba(34,211,238,.4);}50%{box-shadow:0 0 20px rgba(34,211,238,.75);}}
.escape-lock.open{border-color:var(--green);background:rgba(52,211,153,.16);color:var(--green);
  box-shadow:0 0 16px rgba(52,211,153,.5);}
.escape-lock.open .num{background:var(--green);color:#04261a;border-color:var(--green);}

/* the active lock casts a slow-rotating rune-caustic onto the "floor" */
.escape-caustic{position:absolute;left:50%;bottom:8%;width:70vmin;height:30vmin;transform:translateX(-50%);
  z-index:5;pointer-events:none;opacity:calc(.5 - var(--warmth)*.4);
  background:conic-gradient(from 0deg, transparent, rgba(34,211,238,.18) 12%, transparent 28%, rgba(163,230,53,.12) 55%, transparent 72%);
  -webkit-mask-image:radial-gradient(closest-side, #000, transparent);mask-image:radial-gradient(closest-side, #000, transparent);
  animation:escSpin 8s linear infinite;filter:blur(3px);transition:opacity 1.2s ease;}
@keyframes escSpin{to{transform:translateX(-50%) rotate(360deg);}}

/* ===================== PUZZLE SHEET (the relocated qcard) ===================== */
.escape-puzzle{position:relative;z-index:13;max-width:560px;margin:6px auto 0;padding:0 12px 18px;}
/* the relocated .qcard rises from the bottom and is restyled for the scene */
body.escape-on .escape-puzzle .qcard{animation:escRise .45s cubic-bezier(.2,.9,.3,1);
  background:linear-gradient(165deg, rgba(28,18,64,.92), rgba(14,10,32,.96));
  border:1px solid var(--line-bright);box-shadow:0 -8px 40px rgba(0,0,0,.5), 0 0 30px rgba(34,211,238,.12);}
@keyframes escRise{from{transform:translateY(30px);opacity:0;}to{transform:translateY(0);opacity:1;}}
/* hide the normal Q-head counters; the scene shows the lock tag instead */
body.escape-on .escape-puzzle .qhead{display:none;}
body.escape-on .escape-puzzle .qcard{padding:18px;}

/* the in-sheet "I'm stuck" affordance (re-explain, never a dead-end) */
.escape-help{display:flex;gap:10px;margin-top:14px;}
.escape-help button{flex:1;min-height:46px;border-radius:13px;cursor:pointer;border:1px solid rgba(167,139,250,.5);
  background:rgba(255,255,255,.05);color:var(--ink);font-family:'Space Grotesk';font-weight:600;font-size:13.5px;
  display:flex;align-items:center;justify-content:center;gap:7px;}
.escape-help button:active{transform:scale(.97);}

/* ===================== ESCAPE OVERLAYS ===================== */
/* reuse the base .overlay/.sheet from annabel.css; add escape skins */
.sheet.escape-sheet{background:linear-gradient(165deg, rgba(30,20,68,.97), rgba(12,9,28,.98));
  border:1.5px solid var(--line-bright);box-shadow:0 20px 60px rgba(0,0,0,.7), 0 0 34px rgba(34,211,238,.22);text-align:center;}
.sheet.escape-sheet .icon{filter:drop-shadow(0 0 16px rgba(34,211,238,.55));}
.escape-shardart{font-size:54px;line-height:1;margin:4px 0;filter:drop-shadow(0 0 16px rgba(34,211,238,.7));
  animation:escShardSpin 3.4s ease-in-out infinite;}
@keyframes escShardSpin{0%,100%{transform:rotate(-6deg) scale(1);}50%{transform:rotate(6deg) scale(1.08);}}
.escape-shardval{display:inline-block;margin-top:6px;font-family:'Space Grotesk';font-weight:800;font-size:30px;
  color:var(--ghost);text-shadow:0 0 14px rgba(34,211,238,.6);}
.escape-portraitline{font-style:italic;color:var(--muted);margin-top:8px;font-size:15px;}

/* the WIN sheet -- warm gold, the one warm note */
.sheet.escape-win{background:linear-gradient(160deg, rgba(74,52,18,.97), rgba(40,24,10,.98));
  border:1.5px solid var(--gold);box-shadow:0 20px 60px rgba(0,0,0,.7), 0 0 40px rgba(251,191,36,.45);text-align:center;}
.sheet.escape-win h3{color:#ffe39a;text-shadow:0 0 16px rgba(251,191,36,.7);}
.sheet.escape-win .icon{filter:drop-shadow(0 0 20px rgba(251,191,36,.85));}
.escape-skillback{text-align:left;background:rgba(0,0,0,.28);border:1px solid rgba(251,191,36,.4);border-radius:16px;
  padding:14px 16px;margin-top:14px;}
.escape-skillback .s{display:flex;gap:10px;align-items:flex-start;margin:8px 0;font-size:15px;line-height:1.4;color:var(--ink);}
.escape-skillback .s .tick{color:var(--gold);font-weight:800;flex:none;}
.escape-codeline{font-family:'Space Grotesk';font-weight:800;letter-spacing:6px;font-size:30px;color:var(--gold);
  text-shadow:0 0 16px rgba(251,191,36,.6);margin-top:10px;}

/* finale shard-tray + ordering tiles (reuses choice/seq look) */
.escape-tray{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin:14px 0 4px;}
.escape-shardchip{min-width:52px;min-height:52px;padding:8px 10px;border-radius:13px;display:grid;place-items:center;
  font-family:'Space Grotesk';font-weight:800;font-size:20px;cursor:pointer;position:relative;
  background:rgba(34,211,238,.10);border:1px solid rgba(34,211,238,.45);color:var(--ghost);transition:all .15s;}
.escape-shardchip:active{transform:scale(.95);}
.escape-shardchip.picked{background:rgba(163,230,53,.16);border-color:var(--lime);color:var(--lime);}
.escape-shardchip.hidden-frac{color:#ff9bd0;border-color:rgba(255,155,208,.5);background:rgba(255,155,208,.08);font-size:14px;}
.escape-shardchip .ord{position:absolute;top:-8px;left:-6px;width:20px;height:20px;border-radius:50%;font-size:11px;
  display:grid;place-items:center;background:var(--lime);color:#15280a;font-weight:800;}
.escape-finale-q{font-family:'Space Grotesk';font-weight:600;font-size:15.5px;color:var(--lime);margin:6px 0 2px;}

/* held-silence freeze on the win beat (the most charged, but safe, moment) */
.escape-root.escape-frozen .escape-fog,
.escape-root.escape-frozen .escape-candle,
.escape-root.escape-frozen .escape-caustic,
.escape-root.escape-frozen .escape-lock.active{animation-play-state:paused!important;}

/* the gold crack that races up the door on win (SVG path animated via JS class) */
.escape-door .crackline{stroke:var(--gold);stroke-width:2.4;fill:none;filter:drop-shadow(0 0 6px rgba(251,191,36,.9));
  stroke-dasharray:1;stroke-dashoffset:1;}
.escape-door.cracked .crackline{animation:escCrackRace 1.1s ease forwards;}
@keyframes escCrackRace{to{stroke-dashoffset:0;}}

/* gold motes that replace cobwebs on un-haunting */
.escape-mote{position:absolute;width:5px;height:5px;border-radius:50%;background:var(--gold);z-index:6;pointer-events:none;
  opacity:0;box-shadow:0 0 8px rgba(251,191,36,.9);}
.escape-root.escape-exhale .escape-mote{animation:escMote 3.4s ease-in-out infinite;}
@keyframes escMote{0%{opacity:0;transform:translateY(0);}30%{opacity:.9;}100%{opacity:0;transform:translateY(-40px);}}

/* ===================== RESPONSIVE ===================== */
@media (max-width:560px){
  .escape-doorwrap{width:min(78vmin,300px);height:min(58vmin,220px);}
  .escape-lock{width:42px;height:42px;min-width:42px;font-size:18px;}
}
@media (min-width:560px) and (orientation:landscape){
  .escape-stage{padding-top:0;}
  .escape-doorwrap{width:min(40vmin,330px);height:min(30vmin,250px);}
}

/* ===================== REDUCED MOTION (Lewis hard gate) ===================== */
/* annabel.css already neutralises animation globally under reduce; this makes the
   intent explicit for the scene: sweeps/flicker/glitch become instant cross-fades,
   nothing that conveys progress depends on motion. */
@media (prefers-reduced-motion:reduce){
  .escape-vignette,.escape-fog,.escape-candle,.escape-caustic,
  .escape-portrait.glitch,.escape-lie,.escape-exit,.escape-shardart,
  .escape-door,.escape-mote,.escape-lock.active{animation:none!important;}
  .escape-door{transition:none!important;}
  .escape-portrait.glitch .face-r,.escape-portrait.glitch .face-b{transform:none!important;filter:none!important;}
  .escape-lie{animation:none!important;}            /* still struck-through, just static */
  body.escape-on .escape-puzzle .qcard{animation:none!important;}
}
