/* ═══════════════════════════════════════════════════════════════════
   THE SYSTEM
   Both pages load this file first. It is named loha.css because the gym
   page is where it was worked out.
   ─────────────────────────────────────────────────────────────────
   This began as the gym page's own stylesheet, against a main site that
   was pale swept cement with cassette-deck keys. The two were opposites
   on purpose, until the site went dark everywhere — at which point the
   opposition was just two stylesheets doing the same job twice.

   So everything here is shared: the tokens, the corridor layers, the
   plate keys, the chips, the sliders, the door, the rack of tracks, and
   the narrow-screen and reduced-motion rules for all of it.

   What is NOT here is anything only one page has. index.html adds
   dhun.css for the transport and the rooms; the gym pages add nothing.

   One typeface, one script. Every wordmark and every title used to be
   set twice — the record's own script big and the Latin underneath it —
   and the site now sets each one once, in Latin. So Khand does all of
   it and there is no second face to name.

     --haz    the accent. Written from JS — the deck's colour on the gym
              pages, the room's lead pigment on the main one.

   Khand does the shouting on both, because it already is the lettering
   on Indian shop boards.
   ─────────────────────────────────────────────────────────────────
   1  tokens
   2  reset
   3  the corridor, and what sits on it
   4  chrome: keys, chips, sliders
   5  top bar
   6  the deck
   7  the bar
   8  bottom rack
   9  the door
   10 the rack of tracks
   11 narrow screens
   12 reduced motion
   ═══════════════════════════════════════════════════════════════════ */

/* ── 1  tokens ──────────────────────────────────────────────────── */
:root{
  --void:#08090b;
  --steel:#14171c;
  --steel-2:#20252d;
  --edge:#333b45;
  --chalk:#f0ede5;
  --chalk-2:#a8afb8;      /* 7.4:1 on the void */
  --chalk-3:#7e858e;      /* 4.6:1 on the void — the dimmest legal ink */
  --haz:#ffd400;
  --haz-deep:#c9a600;
  --blood:#ff3b2d;
  --ice:#8ce9ff;

  --sign:'Khand','Nirmala UI','Segoe UI',system-ui,sans-serif;

  --shell:clamp(1rem,3vw,2.6rem);
  --ease:cubic-bezier(.2,.7,.3,1);

  /* written every frame by loha.js */
  --split:0px;            /* chromatic split on the title */
  --pulse:0;              /* 0..1 beat envelope */
}

/* ── 2  reset ───────────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;color-scheme:dark}
body{
  margin:0;
  height:100svh;
  /*  There was a `min-height:30rem` here, and it was the whole of the
      60px of dead scroll every page had in phone landscape: 30rem is
      480px against a 420px viewport. It bought nothing — #shell is
      position:fixed to the viewport, so the layout never once consulted
      the height of the body. */
  overflow:hidden;
  background:var(--void);
  color:var(--chalk);
  font-family:var(--sign);
  font-size:clamp(15px,.4vw + 14px,17px);
  line-height:1.4;
  -webkit-font-smoothing:antialiased;
}
h1,h2,p,ol,ul{margin:0}
ol,ul{list-style:none;padding:0}
a{color:inherit}
svg{display:block}
button,input{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--haz);outline-offset:3px}

#yt-host{position:fixed;left:0;bottom:0;width:1px;height:1px;overflow:hidden;opacity:.01;pointer-events:none}

.skip{
  position:fixed;top:-4rem;left:var(--shell);z-index:200;
  background:var(--haz);color:#000;padding:.6rem 1rem;
  text-decoration:none;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;transition:top .2s;
}
.skip:focus{top:.7rem}

/* ── 3  the corridor ────────────────────────────────────────────── */
/*  The corridor sits in a box larger than the window on every side, so
    the shake can throw it around without ever exposing an edge. */
