/* ========================================================
   Knockbox — Beatmaker's Workstation
   Top-down view of a beatmaker's desk
   ======================================================== */

* {
  box-sizing: border-box;
}

/* Reveal the page once this stylesheet is parsed — pairs with the
   `body { opacity: 0; transition: opacity 0.25s }` in critical
   inline CSS to eliminate FOUT during the async main.css load. */
body {
  opacity: 1;
}

/* ============================================================
   Boot sequence — page loads in "powered off" state, JS adds
   .powered-on after the boot animation completes. Props fade in
   on staggered delays matching the LCD boot messages so the
   whole scene comes alive in unison with the sampler.
   ============================================================ */

/* Each prop is PLACED into the scene with directional motion — they slide,
   drop, or settle into their resting position rather than fading in. The
   end frame of every keyframe restores the prop's resting transform
   (rotation, etc.) so the existing static styling stays intact. Easing uses
   a slight back-overshoot so things "thump" into place like real objects. */

/* Notebook — placed down from upper-left */
@keyframes place-notebook {
  0% {
    opacity: 0;
    transform: translate(-50px, -30px) rotate(-12deg);
  }
  60% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(-2deg);
  }
}

/* Polaroid — tossed onto the desk from the upper-right */
@keyframes place-polaroid {
  0% {
    opacity: 0;
    transform: translate(60px, -40px) rotate(15deg);
  }
  60% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: translate(0, 0);
  }
}

/* Vinyl — slid in from the bottom-left edge */
@keyframes place-vinyl {
  0% {
    opacity: 0;
    transform: translate(-60px, 30px);
  }
  60% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: translate(0, 0);
  }
}

/* LP fan — pushed up from below */
@keyframes place-lp-fan {
  0% {
    opacity: 0;
    transform: translate(-30px, 60px);
  }
  60% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: translate(0, 0);
  }
}

/* Soul Brother LP — dropped in from the upper-right corner */
@keyframes place-soul-brother {
  0% {
    opacity: 0;
    transform: translate(60px, -50px) rotate(20deg);
  }
  60% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(6deg);
  }
}

/* Cassette — slid in from the right edge */
@keyframes place-cassette {
  0% {
    opacity: 0;
    transform: translate(70px, 10px);
  }
  60% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: translate(0, 0);
  }
}

/* Sticky note — drops onto the desk from above, twists as it settles */
@keyframes place-sticky {
  0% {
    opacity: 0;
    transform: translate(8px, -80px) rotate(-22deg) scale(0.92);
  }
  55% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(-4deg) scale(1);
  }
}

/* Funk LP — tossed in from the bottom-right corner */
@keyframes place-funk {
  0% {
    opacity: 0;
    transform: translate(70px, 40px) rotate(18deg);
  }
  60% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: translate(0, 0) rotate(4deg);
  }
}

/* Props are hidden during the entire boot sequence — they only appear
   the instant the step cells light up (.powered-on fires at T≈4.02s).
   Once .powered-on is set, each prop runs its placement keyframe with
   a tiny millisecond stagger so they enter the scene one after another
   in quick succession rather than all snapping in at the exact same frame. */
body:not(.powered-on) .prop {
  opacity: 0;
  pointer-events: none;
}

/* Common animation settings — applied only under body.powered-on */
body.powered-on .prop {
  animation-duration: 0.7s;
  animation-timing-function: cubic-bezier(0.34, 1.4, 0.5, 1);
  animation-fill-mode: both;
}

/* Micro-staggers (50ms between props) so they cascade in over ~400ms
   total, starting the moment the step cells light up. */
body.powered-on .prop-notebook {
  animation-name: place-notebook;
  animation-delay: 0ms;
}
body.powered-on .prop-polaroid {
  animation-name: place-polaroid;
  animation-delay: 50ms;
}
body.powered-on .prop-vinyl {
  animation-name: place-vinyl;
  animation-delay: 100ms;
}
body.powered-on .prop-lp-fan {
  animation-name: place-lp-fan;
  animation-delay: 150ms;
}
body.powered-on .prop-soul-brother {
  animation-name: place-soul-brother;
  animation-delay: 200ms;
}
body.powered-on .prop-cassette {
  animation-name: place-cassette;
  animation-delay: 250ms;
}
body.powered-on .prop-sticky {
  animation-name: place-sticky;
  animation-delay: 300ms;
}
body.powered-on .prop-funk {
  animation-name: place-funk;
  animation-delay: 350ms;
}

/* Patch cables fade in over the desk early in the sequence — kept as
   opacity-only since cables don't get "placed", they're already wired up. */
