/* =========================================================================
   Vibecoder POV — hand-inked comic-noir, very dark.
   Order: tokens → layout → scene → screens → HUD → overlay → animations.
   ========================================================================= */

:root {
  /* Don't Starve palette: warm desaturated umber + black ink.
     The narrative accents stay the original ones, because in this room
     they are the only artificial light: monitor green, alert red, lamp cream. */
  --ink: #0B0907;
  --paper: #D9CDB4;
  --umber: #241D18;

  --black: #0B0907;
  --teal: #2E251D;
  --green: #47B99A;
  --red: #E23438;
  --red-shadow: #7B1D27;
  --charcoal: #3A2E23;
  --dust: #8A7C64;
  --cream: #E8C77A;
  --bone: #D9CDB4;

  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  /* the antique serif does half the gothic work: Gorey is pen lettering */
  --sans: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;

  --edge: polygon(0 6px, 6px 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%);
}

* { box-sizing: border-box; }

/* Several rules below set display:flex; without this, `hidden`
   would get overridden and the panels would always stay on screen. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
  background: var(--black);
  color: var(--bone);
  font-family: var(--sans);
  overflow: hidden;
}

body::before {
  /* cool background halo, keeps the black from going flat */
  content: "";
  position: fixed;
  inset: 0;
  background: radial-gradient(120% 90% at 50% 40%, #1A1410 0%, #0B0907 62%);
  z-index: -1;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 99;
  background: var(--cream); color: var(--black); padding: 8px 14px;
  font: 700 13px/1 var(--sans); letter-spacing: .08em; text-transform: uppercase;
}
.skip:focus { left: 12px; top: 12px; }

/* ------------------------------------------------------------------ layout */

#app {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 10px;
}

.stage {
  position: relative;
  width: min(100%, calc((100vh - 62px) * 1.6));
  aspect-ratio: 16 / 10;
  container-type: size;
  background: var(--black);
  overflow: hidden;
  box-shadow: 0 0 0 3px var(--ink), 0 30px 90px #000;
  clip-path: var(--edge);
}

#scene { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.vignette {
  position: absolute; inset: 0; pointer-events: none; z-index: 6;
  background:
    radial-gradient(118% 88% at 50% 44%, transparent 44%, rgba(8,5,3,.72) 100%),
    linear-gradient(to bottom, rgba(8,5,3,.5), transparent 20%, transparent 78%, rgba(8,5,3,.55));
}

.legend {
  margin: 0;
  font: 500 11.5px/1.5 var(--sans);
  letter-spacing: .05em;
  color: #6B5E4A;
  text-align: center;
}
.legend b { color: var(--dust); font-weight: 700; }
.legend kbd { font-family: var(--mono); color: var(--dust); }

/* ------------------------------------------------------------------ scene */

/* --------------------------------------------------- inking the scene */

/* The thick black stroke on EVERY shape is the real Don't Starve trademark:
   legibility doesn't come from fill contrast but from the outline enclosing it.
   `.no-ink` excludes lights, shadows and rim light, which must stay borderless. */
#scene polygon:not(.no-ink):not(.sketch),
#scene polyline:not(.no-ink):not(.sketch) {
  stroke: var(--ink);
  stroke-width: 4.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}
#scene .keys polygon,
#scene #head polygon:last-of-type,
#scene .puff { stroke-width: 2.6; }

/* second pen pass, slightly out of register: the "retraced" line */
.sketch {
  stroke: var(--ink);
  stroke-width: 2.4;
  stroke-opacity: .55;
  stroke-linecap: round;
  stroke-linejoin: round;
}

#scene text { paint-order: stroke fill; stroke: var(--ink); stroke-width: 5; stroke-linejoin: round; }

.hot { cursor: pointer; }
.hot .hit { fill: transparent; pointer-events: all; stroke: transparent; stroke-width: 3; }
.hot:hover .hit { stroke: rgba(232,199,122,.6); stroke-dasharray: 10 7; }
.hot:focus { outline: none; }
.hot:focus-visible .hit { stroke: var(--cream); stroke-dasharray: 8 5; }
.hot:hover { filter: drop-shadow(0 0 10px rgba(232,199,122,.4)); }
.hot:active { filter: drop-shadow(0 0 4px rgba(232,199,122,.25)); }

/* long-press: a visible charge-up so holding feels deliberate rather than
   like a click that didn't register. Duration matches HOLD_MS in interactions.js. */
.hot.is-holding { animation: holdCharge .48s ease-in forwards; }
@keyframes holdCharge {
  from { filter: drop-shadow(0 0 4px rgba(232,199,122,.3)); }
  to   { filter: drop-shadow(0 0 16px rgba(232,199,122,.95)) brightness(1.35); }
}

/* the cat breathes, slowly, indifferent to the credit balance */
#cat-body { transform-box: fill-box; transform-origin: 50% 100%; animation: catBreathe 5.6s ease-in-out infinite; }
@keyframes catBreathe {
  0%, 100% { transform: scale(1, 1); }
  50%      { transform: scale(1.018, 1.03); }
}
/* clicked: it shifts once and settles. It does not wake up. */
#cat-body.cat-stir { animation: catStir 1.8s ease-in-out; }
@keyframes catStir {
  0%, 100% { transform: translate(0, 0) rotate(0); }
  25%      { transform: translate(-3px, -2px) rotate(-.8deg); }
  55%      { transform: translate(2px, 0) rotate(.5deg); }
}

/* konami payoff: every clickable object lights up in sequence */
.hot.egg-flash { animation: eggFlash .7s steps(3); }
@keyframes eggFlash {
  0%, 100% { filter: none; }
  30%      { filter: drop-shadow(0 0 14px rgba(71,185,154,.95)) brightness(1.6); }
  60%      { filter: drop-shadow(0 0 8px rgba(71,185,154,.6)) brightness(1.2); }
}

/* id-qualified selectors to beat `#scene text` (1,0,1), which would force
   a 5-unit stroke: too thick for lettering at this scale */