/*  Both of these need to be bigger than the screen — #room so the shake
    never reveals an edge, #grain so its drift never does. They used to
    get that with a negative inset, but they are position:fixed, and a
    fixed box is laid out against the viewport: body's overflow:hidden
    cannot clip it and neither can overflow:clip on the root. The result
    was 60px of real scroll on every page at phone-landscape height — you
    could drag the whole interface off the top and find nothing under it.
    So the boxes sit at inset:0 and CLIP, and the overhang moved inside
    them, where it is somebody's child and can be clipped like one. */
#room{position:fixed;inset:0;z-index:0;overflow:hidden}
#bg{
  position:absolute;inset:-2.5rem;width:auto;height:auto;
  display:block;will-change:transform;
  /* what shows if WebGL never comes up: a lit floor, not a black hole */
  background:
    radial-gradient(ellipse 90% 55% at 50% 108%, #2a2f38 0%, transparent 70%),
    radial-gradient(ellipse 60% 40% at 50% 38%,  #1a1f26 0%, transparent 72%),
    linear-gradient(#07080a, #0d1014 60%, #050608);
}
/* a hard vignette over the top, so the type always has ground to sit on */
#vig{
  position:fixed;inset:0;z-index:1;pointer-events:none;
  background:
    radial-gradient(ellipse 62% 48% at 50% 46%, rgba(0,0,0,.72) 0%, rgba(0,0,0,.30) 45%, transparent 72%),
    linear-gradient(rgba(0,0,0,.80), transparent 26%, transparent 62%, rgba(0,0,0,.88));
}
/* dust on the lens: scanlines plus a static grain plate */
#grain{
  position:fixed;inset:0;z-index:2;pointer-events:none;opacity:.16;overflow:hidden;
  background-image:
    repeating-linear-gradient(0deg, rgba(0,0,0,.55) 0 1px, transparent 1px 3px),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)' opacity='.5'/></svg>");
  /*  The drift used to translate the whole layer, which is what made it
      need the -50% inset. Moving the BACKGROUND instead gets the same
      shimmer out of a box that never leaves the screen. */
  animation:drift .9s steps(3) infinite;
}
@keyframes drift{
  0%{background-position:0 0, 0 0}        33%{background-position:0 -1px, -17px 9px}
  66%{background-position:0 1px, 11px -6px} 100%{background-position:0 0, 0 0}
}

/*  The shell holds everything you can touch and never moves. Only #type
    below rides the beat, and it has nothing clickable in it. */
#shell{
  position:fixed;inset:0;z-index:3;
  display:flex;flex-direction:column;
  padding:var(--shell);
  gap:.6rem;
}
#type{
  /*  Full width on purpose. As a shrink-to-fit column its clientWidth was
      the width of its widest CHILD, and the title-fitting measurement in
      app.js / loha.js needs the width actually available to it. */
  width:100%;min-width:0;
  display:flex;flex-direction:column;align-items:center;gap:.5rem;
  will-change:transform;
}

/* ── 4  chrome ──────────────────────────────────────────────────── */
/*  A key here is a plate: square, heavy, bordered, and it goes DOWN
    and lights up when struck. Nothing is rounded and nothing glows on
    hover alone. */