@keyframes cables-arrive {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.cables {
  animation: cables-arrive 0.8s ease-out 0.2s both;
}

/* Boot LCD overlay — sits absolutely over the .lcd, hides cells while booting */
.lcd-boot {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "VT323", monospace;
  font-size: clamp(14px, 1.3vw, 22px);
  color: var(--lcd-text, #1f2913);
  letter-spacing: 2px;
  text-shadow: 1px 2px 0 rgba(31, 41, 19, 0.2);
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
  transition: opacity 0.3s ease;
  z-index: 2;
}

/* LCD dark only while NO power is detected — the moment power-on-detected
   fires (T≈0.22s) the LCD lights up green so the boot text is legible. */
body:not(.power-on-detected) .lcd {
  background: linear-gradient(180deg, #1a1f12 0%, #0e120a 100%);
  text-shadow: none;
}

/* Light flicker when the LCD first wakes up (mimics real LCDs settling) */
body.power-on-detected .lcd {
  animation: lcd-wake 0.45s ease-out;
}

@keyframes lcd-wake {
  0% {
    filter: brightness(0.4);
    opacity: 0.7;
  }
  25% {
    filter: brightness(1.3);
    opacity: 1;
  }
  40% {
    filter: brightness(0.85);
  }
  100% {
    filter: brightness(1);
    opacity: 1;
  }
}

/* LCD cells stay hidden behind the boot overlay until the full sequence
   completes — power-on-detected lights the panel, .powered-on reveals
   the live BPM/STEP/MODE/SWING values. */
body:not(.powered-on) .lcd-cell {
  opacity: 0;
}

body:not(.powered-on) .lcd-boot {
  opacity: 1;
}

body.powered-on .lcd-boot {
  opacity: 0;
}

body.powered-on .lcd-cell {
  opacity: 1;
  transition: opacity 0.3s ease 0.2s;
}

/* Brand LED dot dark until power is detected (then pulses alongside the boot) */
body:not(.power-on-detected) .brand-mark .dot {
  animation: none;
  background: radial-gradient(circle at 35% 30%, #3a2a1a 0%, #1a0d05 100%);
  box-shadow:
    inset 0 1px 1px rgba(255, 220, 180, 0.08),
    inset 0 -1px 1px rgba(0, 0, 0, 0.55),
    0 0 0 1px rgba(0, 0, 0, 0.6);
}

/* Pads are plain unlit rubber until powered — only their LED layers
   (::before backlight, ::after playhead) wake up with the machine.
   The lit state itself lives with the pad styles further down. */

/* Pad self-test sweep — JS adds .self-test to each row in sequence */
.track-row.self-test .step::before {
  opacity: 1;
  transition-duration: 0.08s;
}

/* Reduced motion — collapse boot animations to near-instant */
@media (prefers-reduced-motion: reduce) {
  .prop,
  .cables {
    animation-duration: 0.01s;
    animation-delay: 0s;
  }
  .lcd-boot,
  .lcd-cell {
    transition: none;
  }
}

html,
body {
  margin: 0;
  padding: 0;
  overflow: hidden;
  width: 100vw;
  height: 100vh;
  background: #1a120a;
  font-family: "JetBrains Mono", monospace;
  color: #e9e1d3;
}

/* ------ Scene tokens ------
   One key light for the whole scene: a desk lamp above and slightly behind
   the sampler. Every surface follows the same rule — top edges catch warm
   light, bottom edges fall into shadow, cast shadows drop straight down.
   Textures are tiny SVG noise tiles: rasterised once, then just blitted. */
:root {
  --amber: #ff7a2b;
  --edge-hi: rgba(255, 240, 215, 0.16);
  --edge-lo: rgba(0, 0, 0, 0.7);
  /* Long vertical wood fibres */
  --tex-wood: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='600' height='900'><filter id='w' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='0.16 0.005' numOctaves='4' seed='11' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.06  0 0 0 0 0.025  0 0 0 0 0  1.5 0 0 0 -0.55'/></filter><rect width='100%25' height='100%25' filter='url(%23w)'/></svg>");
  /* Pebbled powder-coat / moulded ABS */
  --tex-plastic: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='p' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='2' seed='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 0.95  0 0 0 0 0.88  0.5 0 0 0 -0.22'/></filter><rect width='100%25' height='100%25' filter='url(%23p)'/></svg>");
  /* Sparse dust specks that settle on dark gear */
  --tex-dust: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='320' height='320'><filter id='d' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='1' seed='23' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.95  0 0 0 0 0.9  0 0 0 0 0.8  0 0 0 4 -2.75'/></filter><rect width='100%25' height='100%25' filter='url(%23d)'/></svg>");
}

/* ------ The desk surface ------ */
.desk {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background: /* lamp pool */
      radial-gradient(ellipse 60% 50% at 50% 18%, rgba(255, 200, 130, 0.2), transparent 70%),
      radial-gradient(ellipse 90% 90% at 50% 55%, transparent 40%, rgba(0, 0, 0, 0.55) 100%),
      /* coffee ring left by a mug that sat here too long */
      radial-gradient(
        circle at 30% 26%,
        transparent 0 2.05vw,
        rgba(30, 14, 4, 0.3) 2.2vw,
        rgba(30, 14, 4, 0.1) 2.42vw,
        transparent 2.6vw
      ),
      /* plank seams: dark gap with a lit lip on the far side */
      repeating-linear-gradient(
        90deg,
        transparent 0 calc(27vw - 3px),
        rgba(0, 0, 0, 0.3) calc(27vw - 3px) calc(27vw - 1px),
        rgba(255, 220, 180, 0.06) calc(27vw - 1px) 27vw
      ),
      var(--tex-wood), linear-gradient(180deg, #5a3a22 0%, #4a2e1a 60%, #3a230f 100%);
  background-position:
    0 0,
    0 0,
    0 0,
    11vw 0,
    0 0,
    0 0;
  isolation: isolate;
}

/* Lamp falloff over the whole scene — props near the edges sit in the same
   dimmer light as the wood under them instead of looking pasted on. */
.desk::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 40;
  background: radial-gradient(
    ellipse 78% 72% at 50% 38%,
    rgba(255, 214, 160, 0.05) 0%,
    transparent 45%,
    rgba(8, 4, 0, 0.32) 100%
  );
}

.desk::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 50;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.45 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/></svg>");
  mix-blend-mode: overlay;
  opacity: 0.45;
}

/* SVG cables container — sits in front of desk but behind stage props */
.cables {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  width: 100%;
  height: 100%;
}

/* Two shadows per cable: a tight one where the jacket touches the wood and
   a wide soft one from the lamp. Blurred once; nothing here animates. */
.cable-shadow-contact {
  filter: blur(1.5px);
}

.cable-shadow-soft {
  filter: blur(6px);
}

.stage {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

.stage > * {
  pointer-events: auto;
}

/* === Sampler stage === */
.sampler-stage {
  position: absolute;
  /* Hung from its front edge, well clear of the mic and the avatar: take
     rows make the chassis grow upward only. --stage-drop nudges it back down
     if the title would leave the top of the desk (set by VoxLane). */
  bottom: 33vh;
  left: 50%;
  transform: translate(-50%, var(--stage-drop, 0px));
  width: clamp(820px, 72vw, 1400px);
  display: flex;
  flex-direction: column;
  align-items: center;
  z-index: 10;
}

/* === Absolutely-positioned props === */
.prop {
  position: absolute;
}

.prop-notebook {
  top: 1.5vh;
  left: 1vw;
  width: 21vw;
  max-width: 340px;
  transform: rotate(-2deg);
  /* Above the sampler, so the unfolded page can lie over its corner */
  z-index: 12;
}

.prop-vinyl {
  bottom: 26vh;
  left: -9vw;
  width: 15vw;
  z-index: 3;
}

.prop-lp-fan {
  bottom: 10vh;
  left: -3vw;
  width: 19vw;
  max-width: 320px;
  z-index: 4;
}

.prop-soul-brother {
  top: -3vh;
  right: -3vw;
  width: 15vw;
  max-width: 240px;
  transform: rotate(6deg);
  z-index: 4;
}

.prop-polaroid {
  top: 16vh;
  right: 1vw;
  width: 12vw;
  max-width: 200px;
  z-index: 5;
}

.prop-cassette {
  top: 36vh;
  right: -1.5vw;
  width: 17vw;
  max-width: 280px;
  z-index: 4;
}

.prop-sticky {
  bottom: 12vh;
  left: 38vw;
  width: 9vw;
  max-width: 150px;
  z-index: 6;
  transform: rotate(-4deg);
}

.prop-mic {
  bottom: 12vh;
  left: 57vw;
  width: 13vw;
  max-width: 200px;
  /* above the sampler: on a cramped window the mic must stay reachable */
  z-index: 11;
}

/* The mic comes in with its cable, before the rest of the desk is dressed:
   a lead that ends in nothing looks cut. Same animation before and after
   power-on, so it doesn't play twice. */
body:not(.powered-on) .prop-mic {
  opacity: 1;
}

body:not(.powered-on) .prop-mic,
body.powered-on .prop-mic {
  animation: place-mic 0.8s ease-out 0.2s both;
}

@keyframes place-mic {
  from {
    opacity: 0;
    transform: translateY(-14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.prop-funk {
  bottom: 11vh;
  right: -2vw;
  width: 14vw;
  max-width: 230px;
  transform: rotate(4deg);
  z-index: 4;
}

/* ============ Notebook (engine notes) ============ */
.notebook {
  position: relative;
  background:
    repeating-linear-gradient(180deg, transparent 0 1.4em, rgba(100, 140, 200, 0.18) 1.4em 1.45em),
    linear-gradient(180deg, #f4ecd6 0%, #ede2c4 100%);
  color: #2a1f10;
  padding: 3.5vh 1.4vw 2vh 2vw;
  font-family: "Special Elite", "JetBrains Mono", monospace;
  font-size: clamp(10px, 0.85vw, 14px);
  line-height: 1.5;
  border-radius: 2px;
  transform: rotate(-1.4deg);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 2vh 4vh -1vh rgba(0, 0, 0, 0.7),
    0 1vh 2vh -0.5vh rgba(0, 0, 0, 0.5);
  border-left: 2px solid rgba(220, 80, 80, 0.45);
  overflow: hidden;
  transition:
    transform 0.3s ease,
    box-shadow 0.3s;
}

.notebook::before {
  content: "";
  position: absolute;
  top: -18px;
  left: 50%;
  transform: translateX(-50%) rotate(-2deg);
  width: 120px;
  height: 32px;
  background: linear-gradient(180deg, rgba(255, 250, 220, 0.85), rgba(230, 220, 180, 0.7));
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.35);
  opacity: 0.85;
  border: 1px solid rgba(0, 0, 0, 0.05);
}

.notebook::after {
  content: "";
  position: absolute;
  left: 30px;
  top: 0;
  bottom: 0;
  width: 1px;
  background: rgba(220, 80, 80, 0.5);
}

.notebook:hover {
  transform: rotate(-1deg) translateY(-2px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 3vh 5vh -1vh rgba(0, 0, 0, 0.75),
    0 1.4vh 2.5vh -0.5vh rgba(0, 0, 0, 0.55),
    0 0 0 1px rgba(255, 200, 100, 0.08);
}

.notebook h2 {
  font-family: "Permanent Marker", cursive;
  font-size: 22px;
  color: #c2410c;
  margin: 0 0 14px 0;
  transform: rotate(-1deg);
  letter-spacing: 0.5px;
}

.notebook p {
  margin: 0 0 18px 0;
}

/* Folded down to its heading until it's tapped, so the desk stays clear.
   The folds show: two more layers of paper peek out underneath, and the
   bottom edge is the crease where the rest is tucked under. */
.notebook.is-folded {
  /* Just wide enough for the heading (the hidden text would stretch max-content) */
  width: calc(210px + 3.4vw);
  padding-bottom: calc(1.6vh + 9px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    3px 3px 0 -1px #e6dbbd,
    3px 4px 0 -1px rgba(70, 50, 20, 0.45),
    -2px 7px 0 -2px #ddd1af,
    -2px 8px 0 -2px rgba(70, 50, 20, 0.45),
    0 2vh 4vh -1vh rgba(0, 0, 0, 0.7),
    0 1vh 2vh -0.5vh rgba(0, 0, 0, 0.5);
}

/* The crease: light catches the fold, then the paper turns under into shade */
.notebook-flap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 9px;
  background:
    linear-gradient(
      180deg,
      rgba(255, 255, 255, 0.7) 0 1px,
      rgba(60, 40, 10, 0.28) 1px,
      transparent 70%
    ),
    linear-gradient(180deg, #dccfa9, #d2c49b);
  opacity: 0;
  transition: opacity 0.2s;
}

.notebook.is-folded .notebook-flap {
  opacity: 1;
}

/* Unfolded, the old creases still cross the page */
.notebook-body p + p {
  padding-top: 14px;
  border-top: 1px solid rgba(60, 40, 10, 0.1);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55);
}

.notebook-tour {
  all: unset;
  cursor: pointer;
  font-family: "Permanent Marker", cursive;
  color: #c2410c;
  border-bottom: 2px solid currentColor;
}

.notebook-tour:focus-visible {
  outline: 2px solid #c2410c;
  outline-offset: 4px;
}

.notebook.is-folded h2 {
  margin-bottom: 0;
}

.notebook-toggle {
  all: unset;
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
}

.notebook-toggle:focus-visible {
  outline: 2px solid #c2410c;
  outline-offset: 4px;
}

.notebook-fold {
  font-size: 15px;
  transition: transform 0.25s ease;
}

.notebook:not(.is-folded) .notebook-fold {
  transform: rotate(90deg);
}

.notebook-body {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 0.3s ease;
}

.notebook.is-folded .notebook-body {
  grid-template-rows: 0fr;
}

.notebook-body > div {
  min-height: 0;
  overflow: hidden;
  /* Swings down from the crease as the page opens */
  transform-origin: top;
  transition:
    transform 0.35s ease,
    opacity 0.25s;
}

.notebook.is-folded .notebook-body > div {
  transform: perspective(600px) rotateX(-75deg);
  opacity: 0;
}

.notebook strong {
  background: rgba(255, 230, 120, 0.65);
  padding: 0 3px;
  font-weight: 700;
}

/* ============ Sampler chassis ============ */
.sampler-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 5;
  gap: 0.5vh;
  width: 100%;
}

.sampler-title {
  display: flex;
  align-items: center;
  gap: 1.2vw;
  font-family: "Permanent Marker", cursive;
  font-size: clamp(36px, 4.5vw, 64px);
  color: #f8e6c8;
  text-align: center;
  /* Push the title block up from the sampler chassis for breathing room */
  margin: 0 0 4vh 0;
  letter-spacing: 0.1vw;
  transform: rotate(-2deg);
  text-shadow:
    -1px -1px 0 #2a1810,
    1px 1px 0 #2a1810,
    2px 3px 0 rgba(0, 0, 0, 0.6),
    0 8px 20px rgba(0, 0, 0, 0.6);
}

.sampler-title em {
  font-style: normal;
  color: #ff7a2b;
  text-shadow:
    -1px -1px 0 #2a1810,
    1px 1px 0 #2a1810,
    2px 3px 0 rgba(0, 0, 0, 0.7),
    0 0 18px rgba(255, 122, 43, 0.45);
}

.logo-mark {
  width: clamp(48px, 5vw, 80px);
  height: clamp(48px, 5vw, 80px);
  object-fit: contain;
  filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.5));
  transform: rotate(2deg); /* counter the title's -2deg so the logo sits straight */
}

.tagline-label {
  font-family: "JetBrains Mono", monospace;
  font-size: clamp(8px, 0.6vw, 11px);
  color: rgba(248, 230, 200, 0.55);
  letter-spacing: 0.3vw;
  text-transform: uppercase;
  margin-bottom: 0.5vh;
}

.sampler {
  position: relative;
  width: 100%;
  max-width: 100%;
  padding: 2vh 1.4vw 2.2vh;
  border-radius: 0.8vw;
  isolation: isolate;
  background: /* lamp sheen rolling off the top face */
      radial-gradient(ellipse 75% 60% at 50% -12%, rgba(255, 226, 190, 0.1), transparent 70%),
      var(--tex-plastic), linear-gradient(180deg, #2b2621 0%, #1e1a16 32%, #151210 100%);
  box-shadow: /* chamfered rim: lit along the top, shadowed along the bottom */
    inset 0 1px 0 var(--edge-hi),
    inset 0 3px 4px -2px rgba(255, 240, 215, 0.07),
    inset 0 -2px 3px var(--edge-lo),
    inset 2px 0 2px -1px rgba(255, 255, 255, 0.05),
    inset -2px 0 2px -1px rgba(0, 0, 0, 0.5),
    /* front wall — the body has thickness */
    0 7px 0 #0a0806,
    /* contact shadow, then two softer ambient layers */
    0 10px 4px rgba(0, 0, 0, 0.75),
    0 24px 30px -6px rgba(0, 0, 0, 0.7),
    0 55px 70px -22px rgba(0, 0, 0, 0.75);
}

/* Twenty years of gigs: hairline scratches, corners rubbed down to the
   primer, a worn palm-rest edge and a film of dust. Sits above the paint
   but below every control. */
.sampler::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
  background:
    linear-gradient(172deg, transparent 49.5%, rgba(255, 240, 220, 0.11) 50%, transparent 50.5%) 9%
    97% / 11% 14px no-repeat,
    linear-gradient(8deg, transparent 49.4%, rgba(255, 240, 220, 0.08) 50%, transparent 50.6%) 64%
    3% / 15% 12px no-repeat,
    linear-gradient(-4deg, transparent 49.4%, rgba(255, 240, 220, 0.07) 50%, transparent 50.6%) 93%
    98% / 8% 8px no-repeat,
    radial-gradient(ellipse 9% 16% at 0% 100%, rgba(196, 170, 130, 0.15), transparent 70%),
    radial-gradient(ellipse 7% 13% at 100% 100%, rgba(196, 170, 130, 0.11), transparent 70%),
    radial-gradient(ellipse 6% 12% at 100% 0%, rgba(196, 170, 130, 0.08), transparent 70%),
    radial-gradient(ellipse 32% 5% at 50% 100%, rgba(196, 170, 130, 0.09), transparent 70%),
    var(--tex-dust);
}

.sampler-strip,
.tracks {
  position: relative;
  z-index: 1;
}

/* Corner screws — the slot is a background layer so it can turn while the
   head's lighting stays put (a real screw's highlight doesn't rotate). */
@property --slot {
  syntax: "<angle>";
  inherits: false;
  initial-value: 35deg;
}

.screw,
.transport::before,
.transport::after {
  --rust: transparent;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background:
    linear-gradient(var(--slot), transparent 42%, rgba(0, 0, 0, 0.78) 42% 58%, transparent 58%),
    radial-gradient(circle at 68% 72%, var(--rust), transparent 62%),
    radial-gradient(circle at 50% 26%, #d8d1c2 0%, #8f8778 48%, #37322a 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    inset 0 -1px 1px rgba(0, 0, 0, 0.6),
    /* countersunk seat with a lit lower lip */
    0 0 0 2px rgba(0, 0, 0, 0.78),
    0 1px 0 2px rgba(255, 240, 215, 0.09);
}

.screw {
  position: absolute;
  z-index: 2;
  cursor: pointer;
  transition: --slot 0.55s cubic-bezier(0.3, 0.9, 0.3, 1);
}

.screw.tl {
  top: 9px;
  left: 9px;
}
.screw.tr {
  top: 9px;
  right: 9px;
  --slot: -18deg;
}
.screw.bl {
  bottom: 9px;
  left: 9px;
  --slot: 82deg;
  --rust: rgba(125, 62, 20, 0.5);
}
.screw.br {
  bottom: 9px;
  right: 9px;
  --slot: 118deg;
}

/* Give it a quarter turn */
.screw.tl:hover {
  --slot: 125deg;
}
.screw.tr:hover {
  --slot: 72deg;
}
.screw.bl:hover {
  --slot: 172deg;
}
.screw.br:hover {
  --slot: 208deg;
}

/* Sampler top brand strip */
.sampler-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0.8vw 1vh;
  padding-bottom: 0.8vh;
  /* machined groove: dark cut with a lit lower lip */
  border-bottom: 1px solid rgba(0, 0, 0, 0.65);
  box-shadow: 0 1px 0 rgba(255, 240, 215, 0.07);
  gap: 1vw;
}

.brand-mark {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.5vw;
  font-family: "Bowlby One", sans-serif;
  font-size: clamp(11px, 0.9vw, 16px);
  letter-spacing: 0.25vw;
  /* Machined-into-chassis: letter color matches the chassis dark tone,
     a hair deeper so the face reads as a recessed surface, not paint */
  color: #0e0b08;
  /* The 3D illusion comes entirely from edge shadows + highlights:
     - dark line on the TOP edge of each letter (recess wall facing away from overhead lamp)
     - subtle warm highlight on the BOTTOM edge (chamfered lip catching the lamp glow above)
     - the lamp on the desk is at top center, so all letters share the same light direction */
  text-shadow:
    0 -1px 0 rgba(0, 0, 0, 0.95),
    -1px -1px 1px rgba(0, 0, 0, 0.55),
    0 1px 0 rgba(255, 230, 200, 0.16),
    1px 1px 1px rgba(255, 220, 180, 0.08);
  cursor: default;
  user-select: none;
}

.brand-mark .dot {
  width: 0.5vw;
  height: 0.5vw;
  min-width: 7px;
  min-height: 7px;
  max-width: 10px;
  max-height: 10px;
  border-radius: 50%;
  /* Recessed LED-in-chassis look: dark well + glowing dome inside */
  background: radial-gradient(circle at 35% 30%, #ffb46e 0%, #ff7a2b 45%, #c2410c 90%);
  box-shadow:
    inset 0 1px 1px rgba(255, 220, 180, 0.5),
    inset 0 -1px 1px rgba(0, 0, 0, 0.55),
    0 0 0 1px rgba(0, 0, 0, 0.6),
    0 0 10px rgba(255, 122, 43, 0.55);
  animation: pulse 1.4s ease-in-out infinite;
}

.brand-mark::after {
  content: "BUILT IN THE BASEMENT · '00";
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
  color: rgba(255, 200, 100, 0.7);
  letter-spacing: 0.2vw;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(-4px);
  transition:
    opacity 0.25s ease,
    transform 0.25s ease;
  pointer-events: none;
}

.brand-mark:hover::after {
  opacity: 1;
  transform: translateY(0);
}

/* Opacity-only so the power LED blinks on the compositor */
@keyframes pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.45;
  }
}

/* LCD display — reflective panel behind a glass window, set into a bezel */
.lcd {
  position: relative; /* positioning context for .lcd-boot overlay */
  background: /* pixel grid */
      repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.15) 0 1px, transparent 1px 3px),
      repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.06) 0 1px, transparent 1px 3px),
      /* edge-lit backlight: hotter near the LED on the left */
      radial-gradient(ellipse 55% 150% at 0% 50%, rgba(238, 255, 205, 0.4), transparent 70%),
      linear-gradient(180deg, #b4d491 0%, #98b874 100%);
  color: #1f2913;
  font-family: "VT323", monospace;
  font-size: clamp(14px, 1.3vw, 22px);
  line-height: 1;
  padding: 0.7vh 1vw;
  border-radius: 3px;
  box-shadow:
    inset 0 3px 7px rgba(0, 0, 0, 0.5),
    inset 0 0 0 1px rgba(0, 0, 0, 0.35),
    /* bezel, then the lit lip of the cut-out it sits in */
    0 0 0 3px #0b0908,
    0 0 0 4px rgba(255, 240, 215, 0.06),
    0 2px 0 4px rgba(255, 240, 215, 0.05);
  /* Segments cast a faint shadow onto the reflector behind them */
  text-shadow: 1px 2px 0 rgba(31, 41, 19, 0.2);
  letter-spacing: 1px;
  display: flex;
  gap: 1.2vw;
  align-items: center;
  overflow: hidden; /* keep the boot text clipped to the LCD bounds */
}

/* Lamp reflection on the glass */
.lcd::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
  background: linear-gradient(
    112deg,
    rgba(255, 255, 255, 0.24) 0%,
    rgba(255, 255, 255, 0.07) 24%,
    transparent 24.5%,
    transparent 70%,
    rgba(255, 255, 255, 0.05) 100%
  );
}