#scene text.posterLine { font-family: var(--sans); fill: var(--cream); stroke-width: 2.4; }
#scene text.posterLine-big { font-size: 15px; font-weight: 700; letter-spacing: 1.1px; }
#scene text.posterLine-small {
  font-size: 8.4px; fill: var(--dust); letter-spacing: .2px;
  font-style: italic; stroke-width: 1.5;
}
.keycap { fill: var(--green); font-size: 17px; font-family: var(--mono); pointer-events: none; }

#grainLayer { mix-blend-mode: overlay; }
#walls { filter: none; } /* the hand-drawn wobble now comes from roughen.js, not the displacement filter */
#beamDiag, #windowBeam, #lampCone, #screenBleed, #sideBleed, #wallGlow, #deskSpill { mix-blend-mode: screen; }

#screenGlass, #sideGlass { transition: fill .25s steps(3); }
#screenBleed, #sideBleed { transition: opacity .3s, fill .25s steps(3); }

/* rain and city lights (nodes generated by app.js) */
.drop { stroke: var(--bone); stroke-width: 1.6; stroke-opacity: .3; animation: rainFall linear infinite; }
@keyframes rainFall { from { transform: translate(0, -120px); } to { transform: translate(-26px, 340px); } }

.citylight { animation: cityFlicker steps(2) infinite; }
@keyframes cityFlicker { 0%, 88% { opacity: .85; } 90%, 100% { opacity: .18; } }

/* router wifi signal: the three bars light up in sequence from bottom to
   top, like a "connection attempt" that never quite stabilizes */
.wifi-bar {
  opacity: .25;
  animation: wifiPulse 2.8s steps(2) infinite;
}
@keyframes wifiPulse {
  0%, 5%    { opacity: .25; }
  9%, 16%   { opacity: 1; filter: drop-shadow(0 0 5px rgba(71,185,154,.75)); }
  22%, 100% { opacity: .25; filter: none; }
}
/* on click the router shows its true nature: signal lost for a moment */
.stage.glitch .wifi-bar { animation: none; opacity: .12; filter: none; }

.puff { animation: puffRise 2.6s cubic-bezier(.2,.7,.3,1) forwards; }
@keyframes puffRise {
  0%   { opacity: 0;   transform: translate(0,0) scale(.4); }
  18%  { opacity: .5; }
  100% { opacity: 0;   transform: translate(-58px,-190px) scale(2.1); }
}

/* long-press cloud: rises further, spreads wider, lingers */
.puff-big { animation: puffRiseBig 3.4s cubic-bezier(.2,.7,.3,1) forwards; }
@keyframes puffRiseBig {
  0%   { opacity: 0;   transform: translate(0,0) scale(.45); }
  15%  { opacity: .62; }
  100% { opacity: 0;   transform: translate(-96px,-268px) scale(3.1); }
}

/* ------------------------------------------------------- screens (overlay) */

.screen {
  position: absolute;
  z-index: 3;
  display: flex;
  flex-direction: column;
  font-family: var(--mono);
  color: var(--green);
  overflow: hidden;
  pointer-events: none;
  text-shadow: 0 0 8px rgba(71,185,154,.45);
}

.screen-main {
  left: 35.375%; top: 20.6%; width: 28.625%; height: 26.8%;
  transform: perspective(1400px) rotateX(3deg);
  font-size: 1.02cqw;
}

/* Drawn glass (#sideGlass): 1078,268 → 1400,240 → 1400,520 → 1078,492.
   Trapezoid: right side 280 units tall, left side 224 → ratio 0.8.

   The pivot goes on the RIGHT side, the one at scale 1 (closest to the
   viewer). Anchored on the left instead, scale there was 1.0 and the box
   kept the right side's height (28%) exactly where the glass measures
   22.4%: hence the overflow above and below.

   Parameters derived by solving the perspective projection, not eyeballed:
     s(x) = P / (P − sin17°·x),  pivot at x=0 on the right edge
     s(−W) = 0.8            → P = sin17°·W·0.8/0.2
     cos17°·W·0.8 = 20.125% → W = 26.31%   (projected width = 322/1600)
   The four corners of the projected box match the polygon's exactly. */
.screen-side {
  left: 61.19%; top: 24%; width: 26.31%; height: 28%;
  transform: perspective(30.76cqw) rotateY(-17deg);
  transform-origin: 100% 50%;
  font-size: .82cqw;
  opacity: .96;
}

/* --- monitor top bar --- */
.scr-top {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: .5em;
  padding: .35em .6em;
  background: #08201D;
  border-bottom: 1px solid rgba(71,185,154,.28);
  font-size: .84em; letter-spacing: .12em;
}
.scr-brand { color: var(--green); font-weight: 700; }
.scr-slash { color: var(--teal); }
.scr-mode { color: var(--dust); text-transform: uppercase; }
.scr-credits { margin-left: auto; display: flex; align-items: center; gap: .45em; }
.cred-label { color: var(--dust); font-size: .84em; }
/* Credit gauge, not a progress bar.
   It lives inside the monitor, so it stays in the terminal's green rather
   than going paper-and-ink like the HUD — but it's built as a drawn
   instrument: an uneven ink border, hand-spaced tick marks along the top,
   a segmented fill that empties in notches instead of sliding smoothly,
   and a needle riding the current level. */
.cred-track {
  position: relative;
  width: 7.4em; height: 1.15em;
  background: #071B18;
  border: 1px solid rgba(71,185,154,.5);
  box-shadow: inset 0 0 0 1px rgba(8,5,3,.8), 1px 1px 0 rgba(8,5,3,.6);
  display: block;
  overflow: hidden;
}
/* tick marks: taller ones at the quarters, short ones between */
.cred-track::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: .34em; z-index: 2;
  background:
    repeating-linear-gradient(to right,
      rgba(71,185,154,.55) 0 1px, transparent 1px 25%),
    repeating-linear-gradient(to right,
      rgba(71,185,154,.28) 0 1px, transparent 1px 8.333%);
}
.cred-fill {
  display: block; height: 100%; width: 100%;
  /* notched fill: the segment seams are what make it read as an instrument */
  background:
    repeating-linear-gradient(to right,
      var(--green) 0 calc(8.333% - 1px), rgba(8,5,3,.55) calc(8.333% - 1px) 8.333%);
  transition: width .12s linear, background-color .2s;
}
/* the needle sits at the leading edge of the fill */
.cred-fill::after {
  content: ""; position: absolute; top: -.12em; right: -1px; width: 2px; height: 1.3em;
  background: var(--bone);
  box-shadow: 0 0 4px rgba(217,205,180,.8);
}
.cred-num { color: var(--bone); min-width: 3.4em; text-align: right; }