.key{
  width:3.4rem;height:3.4rem;padding:0;
  display:grid;place-items:center;
  border:2px solid var(--edge);background:rgba(20,23,28,.72);
  color:var(--chalk);cursor:pointer;
  backdrop-filter:blur(3px);
  transition:border-color .12s var(--ease), background .12s var(--ease),
             transform .07s var(--ease), color .12s var(--ease);
}
.key svg{width:1.15rem;height:1.15rem;fill:currentColor}
.key:hover{border-color:var(--haz);color:var(--haz)}
.key:active{transform:translateY(3px) scale(.97);background:var(--haz);color:#000;border-color:var(--haz)}
.key--go{
  width:5rem;height:5rem;border-color:var(--haz);
  background:var(--haz);color:#000;
}
.key--go svg{width:1.7rem;height:1.7rem}
.key--go:hover{background:#fff0a0;border-color:#fff0a0;color:#000}
.key--go:active{transform:translateY(3px) scale(.97)}
.i-pause{display:none}
.key--go[aria-pressed="true"] .i-play{display:none}
.key--go[aria-pressed="true"] .i-pause{display:block}

.chip{
  border:1px solid var(--edge);background:rgba(12,14,18,.68);
  color:var(--chalk-2);cursor:pointer;text-decoration:none;
  padding:.42rem .8rem .38rem;
  font-weight:600;font-size:.82rem;letter-spacing:.12em;text-transform:uppercase;
  display:inline-flex;align-items:center;gap:.4rem;white-space:nowrap;
  backdrop-filter:blur(3px);
  transition:color .14s var(--ease), border-color .14s var(--ease),
             background .14s var(--ease), transform .07s var(--ease);
}
.chip:hover{color:var(--chalk);border-color:var(--chalk-3)}
.chip:active{transform:translateY(2px)}
.chip[aria-pressed="true"],.chip[aria-expanded="true"]{
  background:var(--haz);border-color:var(--haz);color:#000;
}
.chip b{font-weight:700;color:var(--haz);font-variant-numeric:tabular-nums}
.chip[aria-pressed="true"] b,.chip[aria-expanded="true"] b{color:#000}

.slide{display:flex;align-items:center;gap:.5rem}
.slide span{
  font-weight:600;font-size:.72rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--chalk-3);
}
input[type=range]{
  -webkit-appearance:none;appearance:none;background:none;cursor:pointer;
  height:18px;width:5.5rem;
}
input[type=range]::-webkit-slider-runnable-track{
  height:3px;background:linear-gradient(90deg,var(--haz) var(--p,0%),var(--edge) var(--p,0%));
}
input[type=range]::-moz-range-track{height:3px;background:var(--edge)}
input[type=range]::-moz-range-progress{height:3px;background:var(--haz)}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;width:6px;height:16px;border-radius:0;
  background:var(--chalk);margin-top:-6.5px;
}
input[type=range]::-moz-range-thumb{width:6px;height:16px;border-radius:0;border:0;background:var(--chalk)}

/* ── 5  top bar ─────────────────────────────────────────────────── */
#top{
  flex:none;display:flex;align-items:flex-start;justify-content:space-between;
  gap:1rem;
}
.back{
  text-decoration:none;color:var(--chalk-3);
  font-weight:600;font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;
  border-bottom:1px solid transparent;padding-bottom:.15rem;
  transition:color .16s, border-color .16s;
}
.back:hover{color:var(--haz);border-color:var(--haz)}
.mark{text-align:center;line-height:1}
.mark__lat{
  display:block;margin-top:.35rem;
  font-weight:600;font-size:.7rem;letter-spacing:.34em;
  text-transform:uppercase;color:var(--haz);padding-left:.34em;
}
/*  Every header reads the same way now: the name, then what the room is.
    It used to be the name in the record's own script with the Latin
    transliteration under it, which meant the top of each page said the
    same word twice. */
.mark__lat--solo{
  margin-top:0;padding-left:0;
  font-family:var(--sign);font-weight:700;
  font-size:clamp(1.5rem,4.4vw,2.4rem);letter-spacing:.04em;
  color:var(--chalk);
}
.mark__lat--solo + .mark__lat{margin-top:.3rem}

