/* Spud & Root: home/basement.html (a visual gag). Loaded after site.css.
   basement.js drives it: it projects the room, sets data-state on .basement
   (ready -> open -> down -> notice -> scramble -> after -> leaving -> shut,
   with after -> tv -> after while you play the TV, or locked when you
   come back too soon) and data-pose on each of the gang, and adds is-lit,
   is-airing, is-fan-on and so on to .basement as things happen. */

.basement-page {
  overflow: hidden;
  background: #120d1c;
}

.basement {
  position: relative;
}

.stage {
  position: relative;
  height: 100vh;
  height: 100svh;
  min-height: 360px;
  overflow: hidden;
  /* Before the script has drawn anything (and with JavaScript off): the
     kitchen wall and floor, like the restroom's hallway */
  background:
    linear-gradient(#f4ecd6 0 78%, var(--ink) 78% calc(78% + 4px), #efe6d0 calc(78% + 4px));
}

.world,
.fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.fx {
  pointer-events: none;
  overflow: visible;
}
html:not(.js) .world,
html:not(.js) .fx {
  display: none;
}

/* ---------- The door ---------- */
.door {
  /* With JavaScript off it's simply centred; basement.js sets its box so it
     sits exactly in the doorway it draws */
  --dh: min(62vh, 120vw);
  position: absolute;
  left: calc(50% - var(--dh) * 0.221);
  top: calc(78% - var(--dh));
  width: calc(var(--dh) * 0.442);
  height: var(--dh);
  transform-origin: left center;
  transform: rotateY(0deg);
  filter: drop-shadow(0 0 0 transparent);
}
html:not(.js) .door::before {
  /* The casing, when the script isn't there to draw it */
  content: "";
  position: absolute;
  inset: -4.5% -11% 0;
  z-index: -1;
  background: #fbf7ee;
  border: 3px solid var(--ink);
  border-bottom: 0;
}
.door__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
[data-state="ready"] .door,
[data-state="locked"] .door {
  cursor: pointer;
}
[data-state="open"] .door {
  transform: rotateY(96deg);
}
/* Leaving: the door is still open when you get back to the kitchen, then
   it swings shut behind you */
[data-state="leaving"] .door {
  transform: rotateY(96deg);
}
@media (prefers-reduced-motion: no-preference) {
  [data-state="open"] .door {
    transition: transform 0.56s cubic-bezier(0.3, 0.1, 0.3, 1);
  }
  [data-state="shut"] .door {
    transition: transform 0.48s cubic-bezier(0.55, 0, 1, 0.45);
  }
}
/* Once they've been caught, the door has a deadbolt; when you come back
   it has a second note too */
.deadbolt,
.sign-2 {
  visibility: hidden;
}
.is-bolted .deadbolt,
.has-note .sign-2 {
  visibility: visible;
}
.door.is-gone {
  visibility: hidden;
}

.knob {
  position: absolute;
  left: 87.2%;
  top: 51.6%;
  width: 15%;
  aspect-ratio: 1;
  min-width: 34px;
  translate: -50% -50%;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.knob::before {
  content: "";
  position: absolute;
  inset: -12px;
  border-radius: 50%;
}
.knob:disabled {
  cursor: default;
}
.knob svg {
  display: block;
  width: 100%;
  height: 100%;
}
.knob:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
  box-shadow: 0 0 0 9px var(--logo-yellow);
}

/* ---------- The gang: one pose at a time ---------- */
.ch [data-p] {
  display: none;
}
.ch[data-pose="chill"] [data-p~="chill"],
.ch[data-pose="alarm"] [data-p~="alarm"],
.ch[data-pose="jump"] [data-p~="jump"],
.ch[data-pose="reach"] [data-p~="reach"],
.ch[data-pose="fan"] [data-p~="fan"],
.ch[data-pose="spray"] [data-p~="spray"],
.ch[data-pose="yank"] [data-p~="yank"],
.ch[data-pose="run"] [data-p~="run"],
.ch[data-pose="cover"] [data-p~="cover"],
.ch[data-pose="sit"] [data-p~="sit"],
.ch[data-pose="line"] [data-p~="line"] {
  display: inline;
}
/* Legs: standing still, or running while basement.js moves them */
.ch:not(.is-moving) .lg-run,
.ch.is-moving .lg-stand {
  display: none;
}

/* Sitting down. Each character is drawn in the units of its approved SVG,
   so these are in those units: Potato's body rises onto the futon (his
   legs are drawn longer), Truffle drops onto the floor. */
.ch__upper {
  transition: translate 0.12s ease-out;
}
.ch[data-ch="potato"][data-pose="chill"] .ch__upper,
.ch[data-ch="potato"][data-pose="alarm"] .ch__upper {
  translate: 0 -6.5px;
}
.ch[data-ch="truffle"][data-pose="chill"] .ch__upper,
.ch[data-ch="truffle"][data-pose="alarm"] .ch__upper,
.ch[data-ch="truffle"][data-pose="sit"] .ch__upper {
  translate: 0 6.5px;
}

/* ---------- The room ---------- */
.dark {
  mix-blend-mode: multiply;
  opacity: 0.86;
  pointer-events: none;
  transition: opacity 0.08s linear;
}
.glow {
  mix-blend-mode: screen;
}
.is-lit .dark {
  opacity: 0.06;
}
.is-lit .glow > :not(.bulb-glow) {
  opacity: 0.25;
}
.bulb-glow {
  visibility: hidden;
}
.is-lit .bulb-glow {
  visibility: visible;
}
.bulb__glass {
  fill: #e9e4d8;
}
.is-lit .bulb__glass {
  fill: #fff3a0;
}

.win-open,
.is-window-open .win-closed {
  display: none;
}
.is-window-open .win-open {
  display: inline;
}

.blur,
.phones-down {
  visibility: hidden;
}
.is-fan-on .blur,
.is-yanked .phones-down {
  visibility: visible;
}

.haze .puff,
.stair-haze .puff {
  fill: url(#bm-smoke);
}
.haze {
  opacity: 0.85;
}
.stair-haze .puff {
  opacity: 0.75;
}
.source {
  opacity: 0.85;
}
.is-lit .source {
  display: none;
}
.haze {
  transition: translate 6s ease-in-out, opacity 6s ease-in-out;
}
.is-airing .haze {
  translate: -50px -10px;
  opacity: 0.4;
}

/* ---------- Screen effects ---------- */
.under-door {
  visibility: hidden;
}
[data-state="ready"] .under-door,
[data-state="locked"] .under-door,
[data-state="shut"] .under-door {
  visibility: visible;
}
.note {
  opacity: 0;
}
/* The smoke and the notes come and go with what's happening behind the
   door (basement.js: is-smoking, is-playing) */
.basement:not(.is-smoking) .under-door path,
.basement:not(.is-playing) .note {
  visibility: hidden;
}
.cloud {
  visibility: hidden;
}
.cloud.is-puffing {
  visibility: visible;
}
.alert-mark {
  font-family: var(--font-display);
  font-weight: 700;
  fill: var(--ink);
  stroke: #fff;
  stroke-width: 5px;
  paint-order: stroke;
  text-anchor: middle;
}
.mist-puff {
  fill: #ffd6e4;
  opacity: 0;
}
.sfx {
  font-family: var(--font-script);
  fill: var(--logo-yellow);
  stroke: var(--ink);
  stroke-width: 5px;
  stroke-linejoin: round;
  paint-order: stroke;
  text-anchor: middle;
  letter-spacing: 0.02em;
}

/* ---------- "Tap to go down" ---------- */
.hint {
  position: absolute;
  left: 50%;
  bottom: 6%;
  z-index: 2;
  margin: 0;
  padding: 0.1em 0.6em 0.15em;
  white-space: nowrap;
  font-family: var(--font-script);
  font-size: clamp(1.5rem, 6vw, 2.4rem);
  line-height: 1.2;
  color: var(--ink);
  background: var(--white);
  border: var(--stroke) solid var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-sm);
  pointer-events: none;
  translate: -50% 0;
  visibility: hidden;
}
[data-state="ready"] .hint {
  visibility: visible;
}

/* ---------- Way out ---------- */
.leave {
  position: absolute;
  left: max(14px, env(safe-area-inset-left));
  top: max(14px, env(safe-area-inset-top));
  padding: 0.35em 0.9em;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  white-space: nowrap;
  color: var(--ink);
  background: var(--white);
  border: var(--stroke) solid var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-sm);
  text-decoration: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.6s ease;
}
[data-state="after"] .leave,
[data-state="locked"] .leave,
html:not(.js) .leave {
  opacity: 1;
  visibility: visible;
}
.leave:hover {
  background: var(--logo-yellow);
}