body[data-credits="low"] .cred-fill {
  background:
    repeating-linear-gradient(to right,
      var(--red) 0 calc(8.333% - 1px), rgba(8,5,3,.55) calc(8.333% - 1px) 8.333%);
  animation: credPulse .5s steps(2) infinite;
}
body[data-credits="empty"] .cred-fill { background: var(--red-shadow); width: 0 !important; }
body[data-credits="empty"] .cred-fill::after { opacity: 0; }
@keyframes credPulse { 0%,60% { opacity: 1; } 61%,100% { opacity: .35; } }

/* --- terminal --- */
.scr-body {
  flex: 1 1 auto;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: .5em .7em .55em;
  overflow: hidden;
  background: linear-gradient(180deg, rgba(71,185,154,.06), transparent 40%);
}
.term { display: flex; flex-direction: column; gap: .16em; overflow: hidden; }
.term-line { white-space: nowrap; overflow: hidden; text-overflow: clip; opacity: .92; animation: lineIn .16s steps(3); }
.term-line .t-time { color: var(--teal); }
.term-line .t-ok { color: var(--green); }
.term-line .t-warn { color: var(--cream); }
.term-line .t-bad { color: var(--red); }
.term-line .t-dim { color: var(--dust); }
.term-line.is-old { opacity: .42; }
.term-line.term-progress { opacity: 1; animation: none; }
@keyframes lineIn { from { opacity: 0; transform: translateX(-6px); } }

.term-bar { display: inline-block; color: var(--green); letter-spacing: -.05em; }

.term-input { display: flex; align-items: center; gap: .4em; margin-top: .3em; color: var(--bone); }
.term-sign { color: var(--green); }
.caret {
  display: inline-block; width: .58em; height: 1.05em;
  background: var(--green); animation: blink 1s steps(1) infinite; vertical-align: -.15em;
}
@keyframes blink { 0%,50% { opacity: 1; } 51%,100% { opacity: 0; } }

/* --- overlay inside the monitor --- */
.scr-overlay {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; justify-content: center;
  padding: .9em 1em;
  animation: panelIn .16s steps(3);
}
@keyframes panelIn { from { opacity: 0; transform: translateY(-4px); } }

.perm { background: rgba(8,10,9,.94); border: 2px solid var(--red); pointer-events: auto; }
.perm-tag { color: var(--red); font-size: .82em; letter-spacing: .18em; margin-bottom: .5em; }
.perm-title { margin: 0 0 .45em; color: var(--bone); font-size: 1.02em; line-height: 1.32; text-shadow: none; }
.perm-detail { margin: 0 0 .9em; color: var(--dust); font-size: .82em; line-height: 1.3; text-shadow: none; word-break: break-word; }
.perm-actions { display: flex; gap: .6em; }
.pbtn {
  font-family: var(--mono); font-size: .88em; letter-spacing: .1em;
  padding: .38em .8em; border: 2px solid; background: transparent; cursor: pointer;
  clip-path: polygon(0 0, 100% 0, 100% 70%, calc(100% - .5em) 100%, 0 100%);
}
.pbtn kbd { font-size: .82em; opacity: .6; }
.pbtn-allow { color: var(--green); border-color: var(--green); }
.pbtn-allow:hover, .pbtn-allow:focus-visible { background: var(--green); color: var(--black); outline: none; }
.pbtn-deny { color: var(--dust); border-color: var(--charcoal); }
.pbtn-deny:hover, .pbtn-deny:focus-visible { border-color: var(--red); color: var(--red); outline: none; }

.dead { background: rgba(123,29,39,.2); border: 2px solid var(--red); align-items: center; text-align: center; }
.dead-big {
  position: relative; color: var(--red); font-size: 1.7em; font-weight: 700; letter-spacing: .1em;
  animation: glitch .28s steps(2) infinite;
}
.dead-big::after {
  content: attr(data-text); position: absolute; left: 2px; top: 0; color: var(--green);
  opacity: .55; clip-path: inset(38% 0 30% 0);
}
.dead-sub { margin: .5em 0 0; color: var(--bone); font-size: .84em; text-shadow: none; }
@keyframes glitch {
  0% { transform: translate(0,0); } 25% { transform: translate(-3px,1px); }
  50% { transform: translate(2px,-1px); } 75% { transform: translate(-1px,-2px); }
}

/* --- second monitor's feed --- */
/* padding reduced and skewed to the left: the text aligns with the glass's
   left edge instead of sitting inset, gaining useful width. The background
   continues the glass gradient drawn in the SVG (#gScreen: #0F312C →
   #081A17), so the text reads as resting on the screen instead of floating
   in front of it, and a faint light inner border simulates the glass's
   reflection along the panel's edges. */