/*  a chip that is a door to the other room rather than a control */
.chip--go{
  text-decoration:none;color:var(--haz);
  border-color:color-mix(in srgb, var(--haz) 45%, transparent);
}
.chip--go:hover{background:var(--haz);border-color:var(--haz);color:#000}

.stat{
  font-weight:700;font-size:.82rem;letter-spacing:.1em;color:var(--chalk-3);
  font-variant-numeric:tabular-nums;
}
.stat i{font-style:normal;opacity:.5;margin:0 .2em}
.stat span:first-child{color:var(--haz)}

/* ── 6  the deck ────────────────────────────────────────────────── */
#deck{
  flex:1;min-height:0;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.5rem;text-align:center;
}
.cue{
  font-weight:600;font-size:.72rem;letter-spacing:.4em;text-transform:uppercase;
  color:var(--haz);padding-left:.4em;
}
/*  the title takes the whole room. The chromatic split is written from
    JS on the beat — two ghosts, red behind and ice in front, the way a
    misaligned print looks. */
.title{
  font-weight:700;line-height:.86;
  font-size:clamp(2.4rem,12vw,8.5rem);
  letter-spacing:-.015em;text-transform:uppercase;
  color:var(--chalk);
  /*  One line, never two — loha.js measures the text and scales the
      size down to fit rather than letting it wrap. */
  /*  min-width:0 is load-bearing. A flex item defaults to
      min-width:auto, which for nowrap text is the min-content width —
      the whole title. That silently overrode max-width and let the box
      grow to 862px inside a 320px screen, so the measuring code saw a
      box that already fitted and never shrank anything. */
  white-space:nowrap;max-width:100%;min-width:0;
  overflow:hidden;text-overflow:ellipsis;
  text-shadow:
    calc(var(--split) * -1) 0 rgba(255,59,45,.85),
    var(--split) 0 rgba(140,233,255,.75);
}
.by{
  font-weight:600;font-size:clamp(.9rem,2.2vw,1.15rem);
  letter-spacing:.2em;text-transform:uppercase;color:var(--chalk-2);
}
.tags{
  display:flex;gap:.9rem;justify-content:center;
  font-weight:600;font-size:.76rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--chalk-3);
  font-variant-numeric:tabular-nums;min-height:1.1em;
}
.tags span:empty{display:none}

/* ── 7  the bar ─────────────────────────────────────────────────── */
.bar{
  width:min(100%,52rem);display:flex;align-items:center;gap:.85rem;
  margin-top:.9rem;
}
.bar__t{
  font-weight:600;font-size:.82rem;color:var(--chalk-3);
  font-variant-numeric:tabular-nums;min-width:3.6ch;
}
.bar__rail{position:relative;flex:1;height:16px;min-width:0;background:rgba(8,9,11,.7);border:1px solid var(--edge)}
/* the plate stack: hazard diagonals, and they only exist where the song
   has actually got to */
.bar__fill{
  position:absolute;inset:1px auto 1px 1px;width:0;
  background-image:repeating-linear-gradient(-45deg,
    var(--haz) 0 7px, #0b0c0e 7px 14px);
  transition:width .18s linear;
}
/* the beat lands as a white edge riding the head of the stack */
.bar__beat{
  position:absolute;top:-3px;bottom:-3px;width:2px;left:0;
  background:var(--chalk);opacity:0;transform:translateX(-1px);
}
.bar__rail input[type=range]{
  position:absolute;inset:-8px 0;width:100%;height:auto;margin:0;opacity:0;cursor:pointer;
}

.keys{display:flex;align-items:center;gap:.9rem;margin-top:1.1rem}

/* ── 8  bottom rack ─────────────────────────────────────────────── */
#bot{flex:none}
.rack{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:.5rem .7rem;
}

/* ── 9  the loading screen ──────────────────────────────────────── */
/*  There used to be a door here with a button on it, and the button was
    load-bearing: a browser will not start audio without a user gesture,
    so the press that opened the door was also the press that unlocked
    the sound. This replaces it with a screen that fills and then lets
    you in on its own — and keeps the gesture opportunistically, because
    a tap during the load still counts. See made.js's sibling logic in
    app.js / loha.js. */
#boot{
  position:fixed;inset:0;z-index:60;
  display:grid;place-items:center;padding:var(--shell);
  background:var(--void);
  transition:opacity .5s var(--ease), visibility .5s;
}
#boot[data-go]{opacity:0;visibility:hidden;pointer-events:none}
.boot__in{text-align:center;max-width:34rem}
.boot__kick{
  font-weight:600;font-size:.72rem;letter-spacing:.42em;
  text-transform:uppercase;color:var(--chalk-3);padding-left:.42em;
  margin-bottom:1.15rem;
}
/*  The one word on the page that is allowed to be the accent colour and
    not be a control. */
