/* ==========================================================
   KCA rack system v4.
   CSS does the layout; every material and part is a rendered image
   (tools/render_parts.py) lit from the top left, so plates, screws,
   knobs, jacks, reels and buttons carry real shading and shadows.

   Geometry: a 19in rack. 1U = 1.75in, so --u comes from the rack width
   (body is the size container, rack max 1400px). Every unit declares
   .u1 to .u4 and gets that exact height; content is sized in U.
   Pure CSS (Squarespace Custom CSS, Basic plan). Flavors are picked
   with CSS-only radios (body:has(#t-x:checked)).
   ========================================================== */

:root {
  --void: #0a0b0d;
  --stamp-font: "Michroma", "Eurostile", "Arial Narrow", sans-serif;
  --jost: "Jost", "Futura", "Century Gothic", sans-serif;
  --body-font: "Barlow", "Helvetica Neue", Arial, sans-serif;
  --punch-font: "Barlow Condensed", "Arial Narrow", sans-serif;
  --lcd-font: "VT323", "Courier New", monospace;
  --marker-font: "Permanent Marker", "Marker Felt", cursive;

  --amber: #ffb000;
  --red: #ff4d3d;
  --teal: #2ec4b6;
  --violet: #8c6dff;
  --green: #6ad35b;
  --phosphor: #7cff9a;

  /* light falls from above: the top edge of every plate catches it */
  --sheen: linear-gradient(180deg, rgba(255, 255, 255, 0.09), rgba(255, 255, 255, 0.025) 18%, transparent 55%, rgba(0, 0, 0, 0.14));
  --scan: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.14) 0 1px, transparent 1px 3px);
  --grain: 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='.8' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 .5  0 0 0 0 .5  0 0 0 0 .5  0 0 0 .9 0'/></filter><rect width='220' height='220' filter='url(%23n)'/></svg>");
}
/* photographic grain over the whole rack */
body::after { content: ""; position: fixed; inset: 0; z-index: 100; pointer-events: none; background: var(--grain); opacity: 0.16; mix-blend-mode: overlay; }

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; } /* iOS must not inflate text on rotation: every box here is sized to its print */
body {
  margin: 0;
  container-type: inline-size;
  font-family: var(--body-font);
  font-size: 16px;
  line-height: 1.5;
  color: #c9ccd2;
  -webkit-font-smoothing: antialiased;
  background: radial-gradient(1400px 600px at 50% -10%, rgba(255, 255, 255, 0.05), transparent 60%), var(--void);
  background-repeat: no-repeat; /* the highlight is painted once at the top */
  min-height: 100vh; /* the body reaches the bottom of the window: the grain overlay blends over the plate, not over an empty canvas, below a short page */
}
:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; }
.ctl { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
/* on a touch screen every tappable part behaves like hardware: a quick second tap must not zoom the page
   (pinch zoom stays), the printed legend never selects, and iOS paints no grey flash over the rendered button */
button, a, label, input, .pads i { touch-action: manipulation; }
button, label, .btn, .tbtn, .keycell, .hot, .pads i { -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; }

body:has(#t-vintage:checked) { background: radial-gradient(1200px 500px at 50% -10%, rgba(255, 140, 60, 0.08), transparent 60%), #15100c; background-repeat: no-repeat; }
body:has(#t-sampler:checked) { background: #19191a; }
body:has(#t-modular:checked) { background: #0c0e11; }

/* ==========================================================
   THE RACK: rails with holes on the U grid, units bolted between them
   ========================================================== */
.rack {
  --u: calc(min(100cqw, 1400px) * 1.75 / 19);
  --rail: 14px;
  --ear: calc(var(--u) * 0.42);
  --pad-x: calc(var(--ear) + var(--u) * 0.12);
  --pad-y: calc(var(--u) * 0.1);
  --line: calc(var(--u) * 0.31);
  --fs-body: clamp(13px, calc(var(--u) * 0.118), 16px);
  --fs-hero: clamp(15px, calc(var(--u) * 0.15), 19.5px);
  --fs-label: clamp(7.5px, calc(var(--u) * 0.068), 9.5px);
  --fs-name: clamp(8.5px, calc(var(--u) * 0.08), 11px);
  --bz: min(22px, calc(var(--u) * 0.17));
  position: relative;
  max-width: 1400px;
  margin: 0 auto;
  padding: 28px var(--rail) 48px;
}
.rack::before,
.rack::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: var(--rail);
  background: url(img/parts/rail.png) 50% 28px / 14px var(--u) repeat-y, #1c1d21;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.6);
}
.rack::before { left: 0; }
.rack::after { right: 0; }

/* ==========================================================
   FINISHES: a texture, inks, and which rendered parts a unit uses
   ========================================================== */

/* powder-coated black: the default, Studio Black, the deck */
.page-section,
body:has(#t-studio:checked) .page-section,
body:has(#t-mixed:checked) .hw-power {
  --tex: url(img/tex/black.webp); --plate-solid: #26282c;
  --ink: #e4e0d7; --scale: url(img/parts/scale-light.png); --ink-dim: #9a9da5; --ink-line: rgba(228, 224, 215, 0.2); --engrave: 0 1px 0 rgba(0, 0, 0, 0.8);
  --cheek: url(img/tex/ear.webp); --cheek-size: 256px 256px;
  --scr-bg: #1b1306; --scr-ink: #ffb000; --scr-glow: 0 0 8px rgba(255, 176, 0, 0.5);
  --knob: url(img/parts/knob-black.png); --ptr: url(img/parts/ptr-amber.png);
  --btn: url(img/parts/btn-dark.png); --btn-wide: url(img/parts/btn-wide-dark.png); --btn-ink: #e3dfd6;
  --link: #ffb000; --silk: var(--stamp-font); --punch: var(--punch-font);
}

/* cream enamel with wood ears (Vintage Analog; mixed: ID preamp) */
body:has(#t-vintage:checked) .page-section,
body:has(#t-mixed:checked) .hw-preamp {
  --tex: url(img/tex/cream.webp); --plate-solid: #e3d9c2; --scale: url(img/parts/scale-dark.png);
  --ink: #2b241c; --ink-dim: #4a4236; --ink-line: rgba(43, 36, 28, 0.32); --engrave: 0 1px 0 rgba(255, 255, 255, 0.55);
  --cheek: url(img/tex/oak.webp); --cheek-size: 256px 256px;
  --scr-bg: #120a06; --scr-ink: #ff8a3d; --scr-glow: 0 0 9px rgba(255, 120, 40, 0.6);
  --knob: url(img/parts/knob-cream.png); --ptr: url(img/parts/ptr-white.png);
  --btn: url(img/parts/btn-cream.png); --btn-wide: url(img/parts/btn-wide-cream.png); --btn-ink: #2b241c;
  --link: #9a3412; --silk: var(--jost); --punch: var(--jost);
}

/* warm grey ABS (Beat Sampler; mixed: beat units) */
body:has(#t-sampler:checked) .page-section,
body:has(#t-mixed:checked) .hw-sampler {
  --tex: url(img/tex/grey.webp); --plate-solid: #c6c3b9; --scale: url(img/parts/scale-dark.png);
  --ink: #1d1d1c; --ink-dim: #37362f; --ink-line: rgba(29, 29, 28, 0.3); --engrave: 0 1px 0 rgba(255, 255, 255, 0.45);
  --cheek: url(img/tex/wood.webp); --cheek-size: 256px 256px;
  --scr-bg: #a9b66b; --scr-ink: #1c2411; --scr-glow: none;
  --knob: url(img/parts/knob-grey.png); --ptr: url(img/parts/ptr-black.png);
  --btn: url(img/parts/btn-silver.png); --btn-wide: url(img/parts/btn-wide-silver.png); --btn-ink: #141414;
  --link: #a3261f; --silk: var(--jost); --punch: var(--punch-font);
}

/* brushed aluminium (Modular; mixed: meter / sync units) */
body:has(#t-modular:checked) .page-section,
body:has(#t-mixed:checked) .hw-meter {
  --tex: url(img/tex/alu.webp); --plate-solid: #d2d5da; --scale: url(img/parts/scale-dark.png);
  --ink: #121417; --ink-dim: #262a30; --ink-line: rgba(18, 20, 23, 0.36); --engrave: 0 1px 0 rgba(255, 255, 255, 0.7);
  --cheek: url(img/tex/silver.webp); --cheek-size: 256px 256px;
  --scr-bg: #040506; --scr-ink: #7fe7ff; --scr-glow: 0 0 8px rgba(127, 231, 255, 0.55);
  --knob: url(img/parts/knob-alu.png); --ptr: url(img/parts/ptr-black.png);
  --btn: url(img/parts/btn-dark.png); --btn-wide: url(img/parts/btn-wide-dark.png); --btn-ink: #e8ecf1;
  --link: #084a5f; --silk: var(--stamp-font); --punch: var(--punch-font);
}

/* navy (mixed: broadcast preamp) */
body:has(#t-mixed:checked) .hw-recorder {
  --tex: url(img/tex/navy.webp); --plate-solid: #22325a; --scale: url(img/parts/scale-light.png);
  --ink: #dfe8ff; --ink-dim: #93a4c9; --ink-line: rgba(223, 232, 255, 0.22); --engrave: 0 1px 0 rgba(0, 0, 0, 0.7);
  --cheek: url(img/tex/ear.webp); --cheek-size: 256px 256px;
  --scr-bg: #021018; --scr-ink: #5ff6ff; --scr-glow: 0 0 9px rgba(95, 246, 255, 0.55);
  --knob: url(img/parts/knob-white.png); --ptr: url(img/parts/ptr-black.png);
  --btn: url(img/parts/btn-silver.png); --btn-wide: url(img/parts/btn-wide-silver.png); --btn-ink: #0f1a2e;
  --link: #7fd8ff; --silk: var(--stamp-font); --punch: var(--punch-font);
}

/* red hammertone (mixed: talkback) */
body:has(#t-mixed:checked) .hw-talkback {
  --tex: url(img/tex/hammer.webp); --plate-solid: #b3352a; --scale: url(img/parts/scale-light.png);
  --ink: #fff2e8; --ink-dim: #ffd1c2; --ink-line: rgba(255, 242, 232, 0.32); --engrave: 0 1px 0 rgba(0, 0, 0, 0.5);
  --cheek: url(img/tex/ear.webp); --cheek-size: 256px 256px;
  --scr-bg: #1b1306; --scr-ink: #ffb000; --scr-glow: 0 0 8px rgba(255, 176, 0, 0.5);
  --knob: url(img/parts/knob-white.png); --ptr: url(img/parts/ptr-black.png);
  --btn: url(img/parts/btn-cream.png); --btn-wide: url(img/parts/btn-wide-cream.png); --btn-ink: #5a1612;
  --link: #ffe08a; --silk: var(--stamp-font); --punch: var(--punch-font);
}

/* silver (mixed: program selector, rack control) */
body:has(#t-mixed:checked) .hw-mixer,
body:has(#t-mixed:checked) .hw-control {
  --tex: url(img/tex/silver.webp); --plate-solid: #c4c8ce; --scale: url(img/parts/scale-dark.png);
  --ink: #111317; --ink-dim: #262a30; --ink-line: rgba(17, 19, 23, 0.36); --engrave: 0 1px 0 rgba(255, 255, 255, 0.7);
  --cheek: url(img/tex/ear.webp); --cheek-size: 256px 256px;
  --scr-bg: #ebe4ca; --scr-ink: #2a2015; --scr-glow: none;
  --knob: url(img/parts/knob-black.png); --ptr: url(img/parts/ptr-white.png);
  --btn: url(img/parts/btn-dark.png); --btn-wide: url(img/parts/btn-wide-dark.png); --btn-ink: #e8ecf1;
  --link: #8a2c0d; --silk: var(--stamp-font); --punch: var(--punch-font);
}

/* black synth with wood ears (mixed: filter) */
body:has(#t-mixed:checked) .hw-synth {
  --tex: url(img/tex/black.webp); --plate-solid: #26282c;
  --ink: #ecebe6; --scale: url(img/parts/scale-light.png); --ink-dim: #9a9993; --ink-line: rgba(236, 235, 230, 0.2); --engrave: 0 1px 0 rgba(0, 0, 0, 0.8);
  --cheek: url(img/tex/wood.webp); --cheek-size: 256px 256px;
  --scr-bg: #120a06; --scr-ink: #ff8a3d; --scr-glow: 0 0 9px rgba(255, 120, 40, 0.6);
  --knob: url(img/parts/knob-alu.png); --ptr: url(img/parts/ptr-black.png);
  --btn: url(img/parts/btn-dark.png); --btn-wide: url(img/parts/btn-wide-dark.png); --btn-ink: #ecebe6;
  --link: #ff9a5a; --silk: var(--jost); --punch: var(--jost);
}

/* olive crinkle (mixed: tape echo, reel-to-reel) */
body:has(#t-mixed:checked) .hw-tape {
  --tex: url(img/tex/olive.webp); --plate-solid: #4f5d3a; --scale: url(img/parts/scale-light.png);
  --ink: #f1ead2; --ink-dim: #cdc5a6; --ink-line: rgba(241, 234, 210, 0.32); --engrave: 0 1px 0 rgba(0, 0, 0, 0.55);
  --cheek: url(img/tex/ear.webp); --cheek-size: 256px 256px;
  --scr-bg: #1b1306; --scr-ink: #ffb000; --scr-glow: 0 0 8px rgba(255, 176, 0, 0.5);
  --knob: url(img/parts/knob-white.png); --ptr: url(img/parts/ptr-black.png);
  --btn: url(img/parts/btn-cream.png); --btn-wide: url(img/parts/btn-wide-cream.png); --btn-ink: #2c331f;
  --link: #ffd27a; --silk: var(--jost); --punch: var(--jost);
}

/* rear panels are always dark steel, whatever the front is */
:is(#studio, #flipunit) .face.back .page-section {
  --tex: url(img/tex/steel.webp); --plate-solid: #1f2125; --scale: url(img/parts/scale-light.png);
  --ink: #d9d5cc; --ink-dim: #8b8e96; --ink-line: rgba(217, 213, 204, 0.2); --engrave: 0 1px 0 rgba(0, 0, 0, 0.8);
  --cheek: url(img/tex/ear.webp); --cheek-size: 256px 256px;
  --btn: url(img/parts/btn-dark.png); --btn-wide: url(img/parts/btn-wide-dark.png); --btn-ink: #e3dfd6;
  --silk: var(--stamp-font);
}

/* per-unit accent: the LED colour and its rendered lens */
.page-section, .unit-amber { --accent: var(--amber); --led-on: url(img/parts/led-amber-on.png); --led-off: url(img/parts/led-amber-off.png); }
.unit-red { --accent: var(--red); --led-on: url(img/parts/led-red-on.png); --led-off: url(img/parts/led-red-off.png); }
.unit-teal { --accent: var(--teal); --led-on: url(img/parts/led-teal-on.png); --led-off: url(img/parts/led-teal-off.png); }
.unit-violet { --accent: var(--violet); --led-on: url(img/parts/led-violet-on.png); --led-off: url(img/parts/led-violet-off.png); }
.unit-green { --accent: var(--green); --led-on: url(img/parts/led-green-on.png); --led-off: url(img/parts/led-green-off.png); }

/* modular flavour: coloured caps */
body:has(#t-modular:checked) .knob-cell:nth-child(4n + 1) .knob { --knob: url(img/parts/knob-red.png); --ptr: url(img/parts/ptr-white.png); }
body:has(#t-modular:checked) .knob-cell:nth-child(4n + 2) .knob { --knob: url(img/parts/knob-amber.png); --ptr: url(img/parts/ptr-black.png); }
body:has(#t-modular:checked) .knob-cell:nth-child(4n + 3) .knob { --knob: url(img/parts/knob-blue.png); --ptr: url(img/parts/ptr-white.png); }
body:has(#t-modular:checked) .knob-cell:nth-child(4n + 4) .knob { --knob: url(img/parts/knob-white.png); --ptr: url(img/parts/ptr-black.png); }

/* ==========================================================
   THE UNIT
   ========================================================== */
.page-section {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  height: var(--u);
  margin: 0;
  padding: var(--pad-y) var(--pad-x);
  color: var(--ink);
  background: var(--sheen), var(--tex) 0 0 / 256px 256px repeat;
  border-top: 1px solid rgba(255, 255, 255, 0.2);
  border-bottom: 1px solid rgba(0, 0, 0, 0.9);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 -1px 0 rgba(0, 0, 0, 0.35), 0 2px 0 rgba(0, 0, 0, 0.75);
}
.u1 { height: var(--u); }
.u2 { height: calc(var(--u) * 2); }
.u3 { height: calc(var(--u) * 3); }
.u4 { height: calc(var(--u) * 4); }

/* rack ears: a steel flange with a screw seated in the first and last rail hole */
.page-section::before,
.page-section::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: var(--ear);
  background:
    url(img/parts/screw.png) 50% calc(var(--u) / 6 - 8px) / 16px 16px no-repeat,
    url(img/parts/screw.png) 50% calc(100% - (var(--u) / 6 - 8px)) / 16px 16px no-repeat,
    var(--cheek) 0 0 / var(--cheek-size, 256px 256px) repeat;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 -1px 0 rgba(0, 0, 0, 0.5);
}
.page-section::before { left: 0; border-right: 1px solid rgba(0, 0, 0, 0.75); }
.page-section::after { right: 0; border-left: 1px solid rgba(0, 0, 0, 0.75); }

/* 3U and 4U units carry rack handles */
.handle {
  position: absolute;
  z-index: 2;
  top: calc(50% - var(--u) * 0.7);
  left: calc(var(--ear) / 2 - 7px);
  width: 14px;
  height: calc(var(--u) * 1.4);
  border-style: solid;
  border-width: 15px 0;
  border-image: url(img/parts/handle.png) 30 0 fill / 15px 0;
  pointer-events: none;
}
.handle.r { left: auto; right: calc(var(--ear) / 2 - 7px); }

/* model nameplate: engraved badge, model name, power LED */
h4 {
  display: flex;
  align-items: center;
  flex: none;
  gap: 0.9em;
  height: calc(var(--u) * 0.22);
  margin: 0 0 calc(var(--u) * 0.11);
  font-family: var(--silk);
  font-size: var(--fs-name);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
  text-shadow: var(--engrave);
}
h4::before {
  content: "KCA";
  padding: 0.3em 0.6em 0.2em;
  border: 1.5px solid currentColor;
  border-radius: 2px;
  letter-spacing: 0.14em;
}
h4::after {
  content: "";
  flex: none;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--led-on) center / 100% 100% no-repeat;
  box-shadow: 0 0 8px 1px var(--accent);
}

/* 1U units run everything on one line */
.u1 { flex-direction: row; align-items: center; gap: calc(var(--u) * 0.14); }
.u1 h2 { font-size: calc(var(--u) * 0.2); }
.u1 .btn { padding: 0 0.6em; }
.u1 .keyrow { gap: calc(var(--u) * 0.1); }
.u1 h4 { height: auto; margin: 0; }
.u1 > .row { flex: 1 1 auto; }

/* big silkscreen lettering */
h1 {
  margin: 0 0 calc(var(--u) * 0.08);
  font-family: var(--punch);
  font-weight: 800;
  font-size: calc(var(--u) * 0.44);
  line-height: 0.92;
  text-transform: uppercase;
  color: var(--ink);
  text-shadow: var(--engrave);
  text-wrap: balance;
}
h1 em { font-style: normal; color: var(--link); }

/* readouts behind glass: h2 (big), .lcd (small), .screen (text) */
h2, .lcd, .screen {
  position: relative;
  color: var(--scr-ink);
  background: var(--scan), var(--scr-bg);
  border: 6px solid transparent;
  border-image: url(img/parts/bezel.png) 16 fill / 6px;
}
h2 {
  display: inline-block;
  margin: 0;
  padding: 0.12em 0.5em 0.04em;
  font-family: var(--lcd-font);
  font-weight: 400;
  font-size: calc(var(--u) * 0.23);
  line-height: 1.05;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-shadow: var(--scr-glow);
  white-space: nowrap;
}
.lcd {
  display: inline-block;
  flex: none;
  box-sizing: content-box;
  overflow: hidden;
  width: var(--w, auto);
  padding: 0.1em 0.5em 0.02em;
  font-family: var(--lcd-font);
  font-size: calc(var(--u) * 0.17);
  line-height: 1.1;
  text-shadow: var(--scr-glow);
  white-space: nowrap;
}
.screen {
  min-height: 0;
  padding: calc(var(--u) * 0.08) calc(var(--u) * 0.12);
  border-width: 8px;
  border-image-width: 8px;
}
.screen::after, .lcd::after, h2::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.09), transparent 40%), radial-gradient(120% 80% at 50% 110%, rgba(0, 0, 0, 0.22), transparent 60%);
  pointer-events: none;
}
.screen p { font-size: var(--fs-body); line-height: 1.5; }
.screen strong, .screen em { color: inherit; font-style: normal; font-weight: 700; }
.screen a { color: inherit; }
.screen ul { margin: 0; padding-left: 1.2em; font-size: var(--fs-body); line-height: 1.5; }

/* scribble strip: a strip of tape, marker lettering */
h3 {
  display: inline-block;
  align-self: flex-start;
  margin: 0;
  padding: 0.12em 0.5em 0.02em;
  border: 0 10px solid transparent;
  border-image: url(img/parts/tape-strip.png) 0 20 fill / 0 10px;
  font-family: var(--marker-font);
  font-weight: 400;
  font-size: clamp(14px, calc(var(--u) * 0.14), 19px);
  line-height: 1.3;
  letter-spacing: 0.02em;
  color: #1b1b1b;
  transform: rotate(-0.8deg);
}

p { margin: 0 0 0.6em; }
p:last-child { margin-bottom: 0; }
a { color: var(--link); text-underline-offset: 3px; }

/* ---------- silkscreened control zones ---------- */
.zone {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: calc(var(--u) * 0.1);
  min-height: 0;
  /* the zone carries the label's font so the floor below is in the label's own em: if a browser renders the print larger
     (a minimum font size, text-only zoom) the floor grows with it and the label stays inside its box */
  font-size: var(--fs-label);
  min-width: calc(var(--lw, 0) * 1.25em + 34px);
  padding: calc(var(--u) * 0.2) calc(var(--u) * 0.12) calc(var(--u) * 0.12);
  border: 1px solid var(--ink-line);
  border-radius: 5px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 1px 0 rgba(255, 255, 255, 0.05);
}
.zone::before {
  content: attr(data-label);
  position: absolute;
  top: -0.6em;
  left: 10px;
  padding: 0 6px;
  font-family: var(--silk);
  font-size: inherit;
  line-height: 1.2;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink-dim);
  text-shadow: var(--engrave);
  background: var(--plate-solid);
}
.zone.top { justify-content: flex-start; }
:where(.zone > *) { font-size: 1rem; }
.zone.mid { align-items: center; }

/* ---------- buttons: a rendered cap with an LED ---------- */
.btn, .tbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.7em;
  border: 12px solid transparent;
  border-image: var(--btn) 24 fill / 12px;
  font-family: var(--silk);
  font-size: var(--fs-label);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  color: var(--btn-ink);
  cursor: pointer;
  user-select: none;
  transition: transform 0.06s, filter 0.06s;
}
.tbtn { border: 0; border-radius: 6px; background: var(--btn-wide, url(img/parts/btn-wide-dark.png)) center / 100% 100% no-repeat; }
.btn { min-height: calc(var(--u) * 0.3); padding: 0 0.9em; }
.btn::before {
  content: "";
  width: 0.85em;
  height: 0.85em;
  border-radius: 50%;
  background: var(--led-off) center / 100% 100% no-repeat;
}
.btn:hover::before, .btn.on::before { background-image: var(--led-on); box-shadow: 0 0 7px 1px var(--accent); }
.btn:active, .tbtn:active { transform: translateY(2px); filter: brightness(0.92); }
.tbtn { width: calc(var(--u) * 0.34); height: calc(var(--u) * 0.26); padding: 0; font-size: calc(var(--u) * 0.085); letter-spacing: 0; }
.tbtn.rec { color: #d8392c; }
/* printed transport symbols are shapes, not font glyphs: they centre identically in every browser */
.ico { display: block; width: 11px; height: 11px; fill: currentColor; }
.tbtn .ico { width: max(9px, calc(var(--u) * 0.085)); height: max(9px, calc(var(--u) * 0.085)); }
.vkey .ico { width: max(10px, calc(var(--u) * 0.11)); height: max(10px, calc(var(--u) * 0.11)); }
.i-pause { display: none; }
.pause .i-play { display: none; }
.pause .i-pause { display: block; }
.tbtn.wide { width: auto; min-width: var(--cap-w); padding: 0 1em; font-family: var(--silk); font-size: var(--fs-label); letter-spacing: 0.12em; text-indent: 0.12em; } /* a word cap: the print sits inside the cap with a letter's room each side, never against its edges */
.tbtns { display: flex; gap: 6px; flex-wrap: wrap; }
.tbtns.two { display: grid; grid-template-columns: repeat(3, auto); }
.tbtn.on { box-shadow: 0 0 0 1px var(--accent), 0 0 10px var(--accent); }

/* ---------- knobs: a rendered body, the pointer rotates on top ---------- */
.knob-row { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 0.08) calc(var(--u) * 0.14); align-items: flex-end; justify-content: center; }
.knob-cell { display: grid; justify-items: center; gap: 0.3em; width: auto; min-width: calc(var(--u) * 0.5); }
.knob-row.r2 { display: grid; grid-template-columns: repeat(4, auto); }
.knob-row.r2.c3 { grid-template-columns: repeat(3, auto); }
.knob-row.sm { flex-wrap: nowrap; }
/* the synth header row: each section owns a fixed share so none can starve another */
#synth .rows > .row:first-child > .zone { flex: 0 1 auto; width: auto; min-width: -webkit-fit-content; min-width: fit-content; }
#synth .z-pat { flex: 1 1 auto; }
#synth .cells { gap: 3px calc(var(--u) * 0.1); }
#synth .knob-row.sm .knob-cell { min-width: calc(var(--u) * 0.32); }
#synth .keyrow { flex-wrap: nowrap; }
.knob-row.sm { gap: calc(var(--u) * 0.08) calc(var(--u) * 0.1); }
.knob-row.sm .knob-cell { width: auto; min-width: calc(var(--u) * 0.36); }
#monitor .keyrow { gap: calc(var(--u) * 0.08); flex-wrap: nowrap; }
#monitor .vu { gap: 3px; } #monitor .vu i { width: 6px; }
#monitor .zone[data-label="Main"] .stack { gap: 4px; }
.knob {
  --rot: -135deg;
  --kd: min(64px, calc(var(--u) * 0.42));
  position: relative;
  width: var(--kd);
  height: var(--kd);
  background: var(--knob) center / 100% 100% no-repeat;
}
.knob::before {
  content: "";
  position: absolute;
  inset: -18%;
  background: var(--scale) center / 100% 100% no-repeat;
}
.knob::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ptr) center / 100% 100% no-repeat;
  transform: translateY(-5.5%) rotate(var(--rot));
  transition: transform 0.08s linear;
}
.knob.sm { --kd: min(44px, calc(var(--u) * 0.3)); }
/* a zone's knob slot: the size of its knobs (the two sizes above; the narrow regime sets its own), read by a key row
   sharing the zone and by a small knob in a row of full ones, which sits centred in the full one's height so the caps
   are level and the names on one line */
.zone:has(> .knob-row .knob.sm) { --kslot: min(44px, calc(var(--u) * 0.3)); }
.zone:has(> .knob-row .knob:not(.sm)) { --kslot: min(64px, calc(var(--u) * 0.42)); } /* after the small: a row of both takes the full size */
.zone:has(> .knob-row .knob:not(.sm)) > .knob-row .knob.sm { margin: calc((var(--kslot) - var(--kd)) / 2) 0; }
.knob-label { font-family: var(--silk); font-size: var(--fs-label); letter-spacing: 0.14em; text-indent: 0.14em; text-transform: uppercase; line-height: 1.2; color: var(--ink-dim); text-shadow: var(--engrave); text-align: center; white-space: nowrap; }

/* ---------- LEDs ---------- */
.led { display: inline-block; width: 12px; height: 12px; background: var(--led-off) center / 100% 100% no-repeat; }
.led.on { background-image: var(--led-on); border-radius: 50%; box-shadow: 0 0 7px 1px var(--accent); }
/* the LED on a checked radio's key (CRT channels, programs). Declared here on purpose: WebKit resolves a
   url() carried by a variable against the stylesheet that consumes it, so a page-level rule would
   look for the sprite next to the page. */
body:has(#ch1:checked) label[for="ch1"] .led, body:has(#ch2:checked) label[for="ch2"] .led, body:has(#ch3:checked) label[for="ch3"] .led, body:has(#ch4:checked) label[for="ch4"] .led, body:has(#pg1:checked) label[for="pg1"] .led, body:has(#pg2:checked) label[for="pg2"] .led, body:has(#pg3:checked) label[for="pg3"] .led, body:has(#pg4:checked) label[for="pg4"] .led, body:has(#pg5:checked) label[for="pg5"] .led, body:has(#pg6:checked) label[for="pg6"] .led, body:has(#pg7:checked) label[for="pg7"] .led, body:has(#pg8:checked) label[for="pg8"] .led, body:has(#pg9:checked) label[for="pg9"] .led, body:has(#pg10:checked) label[for="pg10"] .led { background-image: var(--led-on); border-radius: 50%; box-shadow: 0 0 7px 1px var(--accent); }

/* ---------- rendered hardware parts ---------- */
.jack, .xlr, .trim, .toggle, .rocker, .iec, .grille, .talk, .reel, .headblock, .vent { display: block; flex: none; background: center / 100% 100% no-repeat; }
.jack { width: min(28px, calc(var(--u) * 0.22)); aspect-ratio: 1; background-image: url(img/parts/jack.png); }
.port .jack { width: min(36px, calc(var(--u) * 0.28)); }
.jack.cv { width: min(22px, calc(var(--u) * 0.17)); background-image: url(img/parts/jack-cv.png); }
.xlr { width: min(40px, calc(var(--u) * 0.31)); aspect-ratio: 1; background-image: url(img/parts/xlr.png); }
.trim { width: 14px; height: 14px; background-image: url(img/parts/trimpot.png); }
.toggle { width: min(20px, calc(var(--u) * 0.155)); aspect-ratio: 20 / 36; background-image: url(img/parts/toggle.png); }
.rocker { width: 26px; height: 40px; background-image: url(img/parts/rocker.png); }
.iec { width: 46px; height: 34px; background-image: url(img/parts/iec.png); }
.grille { width: min(100px, calc(var(--u) * 0.78)); aspect-ratio: 1; background-image: url(img/parts/grille.png); }
.grille.sm { width: min(40px, calc(var(--u) * 0.31)); }
.vent { height: 20px; background: url(img/parts/vent.png) 0 0 / 64px 20px repeat-x; }
.talk { width: min(120px, calc(var(--u) * 0.92)); aspect-ratio: 1; display: grid; place-items: center; background-image: url(img/parts/talk.png); font-family: var(--silk); font-size: max(var(--fs-label), min(calc(var(--u) * 0.08), 11px)); letter-spacing: 0.2em; text-indent: 0.2em; text-transform: uppercase; text-decoration: none; color: #3a0d09; transition: transform 0.08s, filter 0.2s; }
.talk:hover { filter: brightness(1.08) drop-shadow(0 0 18px rgba(255, 190, 70, 0.7)); }
.talk:active { transform: scale(0.97); }

/* pads */
.pads { display: grid; grid-template-columns: repeat(2, calc(var(--u) * 0.36)); gap: calc(var(--u) * 0.05); }
.pads i { display: block; height: calc(var(--u) * 0.36); border: 12px solid transparent; border-image: url(img/parts/pad.png) 24 fill / 12px; transition: box-shadow 0.18s; }
.pads i.hit { border-image-source: url(img/parts/pad-lit.png); box-shadow: 0 0 16px 2px var(--accent); transition: none; }

/* SP-16 sampler pads: a 4x4 bank of the same rubber, each printed with its number and its sound */
.spads { display: grid; grid-template-columns: repeat(4, calc(var(--u) * 0.4)); gap: calc(var(--u) * 0.05); }
.spad { position: relative; display: grid; align-items: end; justify-items: center; height: calc(var(--u) * 0.4); padding: 0 0 4px; margin: 0; border: 12px solid transparent; border-image: url(img/parts/pad.png) 24 fill / 12px; background: none; cursor: pointer; font-family: var(--silk); font-size: var(--fs-label); letter-spacing: 0.08em; text-transform: uppercase; color: #d9d7d0; text-shadow: 0 1px 0 rgba(0, 0, 0, 0.8); transition: box-shadow 0.18s; touch-action: none; -webkit-user-select: none; user-select: none; }
.spad::before { content: attr(data-n); position: absolute; top: -7px; left: -5px; font-size: calc(var(--fs-label) * 0.9); color: #9c9a93; }
.spad::after { content: attr(data-l); max-width: calc(100% + 8px); overflow: hidden; white-space: nowrap; } /* the print may reach the cap's flat top, never its bevel */
.spad.sel { box-shadow: 0 0 0 2px var(--accent); }
.spad.hit { border-image-source: url(img/parts/pad-lit.png); box-shadow: 0 0 16px 2px var(--accent); transition: none; }
.spad:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
#sampler.drop { outline: 2px dashed var(--accent); outline-offset: -8px; }
#sampler .steprow .track { grid-template-columns: calc(var(--u) * 0.46) minmax(0, 1fr); }
/* the sample editor is a grid of rows: readout, waveform, controls; the waveform takes whatever height the pads leave,
   so the canvas never sets the row height (a column flex would size it from the canvas's own 640x150) */
#sampler .z-edit > .stack { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; flex: 1 1 auto; min-height: 0; }
.screen.wave { position: relative; min-height: calc(var(--u) * 0.5); padding: 4px; overflow: hidden; }
.screen.wave canvas { position: absolute; inset: 4px; width: calc(100% - 8px); height: calc(100% - 8px); }
/* the project name is typed straight into its readout */
input.lcd { -webkit-appearance: none; appearance: none; box-sizing: content-box; margin: 0; border-radius: inherit; font: inherit; font-family: var(--lcd-font); font-size: max(16px, calc(var(--u) * 0.17)); color: inherit; text-transform: uppercase; outline: none; min-width: 0; }
input.lcd:focus { box-shadow: 0 0 0 2px var(--accent); }
.keyrow.song .key.cur { box-shadow: 0 0 0 1px var(--accent), 0 0 8px var(--accent); }

/* faders */
.fader {
  position: relative;
  --pos: 40%;
  width: 12px;
  height: calc(var(--u) * 0.9);
  margin: 0 auto;
  border-style: solid;
  border-width: 12px 0;
  border-image: url(img/parts/fader-slot.png) 24 0 fill / 12px 0;
}
.fader::before {
  content: "";
  position: absolute;
  left: -14px;
  right: -14px;
  top: 0;
  bottom: 0;
  background: repeating-linear-gradient(180deg, var(--ink-dim) 0 1px, transparent 1px 10px);
  -webkit-mask: linear-gradient(90deg, #000 0 7px, transparent 7px calc(100% - 7px), #000 calc(100% - 7px));
  mask: linear-gradient(90deg, #000 0 7px, transparent 7px calc(100% - 7px), #000 calc(100% - 7px));
  opacity: 0.6;
}
.fader::after {
  content: "";
  position: absolute;
  left: 50%;
  top: var(--pos);
  width: 34px;
  height: 20px;
  margin: -10px 0 0 -17px;
  background: url(img/parts/fader-cap.png) center / 100% 100% no-repeat;
}

/* reels and tape: a real reel-to-reel face */
.reel { --rd: calc(var(--u) * 1.55); width: var(--rd); height: var(--rd); background-image: url(img/parts/reel.png); }
.reel.sm { --rd: calc(var(--u) * 0.72); background-image: url(img/parts/reel-sm.png); }
.headblock { width: calc(var(--u) * 1.1); height: calc(var(--u) * 0.48); background-image: url(img/parts/headblock.png); }
.tape { position: relative; flex: none; width: calc(var(--u) * 3.5); min-height: 0; }
.tape .reel { position: absolute; top: 0; }
.tape .reel.l { left: 0; }
.tape .reel.r { right: 0; }
.tape .headblock { position: absolute; left: 50%; bottom: 0; transform: translateX(-50%); }
.tape svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.tape path { fill: none; stroke: #3b2515; stroke-width: 3; }
.tape .hi { stroke: rgba(255, 255, 255, 0.18); stroke-width: 1; }
.echo-tape { display: flex; align-items: center; gap: calc(var(--u) * 0.1); }
.spin .reel { animation: reel 1.6s linear infinite; }
.spin .reel + .reel, .spin .reel.r { animation-duration: 2.1s; }
@keyframes reel { to { transform: rotate(360deg); } }

/* analogue VU meter: rendered dial, a needle, glass */
.vumeter {
  position: relative;
  --needle: -40deg;
  width: calc(var(--u) * 0.98);
  aspect-ratio: 1.8;
  overflow: hidden;
  border: 6px solid transparent;
  border-image: url(img/parts/bezel.png) 16 fill / 6px;
  background: url(img/parts/vu-face.png) center / 100% 100% no-repeat;
}
.vumeter::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -36%;
  width: 2px;
  height: 118%;
  margin-left: -1px;
  background: #1a1a1a;
  transform-origin: 50% 100%;
  transform: rotate(var(--needle));
  box-shadow: 1px 0 1px rgba(0, 0, 0, 0.3);
  transition: transform 0.12s;
}
.vumeter::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: url(img/parts/crt-glass.png) center / 100% 100% no-repeat;
  opacity: 0.55;
  pointer-events: none;
}

/* bar-graph meters */
.vu { display: flex; gap: 4px; align-items: stretch; height: calc(var(--u) * 0.16); }
.vu i { width: 8px; background: rgba(0, 0, 0, 0.55); border-radius: 1px; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.7); }
.vu i.on { background: var(--green); box-shadow: 0 0 6px var(--green); }
.vu i.on.hot { background: var(--amber); box-shadow: 0 0 6px var(--amber); }
.vu i.on.clip { background: var(--red); box-shadow: 0 0 6px var(--red); }

/* ---------- CRT: a curved tube in a plastic housing ---------- */
.crt, .monitor {
  position: relative;
  flex: none;
  height: 100%;
  margin: 0;
  border: var(--bz) solid transparent;
  border-image: url(img/parts/crt-bezel.png) 48 fill / var(--bz);
  border-radius: calc(var(--bz) * 0.354); /* the bezel's own rounding, so a shadow or a glow follows the corner */
  background: #040506; /* clipped to the rounded box above: the bezel's corners are see-through, and a lit wall showed the box's own square corner there */
}
.crt { aspect-ratio: 4 / 3; }
#monitor .crt { aspect-ratio: 16 / 9; }
#monitor .tube::after { background-image: url(img/parts/crt-glass-wide.png), repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.26) 0 1px, transparent 1px 3px); }
.tube {
  position: absolute;
  inset: -5px;
  overflow: hidden;
  border-radius: 9% / 11%;
  background: radial-gradient(ellipse at 50% 45%, #0c0e10, #040506 72%);
}
.tube::after, .monitor::after {
  content: "";
  position: absolute;
  inset: -5px;
  z-index: 3;
  border-radius: 9% / 11%;
  background: url(img/parts/crt-glass.png) center / 100% 100% no-repeat, repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.26) 0 1px, transparent 1px 3px);
  pointer-events: none;
}
.tube::after { inset: 0; }
.monitor img { position: absolute; inset: -5px; width: calc(100% + 10px); height: calc(100% + 10px); object-fit: cover; border-radius: 9% / 11%; }
.monitor { width: calc(var(--u) * 3.53); }
.u3 .monitor { width: calc(var(--u) * 2.53); }
.u2 .monitor { width: calc(var(--u) * 1.53); }
.u2 .monitor.wide { width: calc(var(--u) * 2.72); }
.ch { position: absolute; inset: 0; display: none; clip-path: inset(0 round 9% / 11%); } /* the glass has round corners and the picture ends at them: the corners stay black. The overflow clip above does not reach a composited iframe in WebKit; this cut does */
.ch.on { display: block; }
/* phosphor trace */
.scope { width: 100%; height: 100%; }
.scope path { fill: none; stroke: var(--phosphor); stroke-width: 2.2; stroke-linecap: round; filter: drop-shadow(0 0 4px rgba(124, 255, 154, 0.9)); }
.scope .thin { stroke-width: 1.2; opacity: 0.7; }
.scope .grid { stroke: rgba(124, 255, 154, 0.18); stroke-width: 1; filter: none; }
.sweep { animation: sweep 2.6s linear infinite; animation-play-state: paused; }
@keyframes sweep { to { transform: translateX(-400px); } }
/* colour bars */
.bars { background: linear-gradient(90deg, #c0c0c0 0 14.28%, #c0c000 0 28.57%, #00c0c0 0 42.85%, #00c000 0 57.14%, #c000c0 0 71.42%, #c00000 0 85.71%, #0000c0 0); }
.bars::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 28%; background: linear-gradient(90deg, #0000c0 0 14.28%, #131313 0 28.57%, #c000c0 0 42.85%, #131313 0 57.14%, #00c0c0 0 71.42%, #131313 0 85.71%, #c0c0c0 0); }
/* static / no signal */
.static { background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='1' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 .7  0 0 0 0 .7  0 0 0 0 .7  0 0 0 1 0'/></filter><rect width='160' height='160' filter='url(%23n)'/></svg>"); animation: snow 0.14s steps(3) infinite; }
@keyframes snow { 0% { background-position: 0 0; } 100% { background-position: 80px 60px; } }
.static b { position: absolute; left: 8%; bottom: 10%; font-family: var(--lcd-font); font-size: calc(var(--u) * 0.16); font-weight: 400; color: #fff; text-shadow: 0 0 6px #fff; }
/* phosphor text */
.ptext { padding: 7% 8%; font-family: var(--lcd-font); font-size: calc(var(--u) * 0.15); line-height: 1.25; color: var(--phosphor); text-shadow: 0 0 6px rgba(124, 255, 154, 0.8); white-space: pre-line; }
.ptext::after { content: "_"; animation: blink 1s steps(2) infinite; }
/* a menu card line that leads somewhere is a key, a link or a button: the same phosphor print, lit on hover */
.ptext .pline { display: inline; margin: -7px 0; padding: 7px 0; border: 0; background: none; font: inherit; line-height: inherit; color: inherit; text-shadow: inherit; text-decoration: none; cursor: pointer; }
.ptext .pline:hover, .ptext .pline:focus-visible { color: #d8ffe0; text-shadow: 0 0 9px rgba(124, 255, 154, 1); outline: none; }
@keyframes blink { 50% { opacity: 0; } }
.chans { display: grid; gap: 5px; }
.chans .tbtn { width: calc(var(--u) * 0.3); height: calc(var(--u) * 0.22); }

/* ---------- panel keys: small caps with an LED (TASCAM style) ---------- */
.key {
  position: relative;
  display: inline-grid;
  place-items: center;
  place-content: center;
  flex: none;
  width: calc(var(--u) * 0.2);
  height: calc(var(--u) * 0.17);
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: url(img/parts/key.png) center / 100% 100% no-repeat;
  font: inherit;
  color: #1a1b1e;
  cursor: pointer;
  user-select: none;
  transition: transform 0.05s, filter 0.05s;
}
.key.dark { background-image: url(img/parts/key-dark.png); color: #e8e8e4; }
.key.rec { background-image: url(img/parts/key-rec-off.png); }
.key.rec.on, .key.rec:has(.led.on) { background-image: url(img/parts/key-rec.png); }
.key .led { width: 7px; height: 7px; }
.key:active { transform: translateY(1px); filter: brightness(0.94); }
.key.on { box-shadow: 0 0 0 1px var(--accent), 0 0 8px var(--accent); }
.keycell { display: grid; justify-items: center; gap: 3px; text-decoration: none; }
.keycell small { font-family: var(--silk); font-size: var(--fs-label); letter-spacing: 0.14em; text-indent: 0.14em; text-transform: uppercase; line-height: 1.2; color: var(--ink-dim); text-shadow: var(--engrave); white-space: nowrap; }
.keyrow { display: flex; gap: calc(var(--u) * 0.05); align-items: flex-end; flex-wrap: wrap; justify-content: center; }
.keyrow > .keycell, .keyrow > .key { flex: none; }
.keyrow.grid2 { display: grid; grid-template-columns: auto auto; }
.keypair { display: flex; gap: 4px; }
.keygrid { display: grid; grid-template-columns: repeat(3, auto); gap: 5px calc(var(--u) * 0.06); justify-items: center; }
.keygrid.c5 { grid-template-columns: repeat(5, auto); gap: 8px calc(var(--u) * 0.08); }
.keygrid.c4 { grid-template-columns: repeat(4, auto); gap: 8px calc(var(--u) * 0.08); }
.keycell small { max-width: max(calc(var(--u) * 0.8), 9.6em); overflow: hidden; text-overflow: ellipsis; } /* the cap never drops below the print: text bottoms out at 7.5px while U keeps shrinking */
.zone[data-label="Credits"] .keycell small, .zone[data-label="Follow"] .keycell small { max-width: none; } /* credit and follow keys carry whole words */

/* step sequencer: 16 keys, beat markers dark, the running step lit */
.steps16 { display: grid; grid-template-columns: repeat(16, calc(var(--u) * 0.2)); gap: calc(var(--u) * 0.03); justify-items: center; }
.steps16.wide { grid-template-columns: repeat(16, auto); justify-content: space-between; gap: calc(var(--u) * 0.035); }
.steps16 .key:nth-child(4n + 1) { background-image: url(img/parts/key-dark.png); }
.steps16 .key.cur { box-shadow: 0 0 0 1px var(--accent), 0 0 8px var(--accent); }
/* a drum track: the three sound keys carry the track's name under them the way each knob carries its own, the keys' slot
   the knob's height so the keys sit level with the knob caps and the two kinds of name share a line; then the steps.
   --tk is the track's knob size, set once per width here and read by the knobs and the keys' slot alike */
.track { --tk: min(40px, calc(var(--u) * 0.27)); display: grid; grid-template-columns: auto auto minmax(0, 1fr); align-items: center; gap: calc(var(--u) * 0.1); }
.tname { font-family: var(--silk); font-size: var(--fs-label); letter-spacing: 0.14em; text-transform: uppercase; line-height: 1.2; color: var(--ink); text-shadow: var(--engrave); }
.sound-cell { display: grid; justify-items: center; gap: 0.3em; }
.sound-cell .sounds { min-height: var(--tk); align-items: center; flex-wrap: nowrap; }
.sound-cell .tname { text-indent: 0.14em; text-align: center; white-space: nowrap; }
.tracks { display: grid; gap: calc(var(--u) * 0.04); }

/* channel strips: one per track, like a multitrack face */
.strips { display: flex; gap: calc(var(--u) * 0.04); justify-content: space-between; }
#credits .row > .zone:first-child { flex: 0 0 auto; }
#credits .row > .zone.fix { flex: 1 1 0; min-width: 0; }
#credits .hrow { flex-wrap: wrap; }
#credits .jog { width: calc(var(--u) * 0.82); }
#credits .row > .zone[data-label="Select program"] { flex: 0 0 auto; }
#credits .row > .zone[data-label="Program"] { flex: 1 1 0; min-width: 0; }
/* the browse dial sits with the keys; the display takes the rest of the face */
#credits .hrow.cue { gap: calc(var(--u) * 0.18); align-items: center; }
#credits .hrow.cue .knob-cell { min-width: 0; }
/* program keys: broadcast-size caps so the matrix fills the face */
.keygrid.lg { gap: calc(var(--u) * 0.14) calc(var(--u) * 0.1); }
.keygrid.lg .key, .key.lg { width: calc(var(--u) * 0.56); height: calc(var(--u) * 0.34); border-radius: 6px; background-image: url(img/parts/key-wide.png); }
.keygrid.lg .key .led, .key.lg .led { width: 9px; height: 9px; }
.keygrid.lg .keycell { gap: 6px; }
.keygrid.lg .keycell small { max-width: max(calc(var(--u) * 0.86), 11.5em); }
#reader .keyrow { gap: calc(var(--u) * 0.1); }
#credits .screen { overflow: hidden; flex: 1 1 auto; min-height: 0; }
#credits .zone.fix { display: flex; flex-direction: column; }
.strip { display: grid; justify-items: center; align-content: start; gap: 5px; width: calc(var(--u) * 0.54); padding: 4px 0; border-left: 1px solid var(--ink-line); }
.strip:first-child { border-left: 0; }
.strip .num { font-family: var(--silk); font-size: var(--fs-label); color: var(--ink-dim); text-shadow: var(--engrave); }
.strip h3 { font-size: clamp(8.5px, calc(var(--u) * 0.08), 10.5px); transform: none; padding: 0.1em 0.3em; border-width: 0 6px; border-image-width: 0 6px; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.strip .fader { height: calc(var(--u) * 0.78); }

/* one-octave keyboard */
.keyboard { position: relative; display: flex; flex: none; height: calc(var(--u) * 0.72); width: calc(var(--u) * 3.0); }
.wk { flex: 1; margin: 0; padding: 0; background: linear-gradient(180deg, #f6f6f3, #dadad5); border: 1px solid #6b6b68; border-radius: 0 0 4px 4px; box-shadow: inset 0 -4px 0 rgba(0, 0, 0, 0.12), inset 1px 0 0 rgba(255, 255, 255, 0.6); cursor: pointer; }
.bk { position: absolute; top: 0; width: 7.6%; height: 60%; margin: 0; padding: 0; background: linear-gradient(180deg, #2c2d30, #0b0b0c); border: 1px solid #000; border-radius: 0 0 3px 3px; box-shadow: 0 3px 4px rgba(0, 0, 0, 0.6), inset 0 -4px 0 #3a3b3f; cursor: pointer; z-index: 2; }
.bk.p1 { left: 8.7%; } .bk.p2 { left: 21.2%; } .bk.p4 { left: 46.2%; } .bk.p5 { left: 58.7%; } .bk.p6 { left: 71.2%; }
.wk.on { background: linear-gradient(180deg, #ffe3a0, #ffc85c); }
.bk.on { background: linear-gradient(180deg, #ffb64a, #c77a10); }

/* cassette behind the deck window, hubs turn while playing */
.cassette { position: relative; flex: none; width: calc(var(--u) * 1.86); aspect-ratio: 2.4; background: url(img/parts/cassette-window.png) center / 100% 100% no-repeat; }
.cassette.lg { width: calc(var(--u) * 2.4); }
.hub { position: absolute; top: 56%; width: 9.2%; aspect-ratio: 1; translate: -50% -50%; background: url(img/parts/hub.png) center / 100% 100% no-repeat; }
.hub.l { left: 37.1%; }
.hub.r { left: 62.9%; }
@keyframes hubspin { to { rotate: 360deg; } }
body.is-playing .hub, body:has(#play:checked) .hub { animation: hubspin 1.5s linear infinite; }
body.is-playing .hub.r, body:has(#play:checked) .hub.r { animation-duration: 2.2s; }
.jog { --rot: 0deg; flex: none; width: calc(var(--u) * 0.62); aspect-ratio: 1; background: url(img/parts/jog.png) center / 100% 100% no-repeat; transform: rotate(var(--rot)); cursor: grab; touch-action: none; }
.cues li.sel { color: #fff; text-shadow: 0 0 6px currentColor; }
.strip.sel h3 { box-shadow: 0 0 0 1px var(--accent), 0 0 8px var(--accent); }
.lamp { display: inline-grid; place-items: center; place-content: center; width: calc(var(--u) * 0.64); height: calc(var(--u) * 0.26); padding: 0; border: 0; border-radius: 5px; background: url(img/parts/lamp-off.png) center / 100% 100% no-repeat; font-family: "Barlow", Arial, sans-serif; font-weight: 600; font-size: max(8.5px, calc(var(--u) * 0.072)); letter-spacing: 0.08em; text-indent: 0.08em; line-height: 1; text-transform: uppercase; white-space: nowrap; color: #c98f8a; }
.lamp.on { background-image: url(img/parts/lamp-on.png); color: #fff6f0; text-shadow: 0 0 6px #fff; }

/* stacked rows inside a tall unit */
.rows { display: flex; flex: 1 1 auto; flex-direction: column; min-height: 0; gap: calc(var(--u) * 0.1); }
.rows > .row { flex: 1 1 0; }
.rows > .row.fixrow, .rows > .fixrow { flex: 0 0 auto; }
.pattern-row { justify-content: center; }
.tracks .knob.sm { --kd: var(--tk); }
.rows > .tracks { flex: 1 1 auto; align-content: space-evenly; }
.row.intro { position: relative; }
/* the display ends where it used to; the print laps over its right edge by about half a unit */
.row.intro > .stack { flex: 0 0 calc(100% - var(--u) * 2.35); min-width: 0; }
.row.intro .screen { padding-right: calc(var(--u) * 0.6); }
.row.intro .screen p { font-size: var(--fs-hero); line-height: 1.6; max-width: 78ch; }
.row.intro .screen .menu a { margin: 0 0.15em; }
/* the print's borders are set in rack units: percentage padding on a flex item would resolve against the row, not the print */
.polaroid { position: absolute; right: calc(var(--u) * 0.1); top: 50%; z-index: 2; width: calc(var(--u) * 2.7); margin: 0; padding: calc(var(--u) * 0.14) calc(var(--u) * 0.14) calc(var(--u) * 0.56); background: #f3efe6; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06), 0 1px 0 rgba(255, 255, 255, 0.08), 0 8px 18px rgba(0, 0, 0, 0.5); transform: translateY(-50%) rotate(-3deg); }
.polaroid img { display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; }
.polaroid::before { content: ""; position: absolute; left: 50%; top: calc(var(--u) * -0.1); z-index: 2; width: calc(var(--u) * 1.2); height: calc(var(--u) * 0.28); transform: translateX(-50%) rotate(-3deg); background: url(img/parts/tape.png) center / 100% 100% no-repeat; pointer-events: none; }
.rows > .row.fixrow > .zone { padding-top: calc(var(--u) * 0.16); padding-bottom: calc(var(--u) * 0.08); }
.hrow { display: flex; align-items: center; gap: calc(var(--u) * 0.1); }
/* a control group: cells on one wrapping line. Every cell is a fixed-height part line with its legend on the
   line beneath, so parts of any size share one centre line and all legends share one baseline. A bare
   display or title goes in a .cell so it sits on the part line too. Groups side by side align because
   every cell on the rack uses the same --line. */
.cells { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: center; gap: 3px calc(var(--u) * 0.12); }
.cells > :is(.keycell, .knob-cell, .vcr-cell, .cell) { display: grid; grid-template-rows: var(--line) auto; align-items: center; justify-items: center; gap: 3px; width: auto; min-width: calc(var(--u) * 0.22); }
.cells > :is(.keycell, .knob-cell, .vcr-cell) > :is(small, .knob-label) { align-self: start; }
/* a display sharing a line with controls is as tall as that line */
.cells > .cell > .lcd { height: calc(var(--line) - 12px); padding: 0 0.5em; display: inline-flex; align-items: center; }
.cells.tapeline { --line: calc(var(--u) * 0.46); column-gap: 4px; justify-content: center; }
#monitor .zone[data-label="Tape"] { flex: 1 1 auto; min-width: 0; padding-inline: calc(var(--u) * 0.08); } /* five keys and their readout on one line: the zone takes what the row has left, and keeps its sides lean */
@media (max-width: 420px) { #monitor .zone[data-label="Tape"] { flex-basis: 100%; } #monitor .vcr-cell small { font-size: 8px; letter-spacing: 0.06em; text-indent: 0.06em; } } /* a phone: the tape zone takes the row, the main zone goes under, the key legends set tighter */
.cells.tapeline > .cell { display: block; flex: 1 1 100%; margin: 6px 0 0; } /* the readout takes a line of its own under the keys, as wide as their row */
.cells.tapeline .lcd { display: block; width: auto; box-sizing: border-box; text-align: center; }
.cells > .brk { display: none; }
.hrow.stretch { align-items: stretch; flex: 1 1 auto; min-height: 0; }
.screen.curve { flex: 1 1 auto; padding: 4px; }
.screen.curve canvas { display: block; width: 100%; height: 100%; }
.vu.gr i.on { background: var(--red); box-shadow: 0 0 6px var(--red); }
.rearstack { gap: calc(var(--u) * 0.14); flex: 1 1 auto; min-width: 0; }
.rear-side { flex: none; }
.rearstack .ports { gap: calc(var(--u) * 0.1); }
.port.deco { cursor: default; }
.sticker.warn { align-self: center; background: #f0c419; color: #1a1a1a; font-family: var(--silk); font-size: var(--fs-label); letter-spacing: 0.1em; padding: 0.5em 0.8em; transform: rotate(0.6deg); }
/* sub-panels on big units are bolted on */
.u3 .zone::after, .u4 .zone::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    url(img/parts/screw.png) 3px 3px / 10px 10px no-repeat,
    url(img/parts/screw.png) calc(100% - 3px) 3px / 10px 10px no-repeat,
    url(img/parts/screw.png) 3px calc(100% - 3px) / 10px 10px no-repeat,
    url(img/parts/screw.png) calc(100% - 3px) calc(100% - 3px) / 10px 10px no-repeat;
}
.vu.sm { height: calc(var(--u) * 0.1); gap: 3px; } .vu.sm i { width: 6px; }
.vu.v { flex-direction: column-reverse; height: auto; width: 8px; } .vu.v i { width: 8px; height: 5px; }

/* ---------- program display (VFD) ---------- */
.vfd { display: flex; flex-direction: column; justify-content: flex-start; gap: 0.3em; padding-top: calc(var(--u) * 0.12); font-family: var(--lcd-font); line-height: 1.1; }
.vfd .pg { display: none; }
.vfd .pg.on { display: block; }
.vfd b { display: block; margin-bottom: 0.35em; font-weight: 400; font-size: calc(var(--u) * 0.24); text-transform: uppercase; letter-spacing: 0.04em; text-shadow: var(--scr-glow); }
.vfd span { display: block; font-size: calc(var(--u) * 0.2); opacity: 0.9; }
.vfd em { display: block; margin-top: 0.3em; font-style: normal; font-size: calc(var(--u) * 0.15); opacity: 0.65; letter-spacing: 0.08em; text-transform: uppercase; }
/* a page of programs: one line each, the award in small print on the line */
.vfd ul { list-style: none; margin: 0; padding: 0; }
.vfd li { font-size: calc(var(--u) * 0.158); line-height: 1.32; opacity: 0.92; }
.vfd li + li { margin-top: 0.22em; }
.vfd li em { display: inline; margin: 0 0 0 0.6em; font-style: normal; font-size: 0.78em; opacity: 0.6; letter-spacing: 0.06em; text-transform: uppercase; }
.vfd .pgnum { position: absolute; right: calc(var(--u) * 0.14); top: calc(var(--u) * 0.1); font-size: calc(var(--u) * 0.15); opacity: 0.6; letter-spacing: 0.1em; }

/* ---------- tape library: a post per cassette ---------- */
.slots { display: flex; gap: calc(var(--u) * 0.12); align-items: stretch; flex: 1 1 auto; min-height: 0; }
.slot { position: relative; flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: calc(var(--u) * 0.06); padding: calc(var(--u) * 0.16) calc(var(--u) * 0.1) calc(var(--u) * 0.1); border: 1px solid var(--ink-line); border-radius: 5px; }
.slot .cassette { width: 70%; align-self: center; }
.slot .screen { padding: calc(var(--u) * 0.06) calc(var(--u) * 0.1); flex: 1 1 auto; min-height: 0; overflow: hidden; }
.slot .label { position: absolute; left: 14%; right: 14%; top: calc(var(--u) * 0.16 + 100% * 0); }
.slot h3 { position: absolute; left: 50%; transform: translate(-50%, 0) rotate(-0.5deg); top: calc(var(--u) * 0.16 + (100% - var(--u) * 0.16) * 0.06); max-width: 70%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: clamp(11px, calc(var(--u) * 0.1), 14px); z-index: 2; }
.slot .cells.meta { --line: calc(var(--u) * 0.34); justify-content: space-between; }
.slot .screen p { font-size: clamp(11.5px, calc(var(--u) * 0.1), 13.5px); line-height: 1.4; }
.reader { flex: 1 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--scr-ink) transparent; }
.reader h1 { font-family: var(--lcd-font); font-weight: 400; font-size: calc(var(--u) * 0.28); color: inherit; text-shadow: var(--scr-glow); margin-bottom: 0.4em; }
.reader p { font-size: var(--fs-body); line-height: 1.55; margin-bottom: 0.8em; max-width: 70ch; }
.reader p:last-child { margin-bottom: 0; }

/* ---------- light behaves like light: lit parts spill onto the plate around them ---------- */
.led.on { box-shadow: 0 0 7px 1px var(--accent), 0 0 18px 4px color-mix(in srgb, var(--accent) 35%, transparent); }
h4::after { box-shadow: 0 0 8px 1px var(--accent), 0 0 20px 5px color-mix(in srgb, var(--accent) 30%, transparent); }
.lamp.on { box-shadow: 0 0 24px 6px rgba(255, 60, 40, 0.35); }
.lcd, h2 { box-shadow: 0 0 18px 2px color-mix(in srgb, var(--scr-ink) 22%, transparent); }
.screen { box-shadow: 0 0 28px 4px color-mix(in srgb, var(--scr-ink) 16%, transparent); }
.vumeter { box-shadow: 0 0 16px 2px rgba(255, 220, 150, 0.22); }
.pads i.hit, .spad.hit { box-shadow: 0 0 16px 2px var(--accent), 0 0 34px 8px color-mix(in srgb, var(--accent) 30%, transparent); }
.key.on, .tbtn.on, .vkey.on { box-shadow: 0 0 0 1px var(--accent), 0 0 10px var(--accent), 0 0 22px 4px color-mix(in srgb, var(--accent) 30%, transparent); }
.talk { filter: drop-shadow(0 0 22px rgba(255, 190, 70, 0.55)); }

/* low light: the room lights go down, the gear keeps its own light. body:has(#lights-low:checked) or .lowlight */
:is(.lowlight, body:has(#lights-low:checked)) { background: #050506; }
:is(.lowlight, body:has(#lights-low:checked)) .page-section { --ink: #f2f0ea; --ink-dim: #dfe2e6; --ink-line: rgba(242, 240, 234, 0.16); --engrave: 0 1px 0 rgba(0, 0, 0, 0.75); --scale: url(img/parts/scale-light.png); --link: #ffcf6b; background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), var(--sheen), var(--tex) 0 0 / 256px 256px repeat; }
/* pseudo-elements cannot sit inside :is(): CSS drops them silently, so each one is written out */
:is(.lowlight, body:has(#lights-low:checked)) .page-section::before,
:is(.lowlight, body:has(#lights-low:checked)) .page-section::after,
:is(.lowlight, body:has(#lights-low:checked)) .rack::before,
:is(.lowlight, body:has(#lights-low:checked)) .rack::after,
:is(.lowlight, body:has(#lights-low:checked)) .handle { filter: brightness(0.4); }
:is(.lowlight, body:has(#lights-low:checked)) :is(h4, h1, h3, .knob-label, .keycell small, .tname, .port-label, .brand-name, .vcr-cell small, .foot),
:is(.lowlight, body:has(#lights-low:checked)) .zone::before,
:is(.lowlight, body:has(#lights-low:checked)) .pgroup::before { opacity: 0.9; }
:is(.lowlight, body:has(#lights-low:checked)) :is(.knob, .key, .tbtn, .btn, .vkey, .jack, .xlr, .trim, .toggle, .rocker, .iec, .grille, .reel, .headblock, .vent, .fader, .jog, .sticker, .pads i:not(.hit), .cassette) { filter: brightness(0.45); }
:is(.lowlight, body:has(#lights-low:checked)) .logo .k { opacity: 0.6; }
:is(.lowlight, body:has(#lights-low:checked)) .logo .seg.on { filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.35)); }
:is(.lowlight, body:has(#lights-low:checked)) :is(.key.on, .tbtn.on, .vkey.on, .rocker) { filter: brightness(0.75); }
:is(.lowlight, body:has(#lights-low:checked)) .zone { border-color: rgba(255, 255, 255, 0.06); box-shadow: none; }
:is(.lowlight, body:has(#lights-low:checked)) .monitor img { filter: brightness(0.85); }
:is(.lowlight, body:has(#lights-low:checked)) .polaroid { filter: brightness(0.55); }
:is(.lowlight, body:has(#lights-low:checked)) :is(.lcd, h2) { box-shadow: 0 0 26px 4px color-mix(in srgb, var(--scr-ink) 32%, transparent); }
:is(.lowlight, body:has(#lights-low:checked)) .screen { box-shadow: 0 0 44px 8px color-mix(in srgb, var(--scr-ink) 24%, transparent); }
:is(.lowlight, body:has(#lights-low:checked)) .tube { box-shadow: 0 0 60px 12px rgba(220, 235, 255, 0.14); }
:is(.lowlight, body:has(#lights-low:checked)) .led.on { box-shadow: 0 0 8px 2px var(--accent), 0 0 28px 8px color-mix(in srgb, var(--accent) 45%, transparent); }
:is(.lowlight, body:has(#lights-low:checked)) h4::after { box-shadow: 0 0 10px 2px var(--accent), 0 0 30px 8px color-mix(in srgb, var(--accent) 40%, transparent); }
:is(.lowlight, body:has(#lights-low:checked)) .vumeter { filter: brightness(0.9); box-shadow: 0 0 26px 4px rgba(255, 200, 120, 0.3); }
:is(.lowlight, body:has(#lights-low:checked)) body::after, :is(.lowlight, body:has(#lights-low:checked))::after { opacity: 0.1; }

@keyframes logo-s1 { 0.00%, 12.49% { opacity: 1 } 12.50%, 24.99% { opacity: 1 } 25.00%, 37.49% { opacity: 1 } 37.50%, 49.99% { opacity: 1 } 50.00%, 62.49% { opacity: 1 } 62.50%, 74.99% { opacity: 1 } 75.00%, 87.49% { opacity: 1 } 87.50%, 99.99% { opacity: 1 } }
/* the mark meters the sound on any page: the home's tape (#play) and the pages' players (body.playing) */
body:has(#play:checked) .logo .seg:nth-child(1), body.playing .logo .seg:nth-child(1) { animation: logo-s1 1.36s steps(1, end) infinite; }
@keyframes logo-s2 { 0.00%, 12.49% { opacity: 1 } 12.50%, 24.99% { opacity: 1 } 25.00%, 37.49% { opacity: 1 } 37.50%, 49.99% { opacity: 0.2 } 50.00%, 62.49% { opacity: 1 } 62.50%, 74.99% { opacity: 1 } 75.00%, 87.49% { opacity: 1 } 87.50%, 99.99% { opacity: 0.2 } }
body:has(#play:checked) .logo .seg:nth-child(2), body.playing .logo .seg:nth-child(2) { animation: logo-s2 1.36s steps(1, end) infinite; }
@keyframes logo-s3 { 0.00%, 12.49% { opacity: 1 } 12.50%, 24.99% { opacity: 0.2 } 25.00%, 37.49% { opacity: 1 } 37.50%, 49.99% { opacity: 0.2 } 50.00%, 62.49% { opacity: 1 } 62.50%, 74.99% { opacity: 0.2 } 75.00%, 87.49% { opacity: 1 } 87.50%, 99.99% { opacity: 0.2 } }
body:has(#play:checked) .logo .seg:nth-child(3), body.playing .logo .seg:nth-child(3) { animation: logo-s3 1.36s steps(1, end) infinite; }
@keyframes logo-s4 { 0.00%, 12.49% { opacity: 1 } 12.50%, 24.99% { opacity: 0.2 } 25.00%, 37.49% { opacity: 0.2 } 37.50%, 49.99% { opacity: 0.2 } 50.00%, 62.49% { opacity: 1 } 62.50%, 74.99% { opacity: 0.2 } 75.00%, 87.49% { opacity: 0.2 } 87.50%, 99.99% { opacity: 0.2 } }
body:has(#play:checked) .logo .seg:nth-child(4), body.playing .logo .seg:nth-child(4) { animation: logo-s4 1.36s steps(1, end) infinite; }
@keyframes logo-s5 { 0.00%, 12.49% { opacity: 1 } 12.50%, 24.99% { opacity: 0.2 } 25.00%, 37.49% { opacity: 0.2 } 37.50%, 49.99% { opacity: 0.2 } 50.00%, 62.49% { opacity: 0.2 } 62.50%, 74.99% { opacity: 0.2 } 75.00%, 87.49% { opacity: 0.2 } 87.50%, 99.99% { opacity: 0.2 } }
body:has(#play:checked) .logo .seg:nth-child(5), body.playing .logo .seg:nth-child(5) { animation: logo-s5 1.36s steps(1, end) infinite; }

/* ---------- transport bar: brand, one key bank, one display window, power ---------- */
.deck { --cap-w: max(64px, calc(var(--u) * 0.5)); --cap-h: calc(var(--cap-w) * 0.6); --fs-cap: max(8.5px, calc(var(--cap-w) * 0.14)); position: sticky; top: 0; z-index: 30; display: flex; flex-direction: row; align-items: center; gap: calc(var(--u) * 0.12); user-select: none; -webkit-user-select: none; }
.deck .brand { flex: none; margin-right: auto; }
.deck .brand-name { white-space: nowrap; letter-spacing: 0.16em; }
.deck .rocker { flex: none; margin-left: auto; cursor: pointer; }
.tkeys { display: flex; flex: none; align-items: center; gap: 6px; }
/* every deck cap shares one width: the cap's own, or the room the longest print (MANUAL) needs at the size the browser
   actually draws it, with 0.6em clear on each side. A minimum font size makes the print larger; the caps grow with it */
.tkeys .tbtn, .tkeys .tbtn.wide { width: max(var(--cap-w), 5.6em); height: auto; aspect-ratio: 120 / 72; padding: 0 0.6em; font-size: var(--fs-cap); }
/* cap print: pad-printed caps use a plain bold grotesque, not the wide panel face, so a word sits inside the flat face with a fifth of the cap clear on each side */
.tkeys .tbtn.wide { font-family: "Barlow", Arial, sans-serif; font-weight: 600; font-size: var(--fs-cap); letter-spacing: 0.06em; text-indent: 0.06em; }
/* the deck display is exactly as tall as the caps beside it */
.readout { display: inline-flex; flex: none; align-items: center; box-sizing: border-box; width: auto; height: var(--cap-h); padding: 0 0.3em; }
.readout .f { display: inline-block; box-sizing: content-box; width: var(--w, auto); padding: 0 0.45ch; overflow: hidden; white-space: nowrap; text-align: center; }
.readout .f + .f { border-left: 1px solid color-mix(in srgb, var(--scr-ink) 28%, transparent); }
@media (max-width: 1399px) { .deck .brand-name { display: none; } }
.deck:has(.tkeys:not(.aux):not(.goto) > :nth-child(7)) .brand-name { display: none; } /* a seven-cap deck (the Lab) has no room for the name beside the wind keys at full width: the logo stands alone, as it does below 1400px */
@media (max-width: 1199px) { .deck { --cap-w: 60px; } }
/* the seven-cap deck (the Lab) carries eleven caps: Flip and Reset are the rack's only turn and factory-patch keys, Main and
   Manual its page keys, so none of them ever steps off. From 1000 up the readout takes a row of its own under the caps, so
   the caps row has room at every width whatever size the browser gives the print; below 1000 the deck wraps as it always did */
.deck > .brk { display: none; }
@media (min-width: 1000px) {
  .deck:has(.tkeys:not(.aux):not(.goto) > :nth-child(7)) { flex-wrap: wrap; align-content: center; row-gap: 0; height: auto; }
  .deck:has(.tkeys:not(.aux):not(.goto) > :nth-child(7)) > .brk { display: block; flex: 1 1 100%; height: 0; order: 1; } /* the line break: the readout always opens the second row */
  .deck:has(.tkeys:not(.aux):not(.goto) > :nth-child(7)) .readout { order: 2; flex: none; margin: 8px auto 0; }
}
.tkeys.goto .tbtn { text-decoration: none; }
.rocker.off, body:has(#lights-low:checked) .rocker { background-image: url(img/parts/rocker-off.png); } /* the rocker on the bar is the room's light switch: lights down shows it off */
/* every sound source carries its own mains rocker at the right end of its faceplate: on the nameplate line of a tall unit,
   in line with the controls of a 1U unit. The same part as the rack's master rocker on the transport bar. */
.unit-power { position: absolute; top: calc(var(--pad-y) - var(--u) * 0.02); right: var(--pad-x); z-index: 3; width: calc(var(--u) * 0.2); height: calc(var(--u) * 0.31); margin: 0; padding: 0; border: 0; appearance: none; -webkit-appearance: none; background: url(img/parts/rocker.png) center / 100% 100% no-repeat; cursor: pointer; }
.u1 > .unit-power { position: static; align-self: center; }
.unit-power.off { background-image: url(img/parts/rocker-off.png); }
/* a unit switched off: displays and lamps dark, nameplate LED out, controls still there (sprite variables are
   consumed here, in the stylesheet that declares them, so their urls resolve) */
.dev.off :is(.lcd, .screen, h2, .vu, .vumeter, .seq) { filter: brightness(0.1) saturate(0.2); transition: filter 0.4s; }
.dev.off :is(.key.cur, .wk.on, .bk.on) { box-shadow: none; }
.dev.off .wk.on { background: linear-gradient(180deg, #f6f6f3, #dadad5); }
.dev.off .bk.on { background: linear-gradient(180deg, #2c2d30, #0b0b0c); }
.dev.off h4::after, .dev.dead h4::after { background-image: var(--led-off); box-shadow: none; }
.dev.off .led.on { background-image: var(--led-off); box-shadow: none; }
.dev.off :is(.key.on, .pads i.hit, .spad.hit, .spad.sel) { box-shadow: none; }
.dev.off :is(.key.rec.on, .key.rec:has(.led.on)) { background-image: url(img/parts/key-rec-off.png); }
.dev.off .pads i.hit, .dev.off .spad.hit { border-image-source: url(img/parts/pad.png); }

/* ---------- VCR piano keys ---------- */
.vcr { display: flex; gap: 6px; align-items: flex-end; }
.vkey {
  display: grid;
  place-items: center;
  place-content: center;
  flex: none;
  width: calc(var(--u) * 0.4);
  height: calc(var(--u) * 0.46);
  padding: 0;
  border: 12px solid transparent;
  border-image: url(img/parts/vcr-key.png) 24 fill / 12px;
  font: inherit;
  font-size: calc(var(--u) * 0.1);
  color: #e6e6e1;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.8);
  cursor: pointer;
  user-select: none;
  transition: transform 0.05s, filter 0.05s;
}
.vkey { appearance: none; -webkit-appearance: none; background: none; } /* a button's own face must not show round the key's rounded corners */
.vkey.red { border-image-source: url(img/parts/vcr-key-red.png); color: #ffd9d4; }
.vkey:active { transform: translateY(2px); filter: brightness(0.9); }
.vkey.on { box-shadow: 0 0 0 1px var(--accent), 0 0 10px var(--accent); }
.vkey small { font-family: var(--silk); font-size: var(--fs-label); letter-spacing: 0.14em; }
.vcr-cell { display: grid; justify-items: center; gap: 3px; }
.vcr-cell small { font-family: var(--silk); font-size: var(--fs-label); letter-spacing: 0.14em; text-indent: 0.14em; text-transform: uppercase; line-height: 1.2; color: var(--ink-dim); text-shadow: var(--engrave); }

/* picture controls act on the tube */
.tube { filter: brightness(var(--bright, 1)) contrast(var(--contrast, 1)); }
.tube > .ch { transform: translateY(var(--vhold, 0px)); }

.transport { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.deck .vu { height: calc(var(--u) * 0.12); gap: 3px; }
.deck .vu i { width: 6px; }
.deck .zone[data-label="Main"] .knob.sm { --kd: min(40px, calc(var(--u) * 0.27)); }
.lcds { display: flex; gap: 8px; flex-wrap: wrap; }
.steps { display: flex; gap: 6px; flex-wrap: wrap; }
.steps .led:nth-child(4n + 1) { outline: 1px solid var(--ink-line); outline-offset: 2px; }
.seq { position: relative; display: grid; grid-template-columns: repeat(16, 12px); gap: 6px; }
.seq .cursor { position: absolute; top: -3px; bottom: -3px; left: -3px; width: 18px; border-radius: 3px; background: rgba(255, 255, 255, 0.14); box-shadow: 0 0 6px var(--accent); opacity: 0; }
@keyframes chase { to { transform: translateX(288px); } }

/* ---------- unit layouts ---------- */
.row { display: flex; flex: 1 1 auto; min-height: 0; gap: calc(var(--u) * 0.12); align-items: stretch; }
.row > .zone, .row > .stack { flex: 1 1 0; }
.row > .grow { flex: 2 1 0; }
.row > .span3 { flex: 3 1 0; }
.row > .fix { flex: 0 0 auto; }
.row.center { align-items: center; }
.row.center > .zone { align-self: stretch; }
.row > .push { margin-left: auto; }
.stack { display: flex; flex-direction: column; min-height: 0; gap: calc(var(--u) * 0.08); }
.stack .screen { flex: 1 1 auto; overflow: hidden; }
.u2 .stack .screen { padding: calc(var(--u) * 0.06) calc(var(--u) * 0.1); }
.u2 .stack .screen p { font-size: clamp(11.5px, calc(var(--u) * 0.105), 14.5px); line-height: 1.4; }

/* credits = a track sheet on the display */
.cues {
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: var(--lcd-font);
  font-size: calc(var(--u) * 0.125);
  line-height: 1.18;
  counter-reset: cue;
  columns: 2;
  column-gap: calc(var(--u) * 0.2);
}
.cues li { counter-increment: cue; break-inside: avoid; display: grid; grid-template-columns: 2.4ch 1fr; gap: 0.5em; padding: 0.15em 0; }
.cues li::before { content: counter(cue, decimal-leading-zero); opacity: 0.55; }
.cues small { display: block; font-size: 0.8em; opacity: 0.72; }

/* brand */
.brand { display: flex; align-items: center; gap: 1em; text-decoration: none; }
/* the KCA mark: five bars that meter the main output (lit from the bottom), and the K */
.logo { display: block; flex: none; height: var(--cap-h, calc(var(--u) * 0.3)); width: auto; overflow: visible; }
.logo .seg { opacity: 0.2; }
.logo .seg.on { opacity: 1; }
.logo .k { fill: #fff; }
.brand-name { font-family: var(--silk); font-size: var(--fs-label); letter-spacing: 0.22em; color: var(--ink-dim); text-transform: uppercase; line-height: 1.5; text-shadow: var(--engrave); }
.nav { display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 8px; align-items: stretch; }
.zone .nav { grid-auto-flow: row; }

/* ---------- rear panel bits (HTML, prototype B) ---------- */
.ports { display: flex; gap: calc(var(--u) * 0.16); align-items: flex-start; flex-wrap: wrap; }
/* a port group never shrinks: when the row is too narrow the groups wrap, they do not crush into each other */
.pgroup { display: flex; flex: none; gap: calc(var(--u) * 0.08); align-items: flex-end; justify-content: center; font-size: var(--fs-label); min-width: max(calc(var(--u) * 0.72), calc(var(--lw, 4) * 1.25em + 34px)); padding: calc(var(--u) * 0.2) calc(var(--u) * 0.08) calc(var(--u) * 0.06); border: 1px solid var(--ink-line); border-radius: 5px; position: relative; }
:where(.pgroup > *) { font-size: 1rem; }
.pgroup::before { content: attr(data-label); position: absolute; top: -0.6em; left: 8px; padding: 0 5px; font-family: var(--silk); font-size: inherit; letter-spacing: 0.18em; text-transform: uppercase; white-space: nowrap; color: var(--ink-dim); background: var(--plate-solid); }
.vent.wide { width: calc(var(--u) * 1.5); height: 22px; background-size: 64px 22px; }
.port { display: grid; justify-items: center; gap: 5px; cursor: grab; }
.port-label { order: -1; font-family: var(--stamp-font); font-size: var(--fs-label); letter-spacing: 0.12em; color: var(--ink-dim); text-shadow: var(--engrave); text-transform: uppercase; white-space: nowrap; }
.port.hot .jack { filter: drop-shadow(0 0 6px var(--amber)) brightness(1.3); }
.port .trim { margin-top: 2px; }
.sticker {
  display: inline-block;
  padding: 0.5em 0.8em;
  font-family: var(--lcd-font);
  font-size: calc(var(--u) * 0.12);
  line-height: 1.1;
  color: #2a2a2a;
  background: #e9e4d6;
  border-radius: 2px;
  box-shadow: 0 1px 0 #000, 0 2px 4px rgba(0, 0, 0, 0.5);
  transform: rotate(-1.5deg);
}

.foot { position: relative; z-index: 1; padding: calc(var(--u) * 0.2) var(--pad-x) 0; font-family: var(--stamp-font); font-size: var(--fs-label); letter-spacing: 0.2em; text-transform: uppercase; color: #8a8e97; }

/* ---------- responsive: under 960px the rack is too narrow for fixed U heights, so
   units keep their look and stack. Stacked layouts are grid rows, not column flex:
   WebKit sizes nested column flex items from their flex-basis and collapses them. ---------- */
@media (max-height: 599px) { .deck { position: relative; } } /* a very short window keeps the deck in the flow; relative, not static: the ears are absolute children */
@media (max-width: 999px) {
  /* below 1000px the 19-inch proportion cannot hold legible print, so the rack keeps its unit height and lets
     each unit grow: rows wrap, every zone is exactly as wide as its controls need and grows to share the row,
     and inside a zone the controls spread across the panel like a real faceplate. Stacked layouts are grid rows,
     not column flex: WebKit sizes nested column flex items from their flex-basis and collapses them. */
  .rack { --u: clamp(84px, 10.5cqw, 100px); --ear: 22px; --pad-x: 34px; --pad-y: 14px; --bz: 14px; --fs-label: 9px; --line: 30px; padding-top: 20px; }
  .lamp { width: 74px; height: 30px; }
  .page-section, .u1, .u2, .u3, .u4 { display: block; height: auto; min-height: 0; padding-top: 16px; padding-bottom: 18px; }
  h4, .u1 h4 { height: auto; margin: 0 0 20px; }
  .u1 > .unit-power { position: absolute; }
  .stack, .rows { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; min-height: 0; }
  .row { display: flex; flex-wrap: wrap; align-items: stretch; gap: 12px; min-height: 0; }
  .row > *, .row > .zone, .row > .stack, .row > .grow, .row > .span3, .row > .fix, .row > .monitor, .row > .crt, .row > .tape, .row > .push { flex: 1 1 auto; width: auto; min-width: 0; margin-left: 0; }
  .row > .zone { min-width: calc(var(--lw, 0) * 1.25em + 34px); } /* the reset above must not drop a zone below its own label */
  /* a control zone is as wide as its controls, and never narrower than its own label (the label floor comes from --lw on .zone) */
  .row > .zone:not(:has(.screen, .reader, .vfd, .lcd, .steps16, .tracks, .strips, .slots, .rows, .row, .tape)) { width: -webkit-fit-content; width: fit-content; }
  .row > .zone:has(.screen, .reader, .vfd, .lcd) { flex: 3 1 0; min-width: min(100%, max(calc(var(--u) * 2.4), calc(var(--lw, 0) * 1.25em + 34px))); } /* a display zone keeps its floor, and never drops below its own label */
  /* a sixteen-step line is never squeezed: its zone takes a full line when the row cannot hold it */
  .row > .zone:has(.steps16) { flex: 1 1 auto; min-width: -webkit-fit-content; min-width: fit-content; }
  .row > .crt { flex: 1 1 calc(var(--u) * 5.5); }
  .row > .crt + .stack { flex: 1 1 calc(var(--u) * 2.8); grid-template-rows: auto minmax(0, 1fr); } /* the display beside a tube takes the tube's height; stretched auto rows left a hole under the label */
  .row > .stack { flex: 1 1 calc(var(--u) * 3.2); min-width: 0; }
  /* a picture frame holds a percent-sized image, so it needs a real basis: as wide as a photo, never wider than the row */
  .row > .monitor { flex: 0 0 min(100%, 420px, calc(var(--u) * 3.6)); width: auto; margin: 0 auto; }
  .row > .polaroid { position: static; top: auto; align-self: center; flex: 0 0 min(100%, 300px, calc(var(--u) * 2.4)); width: auto; margin: 0 auto; padding: calc(var(--u) * 0.1) calc(var(--u) * 0.1) calc(var(--u) * 0.42); transform: rotate(-2.5deg); }
  .row.intro .screen { padding-right: calc(var(--u) * 0.12); }
  .row.intro > .stack { flex: 1 1 calc(var(--u) * 3.2); }
  .row.intro > .polaroid { margin: 0 calc(var(--u) * 0.1); } /* the tilt needs clearance at the plate edge; equal margins keep it centred on its own line */
  #synth .rows > .row:first-child > .zone { flex: 1 1 auto; }
  /* the program selector drops its desktop shares (and its column flex, which WebKit collapses) */
  #credits .row > .zone, #credits .row > .zone:first-child, #credits .row > .zone.fix, #credits .row > .zone[data-label] { flex: 1 1 auto; width: auto; min-width: -webkit-fit-content; min-width: fit-content; }
  /* a program list wants width: the display takes the first line, the keys share the second with the browse wheel */
  #credits .row > .zone[data-label="Program"] { order: -1; flex: 1 1 100%; min-width: 0; }
  #credits .row > .zone[data-label="Select program"] { flex: 1 1 auto; }
  #credits .zone.fix { flex-direction: row; }
  .keygrid.lg .keycell small { max-width: none; }
  /* a zone's rows keep the faceplate's language at natural size: controls in a cluster with fixed gaps, centred, never spread over the width */
  .zone, .zone.mid, .zone.top { display: flex; flex-direction: row; flex-wrap: wrap; align-items: flex-end; align-content: center; justify-content: center; gap: 12px 20px; min-height: 0; }
  .zone > .rows, .zone > .row, .zone > .stack, .zone > .screen, .zone > .vfd, .zone > .reader { flex: 1 1 100%; }
  .hrow, .pattern-row, .knob-row.sm, #synth .keyrow { flex-wrap: wrap; justify-content: center; }
  .zone > :is(.cells, .keyrow, .knob-row, .hrow, .keygrid) { flex: 1 1 100%; justify-content: center; }
  .keyrow { gap: 8px 18px; } .knob-row, .knob-row.sm { gap: 10px 20px; } .cells { gap: 3px 22px; } .keygrid { gap: 8px 18px; justify-content: center; } .hrow { gap: 10px 16px; } /* a key's print is wider than the key: the gaps keep the prints apart */
  /* sixteen steps on one line across the panel, the keys at their own size evenly along it (eight over eight below 640, where a line cannot seat them) */
  .steps16, .steps16.wide { grid-template-columns: repeat(16, minmax(0, 1fr)); gap: 4px; justify-content: stretch; justify-items: center; }
  .spads { grid-template-columns: repeat(4, 56px); gap: 8px; }
  .spad { height: 56px; }
  #sampler .steprow .track { grid-template-columns: auto minmax(0, 1fr); }
  /* touch floors: tablets and phones are fingers, so every control is at least a fingertip; the key sprite's own size is 33x28 */
  .key { width: 33px; height: 28px; }
  .steps16 .key { width: 28px; height: 26px; }
  .keygrid.lg .key, .key.lg { width: 60px; height: 36px; }
  .knob { --kd: max(40px, min(64px, calc(var(--u) * 0.42))); }
  .knob.sm { --kd: max(34px, min(40px, calc(var(--u) * 0.27))); }
  /* a zone of knobs and keys: the keys' slot is the knobs' size (the two sizes above), so the keys sit level with the caps */
  .zone:has(> .knob-row .knob.sm) { --kslot: max(34px, min(40px, calc(var(--u) * 0.27))); }
  .zone:has(> .knob-row .knob:not(.sm)) { --kslot: max(40px, min(64px, calc(var(--u) * 0.42))); }
  /* the sampler's six edit keys, three and three: cells of one width (a third less the widest gap the cells row takes in
     this regime), so the second line's keys stand under the first's */
  .z-edit .cells > .keycell { flex: 0 0 calc(33.333% - 16px); min-width: 0; }
  /* a zone of one knob row and one key row: the two share a line where the zone holds them, the keys level with the knob
     caps and both kinds of name on one line; where it does not, each takes a line of its own, centred */
  .zone:has(> .knob-row + .keyrow), .zone:has(> .keyrow + .knob-row) { flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: flex-end; }
  .zone:has(> .knob-row + .keyrow) > :is(.knob-row, .keyrow), .zone:has(> .keyrow + .knob-row) > :is(.knob-row, .keyrow) { flex: 0 1 auto; }
  .zone:has(> .knob-row + .keyrow) > .keyrow > .keycell, .zone:has(> .keyrow + .knob-row) > .keyrow > .keycell { grid-template-rows: var(--kslot) auto; align-items: center; gap: 0.3em; }
  .btn { min-height: 36px; }
  .unit-power { width: 26px; height: 40px; }
  /* the drum machine is rows across the panel, designed for its width: a track is two lines, its sounds at the left
     edge and its knobs at the right, then its sixteen steps spanning the panel edge to edge */
  .track { --tk: max(34px, min(40px, calc(var(--u) * 0.27))); grid-template-columns: auto minmax(0, 1fr); justify-content: start; align-items: center; gap: 8px 14px; }
  .track .knob-row { grid-column: 2; justify-self: end; justify-content: flex-start; }
  .tracks { gap: 14px; }
  #drums .pattern-row { justify-content: space-between; } /* a tablet: the pattern row spans the panel (a phone centres it, below) */
  .track .steps16 { grid-column: 1 / -1; }
  #sampler .steprow .track { grid-template-columns: auto minmax(0, 1fr); }
  .hrow > .steps16 { flex: 1 1 100%; min-width: 0; }
  .cells > .brk.narrow { display: block; flex: 1 1 100%; height: 0; }
  .strips { flex-wrap: wrap; justify-content: flex-start; }
  .keyboard { width: calc(var(--u) * 3); max-width: 100%; }
  .slots { flex-wrap: wrap; }
  .slot { flex: 1 1 calc(var(--u) * 2.6); }
  .cassette { width: 100%; max-width: 360px; }
  .nav { grid-auto-flow: row; }
  .monitor, .u2 .monitor, .u2 .monitor.wide, .u3 .monitor, .crt { height: auto; width: 100%; max-width: 420px; aspect-ratio: 4 / 3; }
  #monitor .crt { aspect-ratio: 16 / 9; max-width: 100%; }
  .stack .screen { overflow: visible; }
  .handle { display: none; }
  .tape { width: 100%; height: 260px; }
  .reel { --rd: 150px; }
  .tape .headblock { width: 120px; height: 52px; }
  .cues { columns: 1; }
  .lcd, h2 { white-space: normal; width: auto; max-width: 100%; }
  .page-section::before, .page-section::after { background: var(--cheek) 0 0 / var(--cheek-size) repeat; }
  .rack::before, .rack::after { background: url(img/parts/rail.png) 50% 20px / 14px 129px repeat-y, #1c1d21; }
  /* transport: one line while it fits, wrapping naturally when it does not */
  .deck { --cap-w: 60px; position: relative; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px 14px; }
  .keycell small { max-width: none; }
  .hrow > .knob-label, .zone > .knob-label { flex: 1 1 100%; white-space: normal; text-align: center; }
}
@media (max-width: 699px) {
  /* a narrow deck: the mark and the power rocker on the first line, the display on a line of its own, then a break; the caps share the
     lines after it at the size a thumb wants and no bigger, every group taking the width its caps need in proportion,
     so the Lab's twelve make one line of equal caps where it holds them (640 up) and two below that: the seven rack
     caps, then the five page and patch caps */
  .deck { gap: 0 6px; }
  .deck::after { content: ""; order: 1; flex: 1 1 100%; height: 0; } /* the break: a line of its own, no height, so the lines' own top margins space them */
  .deck .brand { margin-right: auto; }
  .deck .rocker { margin-left: auto; }
  .deck .readout { order: 1; flex: 1 1 100%; min-width: 0; margin: 10px 0 0; font-size: max(11px, calc(var(--u) * 0.17)); } /* the display takes a line of its own, the width of the caps, under the mark's line and before the break */
  .deck .readout .f { flex: 1 1 var(--w, 6ch); width: auto; }
  .deck .tkeys { gap: 6px; min-width: 0; justify-content: center; margin-top: 10px; }
  .deck .tkeys:not(.aux):not(.goto) { order: 2; flex: 7 1 0; }
  .deck .tkeys.aux, .deck .tkeys.goto { order: 3; flex: 2 1 0; }
  .deck .tkeys.look { flex: 1 1 0; }
  .deck .tbtn, .deck .tkeys .tbtn, .deck .tkeys .tbtn.wide { flex: 1 1 0; width: auto; min-width: 0; max-width: 60px; height: auto; padding: 0; }
  .tkeys { gap: 4px; }
  .spads { justify-content: center; }
  .zone.z-pads { flex: 1 1 100%; }
  .cells > .cell:has(.lcd) { flex: 1 1 100%; order: -1; }
  .cells > .brk { display: block; flex: 1 1 100%; height: 0; }
  #drums .pattern-row { justify-content: center; } /* the pattern keys on one line, the groove knobs on the next, each centred */
}
@media (max-width: 639px) { .deck .tkeys:not(.aux):not(.goto) { flex: 1 1 100%; } } /* a phone: the seven rack caps take a line of their own, the page caps the next */
@media (min-width: 640px) and (max-width: 699px) { .deck .tkeys .tbtn.wide { font-size: 7.5px; letter-spacing: 0.02em; text-indent: 0.02em; } } /* twelve on one line are 44 to 49 wide: the word caps print smaller, inside the flat face */
@media (max-width: 379px) {
  /* a small phone: seven caps go four over three at full size rather than squeezed under a fingertip */
  .deck .tkeys:not(.aux):not(.goto):has(> :nth-child(7)):not(:has(> :nth-child(8))) { display: grid; grid-template-columns: repeat(8, 27px); justify-content: center; }
  .deck .tkeys:not(.aux):not(.goto):has(> :nth-child(7)):not(:has(> :nth-child(8))) .tbtn { grid-column: span 2; width: 100%; max-width: none; }
  .deck .tkeys:not(.aux):not(.goto):has(> :nth-child(7)):not(:has(> :nth-child(8))) .tbtn:nth-child(5) { grid-column: 2 / span 2; }
}
@media (max-width: 359px) {
  /* the smallest phones: six caps three by two at full size rather than squeezed, and a display of three fields takes a line of its own */
  .deck .tkeys:not(.aux):not(.goto):has(> :nth-child(6)):not(:has(> :nth-child(7))) { display: grid; grid-template-columns: repeat(3, 60px); justify-content: center; }
  .deck .tkeys:not(.aux):not(.goto):has(> :nth-child(6)):not(:has(> :nth-child(7))) .tbtn { width: 100%; max-width: none; }
}
@media (max-width: 599px) {
  .keygrid.c5, .keygrid.c4 { grid-template-columns: repeat(2, auto); justify-content: center; gap: 10px 20px; }
  /* control groups on a phone: one legend size, tighter gaps, a display takes its own line above its controls,
     and the row titles go (the display already names the row) */
  .rack { --fs-label: 9px; }
  .keyrow.wrap2 { display: grid; grid-template-columns: repeat(2, auto); justify-content: center; justify-items: center; gap: 10px 20px; }
  .keyrow.grid2 { display: flex; } /* the filter's four mode keys on one line: the zone is the panel's width here */
  .keyrow.wrap3 { display: grid; grid-template-columns: repeat(3, auto); justify-content: center; justify-items: center; gap: 10px 18px; }
  .keyrow.wrap4 { display: grid; grid-template-columns: repeat(4, auto); justify-content: center; justify-items: center; gap: 10px 16px; }
  .slot .cells.meta { justify-content: center; }
  .cells { gap: 3px calc(var(--u) * 0.1); }
  .cells > .cell:has(.lcd) { flex: 1 1 100%; order: -1; }
  .cells > .cell:has(.tname) { display: none; }
  .cells > .brk { display: block; flex: 1 1 100%; height: 0; }
  /* one zone per line on a phone; each zone still lays its controls out in a row */
  .row > .zone, .row > .crt, .row > .crt + .stack, .row.intro > .stack { flex: 1 1 100%; min-width: 0; }
  .zone { gap: 12px 16px; }
  .slots { flex-direction: column; }
  .slot .cassette { width: 60%; }
}
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

}

/* ==========================================================
   THE STUDIO: a wide shot of the room above the rack. Every object that stands for a service is a link
   to its unit; the key strip under the picture lists the same links for phones and screen readers.
   ========================================================== */
html { scroll-behavior: smooth; }
.rack .page-section { scroll-margin-top: calc(var(--bar-h, 64px) + 20px); } /* a unit scrolled to lands under the bar: its measured height (core.js keeps --bar-h; 64px where there is no script) and 20px clear */
.scene { --u: calc(min(100cqw, 1400px) * 1.75 / 19); --silk: "Michroma", sans-serif; --fs-label: clamp(7.5px, calc(var(--u) * 0.068), 9.5px); --ink-dim: #9a9da5; --engrave: 0 1px 0 rgba(0, 0, 0, 0.8); --led-on: url(img/parts/led-amber-on.png); --led-off: url(img/parts/led-amber-off.png); --accent: #ffb000; position: relative; max-width: 1400px; margin: 0 auto; background: #0a0b0d; }
.scene .studio { display: block; width: 100%; height: auto; }
.scene .hot { cursor: pointer; outline: none; }
.scene .hot .obj { transition: filter 0.15s; }
.scene .hot:hover .obj, .scene .hot:focus-visible .obj, .scene .hot.lit .obj { filter: brightness(1.25) drop-shadow(0 0 7px rgba(255, 196, 96, 0.6)); }
.scene .tag { opacity: 0; transition: opacity 0.15s; pointer-events: none; }
.scene .tag rect { fill: #0e0f12; stroke: rgba(255, 255, 255, 0.22); }
.scene .tag text { fill: #ffb000; font-family: var(--silk); font-size: 11px; letter-spacing: 0.14em; text-anchor: middle; }
.scene .blip { fill: #ffb000; transform-box: fill-box; transform-origin: center; animation: blip 1.7s ease-in-out infinite; pointer-events: none; }
@keyframes blip { 0%, 100% { opacity: 0.25; transform: scale(0.8); } 50% { opacity: 1; transform: scale(1.25); } }
.scene:has(.hot[data-id="rack"]:hover) .tag[data-for="rack"], .scene:has(.hot[data-id="rack"]:focus-visible) .tag[data-for="rack"] { opacity: 1; }
.scene:has(.hot[data-id="rack"]:hover) .blip[data-for="rack"] { animation: none; opacity: 0; }
.scene:has(.hot[data-id="beats"]:hover) .tag[data-for="beats"], .scene:has(.hot[data-id="beats"]:focus-visible) .tag[data-for="beats"] { opacity: 1; }
.scene:has(.hot[data-id="beats"]:hover) .blip[data-for="beats"] { animation: none; opacity: 0; }
.scene:has(.hot[data-id="mic"]:hover) .tag[data-for="mic"], .scene:has(.hot[data-id="mic"]:focus-visible) .tag[data-for="mic"] { opacity: 1; }
.scene:has(.hot[data-id="mic"]:hover) .blip[data-for="mic"] { animation: none; opacity: 0; }
.scene:has(.hot[data-id="tv"]:hover) .tag[data-for="tv"], .scene:has(.hot[data-id="tv"]:focus-visible) .tag[data-for="tv"] { opacity: 1; }
.scene:has(.hot[data-id="tv"]:hover) .blip[data-for="tv"] { animation: none; opacity: 0; }
.scene:has(.hot[data-id="book"]:hover) .tag[data-for="book"], .scene:has(.hot[data-id="book"]:focus-visible) .tag[data-for="book"] { opacity: 1; }
.scene:has(.hot[data-id="book"]:hover) .blip[data-for="book"] { animation: none; opacity: 0; }
.scene:has(.hot[data-id="phone"]:hover) .tag[data-for="phone"], .scene:has(.hot[data-id="phone"]:focus-visible) .tag[data-for="phone"] { opacity: 1; }
.scene:has(.hot[data-id="phone"]:hover) .blip[data-for="phone"] { animation: none; opacity: 0; }
/* lights low: the room goes dark, the neon, the tube and the pads keep their light */
:is(.lowlight, body:has(#lights-low:checked)) .scene .room { filter: brightness(0.42); }
:is(.lowlight, body:has(#lights-low:checked)) .scene .glow { opacity: 1.6; }
:is(.lowlight, body:has(#lights-low:checked)) .scene .neon { filter: url(#neon) brightness(1.3); }

/* the smallest phones (under 360px) cannot hold eight step keys of a fingertip's width across a unit: four to a row */
@media (max-width: 359px) {
  .steps16, .steps16.wide { grid-template-columns: repeat(4, 1fr); }
  .knob-row.wrap2 { display: grid; grid-template-columns: repeat(2, auto); justify-content: center; justify-items: center; gap: 10px 20px; } /* the echo's four knobs two and two */
  .cells.pattern-row > .keycell, .cells.pattern-row > .knob-cell { flex: 0 0 calc(33.333% - 8px); min-width: 0; } /* the pattern keys three and three, the knobs three across, not five and one */
}

/* ==========================================================
   THE SITE MENU: a bar at the top of every page, its six sections in a row from left to right, each a flat module
   with a glyph and a name. They wait behind the mark at the left; tap the mark and they roll out. CSS only, so it
   works on the Basic plan as well: a checkbox (#menu) and the mark as its label.
   ========================================================== */
/* the bar: a flat strip under the dev bar, nothing of the rack about it. It carries the mark (the menu's switch),
   the page's transport where it has one, and the modules' window. The Lab alone keeps a rack deck for this */
.sitebar { --u: calc(min(100cqw, 1400px) * 1.75 / 19); --pad-x: 20px; --pad-y: 10px; --fs-label: clamp(7.5px, calc(var(--u) * 0.068), 9.5px);
  --ink: #e4e0d7; --ink-dim: #9a9da5; --ink-line: rgba(228, 224, 215, 0.2); --engrave: 0 1px 0 rgba(0, 0, 0, 0.8); --plate-solid: #121316; --link: #ffb000; --silk: var(--stamp-font); --punch: var(--punch-font);
  --scr-bg: #1b1306; --scr-ink: #ffb000; --scr-glow: 0 0 8px rgba(255, 176, 0, 0.5); --btn: url(img/parts/btn-dark.png); --btn-wide: url(img/parts/btn-wide-dark.png); --btn-ink: #e3dfd6;
  position: sticky; top: 0; z-index: 40; min-height: 64px; padding: var(--pad-y) var(--pad-x); color: var(--ink); background: #121316; border-bottom: 1px solid #000; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06); }
.sitebar .brand small { font-family: var(--stamp-font); font-size: 9px; letter-spacing: 0.24em; text-indent: 0.24em; text-transform: uppercase; color: #9a9da5; text-shadow: 0 1px 0 rgba(0, 0, 0, 0.8); }
.sitebar .brand:hover .logo .k, .sitebar .brand:focus-visible .logo .k { filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.6)); }
.sitebar .brand:hover small { color: #e4e0d7; }
@media (max-width: 999px) { .sitebar { --pad-x: 16px; --pad-y: 10px; padding: var(--pad-y) var(--pad-x); } }
/* the modules' window. From 1100 up it is the bar itself, from the mark to the power rocker (to the edge where there is
   none), and the six roll out across it in one row, each a sixth of it. Below 1100 it is a sheet hung under the bar
   (under the mark's row of a deck that has wrapped into rows), edge to edge, over whatever is below. The window's own
   width seats the six (a container query): a row where it is 852px or more, three by two below that, two by three
   below 560px. So no bar ever scrolls its menu or cuts a name, the Lab's deck included */
.deck { --mark-w: 136px; --seam: #24252a; }
.deck .brand { position: relative; z-index: 5; display: flex; align-items: center; gap: 12px; width: var(--mark-w); cursor: pointer; }
.deck .brand small { font-family: var(--stamp-font); font-size: 9px; letter-spacing: 0.24em; text-indent: 0.24em; text-transform: uppercase; color: var(--ink-dim); text-shadow: var(--engrave); white-space: nowrap; }
.deck .brand:hover .logo .k, .deck .brand:focus-visible .logo .k { filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.6)); }
.deck .brand:hover small, body:has(#menu:checked) .deck .brand small { color: var(--ink); }
/* the window is exactly as tall as the mark: its top and bottom are the mark's (an anchor). Where the browser has no
   anchors it is the row's centre and the cap height the mark is drawn at; the Lab's deck is two centred rows, the mark's the upper */
.deck .brand { anchor-name: --mark; }
.deck .menuclip { position: absolute; top: 50%; height: var(--cap-h); translate: 0 -50%; left: calc(var(--pad-x) + var(--mark-w)); right: calc(var(--pad-x) + var(--u) * 0.34); z-index: 4; overflow: hidden; container-type: inline-size; pointer-events: none; }
.deck:where(:has(> .brk)) .menuclip { top: calc(50% - var(--cap-h) - 4px); translate: none; }
@supports (top: anchor(top)) { .deck .menuclip { top: anchor(--mark top); bottom: anchor(--mark bottom); height: auto; translate: none; } }
.deck .menuclip .menubar { width: 100%; height: 100%; pointer-events: auto; }
@media (max-width: 1199px) { .deck { --mark-w: 70px; } .deck .brand small { display: none; } }
@media (min-width: 1100px) { .sitebar:not(:has(.rocker)) .menuclip { right: var(--pad-x); } } /* no power rocker to leave clear: the modules run to the edge */
/* while the modules are out they cover the caps (and, on a one-row bar, the display): a lit cap's halo and the display's glow stay under them, not around them */
@media (min-width: 1100px) { body:has(#menu:checked) .deck .tkeys .tbtn, body:has(#menu:checked) .deck:not(:has(> .brk)) .readout { box-shadow: none; } }
.menubar { box-sizing: border-box; display: flex; gap: 1px; min-width: 0; overflow: hidden; background: var(--seam); border-left: 1px solid var(--seam); transform: translateX(-100%); visibility: hidden; transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1), visibility 0s 0.45s; }
body:has(#menu:checked) .menubar { transform: none; visibility: visible; transition-delay: 0s; }
body:has(#menu:checked) .sitebar .brand small { color: #e4e0d7; }
@media (prefers-reduced-motion: reduce) { .menubar { transition: none; } }
/* a module per section, flat and plain, nothing of the rack about it: a monoline glyph in the section's colour, the
   name in the house condensed face, a line of the colour along the bottom on the page you are on and on hover. The
   six share one width; the hair of light between them is the seam */
.menubar .tile { --hue: var(--amber); position: relative; display: flex; align-items: center; gap: 10px; flex: 1 1 0; min-width: 0; padding: 0 12px; color: #e4e0d7; text-decoration: none; background: #15161a; transition: background 0.15s; }
.menubar .tile.home { --hue: #8ac33e; } .menubar .tile.music { --hue: #ff66c4; } .menubar .tile.podcasts { --hue: #ff8c1e; } .menubar .tile.video { --hue: #3da9ff; } .menubar .tile.audiobooks { --hue: #2ec4b6; } .menubar .tile.lab { --hue: #ffb000; }
.menubar .tile .glyph { flex: none; width: 22px; height: 22px; fill: none; stroke: var(--hue); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* the name is as large as a sixth of the window seats it: the longest (AUDIOBOOKS) runs 5.3 times its size, and the glyph, the gap and the padding take 56px */
.menubar .tile .name { flex: 1 1 auto; min-width: 0; font-family: var(--stamp-font); font-weight: 400; font-size: clamp(9px, calc((100cqw / 6 - 60px) / 13), 14px); line-height: 1; letter-spacing: 0.16em; text-indent: 0.16em; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: color 0.15s; }
.menubar .tile::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--hue); opacity: 0; transition: opacity 0.18s; }
.menubar .tile:hover, .menubar .tile:focus-visible { background: #1c1d22; outline: none; }
.menubar .tile:hover::after, .menubar .tile:focus-visible::after, .menubar .tile[aria-current]::after { opacity: 1; }
.menubar .tile:hover .name, .menubar .tile:focus-visible .name { color: #fff; }
.menubar .tile[aria-current] .name { color: var(--hue); }
.menubar .tile:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--amber); }
.menubar .tile:active { filter: brightness(0.9); }
/* a window under 852px cannot seat six in a row: three by two, and two by three under 560px, the name at one size */
@container (max-width: 851px) { .menubar { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-rows: minmax(0, 1fr); } .menubar .tile .name { font-size: 12px; } }
@container (max-width: 559px) { .menubar { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* below 1100 the window is the sheet: hung from the bar's foot, as tall as its rows, with its shadow on the page (the clip's padding leaves the shadow room) */
@media (max-width: 1099px) {
  .deck .menuclip { top: 100%; bottom: auto; height: auto; translate: none; left: 0; right: 0; padding-bottom: 48px; }
  .deck .menuclip .menubar { height: auto; grid-auto-rows: 48px; border-left: 0; border-top: 1px solid var(--seam); border-bottom: 1px solid #000; box-shadow: 0 18px 40px rgba(0, 0, 0, 0.65); }
  .deck .menuclip .menubar .tile { height: 48px; }
}
/* a deck that has wrapped into rows (the transport bars under 1000) hangs the sheet under its first row, over its own keys */
@media (max-width: 999px) { .deck:has(.readout) .menuclip { top: calc(var(--pad-y) + 44px); } }

/* ==========================================================
   THE LOOK CAP: the rack's five finishes drop from it in a list, the one in use lit. A checkbox and its label, so
   prototype A has it without a script; the script closes the list after a pick where there is one.
   ========================================================== */
.tkeys.look { position: relative; }
.looklist { position: absolute; top: calc(100% + 10px); right: 0; z-index: 45; display: none; min-width: 200px; padding: 8px 0; background: #1a1b20; border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 6px; box-shadow: 0 18px 40px rgba(0, 0, 0, 0.65); }
body:has(#look:checked) .looklist { display: block; }
body:has(#look:checked) .tkeys.look .tbtn { box-shadow: 0 0 0 1px var(--accent), 0 0 10px var(--accent); }
.looklist label { display: flex; align-items: center; gap: 12px; padding: 9px 18px 9px 14px; font-family: var(--punch-font); font-weight: 800; font-size: 16px; line-height: 1; letter-spacing: 0.06em; text-transform: uppercase; white-space: nowrap; color: var(--ink-dim); text-shadow: var(--engrave); cursor: pointer; }
.looklist label:hover { color: var(--ink); background: rgba(255, 255, 255, 0.05); }
.looklist .led { flex: none; width: 10px; height: 10px; }
body:has(#t-mixed:checked) label[for="t-mixed"] .led, body:has(#t-studio:checked) label[for="t-studio"] .led, body:has(#t-vintage:checked) label[for="t-vintage"] .led, body:has(#t-sampler:checked) label[for="t-sampler"] .led, body:has(#t-modular:checked) label[for="t-modular"] .led { background-image: var(--led-on); border-radius: 50%; box-shadow: 0 0 7px 1px var(--accent); }

/* ---------- the steps and the drum tracks on small screens ---------- */
/* below 640 a line cannot seat sixteen steps at the key's size: eight over eight, packed from the start of their row,
   the keys giving up width only on the smallest phones */
@media (max-width: 639px) {
  .steps16, .steps16.wide { grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 6px; }
  .steps16 .key { width: 100%; max-width: 32px; height: 26px; }
}
@media (max-width: 389px) { .steps16, .steps16.wide { gap: 4px; } } /* a small phone: the gap gives way before the key does */
/* a small phone: five keys wrap three over two, the cells one width so the two sit centred under the three, never four over one */
@media (max-width: 389px) {
  .keyrow:has(> :nth-child(5):last-child) { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px 12px; }
  .keyrow:has(> :nth-child(5):last-child) > * { flex: 0 0 calc((100% - 24px) / 3); max-width: 70px; }
}
/* a phone: a track's sounds and knobs still share one line over its steps, at sizes that fit the panel: the keys and the
   knobs closer, the knobs a little smaller; the narrowest phones (under 360) close the groups up to their touch floor */
@media (max-width: 479px) {
  .track { --tk: 32px; gap: 8px 6px; }
  .track .sounds { gap: 8px; }
  .track .knob-row { gap: 0 10px; flex-wrap: nowrap; }
  .track .knob-cell { min-width: 0; }
}
@media (max-width: 359px) {
  .track .sounds { gap: 4px; }
  .track .knob-row { gap: 0 6px; }
}