.lcd .v {
  color: #2a3a16;
  display: inline-block;
}

/* Fixed-width value cells so the LCD never resizes when its values change
   (e.g. mode switching FRICTION → LIMP → LIVE).
   ch counts characters but the LCD also applies letter-spacing: 1px, so
   we add a small calc() padding to keep the cell stable even at the
   longest expected content. */
.lcd .v[data-bind="bpm"] {
  min-width: calc(3ch + 4px);
  text-align: right;
}
.lcd .v[data-bind="step"] {
  min-width: calc(2ch + 3px);
  text-align: right;
}
.lcd .v[data-bind="mode"] {
  /* "FRICTION" = 8 chars + 7 letter-spacing gaps + safety margin */
  min-width: calc(8ch + 12px);
  text-align: left;
}
.lcd .v[data-bind="humanize"] {
  min-width: calc(4ch + 5px);
  text-align: right;
}

.lcd .lbl {
  font-size: clamp(7px, 0.55vw, 10px);
  opacity: 0.6;
  letter-spacing: 1.5px;
  font-family: "JetBrains Mono", monospace;
  margin-bottom: 2px;
}

.lcd-cell {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1;
  min-width: 3.5vw;
  white-space: nowrap;
}

.lcd-cell:not(:last-child) {
  border-right: 1px solid rgba(30, 50, 20, 0.25);
  padding-right: 1vw;
}

/* Sticker on chassis */
.chassis-sticker {
  position: absolute;
  top: 9vh;
  right: -1.5vw;
  font-size: clamp(11px, 0.9vw, 14px);
  transform: rotate(8deg);
  background: #1a0d05;
  color: #ff7a2b;
  border: 1px dashed rgba(255, 122, 43, 0.5);
  font-family: "Permanent Marker", cursive;
  padding: 4px 10px;
  letter-spacing: 1px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
  transform-origin: bottom right;
  pointer-events: auto;
  z-index: 11;
}

.chassis-sticker:hover {
  transform: rotate(12deg) translate(-2px, -1px) skewX(-3deg) scale(1.05);
}

/* ---- Track rows (#app populated by Grid.js) ---- */
/* The pad bed: a recessed plate the pads poke up through */
.tracks,
#app {
  display: flex;
  flex-direction: column;
  gap: 1vh;
  padding: 1.1vh 0.6vw 1.3vh;
  border-radius: 0.5vw;
  background: linear-gradient(180deg, #0f0c0a 0%, #16120f 100%);
  box-shadow:
    inset 0 3px 6px rgba(0, 0, 0, 0.85),
    inset 0 0 0 1px rgba(0, 0, 0, 0.6),
    0 1px 0 rgba(255, 240, 215, 0.08);
}

.track-row {
  display: grid;
  grid-template-columns:
    clamp(96px, 7.4vw, 140px)
    auto
    auto
    1fr;
  column-gap: 0.7vw;
  align-items: center;
  position: relative;
}

.track-info {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.2vh;
  width: 100%;
  min-width: 0;
}

/* Standalone track-name (only briefly visible before SampleUploader wraps it) */
.track-name {
  position: relative;
  display: block;
  font-family: "Bowlby One", sans-serif;
  font-size: clamp(10px, 0.75vw, 14px);
  letter-spacing: 0.08vw;
  color: #f0e8d8;
  text-transform: uppercase;
  user-select: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The wrapper SampleUploader injects becomes an embossed label-maker strip
   stuck to the chassis, colour-coded along its left edge */
.track-info .track-name-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4vw;
  width: 100%;
  padding: 0.6vh 0.35vw 0.6vh 0.55vw;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, transparent 38%, rgba(0, 0, 0, 0.25) 100%),
    #241e18;
  border: none;
  border-left: 3px solid var(--track-color, #ff7a2b);
  border-radius: 2px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 -1px 0 rgba(0, 0, 0, 0.6),
    0 1px 2px rgba(0, 0, 0, 0.7);
}

/* Track-name inside the container: raised white embossed letters */
.track-name-container .track-name {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  padding: 0;
  box-shadow: none;
  border-radius: 0;
  text-align: left;
  font-family: "JetBrains Mono", monospace;
  font-weight: 700;
  font-size: clamp(9px, 0.72vw, 13px);
  letter-spacing: 0.12vw;
  color: #f4eee0;
  text-shadow:
    0 -1px 0 rgba(255, 255, 255, 0.35),
    0 1px 1px rgba(0, 0, 0, 0.9);
}

/* Folder icon button — inset hardware-style control */
.track-info .sample-upload-btn {
  flex-shrink: 0;
  width: clamp(20px, 1.7vw, 26px);
  height: clamp(20px, 1.7vw, 26px);
  padding: 0;
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 3px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 1;
  transition:
    background 0.15s ease,
    border-color 0.15s ease;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    inset 0 -1px 2px rgba(0, 0, 0, 0.6);
}

.track-info .sample-upload-btn:hover {
  background: rgba(255, 122, 43, 0.18);
  border-color: rgba(255, 122, 43, 0.5);
}

.track-info .sample-upload-btn:active {
  transform: translateY(1px);
}

/* MINE / KIT: a small slide switch beside the sample-load key. The cap is
   up and lit when the row plays your own sound, down when it plays the kit's. */
.track-info .sample-source-switch {
  position: relative;
  flex-shrink: 0;
  width: clamp(9px, 0.7vw, 11px);
  height: clamp(20px, 1.7vw, 26px);
  padding: 0;
  background: rgba(0, 0, 0, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 2px;
  cursor: pointer;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.8);
}

.track-info .sample-source-switch[hidden] {
  display: none;
}

.track-info .sample-source-switch::after {
  content: "";
  position: absolute;
  top: 1px;
  left: 1px;
  right: 1px;
  height: calc(50% - 1px);
  border-radius: 1px;
  background: #7a7166;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
  transform: translateY(100%);
  transition:
    transform 0.12s ease,
    background 0.12s ease;
}

.track-info .sample-source-switch[aria-pressed="true"]::after {
  background: #ff7a2b;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    0 0 5px rgba(255, 122, 43, 0.7);
  transform: none;
}

.track-info .folder-icon {
  width: 60%;
  height: 60%;
  color: rgba(255, 255, 255, 0.5);
  transition: color 0.15s ease;
}

.track-info .sample-upload-btn:hover .folder-icon {
  color: #ff7a2b;
}

.track-controls-row {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.4vw;
  margin-top: 0.3vh;
}

/* Ghost mini-dial container — auto-height so the GHOST label sits naturally below */
.track-dial-container {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
}

.track-dial-container .mini-dial-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2vh;
}

.mini-dial-svg {
  width: clamp(38px, 3.4vw, 50px);
  height: clamp(38px, 3.4vw, 50px);
  cursor: ns-resize;
  display: block;
}

.mini-dial-svg:active {
  cursor: grabbing;
}

.mini-knob-group {
  transform-origin: 18px 18px;
  transition: transform 0.05s ease-out;
}

.mini-dial-label {
  font-family: "JetBrains Mono", monospace;
  font-size: clamp(6px, 0.48vw, 8px);
  font-weight: 500;
  color: rgba(255, 255, 255, 0.5);
  text-transform: uppercase;
  letter-spacing: 1.2px;
  text-align: center;
  line-height: 1;
  margin-top: 2px;
}

.mini-dial-arc {
  transition: stroke-dashoffset 0.05s ease-out;
}

/* Swing lock button — matches folder icon button for visual rhythm */
.swing-lock-btn {
  width: clamp(22px, 1.9vw, 28px);
  height: clamp(22px, 1.9vw, 28px);
  padding: 2px;
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 3px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  justify-self: center;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    inset 0 -1px 2px rgba(0, 0, 0, 0.6);
  transition: all 0.2s ease;
}

.swing-lock-btn:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.25);
}

.swing-lock-btn.locked {
  background: rgba(255, 122, 43, 0.18);
  border-color: #ff7a2b;
}

.swing-lock-btn.locked:hover {
  background: rgba(255, 122, 43, 0.28);
}

.lock-icon {
  width: 75%;
  height: 75%;
  color: rgba(255, 255, 255, 0.45);
  transition: all 0.25s ease;
}

.swing-lock-btn:hover .lock-icon {
  color: rgba(255, 255, 255, 0.7);
}

.swing-lock-btn.locked .lock-icon {
  color: #ff7a2b;
}

.lock-icon .lock-body {
  transition: all 0.2s ease;
}

.swing-lock-btn.locked .lock-icon .lock-body {
  fill: rgba(255, 122, 43, 0.3);
}

.lock-icon .lock-shackle {
  transition: all 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55);
  transform-origin: center bottom;
}

.swing-lock-btn:not(.locked) .lock-icon .lock-shackle {
  transform: rotate(-25deg) translateX(-1px);
}

.swing-lock-btn.locked .lock-icon .lock-shackle {
  transform: rotate(0deg) translateX(0);
}

.swing-lock-btn.auto-locked {
  cursor: not-allowed;
  opacity: 0.85;
  position: relative;
}

.swing-lock-btn.auto-locked .lock-icon {
  color: #ff7a2b;
}

.swing-lock-btn.auto-locked::after {
  content: "A";
  position: absolute;
  top: -4px;
  right: -4px;
  font-family: "JetBrains Mono", monospace;
  font-size: 7px;
  font-weight: bold;
  background: #ff7a2b;
  color: #0a0805;
  border-radius: 50%;
  width: 11px;
  height: 11px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
}

/* ---- Pads (the step cells) ----
   Each pad is three stacked layers, so every state change is an opacity
   fade the compositor can run without repainting anything:
     .step          aged silicone cap (static)
     .step::before  amber backlight bleeding through the rubber (step on)
     .step::after   playhead strobe — snaps on, decays like a warm LED */
.track-steps {
  display: grid;
  grid-template-columns: repeat(16, 1fr);
  gap: 0.34vw;
}

