:root{
  --h:2;          /* hue of the room lights, set per threat level */
  --acc:#d9a400;
  --panel:#e2e2dd;
  --ink:#141414;
  --scr:#0b110b;
  --term:#070a07;
  --mono:"IBM Plex Mono",ui-monospace,Consolas,monospace;
}
.lvl-1{--acc:#2fbf4a;--h:125}
.lvl-2{--acc:#d9a400;--h:50}
.lvl-3{--acc:#f07a14;--h:26}
.lvl-4{--acc:#e0201b;--h:2}
.lvl-5{--acc:#ff1414;--h:0}

*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{background:#fff;color:var(--ink);font-family:"Open Sans",system-ui,sans-serif;overflow-x:hidden}
[hidden]{display:none!important}

/* ================= GATE ================= */
#gate{min-height:100vh;padding:16px;display:flex;justify-content:center;background:#fff}
.gate-badge{position:fixed;top:8px;left:9px;width:48px;height:48px;border:1px solid #ddd;border-radius:4px;background:#fff;display:grid;place-items:center}
.gate-badge svg{width:36px;height:36px}
.gb-s{fill:none;stroke:var(--acc);stroke-width:2.4}
.gb-f{fill:var(--acc)}
.gate-inner{width:100%;max-width:384px;margin-top:84px;text-align:center}
.gate-art svg{width:220px;max-width:70%;height:auto}
.tri-f,.ear{fill:var(--acc);opacity:.6}
.lvl-5 .tri{animation:shake .25s infinite}
.gate-domain{font-size:28px;font-weight:600;color:#333;margin:10px 0 50px;letter-spacing:.2px}
.gate-box{position:relative;border:1px solid var(--acc);border-radius:2px;padding:30px 20px 22px}
.gate-tab{position:absolute;left:50%;top:0;transform:translate(-50%,-100%);white-space:nowrap;
  background:var(--acc);color:#fff;font-weight:700;font-size:16px;padding:8px 26px 7px;
  clip-path:polygon(10px 0,calc(100% - 10px) 0,100% 100%,0 100%);border-radius:10px 10px 0 0}
.lvl-1 .gate-tab,.lvl-2 .gate-tab{color:#1a1a1a}
.lvl-5 .gate-tab{animation:flash .6s steps(1) infinite}
.gate-box p{font-size:14px;line-height:1.25;color:#333;margin:0 0 14px}
.gate-meter{margin:0 0 16px}
.gm-segs{display:flex;gap:4px;justify-content:center}
.gm-segs i{width:44px;height:8px;background:#e6e6e2;border-radius:1px}
.gm-segs i.on{background:var(--acc)}
.gm-text{font:12px var(--mono);color:#555;margin-top:6px}
.gate-btn{display:inline-block;background:#0a72d4;color:#fff;text-decoration:none;font-size:16px;padding:6px 31px;border-radius:1px}
.gate-btn:hover{background:#0860b4}
.gate-check{display:inline-flex;align-items:center;gap:8px;margin:18px 0 8px;font-size:14px;color:#444;font-weight:300;cursor:pointer}
.gate-check input{width:16px;height:16px;accent-color:#0a72d4}
.gate-continue{display:block;margin:4px auto 0;background:none;border:0;color:#0a72d4;font:600 16px "Open Sans",sans-serif;cursor:pointer;padding:6px}
.gate-continue:hover{text-decoration:underline}
.gate-fine{margin-top:60px;font-size:11px;color:#aaa;line-height:1.4}
.lvl-5 #gate{animation:redwash 1.2s ease-in-out infinite}

/* ================= ROOM ================= */
#room{position:relative;height:100vh;height:100dvh;min-height:560px;background:#050202;overflow:hidden}
/* the art is 1536×1024; the stage covers the viewport, its lowest 8% (front of the floor) sits below the screen edge,
   and everything on it is placed in % of the art */
#stage{position:absolute;left:50%;bottom:0;width:max(100vw,calc(max(100vh,560px) * 1.5 / .92));aspect-ratio:1536/1024;transform:translateX(-50%) translateY(8%);
  container-type:inline-size}
#beam-grad stop{stop-color:hsl(var(--h) 100% 55%)}
/* the procedural room (scene.js): base metal, lit/moving machines, bloom, dust */
.scene{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
#scene-bloom{mix-blend-mode:screen;opacity:.95}
#scene-air{mix-blend-mode:screen}
/* signal interference over the whole room (operator turning round) */
#snow{position:absolute;inset:0;width:100%;height:100%;z-index:32;pointer-events:none;opacity:0;image-rendering:pixelated;mix-blend-mode:normal}
/* the stare: eye charge and red flash */
#eyeflare{position:absolute;width:0;height:0;z-index:34;pointer-events:none}
#eyeflare::before{content:"";position:absolute;left:0;top:0;width:24px;height:24px;border-radius:50%;transform:translate(-50%,-50%) scale(0);
  background:radial-gradient(circle,#fff 0,#ff3b30 25%,rgba(255,0,0,.55) 50%,transparent 72%);opacity:0}
#eyeflare.charge::before{animation:eye-charge .52s ease-in forwards}
#eyeflare.fire::before{animation:eye-fire .5s ease-out forwards}
@keyframes eye-charge{0%{opacity:.4;transform:translate(-50%,-50%) scale(.3)}70%{opacity:1;transform:translate(-50%,-50%) scale(2.2)}
  85%{transform:translate(-50%,-50%) scale(1.6)}100%{opacity:1;transform:translate(-50%,-50%) scale(3.4)}}
@keyframes eye-fire{0%{opacity:1;transform:translate(-50%,-50%) scale(3.4)}100%{opacity:0;transform:translate(-50%,-50%) scale(70)}}
#impact{position:absolute;inset:0;z-index:35;pointer-events:none;opacity:0}
#impact::before{content:"";position:absolute;inset:0;background:radial-gradient(circle at var(--cx) var(--cy),rgba(255,255,255,.95),rgba(255,30,20,.8) 18%,rgba(140,0,0,.55) 55%,rgba(40,0,0,.6));opacity:0}
#impact.hit{opacity:1}
#impact.hit::before{animation:impact-flash .55s ease-out forwards}
#impact.fade{opacity:0;transition:opacity .8s ease}
@keyframes impact-flash{0%{opacity:1}15%{opacity:.85}100%{opacity:.18}}
#room.interfere::before{content:"";position:absolute;inset:0;z-index:33;pointer-events:none;
  background:repeating-linear-gradient(0deg,rgba(0,0,0,.45) 0 2px,transparent 2px 4px);animation:interfere .07s steps(2) infinite}
@keyframes interfere{0%{background-position:0 0}50%{background-position:0 3px}}
#room::after{content:"";position:absolute;inset:0;z-index:30;pointer-events:none;
  background:radial-gradient(ellipse 75% 70% at 50% 48%,transparent 55%,rgba(0,0,0,.6))}

@keyframes shake{25%{transform:translate(1px,-1px)}75%{transform:translate(-1px,1px)}}
@keyframes flash{50%{background:#1a1a1a}}
@keyframes redwash{50%{background:#fff1f1}}

/* terminal: sits exactly over the one painted in the art */
#term{position:absolute;left:26.89%;top:46.78%;width:46.09%;height:27.34%;
  background:#030101;border:1px solid hsl(var(--h) 71% 13%);color:hsl(var(--h) 73% 55%);font:clamp(10px,.95cqw,15px)/1.42 var(--mono);
  display:flex;flex-direction:column;padding:.9cqw 1.1cqw .6cqw;box-shadow:0 0 30px hsl(var(--h) 100% 52% / .18),inset 0 0 40px hsl(var(--h) 100% 52% / .05)}
.t-head{display:flex;gap:1.1cqw;flex-wrap:wrap;color:hsl(var(--h) 61% 45%)}
.t-head b{color:hsl(var(--h) 100% 68%)}
#th-lvl,#th-name{color:#fff!important;font-weight:600}
.lvl-5 #th-name{animation:blink .6s steps(1) infinite}
.t-dots{margin-left:auto;color:hsl(var(--h) 100% 59%)}
.t-sub{margin:.6cqw 0 .5cqw;color:hsl(var(--h) 60% 34%);line-height:1.5}
.t-sub span{color:hsl(var(--h) 61% 27%)}
.t-feed{flex:1;overflow-y:auto;scrollbar-width:thin;scrollbar-color:hsl(var(--h) 71% 13%) transparent;white-space:pre-wrap;word-break:break-word}
.t-feed div{color:hsl(var(--h) 67% 54%)}
.t-feed div:last-child{color:hsl(var(--h) 100% 75%)}
.t-feed .ts{color:hsl(var(--h) 60% 34%)}
.t-feed .buy{color:hsl(var(--h) 35% 92%)}
.t-feed .sell{color:hsl(var(--h) 100% 59%);font-weight:600}
.t-feed .sys{color:#fff;font-weight:600;text-shadow:0 0 8px hsl(var(--h) 100% 55%)}
.t-feed .dim{color:hsl(var(--h) 56% 42%)}
.t-feed .addr{color:hsl(var(--h) 73% 55%)}
.t-input{display:flex;gap:8px;align-items:center;border:1px solid hsl(var(--h) 68% 17%);border-radius:3px;padding:.25cqw .6cqw;margin-top:.5cqw}
.t-input span{color:hsl(var(--h) 60% 34%)}
.t-input input{flex:1;min-width:0;background:none;border:0;outline:0;color:hsl(var(--h) 100% 75%);font:inherit;caret-color:hsl(var(--h) 100% 59%)}
.t-input input::placeholder{color:hsl(var(--h) 61% 27%)}
.t-foot{display:flex;gap:1.1cqw;flex-wrap:wrap;align-items:center;margin-top:.5cqw;color:hsl(var(--h) 61% 45%);font-size:.92em}
.t-meter{color:hsl(var(--h) 100% 59%)}
.t-foot .demo{color:hsl(var(--h) 58% 30%)}
.t-sound{margin-left:auto;background:none;border:1px solid hsl(var(--h) 68% 17%);color:hsl(var(--h) 61% 45%);font:inherit;padding:0 8px;cursor:pointer;border-radius:3px}
.t-sound:hover{color:#fff}
@keyframes blink{50%{opacity:.12}}

/* rats on the floor */
#rats{position:absolute;inset:0;pointer-events:none;overflow:hidden}
.rat{position:absolute;height:auto;pointer-events:auto;cursor:pointer;user-select:none;-webkit-user-drag:none;
  filter:drop-shadow(0 5px 4px rgba(0,0,0,.9))}

/* the operator in the chair, facing the terminal; poses share one frame (600×760, chair base at 50% / 96%) */
#operator{position:absolute;left:47%;top:88%;width:7.6%;aspect-ratio:600/760;transform:translate(-50%,-96%);z-index:905;
  pointer-events:auto;cursor:pointer;transform-origin:50% 96%;filter:brightness(.85) drop-shadow(0 6px 6px rgba(0,0,0,.9))}
#operator img{position:absolute;inset:0;width:100%;height:100%;opacity:0;transition:opacity .16s linear;
  transform-origin:50% 60%;animation:breathe-op 3.8s ease-in-out infinite}
#operator img.on{opacity:1}
#operator.glitching img{transition:none}
#operator.glitching{animation:op-glitch .09s steps(2) infinite}
#operator.staring{animation:op-stare 2.9s ease-in-out}
@keyframes op-glitch{
  0%{transform:translate(-52%,-96%) skewX(6deg);filter:brightness(1.3) drop-shadow(3px 0 0 rgba(255,0,60,.85)) drop-shadow(-3px 0 0 rgba(0,255,230,.75));clip-path:inset(0 0 38% 0)}
  50%{transform:translate(-47%,-95%) skewX(-5deg);filter:brightness(.7) drop-shadow(-4px 0 0 rgba(255,0,60,.85)) drop-shadow(4px 0 0 rgba(0,255,230,.75));clip-path:inset(30% 0 0 0)}}
@keyframes op-stare{0%,100%{filter:brightness(.85) drop-shadow(0 6px 6px rgba(0,0,0,.9))}
  20%,80%{filter:brightness(1.05) drop-shadow(0 0 10px rgba(255,20,20,.55)) drop-shadow(0 6px 6px rgba(0,0,0,.9))}}
@keyframes breathe-op{0%,100%{transform:scale(1,1)}50%{transform:scale(1.008,.99)}}

/* the hostage: like the frog in the reference, standing right next to the chair */
/* poses share one frame (520×640, base centre at 50% / 97%) */
#pepe{position:absolute;left:42.4%;top:88.6%;width:4.2%;aspect-ratio:520/640;z-index:975;transform:translate(-50%,-97%);
  pointer-events:auto;cursor:pointer;filter:brightness(.8) saturate(.9) drop-shadow(0 6px 5px rgba(0,0,0,.9))}
#pepe img{position:absolute;inset:0;width:100%;height:100%;opacity:0;transform-origin:50% 97%;animation:breathe 3.4s ease-in-out infinite}
#pepe img.on{opacity:1}
#pepe.struggle img{animation:jitter .12s steps(2) infinite}
@keyframes breathe{0%,100%{transform:scale(1,1)}50%{transform:scale(1.012,.982)}}
@keyframes jitter{0%{transform:translateX(-1.5%) rotate(-1deg)}50%{transform:translateX(1.5%) rotate(1deg)}}

/* surveillance drone + its scan beam (viewport px, above the stage) */
#drone{position:absolute;left:0;top:0;width:clamp(40px,4.4vw,76px);transform:translate(-50%,-50%);z-index:20;pointer-events:none;
  filter:drop-shadow(0 10px 8px rgba(0,0,0,.75))}
#drone img{display:block;width:100%;height:auto}
/* alert: only its own red lights blink, brighter than the sprite */
#drone-red{position:absolute;inset:0;mix-blend-mode:screen;filter:brightness(1.6) drop-shadow(0 0 4px #ff2a1a);animation:drone-blink .7s steps(1) infinite}
@keyframes drone-blink{0%{opacity:1}18%{opacity:.15}30%{opacity:1}48%,100%{opacity:0}}
#scan{position:absolute;inset:0;width:100%;height:100%;z-index:19;pointer-events:none;opacity:0;transition:opacity .25s}
#scan.on{opacity:1;animation:beamflick .12s steps(2) infinite}
#beam{fill:url(#beam-grad);mix-blend-mode:screen}
#beam-band{fill:url(#band-grad);mix-blend-mode:screen}
#scan.on{background:rgba(255,30,20,.05)}
#beam-line{stroke:hsl(var(--h) 100% 57%);stroke-width:2;filter:drop-shadow(0 0 6px hsl(var(--h) 100% 52%)) drop-shadow(0 0 14px hsl(var(--h) 100% 52%))}
@keyframes beamflick{50%{opacity:.82}}

@media (max-width:700px){
  .hide-sm{display:none}
  #term{left:50%;transform:translateX(-50%);width:calc(100vw - 32px);height:min(330px,38dvh);top:38%;font-size:11.5px;padding:10px 12px 8px}
  .t-head,.t-foot{gap:10px}
  .gate-domain{font-size:22px}
  .gm-segs i{width:36px}
  .t-foot .demo{display:none}
}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:0s!important;animation-iteration-count:1!important}
}

/* hovering a wall screen: bracketed highlight + a tech readout that follows the pointer */
#scr-hov{position:absolute;pointer-events:none;opacity:0;transition:opacity .12s;
  box-shadow:0 0 0 1px hsla(var(--h),100%,70%,.85),0 0 14px hsla(var(--h),100%,55%,.55),inset 0 0 18px hsla(var(--h),100%,60%,.35);
  background:linear-gradient(hsla(var(--h),100%,70%,.08),hsla(var(--h),100%,70%,.02));mix-blend-mode:screen}
#scr-hov.on{opacity:1;animation:hov-flick .9s steps(2) 1}
#scr-hov::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 0,hsla(var(--h),100%,75%,.35) 50%,transparent 100%);
  background-size:100% 30%;background-repeat:no-repeat;animation:hov-scan 1.4s linear infinite}
#scr-hov i{position:absolute;width:7px;height:7px;border:1.5px solid hsl(var(--h),100%,82%)}
#scr-hov i:nth-child(1){left:-4px;top:-4px;border-right:0;border-bottom:0}
#scr-hov i:nth-child(2){right:-4px;top:-4px;border-left:0;border-bottom:0}
#scr-hov i:nth-child(3){left:-4px;bottom:-4px;border-right:0;border-top:0}
#scr-hov i:nth-child(4){right:-4px;bottom:-4px;border-left:0;border-top:0}
@keyframes hov-scan{0%{background-position:0 -40%}100%{background-position:0 140%}}
@keyframes hov-flick{0%{opacity:.3}50%{opacity:1}}
#scr-tip{position:fixed;left:0;top:0;z-index:2000;pointer-events:none;opacity:0;transition:opacity .15s;
  min-width:220px;max-width:280px;padding:6px 8px;background:#0a0a0a;border:2px solid #141414;
  box-shadow:0 0 0 1px hsla(var(--h),90%,60%,.55),0 8px 24px rgba(0,0,0,.6);
  font:10px/14px var(--mono);color:hsl(var(--h),25%,72%)}
#scr-tip.on{opacity:1}
#scr-tip .t-head{display:flex;justify-content:space-between;gap:10px;padding-bottom:4px;margin-bottom:4px;border-bottom:1px solid #222}
#scr-tip .t-head b{color:hsl(var(--h),100%,70%);letter-spacing:.06em}
#scr-tip .t-head span{color:#777}
#scr-tip .t-grp{color:#cfcfc8}
#scr-tip .t-grp b{color:hsl(var(--h),100%,72%)}
#scr-tip .t-lamp{display:inline-block;width:6px;height:6px;border-radius:50%;margin-right:6px;vertical-align:1px;
  background:hsl(var(--h),100%,60%);box-shadow:0 0 6px hsl(var(--h),100%,55%);animation:lamp 1s steps(1) infinite}
@keyframes lamp{50%{opacity:.25}}
#scr-tip ul{list-style:none;margin:3px 0 0;padding:0}
#scr-tip li{display:grid;grid-template-columns:auto 30px 1fr;gap:8px;color:#9a9a94}
#scr-tip li span:first-child{color:#d6d6d1}
#scr-tip li span:last-child{text-align:right}
#scr-tip .t-foot{margin-top:4px;padding-top:3px;border-top:1px solid #1d1d1d;color:#5d5d58}

#sound.waiting{animation:snd-wait 1s steps(1) infinite}
@keyframes snd-wait{50%{opacity:.35}}

/* breach: RAT overwrites the terminal */
#hack{position:absolute;inset:0;z-index:5;background:#050000;overflow:hidden auto;scrollbar-width:none;cursor:pointer;
  padding:.9cqw 1.1cqw;box-shadow:inset 0 0 60px rgba(255,20,20,.18);animation:hack-in .35s steps(4)}
#hack pre{margin:0;font:inherit;white-space:pre-wrap;color:#ff3a2a;text-shadow:0 0 6px rgba(255,30,20,.7)}
#hack pre div{min-height:1.42em}
#hack .w{color:#fff;text-shadow:0 0 8px #ff2a1a}
#hack .r{color:#ff1414;font-weight:600}
#hack .b{color:#fff;font-weight:700;letter-spacing:.08em;text-shadow:-2px 0 rgba(255,0,60,.9),2px 0 rgba(0,255,230,.55),0 0 12px #ff1414;
  animation:hack-rgb 2.4s steps(1) infinite}
#hack .cur{animation:snd-wait .5s steps(1) infinite}
#hack.done::after{content:"[ click or press any key to reconnect ]";display:block;margin-top:.4em;color:#ff6a5a;animation:snd-wait 1.1s steps(1) infinite}
#hack.jolt{animation:hack-jolt .26s steps(3)}
#term:has(#hack:not([hidden])){border-color:#ff1414;box-shadow:0 0 40px rgba(255,20,20,.45),inset 0 0 40px rgba(255,20,20,.1);animation:term-shake .18s steps(2) 6}
#term:has(#hack:not([hidden]))::after{content:"";position:absolute;inset:0;z-index:6;pointer-events:none;
  background:repeating-linear-gradient(0deg,rgba(0,0,0,.35) 0 1px,transparent 1px 3px)}
#th-kill{color:#fff;background:#c00;padding:0 6px;animation:snd-wait 1s steps(1) infinite}
#th-kill b{color:#fff}
@keyframes hack-in{0%{clip-path:inset(0 0 100% 0)}50%{clip-path:inset(30% 0 40% 0)}100%{clip-path:inset(0)}}
@keyframes hack-jolt{0%{transform:translate(-6px,2px) skewX(-4deg);filter:hue-rotate(40deg)}50%{transform:translate(5px,-1px)}100%{transform:none}}
@keyframes hack-rgb{0%,92%{transform:none}93%{transform:translateX(-3px)}96%{transform:translateX(4px) skewX(8deg)}}
@keyframes term-shake{0%{translate:-4px 1px}100%{translate:3px -2px}}

/* breach alarm: the whole room strobes red under two spinning beacons */
#alarm{position:absolute;inset:0;z-index:30;pointer-events:none;opacity:0;transition:opacity .4s;mix-blend-mode:screen;overflow:hidden}
.hacked #alarm{opacity:1}
#alarm::before{content:"";position:absolute;inset:0;background:radial-gradient(ellipse at 50% 40%,transparent 35%,rgba(255,0,0,.55));
  animation:alarm-pulse .9s ease-in-out infinite}
#alarm .bcn{position:absolute;top:-60vmax;width:120vmax;height:120vmax;
  background:conic-gradient(from 0deg,rgba(255,30,20,.32) 0 22deg,transparent 40deg 180deg,rgba(255,30,20,.32) 180deg 202deg,transparent 220deg);
  animation:alarm-spin 1.6s linear infinite;filter:blur(6px)}
#alarm .l{left:-60vmax}
#alarm .r{right:-60vmax;animation-direction:reverse}
@keyframes alarm-pulse{0%,100%{opacity:.25}50%{opacity:1}}
@keyframes alarm-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){#alarm .bcn{animation:none}#alarm::before{animation-duration:3s}}