.feed-top {
  display: flex; justify-content: space-between; align-items: center;
  padding: .35em .5em .35em .28em; background: #0C2B26; color: var(--dust);
  letter-spacing: .14em; font-size: .9em;
  border-bottom: 1px solid rgba(71,185,154,.3);
}
.feed-live { color: var(--red); }
.feed {
  flex: 1 1 auto; overflow: hidden; padding: .35em .4em .35em .28em;
  display: flex; flex-direction: column; gap: .5em;
  background: linear-gradient(155deg, #12332D 0%, #0A1E1A 62%, #081A17 100%);
  box-shadow: inset 0 0 0 1px rgba(71,185,154,.16), inset 0 12px 22px -14px rgba(0,0,0,.6);
}
.post { border-left: 2px solid var(--teal); padding-left: .35em; animation: lineIn .2s steps(3); }
.post-user { color: var(--dust); font-size: .82em; letter-spacing: .06em; }
.post-text { color: var(--bone); line-height: 1.3; text-shadow: none; }
.post-meta { color: var(--teal); font-size: .78em; }

/* --------------------------------------------------------------------- HUD */

.hud { position: absolute; left: 2.4%; top: 3.6%; z-index: 5; pointer-events: none; }

.hud-panel {
  background: rgba(11,9,7,.86);
  border: 3px solid var(--ink);
  border-left: 6px solid var(--green);
  box-shadow: 0 0 0 2px rgba(217,205,180,.22), 6px 7px 0 rgba(8,5,3,.55);
  padding: .7em .95em .75em;
  min-width: 20cqw;
  clip-path: polygon(0 3px, 8px 0, 100% 2px, calc(100% - 3px) calc(100% - 9px), calc(100% - 11px) 100%, 2px calc(100% - 2px));
}
.hud-row { display: flex; align-items: baseline; gap: .7em; margin-bottom: .25em; }
.hud-k {
  font-size: .78cqw; letter-spacing: .22em; color: var(--dust);
  width: 3.6cqw; flex: 0 0 auto;
}
.hud-v {
  font-size: .95cqw; color: var(--bone); letter-spacing: .01em;
  font-family: var(--mono); max-width: 22cqw;
}
.hud-state { display: flex; align-items: center; gap: .5em; font-size: .95cqw; color: var(--green); font-family: var(--mono); }
.hud-dot { width: .62cqw; height: .62cqw; background: currentColor; display: block; }
.hud-flavor {
  margin-top: .5em; font-size: .8cqw; color: var(--dust); font-style: italic; letter-spacing: .02em;
  max-width: 24cqw; line-height: 1.35;
}
/* A quiet ledger, idle-only: it's a record of what the loop has cost, so it
   only makes sense to read it in the gap between runs, not mid-panic. */
.hud-stats {
  display: none;
  margin: .5em 0 0; font-size: .68cqw; color: var(--dust); opacity: .75;
  letter-spacing: .04em; font-family: var(--mono); max-width: 24cqw;
}
body[data-state="idle"] .hud-stats { display: block; }

body[data-state="agentRunning"] .hud-dot { animation: blink .7s steps(1) infinite; }
body[data-state="permissionPrompt"] .hud-state,
body[data-state="creditsDepleted"] .hud-state { color: var(--red); }
body[data-state="permissionPrompt"] .hud-panel,
body[data-state="creditsDepleted"] .hud-panel { border-left-color: var(--red); }
body[data-state="waiting"] .hud-state,
body[data-state="distraction"] .hud-state { color: var(--dust); }
body[data-state="payment"] .hud-state { color: var(--cream); }
body[data-state="payment"] .hud-panel { border-left-color: var(--cream); }

/* contextual hint */
.hint {
  position: absolute; left: 50%; bottom: 15%; transform: translateX(-50%);
  z-index: 5; margin: 0; pointer-events: none;
  font-size: .95cqw; letter-spacing: .18em; text-transform: uppercase;
  color: var(--cream); background: rgba(8,10,9,.8);
  padding: .45em 1em; border: 1px solid rgba(232,199,122,.35);
  animation: hintPulse 1.1s steps(2) infinite;
}
.hint kbd {
  font-family: var(--mono); color: var(--black); background: var(--cream);
  padding: 0 .34em; letter-spacing: 0;
}
@keyframes hintPulse { 0%,70% { opacity: 1; } 71%,100% { opacity: .45; } }

/* ---------------------------------------------------------------- controls */

.controls {
  /* bottom-left corner: the right one is occupied by the router and
     power strip drawn in the scene (x 77–99%, y 87–99% of the viewBox),
     and the buttons used to land on top of them. The floor is free on the left. */
  position: absolute; left: 2.4%; bottom: 4%; z-index: 5;
  display: flex; align-items: center; gap: .7cqw;
}

.btn {
  font-family: var(--sans); font-weight: 700; font-size: .92cqw;
  letter-spacing: .16em; text-transform: uppercase;
  padding: .7em 1.3em; cursor: pointer;
  background: var(--umber); color: var(--bone);
  border: 3px solid var(--ink);
  box-shadow: 0 0 0 2px rgba(217,205,180,.3), 5px 6px 0 rgba(8,5,3,.6);
  clip-path: polygon(0 2px, 6px 0, 100% 3px, calc(100% - 2px) 64%, calc(100% - .7em) 100%, 3px calc(100% - 2px));
  transition: background-color .12s steps(2), color .12s steps(2), border-color .12s;
}
.btn:hover { border-color: var(--green); color: var(--green); }
.btn:focus-visible { outline: 2px solid var(--cream); outline-offset: 3px; }

.btn-go { color: var(--green); box-shadow: 0 0 0 2px rgba(71,185,154,.5), 5px 6px 0 rgba(8,5,3,.6); }
.btn-go:hover { background: var(--green); color: var(--black); }
.btn-go[disabled] { opacity: .32; cursor: not-allowed; border-color: var(--charcoal); color: var(--dust); background: none; }

.btn-buy {
  color: var(--red); box-shadow: 0 0 0 2px rgba(226,52,56,.55), 5px 6px 0 rgba(8,5,3,.6);
  animation: buyPulse .85s steps(2) infinite;
}
.btn-buy:hover { background: var(--red); color: var(--black); }
@keyframes buyPulse {
  0%,60% { box-shadow: 0 0 0 0 rgba(226,52,56,0); }
  61%,100% { box-shadow: 0 0 18px 0 rgba(226,52,56,.55); }
}

.btn-ghost { font-size: .82cqw; padding: .6em 1em; color: var(--dust); }

/* --- sound: mute toggle + volume slider --- */

.sound { display: flex; align-items: center; gap: .5cqw; }

/* The slider is only meaningful once sound is on, so it stays collapsed
   and non-focusable until then (JS mirrors this with the disabled attr). */
.vol {
  -webkit-appearance: none; appearance: none;
  width: 7cqw; height: 1.5cqw;
  background: transparent; cursor: pointer;
  opacity: 1; transition: opacity .18s, width .18s;
}
.sound[data-on="false"] .vol {
  width: 0; opacity: 0; pointer-events: none;
}
.vol::-webkit-slider-runnable-track {
  height: .5cqw; background: var(--umber);
  border: 2px solid var(--ink);
  box-shadow: 0 0 0 1px rgba(217,205,180,.25);
}
.vol::-moz-range-track {
  height: .5cqw; background: var(--umber);
  border: 2px solid var(--ink);
  box-shadow: 0 0 0 1px rgba(217,205,180,.25);
}
.vol::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: .95cqw; height: 1.35cqw; margin-top: -.48cqw;
  background: var(--cream); border: 2px solid var(--ink);
  box-shadow: 2px 2px 0 rgba(8,5,3,.6);
}
.vol::-moz-range-thumb {
  width: .95cqw; height: 1.35cqw; border-radius: 0;
  background: var(--cream); border: 2px solid var(--ink);
  box-shadow: 2px 2px 0 rgba(8,5,3,.6);
}
.vol:focus-visible { outline: 2px solid var(--cream); outline-offset: 4px; }