.boot__love{color:var(--haz)}
.boot__mark{
  font-family:var(--sign);font-weight:700;line-height:.86;
  font-size:clamp(2.8rem,11vw,6rem);letter-spacing:.01em;color:var(--chalk);
}
.boot__mark span{
  display:block;margin-top:.5rem;
  font-weight:600;font-size:clamp(.78rem,2.2vw,1rem);
  letter-spacing:.52em;text-transform:uppercase;
  color:var(--chalk-3);padding-left:.52em;
}
/*  The bar is the load, and it reaches the end exactly when the screen
    goes. That is why it is a TRANSITION started from JS rather than a CSS
    animation: an animation's clock starts at first paint, the exit timer's
    clock starts when the script runs, and on a slow connection those are
    not the same moment — the bar was still at nothing when the screen
    left. Both are now started inside one requestAnimationFrame, so there
    is a single clock and the two cannot drift. */
.boot__bar{
  width:min(15rem,60vw);height:3px;margin:2.4rem auto 0;
  background:var(--edge);overflow:hidden;
}
.boot__bar i{
  display:block;height:100%;width:100%;
  background:linear-gradient(90deg, var(--haz), color-mix(in srgb, var(--haz) 55%, #fff));
  transform:scaleX(0);transform-origin:0 50%;
  transition:transform var(--boot, 2600ms) linear;
}
#boot[data-run] .boot__bar i{transform:scaleX(1)}
.boot__fine{
  margin-top:1.5rem;
  font-weight:600;font-size:.72rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--chalk-3);
}
.boot__fine span{color:var(--haz);font-variant-numeric:tabular-nums}

/* ── 9b  the studio credit, and the doors behind it ─────────────── */
.chip--made{color:var(--chalk-3)}
.chip--made:hover,.chip--made[aria-expanded="true"]{color:var(--chalk)}
#made{
  position:fixed;inset:0;z-index:55;
  display:grid;place-items:center;padding:var(--shell);
  background:rgba(5,6,8,.95);
  opacity:0;transition:opacity .22s var(--ease);
}
#made[data-open]{opacity:1}
.made__in{width:100%;max-width:52rem;text-align:center}
.made__kick{
  font-weight:600;font-size:.7rem;letter-spacing:.42em;
  text-transform:uppercase;color:var(--chalk-3);padding-left:.42em;
}
.made__mark{
  margin-top:.5rem;font-family:var(--sign);font-weight:700;
  font-size:clamp(2.4rem,8vw,4.4rem);line-height:.9;
  letter-spacing:.01em;color:var(--chalk);
}
.made__line{
  margin:.9rem auto 2rem;max-width:34ch;
  font-weight:500;font-size:clamp(.92rem,2.2vw,1.1rem);color:var(--chalk-2);
}
.made__doors{
  display:grid;gap:.6rem;text-align:left;
  grid-template-columns:repeat(3, minmax(0, 1fr));
}
.door{
  display:flex;flex-direction:column;gap:.16rem;
  padding:1.05rem 1.1rem 1.1rem;text-decoration:none;
  border:1px solid var(--edge);background:rgba(12,14,18,.72);
  transition:border-color .14s var(--ease), background .14s var(--ease),
             transform .07s var(--ease);
}
.door:hover{border-color:var(--haz);background:rgba(18,21,26,.9)}
.door:active{transform:translateY(2px)}
.door__name{
  display:flex;align-items:center;gap:.4rem;
  font-weight:700;font-size:1.05rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--chalk);
}
.door__out{
  width:.8em;height:.8em;flex:none;fill:none;stroke:var(--haz);
  stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;
}
.door__sub{
  font-weight:600;font-size:.68rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--haz);
}
.door__line{margin-top:.35rem;font-size:.82rem;color:var(--chalk-3);line-height:1.35}
.made__close{margin-top:1.6rem}