/* ---------- The TV, to play at the end ----------
   .has-tv once the game has loaded, data-state="tv" while you're over at
   the TV, and .is-tv-on while you're sitting at it, playing */
.tv-quit,
.vcr-done,
.rec-done,
.smoke-done,
.darts-done,
.fan-done,
.hh-done,
.kitchen-done {
  position: absolute;
  top: max(14px, env(safe-area-inset-top));
  left: max(14px, env(safe-area-inset-left));
  padding: 0.35em 0.9em;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  line-height: inherit;
  white-space: nowrap;
  color: var(--ink);
  background: var(--white);
  border: var(--stroke) solid var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.6s ease;
}
.is-tv-on .tv-quit,
.is-vcr-on .vcr-done,
.is-records-on .rec-done,
.is-smoke-on .smoke-done,
.is-darts-on .darts-done,
.is-fan-close .fan-done,
.is-holding .hh-done,
.is-kitchen-close .kitchen-done {
  opacity: 1;
  visibility: visible;
}
.tv-quit:hover,
.vcr-done:hover,
.rec-done:hover,
.smoke-done:hover,
.darts-done:hover,
.fan-done:hover,
.hh-done:hover,
.kitchen-done:hover {
  background: var(--logo-yellow);
}

/* Over the TV, the console and the controller it draws, so a tap on any
   of them sits you down to play */
.tv-hit {
  position: absolute;
  display: none;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.has-tv[data-state="after"] .tv-hit {
  display: block;
}

/* The game itself, laid over the TV's screen. Its 80 by 68 pixels are
   blown up without smoothing, with a scanline every other row and the
   glass darker at the edges. */
.tv-screen {
  position: absolute;
  overflow: hidden;
  background: #5c94fc;
  outline: none;
  touch-action: none;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.25s ease, visibility 0s 0.25s;
}
.tv-screen:focus-visible {
  /* Focused only so the keys reach the game, never by tabbing */
  outline: none;
  box-shadow: none;
}
.tv-screen.is-on {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.25s ease;
}
.tv-screen canvas {
  display: block;
  width: 100%;
  height: 100%;
  image-rendering: crisp-edges;
  image-rendering: pixelated;
}
.tv-screen::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(rgb(0 0 0 / 0.13) 0 50%, transparent 50%) 0 0 / 100% calc(100% / 34),
    radial-gradient(ellipse at 50% 45%, transparent 55%, rgb(0 0 0 / 0.35));
}
/* ---------- The record player ----------
   basement.js swings the tonearm and lifts the record; the record turns
   while .basement has is-spinning. data-state="records" while you're over at it, and .is-records-on while
   you're crouched by it, picking from the crate. */
/* The record lifting off and coming down, when it's changed */
.disc {
  transition: translate 0.45s ease, opacity 0.45s ease;
}
.disc.is-off {
  translate: 0 -18px;
  opacity: 0;
}