.step {
  --rub-hi: #dcd2bf;
  --rub-mid: #b4a993;
  --rub-lo: #80755f;
  --dimple: linear-gradient(transparent, transparent);
  --art-mark: linear-gradient(transparent, transparent);
  --art-ink: rgba(40, 28, 12, 0.72);
  position: relative;
  aspect-ratio: 1;
  border: none;
  border-radius: 7px;
  cursor: pointer;
  background:
    var(--art-mark), var(--dimple),
    /* soft sheen across the domed top */
    radial-gradient(ellipse 85% 55% at 50% 6%, rgba(255, 255, 255, 0.5), transparent 72%),
    linear-gradient(180deg, var(--rub-hi) 0%, var(--rub-mid) 58%, var(--rub-lo) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    inset 0 -4px 6px rgba(60, 45, 25, 0.45),
    /* grime packed into the edge */
    inset 0 0 0 1px rgba(70, 55, 35, 0.3),
    /* side wall of the cap, then its shadow on the bed */
    0 2px 0 #4d4537,
    0 5px 5px rgba(0, 0, 0, 0.65);
  /* Release: the rubber dome springs back with a little overshoot */
  transition:
    transform 0.18s cubic-bezier(0.3, 1.8, 0.5, 1),
    box-shadow 0.18s ease-out;
}

/* Moulded dimple marking each downbeat */
.step.beat {
  --dimple: radial-gradient(circle at 50% 84%, rgba(40, 28, 12, 0.55) 0 1.5px, transparent 2.2px);
}

/* Articulation notches, moulded into the cap so they read lit or unlit.
   Short ticks are grace notes ahead of the hit (tall tick); equal ticks are
   roll hits; three dots are the triplet. */
.step[data-art="flam"] {
  --art-mark:
    linear-gradient(var(--art-ink), var(--art-ink)) calc(50% - 3px) 9px / 2px 5px no-repeat,
    linear-gradient(var(--art-ink), var(--art-ink)) calc(50% + 2px) 5px / 2px 9px no-repeat;
}
.step[data-art="drag"] {
  --art-mark:
    linear-gradient(var(--art-ink), var(--art-ink)) calc(50% - 6px) 9px / 2px 5px no-repeat,
    linear-gradient(var(--art-ink), var(--art-ink)) calc(50% - 1px) 9px / 2px 5px no-repeat,
    linear-gradient(var(--art-ink), var(--art-ink)) calc(50% + 4px) 5px / 2px 9px no-repeat;
}
.step[data-art="roll2"] {
  --art-mark:
    linear-gradient(var(--art-ink), var(--art-ink)) calc(50% - 3px) 5px / 2px 9px no-repeat,
    linear-gradient(var(--art-ink), var(--art-ink)) calc(50% + 3px) 5px / 2px 9px no-repeat;
}
.step[data-art="roll3"] {
  --art-mark:
    linear-gradient(var(--art-ink), var(--art-ink)) calc(50% - 5px) 5px / 2px 9px no-repeat,
    linear-gradient(var(--art-ink), var(--art-ink)) 50% 5px / 2px 9px no-repeat,
    linear-gradient(var(--art-ink), var(--art-ink)) calc(50% + 5px) 5px / 2px 9px no-repeat;
}
.step[data-art="trip"] {
  --art-mark:
    radial-gradient(circle, var(--art-ink) 0 1.6px, transparent 2.2px) calc(50% - 6px) 7px / 5px 5px
    no-repeat,
    radial-gradient(circle, var(--art-ink) 0 1.6px, transparent 2.2px) 50% 7px / 5px 5px no-repeat,
    radial-gradient(circle, var(--art-ink) 0 1.6px, transparent 2.2px) calc(50% + 6px) 7px / 5px 5px
    no-repeat;
}

/* Uneven ageing — downbeats are polished by fingers, others have yellowed
   or picked up grime. Strides differ per row so the wear never lines up
   into columns. */
.step:nth-child(4n + 1) {
  --rub-hi: #e6ddcc;
  --rub-mid: #bfb49f;
}
.track-row:nth-child(odd) .step:nth-child(7n + 3),
.track-row:nth-child(even) .step:nth-child(9n + 6) {
  --rub-hi: #ddd1b8;
  --rub-mid: #b7a98c;
  --rub-lo: #837253;
}
.track-row:nth-child(3n + 1) .step:nth-child(5n + 4),
.track-row:nth-child(3n + 2) .step:nth-child(6n + 2),
.track-row:nth-child(3n) .step:nth-child(11n + 8) {
  --rub-hi: #d2c8b5;
  --rub-mid: #a79c87;
  --rub-lo: #746a56;
}

.step:hover {
  filter: brightness(1.05);
}

/* Press: fast travel down, the cap sinks flush and its shadow closes up */
.step:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 2px 4px rgba(60, 45, 25, 0.5),
    inset 0 -2px 4px rgba(60, 45, 25, 0.4),
    inset 0 0 0 1px rgba(70, 55, 35, 0.3),
    0 0 0 #4d4537,
    0 1px 2px rgba(0, 0, 0, 0.7);
  transition-duration: 0.04s;
}

.step::before,
.step::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
}

/* Backlight: hottest over the LED in the middle, deep amber at the rim,
   with a little light spilling onto the bed around the pad */
.step::before {
  background:
    var(--art-mark), var(--dimple),
    radial-gradient(ellipse 85% 55% at 50% 6%, rgba(255, 255, 255, 0.35), transparent 72%),
    radial-gradient(circle at 50% 55%, #ffd7a3 0%, #ff9443 36%, #f2691c 68%, #b9410d 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.45),
    inset 0 -3px 6px rgba(120, 30, 0, 0.55),
    0 2px 0 #7c2d08,
    0 0 3px rgba(255, 160, 90, 0.8),
    0 0 14px 1px rgba(255, 122, 43, 0.42);
  transition: opacity 0.16s ease-out;
}

body.powered-on .step.active::before {
  opacity: 1;
  transition-duration: 0.05s;
}

.step::after {
  background: radial-gradient(
    circle at 50% 50%,
    rgba(255, 250, 235, 0.8) 0%,
    rgba(255, 236, 205, 0.3) 62%,
    rgba(255, 236, 205, 0.12) 100%
  );
  box-shadow: 0 0 10px 1px rgba(255, 236, 205, 0.3);
  transition: opacity 0.24s ease-out;
}

.step.playing::after {
  opacity: 0.7;
  transition-duration: 0s;
}

.step.active.playing::after {
  opacity: 1;
}

/* ---- VOX lane: the voice take as a fifth row ---- */
.track-row.vox-row[hidden] {
  display: none;
}

/* MUTE and ERASE keys: sit where the drum rows have their sample-load key */
.track-info .vox-key {
  flex-shrink: 0;
  width: clamp(20px, 1.7vw, 26px);
  height: clamp(20px, 1.7vw, 26px);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Bowlby One", sans-serif;
  font-size: clamp(9px, 0.7vw, 12px);
  color: rgba(255, 255, 255, 0.5);
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 3px;
  cursor: pointer;
  transition:
    background 0.15s ease,
    border-color 0.15s ease,
    color 0.15s ease;
}

.vox-key-icon {
  width: 70%;
  height: 70%;
}

.track-info .vox-key:hover {
  color: #ff7a2b;
  background: rgba(255, 122, 43, 0.18);
  border-color: rgba(255, 122, 43, 0.5);
}

.track-info .vox-key:active {
  transform: translateY(1px);
}

.track-info .vox-key[aria-pressed="true"] {
  color: #1a1410;
  background: #ff7a2b;
  border-color: #ff7a2b;
}

/* SAUCE and TUNE sit side by side under the name plate */
.vox-fx-keys {
  display: flex;
  gap: 3px;
}

/* TUNE: a latching key under the name plate */
.vox-tune-btn {
  flex: 1;
  font-family: "Bowlby One", sans-serif;
  font-size: clamp(7px, 0.55vw, 9px);
  letter-spacing: 0.1vw;
  text-transform: uppercase;
  color: rgba(240, 232, 216, 0.55);
  padding: 0.4vh 0.4vw;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, transparent 38%, rgba(0, 0, 0, 0.25) 100%),
    #241e18;
  border: none;
  border-radius: 2px;
  cursor: pointer;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 2px 3px rgba(0, 0, 0, 0.6);
  transition:
    color 0.2s ease,
    box-shadow 0.3s ease,
    background 0.3s ease;
}

.vox-tune-btn:hover {
  color: #f0e8d8;
}

/* SAUCE send: a fader slot under the name plate. Sliding the cap to the
   right uncovers a pearly strip that gets brighter and more thickly
   sequinned the further it goes; the slot glows to match. --dream is 0-1. */
.vox-dream {
  --dream: 0;
  position: relative;
  flex: 1.6;
  display: block;
  border-radius: 2px;
  background: linear-gradient(180deg, #0d0a08 0%, #1d1813 100%);
  box-shadow:
    inset 0 1px 3px rgba(0, 0, 0, 0.9),
    0 1px 0 rgba(255, 255, 255, 0.08),
    0 0 calc(var(--dream) * 12px) rgba(247, 168, 200, calc(var(--dream) * 0.6)),
    0 0 calc(var(--dream) * 24px) rgba(201, 179, 255, calc(var(--dream) * 0.35));
  cursor: ew-resize;
}

.vox-dream-label {
  display: block;
  font-family: "Bowlby One", sans-serif;
  font-size: clamp(7px, 0.55vw, 9px);
  letter-spacing: 0.04vw;
  text-transform: uppercase;
  text-align: center;
  white-space: nowrap;
  padding: 0.4vh 0.15vw;
  color: rgba(240, 232, 216, 0.5);
}

/* The uncovered strip carries its own dark copy of the label */
.vox-dream-fill {
  position: absolute;
  inset: 0;
  border-radius: 2px;
  clip-path: inset(0 calc(100% - var(--dream) * 100%) 0 0 round 2px);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.5) 0%, transparent 45%, rgba(0, 0, 0, 0.12) 100%),
    linear-gradient(90deg, #8a6a52 0%, #ffb37a 30%, #f7a8c8 62%, #c9b3ff 86%, #f4efff 100%);
}

.vox-dream-fill .vox-dream-label {
  color: #2a1030;
}