/* ── 10  the rack of tracks ─────────────────────────────────────── */
#list{
  position:fixed;inset:0;z-index:40;
  /*  Opaque, not a tint: at 96% the corridor and a 6rem song title still
      read straight through the rows behind. A track list has to be a
      list. */
  background:
    radial-gradient(ellipse 80% 50% at 50% 0%, #12151b 0%, transparent 70%),
    #06070a;
  display:flex;flex-direction:column;
  opacity:0;transform:translateY(1.2rem);pointer-events:none;
  transition:opacity .28s var(--ease), transform .28s var(--ease);
}
/*  An id selector outranks the UA's [hidden]{display:none}, so every
    overlay on the site has to say this for itself or the closed panel
    sits over the page eating clicks meant for the deck. This has now
    caught three of them — the track rack, the room picker and the
    studio dialog — so all three are listed here together rather than
    each rediscovering it. */
#list[hidden],#picker[hidden],#made[hidden]{display:none}
/*  And a second line of defence: even mid-fade, a panel that is not
    open must not be in the way. */
#picker:not([data-open]),#made:not([data-open]){pointer-events:none}
#picker[data-open],#made[data-open]{pointer-events:auto}
#list[data-open]{opacity:1;transform:none;pointer-events:auto}
.list__bar{display:flex;gap:.9rem;align-items:center;padding:var(--shell) var(--shell) .8rem}
#q{
  flex:1;min-width:0;padding:.55rem 0;background:none;
  border:0;border-bottom:2px solid var(--edge);
  font-weight:600;font-size:clamp(1.1rem,3vw,1.7rem);
  letter-spacing:.06em;text-transform:uppercase;color:var(--chalk);
}
#q::placeholder{color:var(--chalk-3);text-transform:none;letter-spacing:.02em;font-weight:500}
#q:focus{outline:none;border-color:var(--haz)}
.list__count{
  padding:0 var(--shell) .6rem;
  font-weight:600;font-size:.76rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--chalk-3);font-variant-numeric:tabular-nums;
}
.list__rows{overflow-y:auto;flex:1;padding:0 var(--shell) 3rem}
.list__none{padding:3rem var(--shell);text-align:center;color:var(--chalk-3)}
.row{
  display:grid;grid-template-columns:3rem 1fr auto;gap:.1rem .9rem;
  align-items:center;width:100%;
  padding:.62rem .5rem;background:none;border:0;
  border-bottom:1px solid #1b1f26;text-align:left;cursor:pointer;
  transition:background .12s, padding-left .12s;
}
.row:hover{background:#12151a;padding-left:.85rem}
.row__i{
  grid-row:1 / span 2;font-weight:700;font-size:.95rem;color:var(--chalk-3);
  font-variant-numeric:tabular-nums;
}
.row__t{
  grid-column:2;grid-row:1;
  font-weight:700;font-size:1.05rem;letter-spacing:.05em;
  text-transform:uppercase;color:var(--chalk);line-height:1.2;
}
.row__a{grid-column:2;grid-row:2;font-weight:500;font-size:.86rem;color:var(--chalk-3)}
.row__s{
  grid-column:3;grid-row:1 / span 2;
  font-weight:600;font-size:.88rem;color:var(--chalk-3);font-variant-numeric:tabular-nums;
}
.row[aria-current="true"]{background:#171b21}
.row[aria-current="true"] .row__i,
.row[aria-current="true"] .row__t{color:var(--haz)}

/* ── 11  narrow screens ─────────────────────────────────────────── */
@media (max-width:760px){
  #shell{gap:.4rem}
  #top{gap:.5rem;align-items:center}
  /*  Three things across a 390px bar, and none of them may wrap: a
      two-line back link shoves the wordmark sideways and the whole
      header lists to one side. */
  .back,.mark__lat,.stat{white-space:nowrap}
  .mark__lat{letter-spacing:.2em;font-size:.58rem;margin-top:.25rem}
  .title{font-size:clamp(2rem,13vw,3.4rem);max-width:14ch}
  .keys{margin-top:.7rem;gap:.7rem}
  .rack{gap:.4rem .5rem}
  .slide--vol{display:none}
  .bar{margin-top:.6rem}
}
@media (max-width:420px){
  .chip{padding:.4rem .6rem .36rem;font-size:.74rem;letter-spacing:.08em}
  .slide{display:none}
  /* the arrow alone is the back link once there is no room for the words */
  .back span{display:none}
  .mark__lat{letter-spacing:.16em}
}
@media (pointer:coarse){
  .chip{padding:.62rem .8rem .58rem}
  .row{padding-block:.8rem}
  input[type=range]{height:30px}
}
/* a short landscape phone: give the type back to the corridor */
@media (max-height:520px){
  .title{font-size:clamp(1.6rem,7vw,2.6rem)}
  .cue,.tags{display:none}
  .keys{margin-top:.4rem}
  .key{width:2.8rem;height:2.8rem}
  .key--go{width:3.6rem;height:3.6rem}
}

/* ── 12  reduced motion ─────────────────────────────────────────── */
/*  The shake, the split and the strobing are the whole point of this
    page and are exactly what a vestibular disorder cannot take. On
    reduce, loha.js clamps Force to a floor and stops moving the shell;
    here the grain stops drifting and the transitions go away. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  #grain{animation:none}
  .title{text-shadow:none}
}

/* ── 13  the decks ──────────────────────────────────────────────── */
/*  One page, four playlists — on either room. The switch is a row of
    plates bolted to the wall, not a tab strip: the live one is painted in
    whatever the room is lit with.

    Each deck repaints the whole page, not just the corridor: the accent
    token is swapped on <html data-deck>, so every chip, slider, underline
    and lit key follows the room.

    The GYM room takes the warm half of the wheel — hazard yellow, tungsten
    amber, red, rani pink — and the MAX room takes the cold half plus one
    acid green, so the two pages can never be mistaken for one another.

    Every accent clears 4.5:1 on the void (#08090b) and carries black text
    when a key is pressed down. The tightest are Badmashi's red at 5.6:1
    and Rap's violet at 6.3:1. */
:root[data-deck="era"]{
  --haz:#ff9c24;
  --haz-deep:#c26f10;
}
:root[data-deck="badmashi"]{
  --haz:#ff3b2d;
  --haz-deep:#b3211a;
  --ice:#ff9d94;
}
/*  Rani pink: the colour of every Punjabi wedding tent there has ever
    been. 6.0:1 on the void, 6.4:1 against the black it carries when a key
    is down — the widest margin of the four. */
:root[data-deck="dance"]{
  --haz:#ff3d9a;
  --haz-deep:#b81f68;
  --ice:#8ce9ff;
}
/*  Badmashi is the one deck that is not lit from above. The vignette
    closes in and the ground goes to almost nothing, so the corridor is
    doing the talking and the type sits in what is left. */
/*  ── max.html ──────────────────────────────────────────────────
    Iron is deliberately achromatic: a bare fluorescent tube over
    concrete has no colour, and against four coloured rooms the absence
    reads as its own thing. 17:1 on the void — the brightest on the site,
    which is the point. */
:root[data-deck="iron"]{
  --haz:#e9eff6;
  --haz-deep:#93a3b4;
  --ice:#8ce9ff;
}
/*  Violet at 6.3:1, the tightest accent here and still well clear. */
:root[data-deck="rap"]{
  --haz:#a17bff;
  --haz-deep:#6d4bd1;
  --ice:#d9c8ff;
}
:root[data-deck="volt"]{
  --haz:#22e0ff;
  --haz-deep:#0d8fac;
  --ice:#bff4ff;
}
/*  Safety green — the colour of the sign over the fire door, and the one
    hue neither room had taken. 15.9:1. */
:root[data-deck="rise"]{
  --haz:#a6ff3d;
  --haz-deep:#6aa81c;
  --ice:#e2ffb8;
}
/*  Rap is the other room lit from the side rather than above: same
    treatment as Badmashi, so the corridor carries it. */
:root[data-deck="rap"] #vig,
:root[data-deck="badmashi"] #vig{
  background:
    radial-gradient(ellipse 62% 48% at 50% 46%, rgba(0,0,0,.80) 0%, rgba(0,0,0,.38) 45%, transparent 74%),
    linear-gradient(rgba(0,0,0,.86), transparent 24%, transparent 60%, rgba(0,0,0,.92));
}
#decks{
  flex:none;display:flex;justify-content:center;gap:.4rem;
  margin-top:.2rem;
}
.deck-btn{
  border:1px solid var(--edge);background:rgba(12,14,18,.7);
  color:var(--chalk-2);cursor:pointer;
  padding:.42rem 1.15rem .38rem;
  /*  A plate is a target for a thumb, and the thumb belongs to someone
      who is mid-set. Dropping the year sub-label at 365px shrank these to
      24px tall — legible, and far too small to hit. The height is held
      here so no breakpoint can take it below a reachable size. */
  min-height:44px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.05rem;
  backdrop-filter:blur(3px);
  transition:color .14s var(--ease), border-color .14s var(--ease),
             background .14s var(--ease), transform .07s var(--ease);
}
.deck-btn b{
  font-weight:700;font-size:.86rem;letter-spacing:.16em;text-transform:uppercase;
  line-height:1.1;
}
.deck-btn span{
  font-weight:600;font-size:.64rem;letter-spacing:.14em;
  color:var(--chalk-3);font-variant-numeric:tabular-nums;line-height:1.1;
}
.deck-btn:hover{color:var(--chalk);border-color:var(--chalk-3)}
.deck-btn:active{transform:translateY(2px)}
.deck-btn[aria-pressed="true"]{
  background:var(--haz);border-color:var(--haz);color:#000;
}
.deck-btn[aria-pressed="true"] span{color:rgba(0,0,0,.62)}