/* ---------------------------------------------------------------- boss key */

/* Deliberately generic and bright — Arial, thin gray rules, no ink, no
   texture. It has to read as a completely different, boring product at a
   glance, because the joke IS the contrast with the room. z-index above the
   intro (10) so it can be triggered any time after entering, including, in
   principle, over the payment screen. */
.boss {
  position: absolute; inset: 0; z-index: 11;
  display: flex; flex-direction: column;
  background: #F4F5F7; color: #1B1F23;
  font-family: Arial, Helvetica, sans-serif;
  animation: bossIn .1s steps(2);
}
@keyframes bossIn { from { opacity: 0; } }

.boss-bar {
  flex: 0 0 auto; display: flex; align-items: center; gap: 1.2em;
  padding: .5em 1em; background: #FFFFFF; border-bottom: 1px solid #D6D9DC;
  font-size: .8cqw;
}
.boss-menu { color: #444; }
.boss-title { margin-left: auto; color: #6B7076; font-style: italic; }

.boss-formula {
  flex: 0 0 auto; display: flex; align-items: center; gap: .8em;
  padding: .4em 1em; background: #FBFBFC; border-bottom: 1px solid #E2E4E7;
  font-family: ui-monospace, Menlo, monospace; font-size: .78cqw;
}
.boss-cellref { padding: .1em .6em; background: #FFF; border: 1px solid #C7CBCF; color: #333; }
.boss-fx { color: #8A8F94; font-style: italic; }
.boss-formulaval { color: #1B1F23; }

.boss-grid {
  flex: 1 1 auto; display: grid;
  grid-template-columns: 6em repeat(4, 1fr);
  border-top: 1px solid #E2E4E7;
  font-size: .84cqw;
  overflow: hidden;
}
.boss-cell {
  padding: .55em .7em; border-right: 1px solid #E7E9EB; border-bottom: 1px solid #E7E9EB;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.boss-cell.head { background: #F1F3F5; font-weight: 700; color: #444; }
.boss-cell.label { background: #FAFBFC; font-weight: 600; color: #333; }
.boss-cell.warn { color: #C0392B; font-weight: 700; }

.boss-hint {
  flex: 0 0 auto; margin: 0; padding: .5em 1em;
  font-size: .74cqw; color: #9AA0A6; text-align: right;
  background: #FFFFFF; border-top: 1px solid #E2E4E7;
}
.boss-hint kbd { font-family: ui-monospace, monospace; border: 1px solid #C7CBCF; padding: 0 .4em; }

/* ------------------------------------------------------------------- intro */

.intro {
  position: absolute; inset: 0; z-index: 10;
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(90% 70% at 50% 45%, rgba(20,16,12,.88) 0%, rgba(8,5,3,.97) 70%);
  animation: introIn .5s ease-out;
}
.intro.is-leaving { animation: introOut .45s ease-in forwards; pointer-events: none; }
@keyframes introIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes introOut { to { opacity: 0; transform: scale(1.04); } }

.intro-card { text-align: center; padding: 2cqw; max-width: 62cqw; }

.intro-kicker {
  margin: 0 0 .4em; color: var(--dust);
  font-size: 1cqw; letter-spacing: .42em; text-transform: uppercase;
}
.intro-title {
  margin: 0; color: var(--bone);
  font-family: var(--sans); font-weight: 700;
  font-size: 6.6cqw; line-height: .94; letter-spacing: .02em;
  text-shadow: 5px 6px 0 rgba(8,5,3,.75);
  animation: titleDrop .55s cubic-bezier(.2,1.3,.4,1) both;
}
.intro-title span {
  display: block; color: var(--green);
  font-size: .52em; letter-spacing: .5em;
  margin-top: .18em; text-indent: .5em; /* offsets the trailing letter-spacing */
  animation: titleDrop .55s cubic-bezier(.2,1.3,.4,1) .1s both;
}
@keyframes titleDrop {
  from { opacity: 0; transform: translateY(-14px) rotate(-1.2deg); }
  to   { opacity: 1; transform: translateY(0) rotate(0); }
}

.intro-sub {
  margin: 1.1em 0 0; color: var(--dust);
  font-size: 1.35cqw; font-style: italic; letter-spacing: .02em;
  animation: introFade .5s ease-out .3s both;
}

.intro-cta {
  margin-top: 2.2em; cursor: pointer;
  font-family: var(--sans); font-weight: 700;
  font-size: 1.15cqw; letter-spacing: .22em; text-transform: uppercase;
  padding: .85em 2.2em;
  background: var(--umber); color: var(--cream);
  border: 3px solid var(--ink);
  box-shadow: 0 0 0 2px rgba(232,199,122,.45), 6px 7px 0 rgba(8,5,3,.7);
  clip-path: polygon(0 2px, 8px 0, 100% 3px, calc(100% - 2px) 66%, calc(100% - .8em) 100%, 4px calc(100% - 2px));
  animation: introFade .5s ease-out .45s both;
  transition: background-color .12s steps(2), color .12s steps(2);
}
.intro-cta:hover { background: var(--cream); color: var(--ink); }
.intro-cta:focus-visible { outline: 2px solid var(--cream); outline-offset: 4px; }

.intro-fine {
  margin: 1.5em 0 0; color: #6B5E4A;
  font-size: .85cqw; letter-spacing: .12em;
  animation: introFade .5s ease-out .6s both;
}
@keyframes introFade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }

/* ------------------------------------------------------------- speech bubble/tip */

.bubble {
  position: absolute; z-index: 7; max-width: 24cqw;
  background: var(--bone); color: var(--ink);
  border: 3px solid var(--ink);
  padding: .6em .9em; font-size: .92cqw; font-weight: 600; line-height: 1.3;
  letter-spacing: .01em;
  clip-path: polygon(0 0, 100% 0, 100% 74%, 62% 74%, 52% 100%, 46% 74%, 0 74%);
  padding-bottom: 1.6em;
  animation: bubbleIn .14s steps(2);
  pointer-events: none;
  filter: drop-shadow(4px 6px 0 rgba(8,5,3,.7));
}
.bubble.is-alert { background: var(--red); color: var(--bone); }
.bubble.is-warm { background: var(--cream); }
@keyframes bubbleIn {
  from { opacity: 0; transform: translate(-50%, 8px) scale(.92); }
  to   { opacity: 1; transform: translate(-50%, 0) scale(1); }
}

.tip {
  position: absolute; z-index: 8; pointer-events: none;
  background: var(--ink); color: var(--paper);
  border: 2px solid var(--paper); border-left: 5px solid var(--cream);
  padding: .35em .7em; font-size: .78cqw; letter-spacing: .08em;
  text-transform: uppercase; white-space: nowrap;
}

.flash {
  position: absolute; inset: 0; z-index: 7; pointer-events: none;
  background: var(--red); opacity: 0; mix-blend-mode: screen;
}
.flash.on { animation: flashHit .42s steps(3) forwards; }
@keyframes flashHit { 0% { opacity: .5; } 40% { opacity: .12; } 100% { opacity: 0; } }

.flash.warm.on { background: var(--cream); }

/* camera shake */
.stage.shake { animation: shake .38s steps(2) 2; }
@keyframes shake {
  0% { transform: translate(0,0); } 25% { transform: translate(-5px,2px); }
  50% { transform: translate(4px,-3px); } 75% { transform: translate(-2px,-1px); }
  100% { transform: translate(0,0); }
}

/* ---------------------------------------------------------------- payment */

.pay-wrap {
  position: absolute; inset: 0; z-index: 9;
  display: flex; align-items: center; justify-content: center;
  background: rgba(8,10,9,.86);
  animation: panelIn .18s steps(3);
}
.pay {
  width: 40cqw; padding: 2.2cqw 2.4cqw;
  background: var(--umber);
  border: 4px solid var(--ink);
  outline: 3px solid var(--red); outline-offset: 4px;
  clip-path: polygon(0 20px, 20px 0, 100% 0, 100% calc(100% - 20px), calc(100% - 20px) 100%, 0 100%);
  box-shadow: 0 0 60px rgba(226,52,56,.22);
}
.pay-vendor { margin: 0; color: var(--red); font-size: 1.1cqw; letter-spacing: .24em; font-family: var(--mono); }
.pay-vendor span { color: var(--dust); letter-spacing: .12em; }
.pay-plan { margin: .5em 0 .2em; color: var(--bone); font-size: 1.5cqw; font-weight: 700; letter-spacing: .06em; }
.pay-asterisk { margin: 0 0 .6em; color: var(--dust); font-size: .82cqw; font-style: italic; letter-spacing: .02em; }
.pay-price { margin: .2em 0 .9em; color: var(--cream); font-family: var(--mono); }
.pay-cur { font-size: 1.6cqw; vertical-align: super; }
.pay-num { font-size: 4.2cqw; font-weight: 700; letter-spacing: -.02em; }
.pay-cad { font-size: .95cqw; color: var(--dust); margin-left: .6em; }
.pay-list { margin: 0 0 1.4em; padding: 0; list-style: none; }
.pay-list li {
  color: var(--dust); font-size: .95cqw; line-height: 1.9;
  padding-left: 1.4em; position: relative; font-family: var(--mono);
}
.pay-list li::before { content: "▸"; position: absolute; left: 0; color: var(--green); }
.pay-cta {
  width: 100%; padding: .9em; cursor: pointer;
  background: var(--red); color: var(--bone); border: 0;
  font-family: var(--sans); font-weight: 700; font-size: 1.1cqw;
  letter-spacing: .2em; text-transform: uppercase;
  clip-path: polygon(0 0, 100% 0, 100% 66%, calc(100% - .8em) 100%, 0 100%);
}
.pay-cta:hover { background: var(--red-shadow); }
.pay-cta:focus-visible { outline: 2px solid var(--cream); outline-offset: 3px; }
.pay-cta[disabled] { background: var(--charcoal); color: var(--dust); cursor: wait; }
.pay-fine { margin: .9em 0 0; color: #3E4644; font-size: .78cqw; letter-spacing: .06em; text-align: center; }

/* =========================================================================
   CHARACTER ANIMATIONS
   ========================================================================= */

#character g, #character polygon { transform-box: fill-box; }

#torso { transform-origin: 50% 100%; animation: breathe 5.2s ease-in-out infinite; }
@keyframes breathe {
  0%, 100% { transform: translateY(0) scaleY(1); }
  50%      { transform: translateY(-2px) scaleY(1.006); }
}

#head { transform-origin: 50% 100%; animation: headIdle 7s ease-in-out infinite; }
@keyframes headIdle {
  0%, 100% { transform: translate(0,0) rotate(0deg); }
  30%      { transform: translate(-2px,1px) rotate(-.7deg); }
  62%      { transform: translate(2px,0) rotate(.6deg); }
}

.arm { transition: transform .34s cubic-bezier(.3,.9,.4,1); }
#arm-l { transform-origin: 100% 62%; }
#arm-r { transform-origin: 0% 62%; }

/* --- coding: dry typing --- */
body[data-state="coding"] #arm-l,
body[data-state="coding"] #arm-r { animation: typeArm .22s steps(2) infinite alternate; }
body[data-state="coding"] #arm-r { animation-delay: .11s; }
body[data-state="coding"] #head { animation: headType 1.4s steps(3) infinite; }
@keyframes typeArm { from { transform: translateY(0); } to { transform: translateY(-3px) rotate(.6deg); } }
@keyframes headType {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(2px) rotate(-.5deg); }
}

/* --- agentRunning: still, tense --- */
body[data-state="agentRunning"] #torso { animation: breathe 3.4s ease-in-out infinite; }
body[data-state="agentRunning"] #head { animation: headWatch 4.2s steps(4) infinite; }
@keyframes headWatch {
  0%, 70%  { transform: translate(0,0); }
  78%      { transform: translate(-3px,0) rotate(-1deg); }
  90%      { transform: translate(2px,0) rotate(.8deg); }
  100%     { transform: translate(0,0); }
}

/* --- waiting / distraction: postural collapse --- */
body[data-state="waiting"] #torso,
body[data-state="distraction"] #torso,
body[data-state="creditsDepleted"] #torso {
  animation: slump 6s ease-in-out infinite;
}
@keyframes slump {
  0%, 100% { transform: translateY(6px) rotate(-.4deg); }
  50%      { transform: translateY(9px) rotate(.3deg); }
}
body[data-state="waiting"] #head,
body[data-state="creditsDepleted"] #head { animation: headSlump 8s ease-in-out infinite; }
@keyframes headSlump {
  0%, 100% { transform: translateY(5px) rotate(-1.4deg); }
  50%      { transform: translateY(8px) rotate(-2.2deg); }
}

/* --- one-off gestures (classes added by interactions.js) --- */
#arm-r.reach-vape { animation: reachVape 2.4s cubic-bezier(.4,.9,.3,1); }
@keyframes reachVape {
  0%   { transform: translate(0,0) rotate(0); }
  22%  { transform: translate(120px,26px) rotate(12deg); }
  40%  { transform: translate(-52px,-72px) rotate(-26deg); }
  66%  { transform: translate(-56px,-78px) rotate(-28deg); }
  100% { transform: translate(0,0) rotate(0); }
}
#arm-l.reach-mug { animation: reachMug 2.2s cubic-bezier(.4,.9,.3,1); }
@keyframes reachMug {
  0%   { transform: translate(0,0) rotate(0); }
  24%  { transform: translate(-96px,-14px) rotate(-14deg); }
  46%  { transform: translate(38px,-70px) rotate(22deg); }
  68%  { transform: translate(40px,-74px) rotate(24deg); }
  100% { transform: translate(0,0) rotate(0); }
}
#arm-l.reach-phone { animation: reachPhone 2.1s cubic-bezier(.4,.9,.3,1); }
@keyframes reachPhone {
  0%   { transform: translate(0,0) rotate(0); }
  30%  { transform: translate(-128px,58px) rotate(-22deg); }
  70%  { transform: translate(-120px,20px) rotate(-16deg); }
  100% { transform: translate(0,0) rotate(0); }
}
#head.look-side { animation: lookSide 2.6s ease-in-out; }
@keyframes lookSide {
  0%   { transform: rotate(0) translateX(0); }
  30%  { transform: rotate(5deg) translateX(12px); }
  70%  { transform: rotate(5deg) translateX(12px); }
  100% { transform: rotate(0) translateX(0); }
}
#head.look-window { animation: lookWindow 3s ease-in-out; }
@keyframes lookWindow {
  0%   { transform: rotate(0) translateX(0); }
  28%  { transform: rotate(-7deg) translateX(-16px) translateY(-3px); }
  72%  { transform: rotate(-7deg) translateX(-16px) translateY(-3px); }
  100% { transform: rotate(0) translateX(0); }
}
#torso.recoil { animation: recoil .5s steps(3); }
@keyframes recoil {
  0% { transform: translateY(0); } 40% { transform: translateY(-7px) rotate(-1deg); }
  100% { transform: translateY(0); }
}

/* =========================================================================
   SCENE STATES (light, color, screens)
   ========================================================================= */

#wallGlow, #screenBleed, #deskSpill, #sideBleed, #windowBeam, #beamDiag {
  transition: opacity .4s ease, fill .3s steps(3);
}

/* idle: everything a bit dimmer */
body[data-state="idle"] #screenBleed { opacity: .13; }
body[data-state="idle"] #wallGlow { opacity: .06; }

/* agent at work: the room breathes green */
body[data-state="agentRunning"] #screenBleed { opacity: .3; animation: screenFlicker 3.1s steps(2) infinite; }
body[data-state="agentRunning"] #wallGlow { opacity: .14; }
body[data-state="agentRunning"] #deskSpill { opacity: .6; }
body[data-state="coding"] #screenBleed { opacity: .26; }

@keyframes screenFlicker {
  0%, 92% { opacity: .3; } 93% { opacity: .16; } 95% { opacity: .34; } 97% { opacity: .2; } 100% { opacity: .3; }
}

/* permission requested: red enters the scene */
body[data-state="permissionPrompt"] #screenGlass { fill: #23100F; }
body[data-state="permissionPrompt"] #screenBleed { fill: var(--red); opacity: .26; animation: alertPulse .9s steps(2) infinite; }
body[data-state="permissionPrompt"] #wallGlow { fill: var(--red); opacity: .1; }
body[data-state="permissionPrompt"] #deskSpill { opacity: .2; }
body[data-state="permissionPrompt"] #enterKey { animation: enterGlow .7s steps(2) infinite; }
body[data-state="permissionPrompt"] #rimlight { stroke: var(--red); }
@keyframes alertPulse { 0%,60% { opacity: .26; } 61%,100% { opacity: .1; } }
@keyframes enterGlow {
  0%,60% { fill: var(--charcoal); stroke: var(--green); }
  61%,100% { fill: #2E5E52; stroke: var(--cream); }
}

/* credits depleted: darkness and red */
body[data-state="creditsDepleted"] #screenGlass,
body[data-state="creditsDepleted"] #sideGlass { fill: #1A0708; }
body[data-state="creditsDepleted"] #screenBleed { fill: var(--red); opacity: .34; animation: deadFlicker .18s steps(2) infinite; }
body[data-state="creditsDepleted"] #sideBleed { fill: var(--red); opacity: .1; }
body[data-state="creditsDepleted"] #wallGlow { fill: var(--red); opacity: .12; }
body[data-state="creditsDepleted"] #deskSpill { opacity: .1; }
body[data-state="creditsDepleted"] #rimlight { stroke: var(--red); }
@keyframes deadFlicker { 0% { opacity: .34; } 50% { opacity: .1; } 100% { opacity: .3; } }

/* waiting and distraction: the room powers down */
body[data-state="waiting"] #screenGlass,
body[data-state="distraction"] #screenGlass,
body[data-state="payment"] #screenGlass { fill: #0A1211; }
body[data-state="waiting"] #screenBleed,
body[data-state="distraction"] #screenBleed { opacity: .06; }
body[data-state="waiting"] #wallGlow,
body[data-state="distraction"] #wallGlow { opacity: .04; }
body[data-state="waiting"] #deskSpill,
body[data-state="distraction"] #deskSpill { opacity: .12; }
body[data-state="distraction"] #sideBleed { opacity: .26; }
body[data-state="distraction"] .screen-side { opacity: 1; }
body[data-state="waiting"] .screen-main .scr-body,
body[data-state="distraction"] .screen-main .scr-body { opacity: .25; }

/* restart: dopamine hit */
body[data-state="restart"] #screenGlass { fill: #145046; }
body[data-state="restart"] #screenBleed { opacity: .55; }
body[data-state="restart"] #wallGlow { opacity: .26; }
body[data-state="restart"] #deskSpill { opacity: .85; }
body[data-state="restart"] .screen-main { animation: rebootZoom .5s cubic-bezier(.2,1.4,.4,1); }
@keyframes rebootZoom {
  0% { transform: perspective(1400px) rotateX(3deg) scale(.9); filter: brightness(2.4); }
  100% { transform: perspective(1400px) rotateX(3deg) scale(1); filter: brightness(1); }
}

/* lamp */
body[data-lamp="off"] #lampCone { opacity: 0; }
body[data-lamp="off"] #lampBulb { fill: var(--charcoal); }
body[data-lamp="off"] #rimlightWarm { opacity: 0; }
#lampCone, #lampBulb, #rimlightWarm { transition: opacity .18s steps(2), fill .18s steps(2); }

/* While the agent works, the lamp is not quite steady. The long cycle with
   the dips bunched near the end means most of it is calm and the flicker
   arrives unpredictably rather than on a visible beat. Only while lit and
   only during agentRunning, so it reads as strain on the room's power
   rather than as a broken bulb. */
body[data-state="agentRunning"][data-lamp="on"] #lampCone {
  animation: lampFlicker 7.3s steps(2) infinite;
}
body[data-state="agentRunning"][data-lamp="on"] #lampBulb {
  animation: lampBulbFlicker 7.3s steps(2) infinite;
}
@keyframes lampFlicker {
  0%, 71%   { opacity: 1; }
  72%       { opacity: .55; }
  73%, 84%  { opacity: 1; }
  85%       { opacity: .38; }
  86%       { opacity: .92; }
  87%       { opacity: .6; }
  88%, 100% { opacity: 1; }
}
@keyframes lampBulbFlicker {
  0%, 71%   { fill: var(--cream); }
  72%       { fill: #8A6E3A; }
  73%, 84%  { fill: var(--cream); }
  85%       { fill: #6E5730; }
  86%       { fill: var(--cream); }
  87%       { fill: #8A6E3A; }
  88%, 100% { fill: var(--cream); }
}

/* weather through the window — cycles calm → storm → fog on each click */
#rain, #fog, #skyline, #cityLights { transition: opacity .9s ease; }

body[data-weather="storm"] #rain { opacity: 1; }
body[data-weather="calm"] #rain { opacity: .3; }
body[data-weather="storm"] .drop { animation-duration: .42s !important; }

/* fog: the city all but disappears, and what's left of it stops twinkling */
body[data-weather="fog"] #fog { opacity: 1; }
body[data-weather="fog"] #rain { opacity: .12; }
body[data-weather="fog"] #skyline { opacity: .3; }
body[data-weather="fog"] #cityLights { opacity: .22; }
body[data-weather="fog"] .citylight { animation: none; }
body[data-weather="fog"] .drop { animation-duration: 1.4s !important; }

.fog-band { animation: fogDrift linear infinite; }
.fog-band:nth-child(1) { animation-duration: 34s; }
.fog-band:nth-child(2) { animation-duration: 47s; animation-direction: reverse; }
.fog-band:nth-child(3) { animation-duration: 61s; }
@keyframes fogDrift {
  from { transform: translateX(-60px); }
  to   { transform: translateX(60px); }
}

/* router flicker */
.stage.glitch #screenBleed, .stage.glitch #sideBleed { animation: deadFlicker .1s steps(2) 6; }

/* =========================================================================
   Accessibility and small screens
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .caret { animation: none; opacity: 1; }
}

@media (max-width: 720px), (max-height: 460px) {
  .legend { display: none; }
  .hud-panel { padding: .5em .6em; }
}