/* Sequins: sparse at the dry end, thick at the wet end, and they twinkle */
.vox-dream-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 22% 68%, #fff 0 0.6px, transparent 1.2px),
    radial-gradient(circle at 41% 26%, #fff 0 0.7px, transparent 1.4px),
    radial-gradient(circle at 55% 74%, #fff 0 0.7px, transparent 1.4px),
    radial-gradient(circle at 64% 30%, #fff 0 0.9px, transparent 1.7px),
    radial-gradient(circle at 72% 62%, #fff 0 0.8px, transparent 1.6px),
    radial-gradient(circle at 79% 22%, #fff 0 1px, transparent 2px),
    radial-gradient(circle at 85% 78%, #fff 0 1px, transparent 2px),
    radial-gradient(circle at 90% 40%, #fff 0 1.2px, transparent 2.4px),
    radial-gradient(circle at 95% 68%, #fff 0 1.1px, transparent 2.2px),
    radial-gradient(circle at 98% 20%, #fff 0 1.3px, transparent 2.6px);
  animation: dream-twinkle 1.6s ease-in-out infinite alternate;
}

@keyframes dream-twinkle {
  from {
    opacity: 0.35;
  }
  to {
    opacity: 1;
  }
}

/* Fader cap: a ridged chrome cap, taller than its slot so there is
   something to get hold of, with an index line down the middle */
.vox-dream-cap {
  position: absolute;
  top: -3px;
  bottom: -3px;
  left: clamp(5px, calc(var(--dream) * 100%), calc(100% - 5px));
  width: 10px;
  transform: translateX(-50%);
  border-radius: 2px;
  background:
    linear-gradient(90deg, transparent 0 4px, #ff7a2b 4px 6px, transparent 6px),
    repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.4) 0 1px, transparent 1px 2px),
    linear-gradient(180deg, #f6f1e8 0%, #b9b1a5 45%, #6b645b 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.8),
    inset 0 -1px 0 rgba(0, 0, 0, 0.5),
    0 2px 4px rgba(0, 0, 0, 0.85),
    0 0 0 1px rgba(0, 0, 0, 0.6);
  transition:
    transform 0.12s ease,
    filter 0.12s ease;
}

.vox-dream:hover .vox-dream-cap {
  filter: brightness(1.2);
  transform: translateX(-50%) scaleY(1.08);
}

.vox-dream:active .vox-dream-cap {
  transform: translateX(-50%) scaleY(0.96);
}

/* The real control: an invisible range input over the slot */
.vox-dream-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: grab;
}

.vox-dream-input:active {
  cursor: grabbing;
}

.vox-dream:focus-within {
  outline: 1px solid #f7a8c8;
  outline-offset: 1px;
}

@media (prefers-reduced-motion: reduce) {
  .vox-dream-fill::after {
    animation: none;
  }
}

.vox-fx-keys button {
  padding-inline: 0.15vw;
  letter-spacing: 0.04vw;
  white-space: nowrap;
}

/* TUNE key: lit amber, like the other latching mode keys */
.vox-tune-btn[aria-pressed="true"] {
  color: #1a0f06;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.25) 0%, transparent 40%, rgba(0, 0, 0, 0.15) 100%),
    #ff7a2b;
}

/* FOLLOW key: sits where the drum rows have their swing lock */
.swing-lock-btn.vox-follow-btn {
  font-family: "Bowlby One", sans-serif;
  font-size: clamp(9px, 0.7vw, 12px);
  color: #ffc58a;
  text-shadow: 0 0 6px rgba(255, 122, 43, 0.6);
}

/* Chop screen: a second LCD the width of the pads, showing the take's
   waveform with its slice markers. Same glass and backlight as the main one. */
.vox-lcd {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  margin: 4px 4px 4px 0;
  background:
    repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.12) 0 1px, transparent 1px 3px),
    radial-gradient(ellipse 40% 150% at 0% 50%, rgba(238, 255, 205, 0.4), transparent 70%),
    linear-gradient(180deg, #b4d491 0%, #98b874 100%);
  color: #1f2913;
  border-radius: 3px;
  overflow: hidden;
  box-shadow:
    inset 0 3px 7px rgba(0, 0, 0, 0.5),
    inset 0 0 0 1px rgba(0, 0, 0, 0.35),
    0 0 0 3px #0b0908,
    0 0 0 4px rgba(255, 240, 215, 0.06),
    0 2px 0 4px rgba(255, 240, 215, 0.05);
}

/* Lamp reflection on the glass */
.vox-lcd::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    112deg,
    rgba(255, 255, 255, 0.2) 0%,
    rgba(255, 255, 255, 0.05) 12%,
    transparent 12.5%
  );
}

.vox-screen {
  position: relative;
  height: clamp(58px, 5.4vw, 92px);
  cursor: pointer;
  touch-action: none;
}

/* Both take rows showing: shallower screens, so the unit still fits the desk */
.two-takes .vox-screen {
  height: clamp(36px, 3vw, 50px);
}

.vox-screen canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* The step being played, as an inverse-video block sliding along */
.vox-playhead {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  background: rgba(31, 41, 19, 0.2);
  opacity: 0;
  pointer-events: none;
}

/* Soft keys along the bottom of the screen: a readout, then CHOP and GRID */
.vox-softkeys {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 2px 4px 3px 6px;
  border-top: 1px solid rgba(31, 41, 19, 0.35);
  font-family: "VT323", monospace;
  font-size: clamp(11px, 0.95vw, 15px);
  line-height: 1;
  letter-spacing: 1px;
}

.vox-readout {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: #2a3a16;
}

/* Inverse video, as function-key labels are drawn */
.vox-soft {
  position: relative;
  z-index: 1;
  flex: none;
  font: inherit;
  letter-spacing: 1px;
  color: #b4d491;
  background: #1f2913;
  border: none;
  border-radius: 1px;
  padding: 1px 6px 2px;
  cursor: pointer;
}

.vox-soft:hover {
  background: #33451d;
}

.vox-soft:disabled {
  opacity: 0.3;
  cursor: default;
}

/* SLIDE / SWAP / COPY: one of the three is lit, like a latching mode switch */
.vox-tools {
  display: flex;
  flex: none;
  gap: 1px;
  margin-right: 4px;
}

.vox-tools .vox-soft {
  color: #1f2913;
  background: transparent;
  box-shadow: inset 0 0 0 1px rgba(31, 41, 19, 0.75);
}

.vox-tools .vox-soft:hover {
  background: rgba(31, 41, 19, 0.18);
}

.vox-tools .vox-soft[aria-pressed="true"] {
  color: #d6ecb8;
  background: #b3200a;
  box-shadow: none;
}

.vox-soft:focus-visible {
  outline: 2px solid #b3200a;
  outline-offset: 1px;
}

/* A muted lane: the screen's backlight drops */
.vox-row.is-muted .vox-screen {
  opacity: 0.4;
}

/* Sample drop overlay — overrides SampleUploader's TR-909 styling */
.track-row.sample-drop-zone .sample-drop-overlay {
  background: rgba(20, 17, 13, 0.92);
  border: 2px solid #ff7a2b;
  border-radius: 4px;
  backdrop-filter: blur(2px);
}

.track-row.sample-drop-zone .sample-drop-overlay-text {
  font-family: "Bowlby One", sans-serif;
  color: #fef3e2;
  font-size: clamp(11px, 0.85vw, 14px);
  letter-spacing: 1.5px;
  text-transform: uppercase;
}

.track-row.sample-drop-zone .sample-drop-overlay-track {
  font-family: "JetBrains Mono", monospace;
  color: #ff7a2b;
  font-size: clamp(9px, 0.65vw, 11px);
  font-weight: 700;
  letter-spacing: 1.5px;
  margin-top: 4px;
}

.track-row.sample-drop-zone.drag-over .sample-drop-overlay {
  animation: dropzone-glow 1.2s ease-in-out infinite;
}

@keyframes dropzone-glow {
  0%,
  100% {
    border-color: #ff7a2b;
    box-shadow: 0 0 12px rgba(255, 122, 43, 0.35);
  }
  50% {
    border-color: #ff9d50;
    box-shadow: 0 0 22px rgba(255, 122, 43, 0.55);
  }
}

/* ---- Transport — a rack-style control strip along the desk's front edge ---- */
.transport {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 9vh;
  /* Above the desk's lamp falloff (40): the strip is the front edge of the
     desk, and dimmed with the corners its keys read as switched off */
  z-index: 45;
  background:
    var(--tex-plastic),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.022) 0 1px, rgba(0, 0, 0, 0.03) 1px 3px),
    linear-gradient(180deg, #25201b 0%, #191511 40%, #0e0b09 100%);
  padding: 0 calc(3vw + 20px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.2vw;
  box-shadow:
    inset 0 1px 0 var(--edge-hi),
    inset 0 4px 5px -3px rgba(255, 240, 215, 0.06),
    0 -2px 0 #070504,
    0 -12px 26px rgba(0, 0, 0, 0.6);
}

/* Rack screws at each end (head styling shared with the chassis screws) */
.transport::before,
.transport::after {
  content: "";
  position: absolute;
  top: 50%;
  margin-top: -7px;
}

.transport::before {
  left: 1.2vw;
  --slot: 64deg;
}

.transport::after {
  right: 1.2vw;
  --slot: -12deg;
}

.transport-group {
  display: flex;
  align-items: center;
  gap: 1vw;
}

/* Keycap sitting in a routed pocket: dark seat, lit lower lip, visible
   side wall. Pressing it removes the wall and closes the shadow. */
.transport-btn {
  position: relative;
  font-family: "Bowlby One", sans-serif;
  letter-spacing: 0.2vw;
  font-size: clamp(10px, 0.78vw, 13px);
  padding: 1.2vh 1.4vw;
  border-radius: 4px;
  border: none;
  cursor: pointer;
  text-transform: uppercase;
  background: linear-gradient(180deg, #453c32 0%, #2f2720 55%, #241d17 100%);
  color: #f0e8d8;
  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.7);
  box-shadow:
    inset 0 1px 0 rgba(255, 240, 215, 0.2),
    inset 0 -2px 3px rgba(0, 0, 0, 0.5),
    0 3px 0 #120e0b,
    0 3px 0 2px #060504,
    0 4px 0 2px rgba(255, 240, 215, 0.07),
    0 7px 8px rgba(0, 0, 0, 0.5);
  transition:
    transform 0.16s cubic-bezier(0.3, 1.7, 0.5, 1),
    box-shadow 0.16s ease-out,
    filter 0.1s;
}

.transport-btn:hover {
  filter: brightness(1.1);
}

.transport-btn:active {
  transform: translateY(3px);
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.6),
    inset 0 -1px 2px rgba(0, 0, 0, 0.4),
    0 0 0 #120e0b,
    0 0 0 2px #060504,
    0 1px 0 2px rgba(255, 240, 215, 0.07),
    0 1px 2px rgba(0, 0, 0, 0.5);
  transition-duration: 0.04s;
}

/* Play: translucent amber cap over a lamp */
.transport-btn.primary {
  background:
    radial-gradient(ellipse 90% 60% at 50% 0%, rgba(255, 255, 255, 0.28), transparent 70%),
    linear-gradient(180deg, #f5853b 0%, #d9531b 60%, #b9410d 100%);
  color: #1a0d05;
  text-shadow: 0 1px 0 rgba(255, 200, 150, 0.35);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.4),
    inset 0 -2px 3px rgba(120, 40, 0, 0.6),
    0 3px 0 #6e2707,
    0 3px 0 2px #060504,
    0 4px 0 2px rgba(255, 240, 215, 0.07),
    0 7px 8px rgba(0, 0, 0, 0.5);
}

/* Latched: the cap stays down and the lamp behind it comes on */
.transport-btn.primary.is-playing {
  transform: translateY(2px);
  background:
    radial-gradient(ellipse 70% 90% at 50% 55%, #ffd7a3 0%, #ff9443 45%, transparent 100%),
    linear-gradient(180deg, #f5853b 0%, #d9531b 100%);
  box-shadow:
    inset 0 2px 3px rgba(120, 40, 0, 0.45),
    0 1px 0 #6e2707,
    0 1px 0 2px #060504,
    0 2px 0 2px rgba(255, 240, 215, 0.07),
    0 0 18px 2px rgba(255, 122, 43, 0.5);
}

.reset-samples-btn.has-custom {
  color: #ffb46e;
  text-shadow:
    0 -1px 0 rgba(0, 0, 0, 0.7),
    0 0 8px rgba(255, 122, 43, 0.7);
}

/* MIXER key: latches, and stays lit while the faders are showing */
.mixer-btn[aria-pressed="true"] {
  color: #ffb46e;
  text-shadow:
    0 -1px 0 rgba(0, 0, 0, 0.7),
    0 0 8px rgba(255, 122, 43, 0.7);
  box-shadow:
    inset 0 2px 5px rgba(0, 0, 0, 0.7),
    inset 0 0 0 1px rgba(255, 122, 43, 0.35);
}

/* ---- Mixer: one long fader per row, laid over its pads or chop screen ---- */
.track-steps {
  position: relative;
}

.mix-strip {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: none;
  align-items: center;
  gap: 1vw;
  padding: 0 0.4vw 0 1vw;
  background: linear-gradient(180deg, #17130f 0%, #1f1a15 100%);
  border-radius: 4px;
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, 0.85),
    inset 0 0 0 1px rgba(255, 240, 215, 0.05);
}

body.mixer-open .mix-strip {
  display: flex;
}

/* The pads keep their place (so the rows keep their height) but go dark,
   glow and all, while the faders are up */
body.mixer-open .track-steps .step,
body.mixer-open .vox-lcd > :not(.mix-strip) {
  visibility: hidden;
}

/* The slot the cap rides in: a dark groove with a scale printed under it */
.mix-slot {
  --level: 80%;
  position: relative;
  flex: 1;
  align-self: stretch;
  cursor: ew-resize;
  touch-action: none;
  outline: none;
  background:
    linear-gradient(#0a0806, #0a0806) center / 100% 6px no-repeat,
    repeating-linear-gradient(90deg, rgba(240, 232, 216, 0.22) 0 1px, transparent 1px 5%) left
    calc(50% + 11px) / 100% 5px no-repeat;
}

.mix-slot:focus-visible {
  box-shadow: 0 0 0 1px rgba(255, 122, 43, 0.6);
}

/* Lit from the left edge up to the cap, in the row's own colour */
.mix-fill {
  position: absolute;
  top: calc(50% - 2px);
  left: 0;
  width: var(--level);
  height: 4px;
  border-radius: 2px;
  background: var(--track-color, #ff7a2b);
  box-shadow: 0 0 8px var(--track-color, #ff7a2b);
  opacity: 0.9;
}

/* Unity (0 dB): a notch across the groove */
.mix-unity {
  position: absolute;
  top: calc(50% - 9px);
  left: 80%;
  width: 1px;
  height: 18px;
  background: rgba(240, 232, 216, 0.55);
}

.mix-cap {
  position: absolute;
  top: 50%;
  left: var(--level);
  width: clamp(16px, 1.4vw, 24px);
  height: min(70%, 34px);
  transform: translate(-50%, -50%);
  border-radius: 3px;
  background:
    linear-gradient(
      90deg,
      transparent calc(50% - 1px),
      #2a2118 calc(50% - 1px) calc(50% + 1px),
      transparent calc(50% + 1px)
    ),
    linear-gradient(180deg, #e6dcc8 0%, #b9ad96 55%, #8a7e68 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 2px 4px rgba(0, 0, 0, 0.7);
  pointer-events: none;
}

.mix-value {
  flex: none;
  width: 6em;
  text-align: right;
  white-space: nowrap;
  font-family: "JetBrains Mono", monospace;
  font-size: clamp(9px, 0.72vw, 12px);
  letter-spacing: 0.05vw;
  color: #d9cfbb;
}

.tempo-display {
  display: flex;
  align-items: center;
  gap: 0.6vw;
  font-family: "JetBrains Mono", monospace;
  font-size: clamp(9px, 0.7vw, 12px);
  letter-spacing: 0.2vw;
  /* silk-screened legend */
  color: rgba(240, 232, 216, 0.5);
  text-transform: uppercase;
}

/* LED readout behind smoked red glass */
.tempo-num {
  font-family: "VT323", monospace;
  font-size: clamp(20px, 1.7vw, 30px);
  background:
    linear-gradient(
      112deg,
      rgba(255, 255, 255, 0.12) 0%,
      rgba(255, 255, 255, 0.03) 30%,
      transparent 30.5%
    ),
    #170b05;
  color: #ff7a2b;
  padding: 0.4vh 1vw;
  border-radius: 3px;
  min-width: 4.2vw;
  text-align: center;
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, 0.85),
    0 0 0 2px #060504,
    0 1px 0 2px rgba(255, 240, 215, 0.08);
  text-shadow: 0 0 8px rgba(255, 122, 43, 0.6);
  cursor: ns-resize;
  user-select: none;
  border: none;
  outline: none;
}

.tempo-num:focus {
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, 0.85),
    0 0 0 2px #060504,
    0 0 0 4px rgba(255, 122, 43, 0.5);
}

/* Mode select — three interlocked push switches in one pocket. The chosen
   one stays latched down with its legend lit; the others stand proud. */
.mode-toggle {
  display: flex;
  align-items: center;
  gap: 3px;
  background: #080605;
  border-radius: 5px;
  padding: 3px 3px 6px;
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, 0.8),
    0 1px 0 rgba(255, 240, 215, 0.08);
}

.mode-toggle .lbl,
.mode-toggle .mode-label {
  font-family: "JetBrains Mono", monospace;
  font-size: clamp(9px, 0.7vw, 11px);
  letter-spacing: 0.15vw;
  color: rgba(240, 232, 216, 0.45);
  padding: 0.8vh 0.8vw;
  text-transform: uppercase;
  align-self: center;
}

.mode-btn {
  position: relative;
  font-family: "Bowlby One", sans-serif;
  font-size: clamp(10px, 0.78vw, 12px);
  letter-spacing: 0.15vw;
  padding: 1.1vh 1vw 0.7vh;
  background: linear-gradient(180deg, #3b332b 0%, #2a231d 60%, #211b16 100%);
  color: rgba(240, 232, 216, 0.55);
  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.7);
  border: none;
  border-radius: 3px;
  cursor: pointer;
  text-transform: uppercase;
  box-shadow:
    inset 0 1px 0 rgba(255, 240, 215, 0.16),
    inset 0 -2px 3px rgba(0, 0, 0, 0.45),
    0 3px 0 #110d0a;
  transition:
    transform 0.16s cubic-bezier(0.3, 1.7, 0.5, 1),
    box-shadow 0.16s ease-out,
    color 0.15s ease;
}

/* Indicator window set into the top of each cap */
.mode-btn::before {
  content: "";
  position: absolute;
  top: 3px;
  left: 50%;
  width: 34%;
  height: 2px;
  margin-left: -17%;
  border-radius: 1px;
  background: #140a05;
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.8);
  transition:
    background 0.12s ease,
    box-shadow 0.12s ease;
}

.mode-btn:hover {
  color: rgba(240, 232, 216, 0.9);
}

.mode-btn:active,
.mode-btn.active {
  transform: translateY(3px);
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.6),
    0 0 0 #110d0a;
}

.mode-btn.active {
  background: linear-gradient(180deg, #4a3526 0%, #33241a 100%);
  color: #ffc58a;
  text-shadow:
    0 -1px 0 rgba(0, 0, 0, 0.7),
    0 0 8px rgba(255, 122, 43, 0.75);
}

.mode-btn.active::before {
  background: #ffb46e;
  box-shadow:
    0 0 4px #ff7a2b,
    0 0 9px rgba(255, 122, 43, 0.7);
}

/* NOTE REPEAT — the same interlocked switches as the hi-hat mode select,
   cut smaller to sit on the brand strip */
.note-repeat .lbl {
  font-size: clamp(7px, 0.5vw, 9px);
  line-height: 1.25;
  letter-spacing: 0.1vw;
  padding: 0 0.5vw 0 0.4vw;
}

.note-repeat .mode-btn {
  font-size: clamp(8px, 0.62vw, 10px);
  letter-spacing: 0.08vw;
  padding: 1vh 0.55vw 0.55vh;
}

/* ============================================================
   Humanize potentiometer — mounted on the sampler chassis,
   right of the LCD. Chassis-matched dark metal with a modern
   orange LED progress ring.
   ============================================================ */
.chassis-pot {
  /* CSS variables consumed by Dial.js's SVG so the knob reads as
     chassis-machined hardware rather than TR-909 silver. */
  --dial-bezel: #14110d;
  --dial-bezel-stroke: #0a0805;
  --dial-bezel-inner: #1c1814;
  --dial-bezel-inner-stroke: #0a0805;
  --dial-track-bg: #0a0805;
  --dial-track-inactive: #1c1814;
  --dial-accent: #ff7a2b;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* Wrapper: knob only, no vertical stacking — keeps strip horizontally balanced */
.chassis-pot .dial-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  padding: 0;
  margin: 0;
}

/* Hide the embedded label and value — the LCD's SWING cell already shows the % */
.chassis-pot .dial-label,
.chassis-pot .dial-value {
  display: none;
}

/* Knob sized to match the LCD's vertical extent so the strip reads as one row */
.chassis-pot .dial-container {
  position: relative;
  width: clamp(38px, 3.4vw, 50px);
  height: clamp(38px, 3.4vw, 50px);
  padding: 0;
  margin: 0;
}

.chassis-pot .dial-svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* Inset bezel ring so the pot looks bolted INTO the chassis surface */
.chassis-pot .dial-container::before {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: 50%;
  background: radial-gradient(
    circle at 50% 35%,
    rgba(255, 255, 255, 0.04) 0%,
    rgba(0, 0, 0, 0.3) 60%,
    rgba(0, 0, 0, 0.6) 100%
  );
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.06),
    inset 0 -1px 1px rgba(0, 0, 0, 0.7),
    0 1px 0 rgba(255, 255, 255, 0.04);
  z-index: -1;
}

/* Soft halo behind the active ring — modern LED glow that bleeds into the chassis */
.chassis-pot .dial-glow {
  filter: drop-shadow(0 0 4px rgba(255, 122, 43, 0.55)) drop-shadow(0 0 1px rgba(255, 122, 43, 0.9));
}

/* ---- Vinyl record (SIDE A) ---- */
.vinyl {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
  /* Layers, top to bottom: Tamla 45 label (transparent PNG, so the spindle
     hole shows through), the smooth run-out band around it, two silent
     bands between tracks, then the grooves themselves. */
  background:
    url("../public/images/label-tamla-54196.png?v=2") center / 40% 40% no-repeat,
    radial-gradient(circle closest-side, #2e2822 0 50%, #0d0b09 50.5% 52.5%, transparent 53%),
    radial-gradient(
      circle closest-side,
      transparent 0 66%,
      rgba(255, 240, 215, 0.14) 66.4% 67.4%,
      transparent 67.8% 82%,
      rgba(255, 240, 215, 0.11) 82.4% 83.2%,
      transparent 83.6%
    ),
    repeating-radial-gradient(circle at center, #100d0b 0 1px, #2f2923 1px 3px),
    #100d0b;
  box-shadow:
    0 2vh 4vh -1vh rgba(0, 0, 0, 0.8),
    0 1vh 2vh -0.5vh rgba(0, 0, 0, 0.5),
    /* moulded rim catching the lamp */
    inset 0 0 0 1px rgba(255, 240, 215, 0.18),
    inset 0 0 0 4px rgba(0, 0, 0, 0.35);
  transform: rotate(-4deg);
  transition: transform 0.4s ease;
}

/* Lamp reflection in the grooves: two bright wedges pointing at the light.
   It lives on the prop, not the record, so it holds still while the vinyl
   spins underneath. Masked off the label. */
.prop-vinyl::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  background: conic-gradient(
    from 28deg,
    transparent 0deg,
    rgba(255, 240, 215, 0.3) 24deg,
    transparent 50deg,
    transparent 180deg,
    rgba(255, 240, 215, 0.18) 204deg,
    transparent 230deg
  );
  -webkit-mask: radial-gradient(circle closest-side, transparent 52%, #000 54%);
  mask: radial-gradient(circle closest-side, transparent 52%, #000 54%);
}

/* Kraft-paper inner sleeve — pale enough that the black disc reads against it */
.sleeve {
  position: absolute;
  inset: -0.6vh -1vw -1vh -0.8vw;
  background: var(--tex-wood), linear-gradient(135deg, #bfa981 0%, #a8926b 60%, #948058 100%);
  z-index: -1;
  transform: rotate(-2deg);
  box-shadow:
    0 2vh 4vh -1vh rgba(0, 0, 0, 0.6),
    inset 0 1px 0 rgba(255, 245, 220, 0.35),
    inset 0 0 30px rgba(70, 45, 15, 0.35);
}

.prop-vinyl {
  transition: transform 0.3s ease;
}

.prop-vinyl:hover {
  transform: translateY(-3px);
}

.prop-vinyl:hover .vinyl {
  animation: vinyl-spin 3.5s linear infinite;
  transform: rotate(0deg);
}

@keyframes vinyl-spin {
  to {
    transform: rotate(360deg);
  }
}

.prop-vinyl .sticker {
  z-index: 1; /* above the groove reflection */
  transition:
    transform 0.25s ease,
    opacity 0.25s;
}

.prop-vinyl:hover .sticker {
  opacity: 0;
  pointer-events: none;
}

/* ---- Polaroid ---- */
.polaroid {
  background: #f4ecd6;
  padding: 0.7vw 0.7vw 2.2vw 0.7vw;
  box-shadow:
    0 2vh 3vh -1vh rgba(0, 0, 0, 0.6),
    0 0.8vh 1.6vh -0.5vh rgba(0, 0, 0, 0.4);
  transform: rotate(2.5deg);
  position: relative;
  width: 100%;
  transition:
    transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 0.3s;
}

.polaroid:hover {
  transform: rotate(1deg) translateY(-4px) scale(1.03);
  box-shadow:
    0 3vh 4vh -1vh rgba(0, 0, 0, 0.65),
    0 1.2vh 2vh -0.4vh rgba(0, 0, 0, 0.45);
}

.polaroid-photo {
  width: 100%;
  aspect-ratio: 1.1 / 1;
  background: linear-gradient(135deg, #3a2a1a 0%, #1a1208 100%);
  overflow: hidden;
}

.polaroid-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* faded instant film */
  filter: sepia(0.3) contrast(0.92) saturate(0.85) brightness(1.08);
}

.polaroid-caption {
  position: absolute;
  bottom: 0.4vw;
  left: 0;
  right: 0;
  text-align: center;
  font-family: "Permanent Marker", cursive;
  color: #2a1f10;
  font-size: clamp(10px, 0.75vw, 13px);
}

/* ---- Sticky note ---- */
.sticky {
  background: linear-gradient(180deg, #fde047 0%, #facc15 100%);
  color: #1a1208;
  padding: 1.2vh 1vw;
  font-family: "Permanent Marker", cursive;
  font-size: clamp(11px, 0.85vw, 14px);
  line-height: 1.4;
  width: 100%;
  box-shadow:
    0 1.5vh 2.5vh -0.5vh rgba(0, 0, 0, 0.55),
    0 0.5vh 1vh -0.2vh rgba(0, 0, 0, 0.4);
  transform: rotate(-2deg);
  position: relative;
  transition:
    transform 0.25s cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 0.25s;
}

.sticky::before {
  content: "";
  position: absolute;
  top: -8px;
  left: 50%;
  transform: translateX(-50%) rotate(-3deg);
  width: 40%;
  height: 12px;
  background: rgba(255, 250, 220, 0.7);
  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.25);
}

.sticky:hover {
  transform: rotate(-2deg) translateY(-6px) scale(1.04);
  box-shadow:
    0 2.5vh 4vh -0.5vh rgba(0, 0, 0, 0.55),
    0 1vh 1.5vh -0.2vh rgba(0, 0, 0, 0.4);
}

/* ---- Cassette = MIDI Export ---- */
.cassette {
  position: relative;
  width: 100%;
  aspect-ratio: 1.55;
  /* Smoke-grey shell rather than black, so its mouldings are readable:
     two case screws in the lower corners, then the plastic itself */
  background:
    radial-gradient(circle at 4.5% 91%, #a39a8b 0 1.6px, #120e0b 1.9px 3.2px, transparent 3.6px),
    radial-gradient(circle at 95.5% 91%, #a39a8b 0 1.6px, #120e0b 1.9px 3.2px, transparent 3.6px),
    var(--tex-plastic), linear-gradient(180deg, #4a4138 0%, #352d26 55%, #28211b 100%);
  border-radius: 6px;
  padding: 0.9vh 0.7vw;
  border: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 240, 215, 0.28),
    inset 0 0 0 1px rgba(255, 240, 215, 0.07),
    inset 0 -2px 3px rgba(0, 0, 0, 0.5),
    0 2vh 3vh -0.8vh rgba(0, 0, 0, 0.7),
    0 0.6vh 1.2vh rgba(0, 0, 0, 0.5),
    0 0 22px rgba(255, 122, 43, 0.18);
  transform: rotate(-2.5deg);
  transition:
    transform 0.3s ease,
    box-shadow 0.3s ease;
}

.cassette:hover {
  transform: rotate(-2.5deg) translateY(-3px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.1),
    0 2.6vh 4vh -0.8vh rgba(0, 0, 0, 0.75),
    0 1vh 1.8vh rgba(0, 0, 0, 0.55),
    0 0 32px rgba(255, 122, 43, 0.32);
}

.cassette-label {
  background: linear-gradient(180deg, #f4ecd6 0%, #e6d8ba 100%);
  height: 55%;
  border-radius: 2px;
  padding: 0.6vh 0.7vw;
  font-family: "Permanent Marker", cursive;
  color: #2a1f10;
  font-size: clamp(10px, 0.7vw, 12px);
  position: relative;
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    0 1px 2px rgba(0, 0, 0, 0.3);
}

.cassette-label .tagline {
  font-family: "JetBrains Mono", monospace;
  font-size: clamp(7px, 0.5vw, 9px);
  letter-spacing: 1.5px;
  color: #6b4a2a;
  margin: 0;
  text-transform: uppercase;
}

.cassette-label .title {
  font-size: clamp(13px, 1.1vw, 18px);
  letter-spacing: 1px;
  line-height: 1.1;
  transition: text-shadow 0.3s;
}

/* One hand-written line per format: MIDI, WAV, stems, groove */
.cassette-actions {
  display: flex;
  justify-content: center;
  gap: 0.3vw;
}

.cassette-label .cassette-action {
  font-family: "Permanent Marker", cursive;
  /* Four formats share one line of the label */
  font-size: clamp(8px, 0.6vw, 10.5px);
  color: #c2410c;
  background: none;
  border: none;
  padding: 0.2vh 0.1vw;
  margin: 0;
  cursor: pointer;
  letter-spacing: 0.2px;
  white-space: nowrap;
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 2px;
  animation: cassette-action-pulse 2.4s ease-in-out infinite;
}

.cassette-label .cassette-action:hover {
  color: #7c2d08;
  animation: none;
}

.cassette-label .cassette-action:focus-visible {
  outline: 2px solid #c2410c;
  outline-offset: 1px;
  border-radius: 2px;
}

@keyframes cassette-action-pulse {
  0%,
  100% {
    opacity: 0.85;
  }
  50% {
    opacity: 1;
  }
}

.cassette:hover .cassette-label .title {
  text-shadow: 0 0 6px rgba(255, 200, 80, 0.5);
}

.cassette-reels {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 0.8vh;
  padding: 0 0.8vw;
  height: 35%;
}

.reel {
  width: 2.2vw;
  height: 2.2vw;
  max-width: 38px;
  max-height: 38px;
  min-width: 24px;
  min-height: 24px;
  border-radius: 50%;
  /* Spindle hole, cream hub ring with the tape pack wound round it, and
     drive teeth showing through the middle (they make the spin visible) */
  background:
    radial-gradient(circle closest-side, #120e0b 0 13%, transparent 14%),
    radial-gradient(circle closest-side, transparent 0 36%, #ece3cf 37% 58%, #4a2c1a 60% 100%),
    repeating-conic-gradient(from 0deg, #ece3cf 0 22deg, #1f1914 22deg 60deg);
  box-shadow:
    0 0 0 1px rgba(255, 240, 215, 0.22),
    0 0 0 3px rgba(0, 0, 0, 0.45);
  transition: transform 0.3s ease;
}

/* Take-up reel: nearly empty, so less tape around the hub */
.reel:nth-child(2) {
  background:
    radial-gradient(circle closest-side, #120e0b 0 13%, transparent 14%),
    radial-gradient(
      circle closest-side,
      transparent 0 36%,
      #ece3cf 37% 58%,
      #4a2c1a 60% 74%,
      #17120e 76% 100%
    ),
    repeating-conic-gradient(from 0deg, #ece3cf 0 22deg, #1f1914 22deg 60deg);
}

.cassette:hover .reel {
  animation: reel-spin 3.2s linear infinite;
}

.cassette:hover .reel:nth-child(2) {
  animation-direction: reverse;
}

@keyframes reel-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.cassette-window {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 50%;
  height: 60%;
  /* Amber-tinted window with a lamp glare across one corner */
  background:
    linear-gradient(
      112deg,
      rgba(255, 255, 255, 0.3) 0%,
      rgba(255, 255, 255, 0.08) 24%,
      transparent 24.5%
    ),
    linear-gradient(180deg, rgba(226, 190, 132, 0.6), rgba(160, 122, 78, 0.55));
  border-radius: 4px;
  border: 1px solid rgba(255, 240, 215, 0.3);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.45);
}

.cassette-confirm {
  position: absolute;
  top: 22%;
  left: 10%;
  right: 10%;
  padding: 0.6vh 0.6vw;
  background: #ff7a2b;
  color: #0a0805;
  font-family: "Permanent Marker", cursive;
  font-size: clamp(10px, 0.85vw, 14px);
  text-align: center;
  border-radius: 2px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  z-index: 10;
  transition:
    opacity 0.25s ease,
    transform 0.25s ease;
}

.cassette.is-confirming .cassette-confirm {
  opacity: 1;
  transform: translateY(0);
}

.cassette.is-confirming .reel {
  animation: reel-spin 0.8s linear 2;
}

/* Tape rolls for as long as an audio bounce is rendering */
.cassette.is-rendering .reel {
  animation: reel-spin 0.5s linear infinite;
}

/* ---- Microphone = voice in ---- */
.mic-btn {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
}

.mic-body {
  width: 100%;
  /* One shadow for the whole mic, thrown down-right by the lamp */
  filter: drop-shadow(5px 9px 6px rgba(0, 0, 0, 0.6));
  transition: transform 0.25s ease;
}

.mic-body svg {
  display: block;
  width: 100%;
  height: auto;
}

.mic-btn:hover .mic-body {
  transform: translateY(-3px);
}

.mic-btn:focus-visible {
  outline: 2px solid #ff7a2b;
  outline-offset: 4px;
  border-radius: 4px;
}

/* Tally light by the switch: dark, blinking while armed, solid while recording */
.mic-tally {
  fill: #3a0f08;
  stroke: #0d0b09;
  stroke-width: 1.2;
}

.prop-mic[data-state="arming"] .mic-tally,
.prop-mic[data-state="waiting"] .mic-tally,
.prop-mic[data-state="countin"] .mic-tally {
  fill: #ff4a26;
  animation: pulse 0.5s steps(2, jump-none) infinite;
}

.prop-mic[data-state="recording"] .mic-tally {
  fill: #ff3b1f;
  filter: drop-shadow(0 0 4px #ff3b1f);
}

/* Strip of masking tape with the instruction written on it */
.mic-tag {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  /* stuck to the desk in the space under the mic's tail */
  position: absolute;
  right: -2vw;
  bottom: -0.8vh;
  padding: 0.45vh 0.9vw 0.5vh;
  background: linear-gradient(180deg, #f1e7c9 0%, #e2d4ad 100%);
  color: #2a1f10;
  transform: rotate(-3deg);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    0 2px 5px rgba(0, 0, 0, 0.5);
  /* torn ends */
  clip-path: polygon(0 12%, 2% 0, 98% 6%, 100% 0, 99% 88%, 100% 100%, 2% 94%, 0 100%);
}

.mic-tag-text {
  font-family: "Permanent Marker", cursive;
  font-size: clamp(10px, 0.82vw, 13px);
  letter-spacing: 0.5px;
  color: #c2410c;
  white-space: nowrap;
}

.mic-tag-hint {
  font-family: "JetBrains Mono", monospace;
  font-size: clamp(7px, 0.52vw, 9px);
  letter-spacing: 0.5px;
  color: #6b4a2a;
  white-space: nowrap;
}

/* Input meter: a strip along the bottom of the tape while the mic is open */
.mic-meter {
  display: none;
  width: 100%;
  height: 3px;
  margin-top: 2px;
  background: rgba(42, 31, 16, 0.25);
  border-radius: 2px;
  overflow: hidden;
}

.prop-mic:not([data-state="idle"]) .mic-meter,
.prop-mic.is-listening .mic-meter {
  display: block;
}

.mic-meter-fill {
  display: block;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, #4d7c0f 0%, #65a30d 60%, #f59e0b 85%, #dc2626 100%);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.08s linear;
}

.prop-mic[data-state="recording"] .mic-tag-text,
.prop-mic[data-state="countin"] .mic-tag-text {
  color: #b3200a;
}

.prop-mic.drag-over .mic-body {
  transform: translateY(-5px) scale(1.04);
}

.prop-mic.drag-over .mic-tag {
  background: #ffb46e;
}

/* VOCAL / BEATBOX: two strips of embossed label tape; the one in use is orange */
.mic-mode {
  position: absolute;
  top: -1.4vh;
  left: -0.4vw;
  display: flex;
  gap: 3px;
  transform: rotate(-5deg);
}

.mic-mode-btn,
.mic-load-btn {
  font-family: "Bowlby One", sans-serif;
  font-size: clamp(7px, 0.55vw, 9px);
  letter-spacing: 0.08vw;
  text-transform: uppercase;
  color: rgba(240, 232, 216, 0.6);
  padding: 0.45vh 0.4vw;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, transparent 38%, rgba(0, 0, 0, 0.25) 100%),
    #241e18;
  border: none;
  border-radius: 2px;
  cursor: pointer;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 2px 3px rgba(0, 0, 0, 0.6);
}

.mic-mode-btn:hover,
.mic-load-btn:hover {
  color: #f0e8d8;
}

/* LOAD: a momentary key, set a little apart from the two-way switch */
.mic-load-btn {
  margin-left: 0.3vw;
  white-space: nowrap;
}

.mic-mode-btn.active {
  color: #1a0f06;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.25) 0%, transparent 40%, rgba(0, 0, 0, 0.15) 100%),
    #ff7a2b;
}

/* INPUT and MON: small print above the mode keys, for which mic or
   interface the lead is plugged into and whether it is heard. Kept flat
   and quiet so the mode keys stay the main choice. */
.mic-io {
  position: absolute;
  top: -3.9vh;
  left: -0.6vw;
  display: flex;
  align-items: center;
  gap: 0.7vw;
  transform: rotate(-5deg);
}

.mic-input-btn,
.mic-mon-btn,
.mic-menu-item,
.mic-menu-channels button {
  font-family: "JetBrains Mono", monospace;
  font-size: clamp(9px, 0.68vw, 11.5px);
  font-weight: 500;
  letter-spacing: 1px;
  text-transform: uppercase;
  white-space: nowrap;
  color: rgba(240, 232, 216, 0.78);
  padding: 2px 0;
  background: none;
  border: none;
  cursor: pointer;
  transition: color 0.15s ease;
}

.mic-input-btn:hover,
.mic-mon-btn:hover,
.mic-menu-item:hover,
.mic-menu-channels button:hover {
  color: #f0e8d8;
}

.mic-input-btn {
  border-bottom: 1px dotted rgba(240, 232, 216, 0.45);
}

/* MON has a lamp that lights while the input is being played back */
.mic-mon-btn {
  display: flex;
  align-items: center;
  gap: 4px;
}

.mic-mon-btn::before,
.mic-menu-item::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(240, 232, 216, 0.3);
  transition:
    background 0.15s ease,
    box-shadow 0.15s ease;
}

.mic-mon-btn[aria-pressed="true"],
.mic-menu-item[aria-pressed="true"],
.mic-menu-channels button[aria-pressed="true"] {
  color: #f0e8d8;
}

.mic-mon-btn[aria-pressed="true"]::before,
.mic-menu-item[aria-pressed="true"]::before {
  background: #ff7a2b;
  box-shadow: 0 0 5px rgba(255, 122, 43, 0.8);
}

.mic-input-btn:focus-visible,
.mic-mon-btn:focus-visible,
.mic-menu-item:focus-visible,
.mic-menu-channels button:focus-visible {
  outline: 1px solid #ff7a2b;
  outline-offset: 2px;
}

/* Input select: a flat slip that opens above the labels */
.mic-input-menu {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  min-width: 100%;
  padding: 6px 10px;
  background: rgba(22, 18, 14, 0.97);
  border: 1px solid rgba(240, 232, 216, 0.1);
  border-radius: 3px;
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.45);
}

.mic-input-menu[hidden] {
  display: none;
}

/* The key's own tooltip would sit on top of the open panel */
body:has(.mic-input-btn[aria-expanded="true"]) .tooltip {
  display: none;
}

.mic-menu-head {
  margin: 0 0 3px;
  font-family: "JetBrains Mono", monospace;
  font-size: clamp(8px, 0.58vw, 10px);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: rgba(240, 232, 216, 0.55);
}

/* Each input has a lamp that lights on the one in use */
.mic-menu-item {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 4px 0;
  text-align: left;
}

.mic-menu-channels {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 3px;
  padding-top: 4px;
  border-top: 1px solid rgba(240, 232, 216, 0.1);
  font-family: "JetBrains Mono", monospace;
  font-size: clamp(8px, 0.58vw, 10px);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: rgba(240, 232, 216, 0.55);
}

.mic-menu-channels button[aria-pressed="true"] {
  color: #ff7a2b;
}

/* Only offered once there is a take to erase */
.mic-erase {
  display: none;
  position: absolute;
  right: -2vw;
  bottom: -2.8vh;
  font-family: "Permanent Marker", cursive;
  font-size: clamp(8px, 0.62vw, 10px);
  color: rgba(254, 243, 226, 0.6);
  background: none;
  border: none;
  cursor: pointer;
}

.prop-mic.has-take .mic-erase,
.prop-mic.can-restore .mic-erase {
  display: block;
}

.prop-mic.can-restore .mic-erase {
  color: #ffc58a;
}

.mic-erase:hover {
  color: #ff7a2b;
}

/* Stickers/labels */
.sticker {
  position: absolute;
  font-family: "Permanent Marker", cursive;
  color: #fef3e2;
  font-size: 12px;
  letter-spacing: 1px;
  background: #c2410c;
  padding: 4px 10px;
  transform: rotate(-6deg);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
}

/* ====================================================
   LP sleeves
   ==================================================== */
.lp-with-peek {
  position: relative;
}

.lp-with-peek .lp {
  position: relative;
  z-index: 2;
  transition: transform 0.45s cubic-bezier(0.3, 0.7, 0.4, 1.4);
}

.lp-vinyl-peek {
  position: absolute;
  top: 4%;
  right: 4%;
  width: 92%;
  height: 92%;
  border-radius: 50%;
  background:
    url("../public/images/label-tamla-54243.png?v=2") center / 38% 38% no-repeat,
    radial-gradient(circle at center, #15110a 0 22%, #0a0805 22.3% 23.5%, transparent 23.8%),
    repeating-radial-gradient(circle at center, #0a0805 0 1px, #1a1510 1px 3px),
    #0a0805;
  box-shadow:
    0 4px 14px rgba(0, 0, 0, 0.6),
    inset 0 0 40px rgba(0, 0, 0, 0.4);
  transform: translate(0, 0) rotate(0deg);
  transition: transform 0.55s cubic-bezier(0.3, 0.7, 0.4, 1.4);
  z-index: 1;
  pointer-events: none;
}

.lp-with-peek:hover .lp-vinyl-peek {
  transform: translate(55%, 6%) rotate(18deg);
}

.lp-with-peek:hover .lp {
  transform: translate(-3%, -1%);
}

.lp {
  position: relative;
  aspect-ratio: 1;
  background: #1a1510;
  box-shadow:
    0 18px 30px -10px rgba(0, 0, 0, 0.7),
    0 6px 14px -4px rgba(0, 0, 0, 0.5),
    inset 0 0 0 1px rgba(255, 255, 255, 0.04),
    inset 0 -3px 6px rgba(0, 0, 0, 0.5);
  overflow: hidden;
  user-select: none;
}

.lp::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: /* ring wear: the record inside has rubbed its outline through the print */
      radial-gradient(
        circle at 50% 50%,
        transparent 41%,
        rgba(255, 255, 255, 0.32) 43%,
        transparent 46%
      ),
      radial-gradient(ellipse 80% 30px at 50% 0%, rgba(255, 255, 255, 0.06), transparent 60%),
      radial-gradient(ellipse 30px 80% at 0% 50%, rgba(0, 0, 0, 0.45), transparent 60%),
      radial-gradient(ellipse 30px 80% at 100% 50%, rgba(0, 0, 0, 0.45), transparent 60%);
  mix-blend-mode: overlay;
  opacity: 0.7;
}

.lp::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    135deg,
    transparent 35%,
    rgba(255, 255, 255, 0.12) 45%,
    transparent 55%,
    rgba(255, 255, 255, 0.04) 65%,
    transparent 80%
  );
  z-index: 5;
}

/* Photo LP variant */
.lp--photo {
  background: #15110a;
  display: flex;
  flex-direction: column;
}

.lp-photo-img {
  flex: 1;
  background: #2a1810;
  overflow: hidden;
  position: relative;
}

.lp-photo-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.lp--photo .footer {
  background: #1a0d05;
  color: #ff7a2b;
  padding: 8px 12px;
  font-family: "Bowlby One", sans-serif;
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  border-top: 1px solid rgba(255, 122, 43, 0.3);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.lp--photo .footer small {
  font-family: "JetBrains Mono", monospace;
  font-size: 8px;
  opacity: 0.6;
  letter-spacing: 1.5px;
}

/* Circles variant */
.lp--circles {
  background:
    radial-gradient(circle at 30% 35%, #f59e0b 0 90px, transparent 92px),
    radial-gradient(circle at 65% 60%, #c2410c 0 60px, transparent 62px),
    radial-gradient(circle at 75% 30%, #fef3e2 0 30px, transparent 32px),
    linear-gradient(135deg, #2a1810 0%, #4a2818 100%);
  padding: 14px 14px 18px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  color: #f4ecd6;
}

.lp--circles .meta {
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
  letter-spacing: 2px;
  opacity: 0.7;
  text-transform: uppercase;
}

.lp--circles .title {
  font-family: "Bowlby One", sans-serif;
  font-size: clamp(16px, 1.5vw, 22px);
  letter-spacing: 1px;
  margin-top: 4px;
  text-transform: uppercase;
  line-height: 0.95;
}

/* Stripes variant */
.lp--stripes {
  background: repeating-linear-gradient(45deg, #c2410c 0 18px, #1a0d05 18px 36px);
  display: flex;
  align-items: center;
  justify-content: center;
}

.lp--stripes .badge {
  background: #fef3e2;
  color: #1a0d05;
  padding: 12px 14px;
  font-family: "Bowlby One", sans-serif;
  font-size: clamp(12px, 1.2vw, 18px);
  letter-spacing: 1px;
  text-align: center;
  line-height: 1;
  transform: rotate(-3deg);
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
}

.lp--stripes .badge small {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
  margin-top: 6px;
  letter-spacing: 2px;
  font-weight: 400;
  opacity: 0.7;
}

/* Portrait variant */
.lp--portrait {
  background: linear-gradient(180deg, #c2410c 0%, #7a2810 100%);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* One-colour press job: black photo ink multiplied onto orange stock */
.lp-portrait-img {
  flex: 1;
  min-height: 0;
  background: #e8742f;
  overflow: hidden;
}

.lp-portrait-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 20%;
  display: block;
  filter: grayscale(1) contrast(1.15);
  mix-blend-mode: multiply;
}

.lp--portrait .text {
  font-family: "Bowlby One", sans-serif;
  color: #fef3e2;
  font-size: 13px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  text-align: center;
}

.lp--portrait .text small {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 8px;
  font-weight: 400;
  letter-spacing: 2px;
  margin-top: 2px;
  opacity: 0.75;
}

/* Live-album variant: full-bleed concert photo, title set in the dark */
.lp--live img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 60% 0%;
  display: block;
}

.lp--live .title {
  position: absolute;
  top: 5%;
  left: 7%;
  /* series line sits above the title, keeping both in the dark of the photo */
  display: flex;
  flex-direction: column-reverse;
  font-family: "Bowlby One", sans-serif;
  font-size: clamp(12px, 1.15vw, 18px);
  line-height: 1;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: #ffb46e;
}

.lp--live .title small {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
  font-weight: 400;
  letter-spacing: 2px;
  margin-bottom: 5px;
  color: #fef3e2;
  opacity: 0.75;
}

/* Fanned LP cluster */
.lp-fan {
  position: relative;
  aspect-ratio: 1.6;
  flex-shrink: 0;
  width: 100%;
}

.lp-fan > .lp-with-peek {
  position: absolute;
  top: 0;
  left: 0;
  width: 55%;
  aspect-ratio: 1;
}

.lp-fan > .lp-with-peek > .lp {
  width: 100%;
  height: 100%;
}

.prop-funk {
  transition: transform 0.3s ease;
}

.prop-funk:hover {
  transform: rotate(2deg) translateY(-3px);
}

/* ---- Avatar canvas (head-bob character) — fixed to bottom of screen ---- */
#avatar-canvas {
  position: fixed;
  bottom: 9.5vh;
  left: 50%;
  transform: translateX(-50%);
  width: clamp(100px, 10vw, 160px);
  height: clamp(100px, 10vw, 160px);
  display: block;
  background: transparent;
  pointer-events: none;
  z-index: 25;
  filter: drop-shadow(0 0.8vh 1.6vh rgba(0, 0, 0, 0.6));
}

/* ========================================================
   The tour — a sticky note that hops around the desk while
   the lamp is turned down on everything else
   ======================================================== */
.tour {
  position: fixed;
  inset: 0;
  z-index: 2000;
}

/* The lit patch; its shadow is the dimmed room */
.tour-spot {
  position: absolute;
  border-radius: 14px;
  box-shadow:
    0 0 0 200vmax rgba(12, 7, 3, 0.64),
    inset 0 0 0 2px rgba(255, 200, 120, 0.55),
    inset 0 0 26px rgba(255, 190, 110, 0.25);
  transition:
    left 0.4s cubic-bezier(0.4, 0, 0.2, 1),
    top 0.4s cubic-bezier(0.4, 0, 0.2, 1),
    width 0.4s cubic-bezier(0.4, 0, 0.2, 1),
    height 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.tour-note {
  position: absolute;
  width: min(310px, calc(100vw - 24px));
  padding: 26px 20px 16px;
  background: linear-gradient(180deg, #fde047 0%, #facc15 100%);
  color: #1a1208;
  transform: rotate(var(--tour-tilt, -1.5deg));
  box-shadow:
    0 22px 34px -10px rgba(0, 0, 0, 0.7),
    0 8px 14px -6px rgba(0, 0, 0, 0.5);
  transition:
    left 0.4s cubic-bezier(0.34, 1.3, 0.64, 1),
    top 0.4s cubic-bezier(0.34, 1.3, 0.64, 1),
    transform 0.4s ease;
}

/* A strip of tape holds it down */
.tour-note::before {
  content: "";
  position: absolute;
  top: -9px;
  left: 50%;
  transform: translateX(-50%) rotate(-3deg);
  width: 34%;
  height: 16px;
  background: rgba(255, 250, 220, 0.75);
  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.25);
}

.tour-title {
  margin: 0 0 8px;
  font-family: "Permanent Marker", cursive;
  font-size: 21px;
  line-height: 1.15;
  color: #9a3412;
}

.tour-text {
  margin: 0 0 16px;
  font-family: "Special Elite", "JetBrains Mono", monospace;
  font-size: 14px;
  line-height: 1.5;
}

.tour-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.tour-count {
  flex: 1;
  text-align: center;
  font-family: "JetBrains Mono", monospace;
  font-size: 10px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: rgba(26, 18, 8, 0.55);
}

.tour-note button {
  all: unset;
  cursor: pointer;
  font-family: "Permanent Marker", cursive;
}

.tour-note button[hidden] {
  display: none;
}

.tour-note .tour-next {
  margin-left: auto;
  padding: 6px 14px;
  font-size: 15px;
  color: #fde047;
  background: #1a1208;
  border-radius: 3px;
  transform: rotate(-1deg);
  transition: transform 0.15s;
}

.tour-note .tour-next:hover {
  transform: rotate(-1deg) scale(1.06);
}

.tour-note .tour-back {
  font-size: 13px;
  color: rgba(26, 18, 8, 0.7);
}

.tour-note .tour-skip {
  position: absolute;
  top: 8px;
  right: 12px;
  font-size: 11px;
  color: rgba(26, 18, 8, 0.55);
}

.tour-note .tour-back:hover,
.tour-note .tour-skip:hover {
  color: #1a1208;
}

.tour-note button:focus-visible {
  outline: 2px solid #9a3412;
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .tour-spot,
  .tour-note {
    transition: none;
  }
}

/* ========================================================
   J-card — the last bounce, listed on a card that sits under
   the cassette. Each file is a strip of masking tape that can
   be dragged out of the browser.
   ======================================================== */
.cassette-tray {
  position: absolute;
  top: calc(100% - 0.6vh);
  left: 6%;
  right: 12%;
  z-index: -1;
  display: flex;
  flex-wrap: wrap;
  gap: 5px 6px;
  padding: 1.6vh 0.7vw 1vh;
  background:
    repeating-linear-gradient(180deg, transparent 0 1.25em, rgba(100, 140, 200, 0.16) 1.25em 1.3em),
    linear-gradient(180deg, #efe5cb 0%, #e3d6b6 100%);
  border-radius: 0 0 3px 3px;
  box-shadow:
    inset 0 6px 8px -4px rgba(0, 0, 0, 0.45),
    0 1.2vh 2vh -0.6vh rgba(0, 0, 0, 0.6);
  transform: rotate(-1.2deg);
  transform-origin: top center;
  animation: tray-slide 0.45s cubic-bezier(0.34, 1.3, 0.5, 1);
}

.cassette-tray[hidden] {
  display: none;
}

@keyframes tray-slide {
  from {
    opacity: 0;
    transform: translateY(-60%) rotate(-1.2deg);
  }
}

.tray-heading {
  flex-basis: 100%;
  margin: 0;
  font-family: "Permanent Marker", cursive;
  font-size: clamp(9px, 0.7vw, 12px);
  color: #6b4a2a;
}

.tray-strip {
  padding: 2px 8px 3px;
  font-family: "Permanent Marker", cursive;
  font-size: clamp(9px, 0.72vw, 12px);
  color: #2a1f10;
  text-decoration: none;
  text-transform: uppercase;
  background: linear-gradient(180deg, rgba(255, 250, 225, 0.95), rgba(236, 224, 184, 0.9));
  /* Torn ends */
  clip-path: polygon(0 12%, 3% 0, 97% 4%, 100% 20%, 99% 88%, 96% 100%, 4% 96%, 1% 82%);
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.35);
  cursor: grab;
  transition: transform 0.15s ease;
}

.tray-strip:nth-child(odd) {
  transform: rotate(-1.5deg);
}

.tray-strip:nth-child(even) {
  transform: rotate(1.2deg);
}

.tray-strip:hover {
  transform: translateY(-2px) rotate(0deg);
  color: #c2410c;
}

.tray-strip:active {
  cursor: grabbing;
}

.tray-strip:focus-visible {
  outline: 2px solid #c2410c;
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .cassette-tray {
    animation: none;
  }
}

/* ========================================================
   Too small — on a phone (or anything the sampler can't fit
   on) the desk is covered by a note sending you to a laptop.
   The same sizes are named in main.js (TOO_SMALL).
   ======================================================== */
.too-small {
  display: none;
}

@media (max-width: 899px), (max-height: 480px) {
  .too-small {
    position: fixed;
    inset: 0;
    z-index: 3000;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: 28px;
    text-align: center;
    overflow-y: auto;
    background:
      repeating-linear-gradient(
        90deg,
        rgba(0, 0, 0, 0.1) 0 2px,
        transparent 2px 9px,
        rgba(255, 200, 140, 0.025) 9px 10px,
        transparent 10px 23px
      ),
      radial-gradient(ellipse at 50% 30%, #4a2c14 0%, #2a180b 55%, #170e06 100%);
  }

  .too-small-logo {
    width: min(46vw, 34vh, 220px);
    height: auto;
    filter: drop-shadow(0 10px 18px rgba(0, 0, 0, 0.6));
    transform: rotate(-3deg);
  }

  .too-small-kicker {
    margin: 0;
    font-size: 11px;
    letter-spacing: 5px;
    text-transform: uppercase;
    color: rgba(248, 230, 200, 0.55);
  }

  .too-small-title {
    margin: 0;
    max-width: 14em;
    font-family: "Permanent Marker", cursive;
    font-size: clamp(26px, 8vw, 40px);
    font-weight: 400;
    line-height: 1.1;
    color: #f8e6c8;
    transform: rotate(-2deg);
    text-shadow:
      2px 3px 0 rgba(0, 0, 0, 0.6),
      0 8px 20px rgba(0, 0, 0, 0.6);
  }

  .too-small-title em {
    font-style: normal;
    color: #ff7a2b;
  }

  .too-small-text {
    margin: 0;
    max-width: 24em;
    font-size: 15px;
    line-height: 1.5;
    color: rgba(248, 230, 200, 0.85);
  }

  .too-small-copy {
    margin-top: 8px;
    padding: 12px 18px;
    font-family: "JetBrains Mono", monospace;
    font-size: 14px;
    font-weight: 700;
    color: #1a0f06;
    background: #ff7a2b;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transform: rotate(-1.5deg);
    box-shadow: 0 4px 0 #6e2707;
  }

  .too-small-copy:active {
    transform: rotate(-1.5deg) translateY(3px);
    box-shadow: 0 1px 0 #6e2707;
  }
}