/* the tap key goes quiet once this track's tempo has actually been set */
#k-tap.is-set b{color:var(--ice)}
#k-tap.is-set[aria-pressed="true"] b{color:#000}

@media (max-width:420px){
  .deck-btn{padding:.36rem .6rem .32rem}
  .deck-btn b{font-size:.74rem;letter-spacing:.07em}
  .deck-btn span{font-size:.56rem;letter-spacing:.06em}
  #decks{gap:.3rem}
}
/*  Four decks across a 320px screen. The year ranges are the first thing
    to go — the names already say what each one is, and a rail you have to
    scroll to find the fourth deck on is worse than a rail without dates. */
@media (max-width:365px){
  .deck-btn{padding:.34rem .42rem .3rem;min-height:42px}
  .deck-btn b{font-size:.68rem;letter-spacing:.03em}
  .deck-btn span{display:none}
  #decks{gap:.22rem}
}
@media (max-height:520px){
  #decks{margin-top:0}
  .deck-btn span{display:none}
}

/*  On a narrow screen the title is allowed past the shell's side padding.
    It is the one element on the page long enough to need it, and at 320px
    those two gutters are about a tenth of the usable width — the
    difference between a title fitting and being ellipsised. */
@media (max-width:480px){
  .title{
    width:calc(100% + var(--shell) * 2);
    max-width:calc(100% + var(--shell) * 2);
    margin-inline:calc(var(--shell) * -1);
  }
}