.rec-hit {
  position: absolute;
  display: none;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
[data-state="after"] .rec-hit {
  display: block;
}

/* The crate of records, along the bottom of the screen */
.crate {
  position: absolute;
  left: 50%;
  bottom: max(14px, env(safe-area-inset-bottom));
  width: min(640px, calc(100% - 28px));
  max-height: 58%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  color: var(--ink);
  background: var(--cream);
  border: var(--stroke) solid var(--ink);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  translate: -50% 0;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.3s ease, visibility 0s 0.3s;
}
.is-records-on .crate {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.3s ease;
}
.crate__head {
  margin: 0;
  font-family: var(--font-script);
  font-size: 1.6rem;
  line-height: 1;
}
.crate__list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px;
  margin: 0;
  padding: 2px;
  list-style: none;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.record {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: 100%;
  padding: 6px 8px 6px 6px;
  font-family: var(--font-display);
  text-align: left;
  color: var(--ink);
  background: var(--white);
  border: 2px solid var(--ink);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.record:hover {
  background: var(--logo-yellow);
}
.record[aria-pressed="true"] {
  background: var(--logo-yellow);
  box-shadow: inset 0 0 0 2px var(--ink);
}
/* The 78: black, with its label (each its own colour) and the hole */
.record__disc {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background:
    radial-gradient(circle, var(--ink) 0 2px, var(--label) 2.5px 9px, transparent 9.5px),
    repeating-radial-gradient(circle, #231f20 0 1.5px, #3a3436 1.5px 2.5px);
  border: 2px solid var(--ink);
}
@media (prefers-reduced-motion: no-preference) {
  .record[aria-pressed="true"] .record__disc {
    animation: basement-turn 0.77s linear infinite;
  }
}
.record__text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.15;
}
.record__title {
  font-weight: 600;
  font-size: 0.95rem;
}
.record__by {
  font-size: 0.75rem;
  color: var(--ink-soft);
}
.crate__off {
  align-self: flex-start;
  padding: 0.25em 0.8em;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink);
  background: var(--white);
  border: 2px solid var(--ink);
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.crate__off:hover {
  background: var(--logo-yellow);
}
.crate__off[disabled] {
  opacity: 0.45;
  cursor: default;
  background: var(--white);
}

/* ---------- The VCR's clock ----------
   data-state="vcr" while you're over at the VCR, and .is-vcr-on while
   you're crouched in front of it. basement.js lays .vcr-hit over the VCR
   at the end, and the .vcr-key buttons over the ones drawn on it. */
.vcr-hit,
.vcr-key {
  position: absolute;
  display: none;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
[data-state="after"] .vcr-hit,
.is-vcr-on .vcr-key {
  display: block;
}
.vcr-key {
  border-radius: 8px;
}
.vcr-key:hover {
  background: rgb(255 255 255 / 0.12);
}
.vcr-key:active {
  background: rgb(0 0 0 / 0.3);
}
.vcr-clock {
  font-variant-numeric: tabular-nums;
}
/* The part you're setting is brighter (and flashes, below) */
.vcr-clock[data-setting="h"] .vcr-clock__h,
.vcr-clock[data-setting="m"] .vcr-clock__m {
  fill: #e6ffe9;
}

/* ---------- The smoke detector ----------
   data-state="smoke" while you're going up to it, and .is-smoke-on while
   you're up there. basement.js lays .smoke-hit over it at the end and
   .cap-pull over the shower cap. .is-uncapping while the cap comes off,
   .is-uncapped after, which makes everyone more nervous (below). */
.smoke-hit,
.cap-pull {
  position: absolute;
  display: none;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.basement:not(.is-uncapped)[data-state="after"] .smoke-hit,
.is-smoke-on:not(.is-uncapping):not(.is-uncapped) .cap-pull {
  display: block;
}
.cap-hint {
  position: absolute;
  left: 50%;
  bottom: 8%;
  z-index: 2;
  margin: 0;
  padding: 0.1em 0.6em 0.15em;
  white-space: nowrap;
  font-family: var(--font-script);
  font-size: clamp(1.4rem, 5.5vw, 2.2rem);
  line-height: 1.2;
  color: var(--ink);
  background: var(--white);
  border: var(--stroke) solid var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-sm);
  pointer-events: none;
  translate: -50% 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0s 0.3s;
}
.is-smoke-on:not(.is-uncapping):not(.is-uncapped) .cap-hint {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.3s ease;
}
.is-uncapped .cap,
.floor-cap {
  display: none;
}
.is-uncapped .floor-cap {
  display: inline;
}
.is-uncapping .smoke-done,
.is-uncapped .smoke-done {
  opacity: 0;
  visibility: hidden;
}
.is-smoke-on .stage {
  -webkit-tap-highlight-color: transparent;
}

/* ---------- The fan ----------
   data-state="fan" while you're going over to it, and .is-fan-close while
   you're crouched at it. basement.js lays .fan-hit over it at the end and
   the .fan-key buttons over the speeds along its top. data-fan on
   .basement is its speed: 0 off, 1 low, 2 medium, 3 high. */
.fan-hit,
.fan-key {
  position: absolute;
  display: none;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
[data-state="after"] .fan-hit,
.is-fan-close .fan-key {
  display: block;
}
.fan-key--dial {
  border-radius: 50%;
}
.fan-key:hover {
  background: rgb(255 255 255 / 0.18);
}
.fan-dial .is-on {
  fill: #e5322d;
}
/* Pointing at the speed it's on: -90deg off, -40 low, 40 medium, 90 high */
.fan-knob {
  transform-box: view-box;
  transform-origin: 12px -59px;
  rotate: var(--knob, 90deg);
  transition: rotate 0.25s var(--ease-out);
}
.basement[data-fan="1"] .blur {
  opacity: 0.25;
}
.basement[data-fan="2"] .blur {
  opacity: 0.4;
}

/* ---------- The kitchen clock and calendar ----------
   Upstairs, by the door (data-state="ready" or "locked"): basement.js lays
   .clock-hit and .cal-hit over them. Tapping one steps you up to it
   (data-state="clock" or "calendar", then .is-kitchen-close): the clock's
   .clock-face takes a drag round, and the calendar's page flips with a
   tap or the arrows in .cal-nav. */
.clock-hit,
.cal-hit,
.clock-face,
.cal-page-hit {
  position: absolute;
  display: none;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.clock-hit,
.clock-face {
  border-radius: 50%;
}
[data-state="ready"] .clock-hit,
[data-state="ready"] .cal-hit,
[data-state="locked"] .clock-hit,
[data-state="locked"] .cal-hit,
.is-kitchen-close[data-state="clock"] .clock-face,
.is-kitchen-close[data-state="calendar"] .cal-page-hit {
  display: block;
}
.clock-face {
  cursor: grab;
  touch-action: none;
}
.clock-face:active {
  cursor: grabbing;
}
.clock-face:focus-visible {
  outline: 3px solid var(--logo-yellow);
  outline-offset: 4px;
}
.cal-nav {
  position: absolute;
  left: 50%;
  bottom: max(16px, env(safe-area-inset-bottom));
  z-index: 2;
  display: none;
  gap: 18px;
  translate: -50% 0;
}
.is-kitchen-close[data-state="calendar"] .cal-nav {
  display: flex;
}
.cal-nav button {
  width: 56px;
  height: 56px;
  padding: 0 0 6px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 2.2rem;
  line-height: 1;
  color: var(--ink);
  background: var(--white);
  border: var(--stroke) solid var(--ink);
  border-radius: 50%;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}
.cal-nav button:hover {
  background: var(--logo-yellow);
}
.kitchen-hint {
  position: absolute;
  left: 50%;
  bottom: 6%;
  z-index: 2;
  margin: 0;
  padding: 0.1em 0.6em 0.15em;
  white-space: nowrap;
  font-family: var(--font-script);
  font-size: clamp(1.25rem, 5vw, 2rem);
  line-height: 1.2;
  color: var(--ink);
  background: var(--white);
  border: var(--stroke) solid var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-sm);
  pointer-events: none;
  translate: -50% 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0s 0.3s;
}
.is-kitchen-close[data-state="clock"] .kitchen-hint {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.3s ease;
}
/* A page going over the top (or coming back down) */
.cal-page--old {
  transform-box: view-box;
  transform-origin: -74px -166px;
  animation: basement-flip 0.42s ease-in both;
  pointer-events: none;
}
.cal-page--back {
  transform-box: view-box;
  transform-origin: -74px -166px;
  animation: basement-flip 0.42s ease-out reverse both;
}

/* ---------- The handheld ----------
   data-state="handheld" while you've picked it up. basement.js lays
   .hh-hit over the one on the futon at the end; tapping it lifts .handheld
   from there (--lift, set by basement.js) up in front of you
   (.is-holding), with the room dimmed behind. .is-hh-on while it's
   switched on. The buttons over it are placed in its own millimetres
   (its viewBox is 92 by 152, from -1, -3). */
.hh-hit {
  position: absolute;
  display: none;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
[data-state="after"] .hh-hit {
  display: block;
}
.handheld-dim {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: rgb(18 10 30 / 0.5);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s ease, visibility 0s 0.4s;
}
.handheld {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 3;
  height: min(88%, calc(94vw * 152 / 92));
  aspect-ratio: 92 / 152;
  translate: -50% -50%;
  transform: var(--lift, none);
  opacity: 0;
  visibility: hidden;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.45s var(--ease-out), opacity 0.2s ease, visibility 0s 0.45s;
}
.is-holding .handheld {
  transform: none;
  opacity: 1;
  visibility: visible;
  transition: transform 0.5s var(--ease-out), opacity 0.15s ease;
}
.is-holding .handheld-dim {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.4s ease;
}
.handheld:focus,
.handheld:focus-visible {
  /* Focused only so the keys reach the game */
  outline: none;
  box-shadow: none;
}
.handheld__body {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  filter: drop-shadow(0 10px 18px rgb(0 0 0 / 0.45));
}
.handheld__lcd {
  position: absolute;
  left: 23.913%;
  top: 17.105%;
  width: 52.174%;
  height: 28.421%;
  image-rendering: crisp-edges;
  image-rendering: pixelated;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.is-hh-on .handheld__lcd {
  opacity: 1;
}
.hh-led {
  transition: fill 0.15s ease;
}
.is-hh-on .hh-led {
  fill: #ff3326;
}
.hh-switch {
  transition: translate 0.15s ease;
}
.is-hh-on .hh-switch {
  translate: 8.5px 0;
}
.is-hh-on .futon-handheld__lcd {
  fill: #9bbc0f;
}
.is-holding .futon-handheld {
  visibility: hidden;
}
/* The buttons: invisible, over the ones drawn */
.hh-btn {
  position: absolute;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.hh-btn:focus-visible {
  outline: 3px solid var(--logo-yellow);
  outline-offset: 0;
}
.hh-btn--power { left: 11.96%; top: 0; width: 21.74%; height: 7.24%; border-radius: 10px; }
.hh-btn--dpad { left: 6.52%; top: 60.86%; width: 33.15%; height: 20.07%; border-radius: 12px; }
.hh-btn--a { left: 78.26%; top: 61.18%; width: 17.39%; height: 10.53%; }
.hh-btn--b { left: 61.41%; top: 66.45%; width: 16.85%; height: 10.53%; }
.hh-btn--select { left: 32.61%; top: 80.26%; width: 15.22%; height: 9.21%; border-radius: 10px; }
.hh-btn--start { left: 47.83%; top: 80.26%; width: 15.22%; height: 9.21%; border-radius: 10px; }
/* Pressed: the drawn one goes in */
.hh-part {
  transition: filter 0.05s linear;
}
.hh-part.is-down {
  filter: brightness(0.72);
}
/* The d-pad rocks towards the way it's pressed */
.hh-part[data-part="dpad"] {
  transition: translate 0.05s linear, filter 0.05s linear;
}
.hh-part[data-dir="left"] { translate: -0.5px 0; }
.hh-part[data-dir="right"] { translate: 0.5px 0; }
.hh-part[data-dir="up"] { translate: 0 -0.5px; }
.hh-part[data-dir="down"] { translate: 0 0.5px; }
/* The keys, for a keyboard, along the bottom */
.handheld-keys {
  position: absolute;
  left: 50%;
  bottom: max(8px, env(safe-area-inset-bottom));
  z-index: 3;
  max-width: calc(100% - 28px);
  margin: 0;
  padding: 0.3em 0.8em;
  font-family: var(--font-display);
  font-size: 0.8rem;
  line-height: 1.35;
  text-align: center;
  color: var(--ink);
  background: rgb(255 255 255 / 0.92);
  border: 2px solid var(--ink);
  border-radius: 12px;
  translate: -50% 0;
  pointer-events: none;
  display: none;
}
@media (hover: hover) and (pointer: fine) and (min-width: 720px) {
  .is-holding .handheld-keys {
    display: block;
  }
  .handheld {
    height: min(84%, calc(94vw * 152 / 92));
    top: 47%;
  }
}

/* ---------- The light's pull chain ----------
   basement.js lays .chain-hit over it at the end. Pulling it adds
   is-pulled to .pull-chain and is-swinging to .bulb for a moment. */
.chain-hit {
  position: absolute;
  display: none;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
[data-state="after"] .chain-hit {
  display: block;
}

/* ---------- Darts ----------
   data-state="darts" while you're stepping up to the line, and
   .is-darts-on while you're there, playing. basement.js lays .darts-hit
   over the board at the end, fills the card, the meter (--power, 0 to 1)
   and moves the .aim in .fx while you're holding. .is-charging while
   you're holding. */
.darts-hit {
  position: absolute;
  display: none;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
[data-state="after"] .darts-hit {
  display: block;
}
.darts-ui {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0s 0.3s;
}
.is-darts-on .darts-ui {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.3s ease;
}
.is-darts-on .stage {
  cursor: crosshair;
}
.darts-card {
  position: absolute;
  top: max(14px, env(safe-area-inset-top));
  right: max(14px, env(safe-area-inset-right));
  z-index: 2;
  min-width: 7.5em;
  padding: 0.45em 0.8em 0.5em;
  font-family: var(--font-display);
  font-size: 0.95rem;
  line-height: 1.25;
  color: var(--ink);
  background: var(--white);
  border: var(--stroke) solid var(--ink);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
  pointer-events: none;
}
.darts-card p {
  margin: 0;
}
.darts-card__darts {
  display: flex;
  gap: 0.3em;
  margin: 0 0 0.3em;
  padding: 0;
  list-style: none;
}
.darts-card__darts li {
  flex: 1;
  min-width: 2.2em;
  padding: 0.05em 0.2em;
  text-align: center;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  border-radius: 6px;
  background: #f1ebdc;
}
.darts-card__darts li.is-hit {
  background: var(--logo-yellow);
}
.darts-card__total b,
.darts-card__best b {
  float: right;
  margin-left: 0.8em;
  font-variant-numeric: tabular-nums;
}
.darts-card__best {
  font-size: 0.85em;
  opacity: 0.75;
}
/* The power meter, right beside the board (basement.js places it): the
   sweet spot's the green band, and the fill goes green in it */
.darts-meter {
  --power: 0;
  position: absolute;
  z-index: 2;
  width: clamp(24px, 4vmin, 34px);
  overflow: hidden;
  background: var(--white);
  border: 3px solid var(--ink);
  border-radius: 12px;
  box-shadow: var(--shadow-sm);
  pointer-events: none;
  transition: scale 0.12s ease;
}
.darts-meter__sweet {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  bottom: 64%;
  height: 16%;
  background: rgb(151 215 0 / 0.5);
  border-block: 3px solid var(--ink);
}
.darts-meter__fill {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 100%;
  background: linear-gradient(to top, var(--logo-yellow), #ff8a2a 55%, #e5322d);
  transform-origin: 50% 100%;
  scale: 1 var(--power);
}
.darts-meter.is-sweet {
  scale: 1.12;
}
.darts-meter.is-sweet .darts-meter__fill {
  background: #97d700;
}
.darts-hint {
  position: absolute;
  left: 50%;
  bottom: 6%;
  z-index: 2;
  margin: 0;
  padding: 0.1em 0.6em 0.15em;
  white-space: nowrap;
  font-family: var(--font-script);
  font-size: clamp(1.25rem, 5vw, 2rem);
  line-height: 1.2;
  color: var(--ink);
  background: var(--white);
  border: var(--stroke) solid var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-sm);
  pointer-events: none;
  translate: -50% 0;
  transition: opacity 0.3s ease;
}
.is-charging .darts-hint,
.has-thrown .darts-hint {
  opacity: 0;
}
.aim {
  display: none;
}
.is-charging .aim,
.is-darts-on.is-aiming .aim {
  display: inline;
}

.is-tv-on .stage,
.is-vcr-on .stage,
.is-darts-on .stage {
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* "It's locked." */
.locked-note {
  position: absolute;
  left: 50%;
  bottom: 6%;
  z-index: 2;
  margin: 0;
  padding: 0.1em 0.6em 0.15em;
  white-space: nowrap;
  font-family: var(--font-script);
  font-size: clamp(1.5rem, 6vw, 2.4rem);
  line-height: 1.2;
  color: var(--ink);
  background: var(--white);
  border: var(--stroke) solid var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-sm);
  pointer-events: none;
  opacity: 0;
  translate: -50% 8px;
  transition: opacity 0.9s ease, translate 0.9s ease;
}
.locked-note.is-shown {
  opacity: 1;
  translate: -50% 0;
  transition-duration: 0.15s;
}

/* ---------- How nervous the gang are ----------
   basement.js adds up what you've done to them (setNerves()) and sets
   --nerves (0 to 1: 0.1 is 10% more nervous), --shake and --shiver for the
   shaking and sweating, which grow with it, and the levels as classes:
   .nerves-1 (5% and up), .nerves-2 (15% and up), .nerves-3 (25% and up).
   Each level changes their faces (the parts marked f- give way to the n-
   ones, drawn in home/basement.html):
   1, uneasy: worried brows, and a second drop of sweat
   2, nervous: eyes wide, darting about, and a tight, forced grin
   3, sweating bullets: wider eyes with small pupils, a gritted grimace
      (in place of Rosemary's lips too), and a third drop of sweat
   Worried, not panicking: it's kept to about three-quarters of what it
   could be. */
.basement {
  --nerves: 0;
  --shake: 0px;
  --shiver: 2.2s;
}
.n-brows,
.n-eyes,
.n-mouth,
.sweat--extra,
.sweat--more {
  display: none;
}
.nerves-1 .n-brows,
.nerves-1 .sweat--extra,
.nerves-2:not(.nerves-3) .n-eyes--2,
.nerves-2:not(.nerves-3) .n-mouth--2,
.nerves-3 .n-eyes--3,
.nerves-3 .n-mouth--3,
.nerves-3 .sweat--more {
  display: inline;
}
.nerves-1 .f-brows,
.nerves-2 .f-eyes,
.nerves-2 .f-mouth,
.nerves-3 .f-lips {
  display: none;
}

/* Hidden until the script has drawn the scene, so the door never jumps.
   Shown anyway after a moment if the script fails. */
.js [data-state="pending"] .stage {
  visibility: hidden;
  animation: basement-fallback 0s 1.5s forwards;
}
@keyframes basement-fallback {
  to { visibility: visible; }
}

/* ---------- Motion ---------- */
/* Running legs flick between two frames */
.ch.is-moving .lg-run--a {
  animation: basement-run-a 0.22s steps(1) infinite;
}
.ch.is-moving .lg-run--b {
  animation: basement-run-b 0.22s steps(1) infinite;
}
@keyframes basement-run-a {
  0% { visibility: visible; }
  50% { visibility: hidden; }
}
@keyframes basement-run-b {
  0% { visibility: hidden; }
  50% { visibility: visible; }
}

@media (prefers-reduced-motion: no-preference) {
  /* The bass thumping behind the door */
  [data-state="ready"] .sign,
  [data-state="locked"] .sign,
  [data-state="shut"] .sign {
    transform-box: fill-box;
    transform-origin: 50% 0;
    animation: basement-thump 0.714s ease-out infinite;
  }
  [data-state="ready"] .hint {
    animation: basement-bob 1.6s ease-in-out infinite;
  }
  .under-door path {
    transform-box: fill-box;
    transform-origin: 50% 100%;
    animation: basement-wisp 2.6s ease-out infinite;
  }
  .under-door .wisp-b {
    animation-delay: -1.3s;
  }
  .note {
    animation: basement-note 3.4s ease-out infinite;
  }
  .note--b {
    animation-delay: -1.7s;
  }
  .cloud.is-puffing .cloud__puff {
    animation: basement-cloud 1.1s cubic-bezier(0.2, 0.7, 0.3, 1) both;
  }
  .cloud.is-puffing .cloud__puff--l {
    animation-name: basement-cloud-l;
    animation-delay: 0.08s;
  }
  .cloud.is-puffing .cloud__puff--r {
    animation-name: basement-cloud-r;
    animation-delay: 0.16s;
  }

  .incense,
  .source,
  .wisp {
    transform-box: fill-box;
    transform-origin: 50% 100%;
    animation: basement-wisp 3s ease-out infinite;
  }
  .wisp {
    animation-duration: 2.4s;
  }
  /* Nobody ever set the VCR's clock. Setting it, the part you're on
     flashes. */
  /* A 78 goes round in 0.77 seconds. Paused, it stops where it is. */
  .disc__spin {
    animation: basement-turn 0.77s linear infinite paused;
  }
  .is-spinning .disc__spin {
    animation-play-state: running;
  }
  .vcr-clock.is-unset,
  .vcr-clock[data-setting="h"] .vcr-clock__h,
  .vcr-clock[data-setting="m"] .vcr-clock__m {
    animation: basement-flash 1s steps(1) infinite;
  }
  .is-fan-on .blades {
    transform-box: fill-box;
    transform-origin: 50% 50%;
    animation: basement-spin 0.16s linear infinite;
  }
  .basement[data-fan="2"] .blades {
    animation-duration: 0.3s;
  }
  .basement[data-fan="1"] .blades {
    animation-duration: 0.65s;
  }
  .haze .puff--a { animation: basement-drift 9s ease-in-out infinite alternate; }
  .haze .puff--b { animation: basement-drift 11s ease-in-out -4s infinite alternate-reverse; }
  .haze .puff--c { animation: basement-drift 13s ease-in-out -2s infinite alternate; }
  .is-lit .bulb {
    transform-box: view-box;
    transform-origin: 0 0;
    animation: basement-sway 2.6s ease-in-out both;
  }
  /* Pulled: the chain gives and springs back, and the light swings */
  .pull-chain.is-pulled {
    animation: basement-pull 0.4s ease-out both;
  }
  .bulb.is-swinging {
    transform-box: view-box;
    transform-origin: 0 0;
    animation: basement-swing 1.8s ease-in-out both;
  }

  /* The gang */
  .ch[data-pose="chill"] .ch__upper {
    transform-box: fill-box;
    transform-origin: 50% 100%;
    animation: basement-breathe 2.8s ease-in-out infinite;
  }
  .ch[data-ch="rosemary"][data-pose="chill"] .ch__upper {
    animation-duration: 3.6s;
  }
  .ch[data-ch="garlic"][data-pose="chill"] .ch__upper {
    transform-box: view-box;
    transform-origin: 26px 96px;
    animation: basement-groove 0.714s ease-in-out infinite;
  }
  .ch[data-ch="truffle"][data-pose="chill"] .chew {
    transform-box: fill-box;
    transform-origin: 50% 50%;
    animation: basement-chew 0.36s ease-in-out infinite;
  }
  .ch[data-pose="alarm"] .ch__rig,
  .ch[data-pose="yank"] .ch__rig {
    animation: basement-jolt 0.22s var(--ease-out) both;
  }
  .ch[data-pose="fan"] .swing {
    transform-box: view-box;
    transform-origin: 26.5px 22px;
    animation: basement-fan 0.18s ease-in-out infinite alternate;
  }
  .ch[data-pose="fan"] .whoosh {
    animation: basement-flicker 0.18s steps(1) infinite;
  }
  .ch[data-pose="spray"] .spray-arm {
    transform-box: view-box;
    transform-origin: 21.8px 40.5px;
    animation: basement-sweep 0.5s ease-in-out infinite alternate;
  }
  .ch.is-moving .ch__rig {
    transform-box: view-box;
    transform-origin: 0 0;
    animation: basement-hurry 0.22s ease-in-out infinite;
  }
  .ch[data-pose="cover"] .ch__upper {
    transform-box: view-box;
    transform-origin: 23px 38px;
    animation: basement-squash 0.4s var(--ease-spring) both;
  }
  .ch[data-pose="line"] .eyes,
  .ch[data-pose="sit"] .eyes {
    transform-box: fill-box;
    transform-origin: 50% 60%;
    animation: basement-blink 4.2s linear infinite;
  }
  .ch[data-ch="rosemary"] .eyes { animation-delay: -1.4s; }
  .ch[data-ch="garlic"] .eyes { animation-delay: -2.6s; animation-duration: 3.4s; }
  .ch[data-ch="truffle"] .eyes { animation-delay: -0.6s; animation-duration: 5s; }
  /* Sweating faster the more nervous they are (10% more nervous, 10%
     faster), and a shiver for the last tenth of every couple of seconds,
     harder and more often as it goes up */
  .ch[data-pose="line"] .sweat,
  .ch[data-pose="sit"] .sweat {
    animation: basement-sweat calc(1.8s / (1 + var(--nerves))) ease-in infinite;
  }
  .ch[data-pose] .sweat--extra {
    animation-delay: -0.8s;
  }
  .ch[data-pose] .sweat--more {
    animation-delay: -1.3s;
  }
  .nerves-1 .ch[data-pose="line"] .ch__rig,
  .nerves-1 .ch[data-pose="sit"] .ch__rig {
    animation: basement-shiver var(--shiver) linear infinite;
  }
  .nerves-1 .ch[data-ch="rosemary"] .ch__rig { animation-delay: -0.7s; }
  .nerves-1 .ch[data-ch="garlic"] .ch__rig { animation-delay: -1.5s; animation-duration: calc(var(--shiver) * 0.86); }
  .nerves-1 .ch[data-ch="truffle"] .ch__rig { animation-delay: -0.3s; animation-duration: calc(var(--shiver) * 1.18); }
  /* Their eyes darting about (2), and their pupils trembling (3) */
  .n-eyes--2 .n-pupils {
    animation: basement-glance 3.4s steps(1) infinite;
  }
  .ch[data-ch="rosemary"] .n-pupils { animation-delay: -0.9s; }
  .ch[data-ch="garlic"] .n-pupils { animation-delay: -1.7s; }
  .ch[data-ch="truffle"] .n-pupils { animation-delay: -0.4s; }
  .n-eyes--3 .n-pupils {
    animation: basement-tremble 0.22s steps(2) infinite;
  }
  /* The smoke detector's light, blinking now you can see it */
  .is-uncapped .smoke__led {
    animation: basement-led 2s steps(1) infinite;
  }
  /* The shower cap: pulled down, stretching, until it snaps off and drops */
  .is-uncapping .cap {
    transform-box: view-box;
    transform-origin: 0 0;
    animation: basement-uncap 1.1s ease-in both;
  }
  .knob.is-jiggling svg {
    animation: basement-jiggle 0.45s ease-in-out both;
  }
  .door.is-rattling {
    animation: basement-rattle 0.45s linear both;
  }
  .alert-mark {
    animation: basement-pop 0.22s var(--ease-spring) both;
  }
  .mist-puff {
    animation: basement-mist 1.3s ease-out both;
  }
  .sfx {
    animation: basement-sfx 1.2s var(--ease-out) both;
  }
}

@keyframes basement-jiggle {
  0%, 100% { rotate: 0deg; }
  15% { rotate: -32deg; }
  35% { rotate: 26deg; }
  55% { rotate: -18deg; }
  75% { rotate: 10deg; }
}
@keyframes basement-rattle {
  0%, 100% { translate: 0 0; }
  15%, 55% { translate: -3px 0; }
  35%, 75% { translate: 3px 0; }
}
@keyframes basement-bob {
  0%, 100% { translate: -50% 0; }
  50% { translate: -50% -6px; }
}
@keyframes basement-thump {
  0% { scale: 1; }
  12% { scale: 1.035 0.97; }
  40% { scale: 1; }
}
@keyframes basement-turn {
  to { rotate: 1turn; }
}
@keyframes basement-flash {
  50% { fill-opacity: 0; }
}
@keyframes basement-wisp {
  0% { opacity: 0; translate: 0 10px; }
  30% { opacity: 0.85; }
  100% { opacity: 0; translate: 0 -30px; }
}
@keyframes basement-note {
  0% { opacity: 0; translate: 0 0; }
  20% { opacity: 0.8; }
  100% { opacity: 0; translate: 10px -60px; }
}
@keyframes basement-cloud {
  0% { opacity: 1; scale: 0.35; }
  55% { opacity: 0.95; }
  100% { opacity: 0; scale: 3.4; }
}
@keyframes basement-cloud-l {
  0% { opacity: 1; scale: 0.4; translate: 0 0; }
  100% { opacity: 0; scale: 2.6; translate: -260px -120px; }
}
@keyframes basement-cloud-r {
  0% { opacity: 1; scale: 0.4; translate: 0 0; }
  100% { opacity: 0; scale: 2.4; translate: 280px -60px; }
}
@keyframes basement-spin {
  to { rotate: 360deg; }
}
@keyframes basement-drift {
  from { translate: -14px 0; }
  to { translate: 14px 3px; }
}
@keyframes basement-sway {
  0% { rotate: 18deg; }
  25% { rotate: -12deg; }
  50% { rotate: 7deg; }
  75% { rotate: -3deg; }
  100% { rotate: 0deg; }
}
@keyframes basement-pull {
  0% { translate: 0 0; }
  30% { translate: 0 4px; }
  60% { translate: 0 -0.8px; }
  100% { translate: 0 0; }
}
@keyframes basement-swing {
  0% { rotate: 0deg; }
  15% { rotate: 9deg; }
  40% { rotate: -6deg; }
  65% { rotate: 3deg; }
  85% { rotate: -1deg; }
  100% { rotate: 0deg; }
}
@keyframes basement-flip {
  0% { scale: 1 1; opacity: 1; }
  70% { opacity: 1; }
  100% { scale: 1 -0.35; opacity: 0; }
}
@keyframes basement-breathe {
  0%, 100% { scale: 1 1; }
  50% { scale: 1.01 0.985; }
}
@keyframes basement-groove {
  0%, 100% { rotate: -3deg; }
  50% { rotate: 3deg; }
}
@keyframes basement-chew {
  0%, 100% { scale: 1 1; }
  50% { scale: 0.9 1.5; }
}
@keyframes basement-jolt {
  0% { translate: 0 0; }
  40% { translate: 0 -8px; }
  100% { translate: 0 0; }
}
@keyframes basement-fan {
  from { rotate: -16deg; }
  to { rotate: 16deg; }
}
@keyframes basement-flicker {
  0% { opacity: 1; }
  50% { opacity: 0; }
}
@keyframes basement-sweep {
  from { rotate: -12deg; }
  to { rotate: 22deg; }
}
@keyframes basement-hurry {
  0%, 100% { rotate: -3deg; }
  50% { rotate: 3deg; }
}
@keyframes basement-squash {
  0% { scale: 1 1; }
  40% { scale: 1.3 0.7; }
  100% { scale: 1.12 0.88; }
}
@keyframes basement-blink {
  0%, 92%, 100% { scale: 1 1; }
  95% { scale: 1 0.1; }
}
@keyframes basement-shiver {
  0%, 90%, 100% { translate: 0 0; }
  91% { translate: calc(var(--shake) * -1) 0; }
  93% { translate: var(--shake) 0; }
  95% { translate: calc(var(--shake) * -0.75) 0; }
  97% { translate: calc(var(--shake) * 0.6) 0; }
  99% { translate: calc(var(--shake) * -0.35) 0; }
}
@keyframes basement-glance {
  0% { translate: 0 0; }
  30% { translate: 0.8px 0; }
  52% { translate: -0.15px 0.2px; }
  78% { translate: 0.5px -0.15px; }
}
@keyframes basement-tremble {
  0% { translate: 0 0; }
  50% { translate: 0.1px 0.07px; }
}
@keyframes basement-uncap {
  0% { scale: 1 1; translate: 0 0; rotate: 0deg; }
  22% { scale: 1.02 1.35; translate: 0 0.6px; rotate: 0deg; }
  32% { scale: 0.98 1.3; translate: 0 0.4px; rotate: 0deg; }
  42% { scale: 1.04 1.6; translate: 0 1px; rotate: -2deg; }
  46% { scale: 1 1; translate: 0 3px; rotate: 6deg; }
  100% { scale: 1 1; translate: 8px 90px; rotate: 160deg; }
}
@keyframes basement-led {
  0%, 12% { fill-opacity: 1; }
  12.01%, 100% { fill-opacity: 0.25; }
}
@keyframes basement-sweat {
  0% { translate: 0 0; opacity: 1; }
  100% { translate: 0 9px; opacity: 0; }
}
@keyframes basement-pop {
  0% { scale: 0; }
  100% { scale: 1; }
}
@keyframes basement-sfx {
  0% { scale: 0.3; opacity: 1; }
  14% { scale: 1.12; }
  24% { scale: 1; }
  70% { opacity: 1; translate: 0 0; }
  100% { opacity: 0; translate: 0 -12px; }
}
@keyframes basement-mist {
  0% { opacity: 0.85; scale: 0.3; }
  100% { opacity: 0; scale: 1.8; translate: -30px -30px; }
}
