/* =====================================================================
   Raadio — warm paper surfaces, soft raised controls, one caramel accent.
   The front page is styled like a light retro radio: a sunken display with
   digital type, a tuner scale, a sunken waveform window, presets as chips.
   ===================================================================== */

:root {
  --cream: #ebe7e0;
  --cream-deep: #e0dbd2;
  --ink: #26241f;
  --ink-soft: #5f5a51;
  --gold: #b8894b;            /* caramel: bars, needle, accents */
  --gold-deep: #835d2a;       /* caramel for text on paper (5:1) */
  --gold-fill: #9a6d36;       /* filled chips with light text (4.6:1) */
  --gold-soft: rgba(184, 137, 75, 0.16);
  --live: #c9406c;            /* flamingo pink: "on air" text and the dislike key (4.6:1) */
  --flamingo: #f0779c;        /* the brighter pink of the "on air" dot */
  --shadow: #cfc7ba;
  --highlight: #ffffff;
  --well: #dfd9cf;            /* sunken display and wave window */
  --well-ink: #24221e;
  --scale: rgba(38, 36, 31, 0.32);
  /* Keys: near-white with a soft top-left light, and a wide, faint shadow */
  /* Every button: a face brighter than the page, darker than the page while pressed */
  --btn-face: #f0ede8;
  --btn-pressed: #d9d3c9;
  --key-top: #f2efea;
  --key-bottom: #edeae4;
  --key-dish-top: #e2ddd4;
  --key-dish-bottom: #f1eee9;
  --key-shadow: rgba(90, 76, 55, 0.20);
  --drop-wide: rgba(84, 68, 44, 0.26);   /* soft fall-off under raised things */
  --drop-near: rgba(60, 48, 30, 0.18);   /* tight contact shadow */
  --rim: rgba(255, 255, 255, 0.55);      /* hairline catch-light on the top edge */
  --key-icon: #6f695f;
  --display: #1f1d19;
  --display-ink: #efe6cf;
  --amber: #e8c56a;
  --danger: #b5523f;
  --wave-off: rgba(95, 90, 81, 0.22);
  --wave-base: rgba(95, 90, 81, 0.34);
  --noise-filter: none;

  --radius: 28px;
  --radius-md: 20px;
  --radius-sm: 14px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  --serif: "Mulish", "Helvetica Neue", Arial, system-ui, sans-serif;   /* one face everywhere: Mulish */
  /* Studio face: a sans built for legibility at small sizes (open shapes, roomy spacing) */
  --sans: "Mulish", "Helvetica Neue", Arial, system-ui, sans-serif;
  --line: #d6ccb6;            /* flat borders in the studio */
  --tick: rgba(143, 113, 52, 0.45);
  --mono: "Mulish", "Helvetica Neue", Arial, system-ui, sans-serif;
  /* Mulish for everything, and an old computer terminal's face for the station display */
  --ui: "Mulish", "Helvetica Neue", Arial, system-ui, sans-serif;
  --digit: "Mulish", "Helvetica Neue", Arial, system-ui, sans-serif;
  --crt: "VT323", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;

  color-scheme: light;
}

/* Composite shadows live on body so they pick up the dark-mode colours below.
   One light for everything (glass, keys, logo, cards): from the top left, a little in front,
   so every shadow falls down and slightly to the right. */
body {
  --raise-lg: 11px 28px 56px var(--drop-wide), 3px 8px 18px var(--drop-near);
  --raise: 5px 12px 24px var(--drop-wide), 1px 3px 7px var(--drop-near), inset 0 1px 0 var(--rim);
  --raise-sm: 2px 6px 14px var(--drop-wide), 1px 2px 4px var(--drop-near), inset 0 1px 0 var(--rim);
  --raise-xs: 1px 3px 8px var(--drop-wide), 0 1px 2px var(--drop-near), inset 0 1px 0 var(--rim);
  --press: inset 6px 6px 12px var(--shadow), inset -6px -6px 12px var(--highlight);
  --press-sm: inset 3px 3px 6px var(--shadow), inset -3px -3px 6px var(--highlight);
  --key: var(--raise);
  --key-sm: var(--raise-sm);
  --edge: 0 0 0 transparent;
}

body.dark-mode {
  --cream: #1d1b18;
  --cream-deep: #25221e;
  --ink: #f1ece2;
  --ink-soft: #bdb6a8;
  --gold: #c99a5b;
  --gold-deep: #d9ad70;
  --gold-fill: #b8894b;
  --gold-soft: rgba(201, 154, 91, 0.2);
  --live: #f491b2;
  --flamingo: #f27fa4;
  --shadow: #0f0e0c;
  --highlight: #2b2824;
  --well: #161512;
  --well-ink: #efe9dd;
  --scale: rgba(241, 236, 226, 0.3);
  --wave-base: rgba(241, 236, 226, 0.24);
  --btn-face: #2c2924;
  --btn-pressed: #131210;
  --key-top: #33302a;
  --key-bottom: #2a2722;
  --key-dish-top: #1a1815;
  --key-dish-bottom: #2a2723;
  --key-shadow: rgba(0, 0, 0, 0.55);
  --drop-wide: rgba(0, 0, 0, 0.55);
  --drop-near: rgba(0, 0, 0, 0.45);
  --rim: rgba(255, 255, 255, 0.06);
  --key-icon: #c9c2b4;
  --display: #0e0d0b;
  --wave-off: rgba(242, 237, 226, 0.14);
  --noise-filter: invert(1);
  --line: #3d3830;
  --tick: rgba(216, 184, 110, 0.45);
  color-scheme: dark;
}

/* ---------- Lite mode (old Android / slow devices) ----------
   No neumorphic double shadows, no 3D, no blur, no text glow:
   these are what flicker on Chrome 138 / Android 9. */
body.lite {
  /* "none" can't sit inside a shadow list, so use an empty shadow instead */
  --raise-lg: 0 0 0 transparent;
  --raise: 0 0 0 transparent;
  --raise-sm: 0 0 0 transparent;
  --raise-xs: 0 0 0 transparent;
  --press: 0 0 0 transparent;
  --press-sm: 0 0 0 transparent;
  --edge: 0 0 0 1px rgba(196, 163, 90, 0.4);
}

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--ui);
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100dvh;
  font-variant-numeric: tabular-nums;     /* times and counts don't jiggle */
  overflow-x: hidden;
  text-rendering: optimizeLegibility;
}

/* Static paper texture, on its own fixed layer so it never repaints */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .32 0 0 0 0 .27 0 0 0 0 .18 .38 0 0 0 -.13'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  filter: var(--noise-filter);
  opacity: 0.9;
}
body.lite::before { display: none; }

#ambient {
  position: fixed;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
body.lite #ambient { display: none; }

button, input { font: inherit; color: inherit; }
button { -webkit-user-select: none; user-select: none; touch-action: manipulation; }
[hidden] { display: none !important; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------- Icons ---------- */
.icon { width: 26px; height: 26px; fill: currentColor; flex: none; display: block; }
.icon--sm { width: 20px; height: 20px; }
.icon--lg { width: 32px; height: 32px; }
.icon--xl { width: 44px; height: 44px; }

/* ---------- Stage & flip ---------- */
.stage {
  position: relative;
  z-index: 1;
  min-height: 100dvh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);   /* wide content (scrolling text) can't stretch the page */
  place-items: center;
  padding: max(20px, env(safe-area-inset-top)) 16px calc(24px + env(safe-area-inset-bottom));
}

.float-wrap {
  width: 100%;
  max-width: 460px;
  perspective: 1400px;
  animation: float 7s ease-in-out infinite;
  will-change: transform;
}

/* Translate only: rotating a shadowed, text-heavy card is what made text shimmer */
@keyframes float {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50% { transform: translate3d(0, -8px, 0); }
}

/* Switching between radio and studio: a 3D card flip.
   Each face turns on its own (perspective() in its transform) instead of rotating a
   preserve-3d parent, and the face turned away is hidden once the turn ends; those two
   things avoid most of the flicker Android showed with the old flip. */
.flip { position: relative; }

/* The face you're looking at has no 3D transform at rest: browsers draw a 3D-transformed
   layer at the size it had during the last turn (edge-on, it's a sliver) and could leave the
   name plate and the display blurry after coming back from the studio until a refresh */
.face {
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  transform: none;
}

.flip.is-switching .face { will-change: transform; }

/* The back face fills the card; the card grows while the studio is open */
.face--back {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--gold) transparent;
  transform: perspective(1600px) rotateY(180deg);
  visibility: hidden;
}
.flip.is-flipped .face--front { transform: perspective(1600px) rotateY(-180deg); visibility: hidden; }
.flip.is-flipped .face--back { transform: none; visibility: visible; }

/* During the turn: hold the floating still and keep the busy parts of the studio cheap */
.is-turning .float-wrap { animation-play-state: paused; }

/* Bigger studio: +20% wide and +40% tall, never past the screen */
.float-wrap.is-grown { max-width: 552px; }
.flip.is-grown { height: min(calc(var(--front-h) * 1.4), calc(100dvh - 24px)) !important; }

body.lite .float-wrap { animation: none; will-change: auto; }

/* ---------- Deck (the main card) ---------- */
.deck {
  border-radius: var(--radius);
  background: var(--cream);
  box-shadow: var(--raise-lg), var(--edge);
  padding: 26px 22px 18px;
}

.face--front {
  position: relative;
  font-family: var(--ui);
  touch-action: pan-y;          /* horizontal swipes reach the skip gesture */
  display: flex;
  flex-direction: column;
}

/* ---------- Corner button (login / profile / radio) ---------- */
.corner-btn {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 5;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 12px;
  background: linear-gradient(145deg, var(--key-top), var(--key-bottom));
  color: var(--key-icon);
  display: grid;
  place-items: center;
  cursor: pointer;
  opacity: 0.8;
  box-shadow: var(--key-sm), var(--edge);
  transition: transform 0.15s var(--ease), opacity 0.15s;
}
.corner-btn::before { content: ""; position: absolute; inset: -6px; border-radius: 16px; } /* 52px touch area */
.corner-btn:hover { opacity: 1; }
.corner-btn:active { transform: scale(0.94); background: var(--btn-pressed); box-shadow: var(--press-sm), var(--edge); }
.corner-btn .icon { width: 19px; height: 19px; }
.corner-btn--sm { width: 36px; height: 36px; top: 12px; right: 12px; }

/* ---------- Brand ---------- */
.brand {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 0 52px 20px 0;
}

h1 {
  margin: 2px 0 0;
  font-size: 2.2rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1;
}

.greeting { margin: 6px 0 0; color: var(--ink-soft); font-style: italic; font-size: 1.05rem; }

/* ---------- Station display: a light, sunken panel ---------- */
.plate {
  flex: 1 0 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  margin: 0 0 20px;
  padding: 14px 18px 14px;
  border-radius: 22px;
  background: var(--well);
  color: var(--well-ink);
  box-shadow: var(--press), var(--edge);
}
body.lite .plate { box-shadow: inset 0 0 0 1px var(--line); }

.plate-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }

.dots { display: flex; gap: 6px; }
.dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--gold); opacity: 0.3; }

/* "Live" label: a red dot and small mono caps, no frame */
.onair {
  position: relative;
  padding: 3px 0 3px 15px;
  font-family: var(--digit);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  opacity: 0.7;
}
.onair::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 50%;
  width: 7px;
  height: 7px;
  margin-top: -3.5px;
  border-radius: 50%;
  background: var(--ink-soft);
  opacity: 0.5;
}
.is-live .onair { color: var(--live); opacity: 1; }
.is-live .onair::before { background: var(--flamingo); opacity: 1; animation: blink 1.6s steps(2, jump-none) infinite; }
.is-live .dots i:first-child { opacity: 1; }
.is-connecting .dots i { animation: blink 0.9s steps(2, jump-none) infinite; }
.is-connecting .dots i:nth-child(2) { animation-delay: 0.3s; }
.is-connecting .dots i:nth-child(3) { animation-delay: 0.6s; }

/* HQ / Saver: a preset chip. Raised when off, filled caramel when on (like P4) */
.plate-chips { display: flex; align-items: center; gap: 12px; }
.q-chip {
  min-height: 26px;
  padding: 3px 11px;
  border: 0;
  border-radius: 9px;
  background: var(--btn-face);
  color: var(--ink-soft);
  font-family: var(--digit);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: inset 0 0 0 1px var(--scale);
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.15s var(--ease), background-color 0.2s, color 0.2s;
}
.q-chip[aria-pressed="true"] {
  background: var(--gold-fill);
  color: #fffaf1;
  box-shadow: none;
}
.q-chip:active { transform: scale(0.95); background: var(--btn-pressed); color: var(--ink); box-shadow: none; }
.q-chip:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.q-chip[hidden] { display: none; }

/* opacity-only, on tiny elements: cheap and flicker-free */
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

/* The big readout: dark typewriter digits on the light panel */
.plate-status {
  margin: auto 0 0;            /* with the news' auto top margin: readout sits mid-panel */
  font-family: var(--digit);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--well-ink);
  overflow: hidden;
  white-space: nowrap;
}

/* Tuner scale under the readout: fine ticks, longer every fifth, and a caramel needle
   that drifts a little while the station is live (transform only) */
.plate-scale {
  position: relative;
  height: 20px;
  margin: 8px 2px 4px;
  background:
    repeating-linear-gradient(to right, var(--scale) 0 1px, transparent 1px 40px) left bottom / 100% 12px no-repeat,
    repeating-linear-gradient(to right, var(--scale) 0 1px, transparent 1px 8px) left bottom / 100% 6px no-repeat;
  opacity: 0.9;
}
.plate-scale i {
  position: absolute;
  left: 50%;
  bottom: -3px;
  width: 2px;
  height: 22px;
  margin-left: -1px;
  border-radius: 2px;
  background: var(--gold);
}
.is-live .plate-scale i { animation: tune 9s ease-in-out infinite alternate; }
@keyframes tune { from { transform: translate3d(-18px, 0, 0); } to { transform: translate3d(14px, 0, 0); } }

/* Text on the display that doesn't fit scrolls right-to-left in a loop
   (script.js adds .mq--run). Holding it pauses. Otherwise it ends in "…". */
.mq {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.mq--run {
  display: inline-block;
  overflow: visible;
  text-overflow: clip;
  will-change: transform;
}

.plate-news {
  min-width: 0;
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--scale);
}
.plate-label {
  margin: 0 0 6px;
  font-family: var(--digit);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold-deep);
}
.news-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 5px; }
.news-list li {
  display: flex;
  gap: 10px;
  align-items: baseline;
  font-size: 0.95rem;
  line-height: 1.25;
  min-width: 0;
  overflow: hidden;
}
.news-time {
  flex: none;
  font-family: var(--digit);
  font-size: 0.72rem;
  color: var(--gold-deep);
}
.news-text { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; color: var(--well-ink); font-weight: 500; }
.news-empty { color: var(--ink-soft); }

/* ---------- Glass: the display and the waveform window sit behind a clear pane ----------
   Static pictures moved only with transform/opacity (no repaints):
   ::after   the pane itself: a faint tint, a curved highlight across the top, a bright
             top edge and a darker bottom edge, a soft glow just inside the rim (where thick
             glass catches light), and a few faint scratches here and there
   ::before  the reflection, larger than the box, sliding as the card floats
   .glass-scratch  fine scratches, almost invisible, that light up only where the moving
             reflection passes over them (a mask window travels with the light)
   Both run on the card's 7 s float cycle, so the light seems to move with it. */
.plate, .wave { position: relative; isolation: isolate; overflow: hidden; }
.plate::before, .wave::before, .plate::after, .wave::after {
  content: "";
  position: absolute;
  z-index: 2;
  pointer-events: none;
}
.plate::after, .wave::after {
  inset: 0;
  border-radius: inherit;
  background:
    radial-gradient(120% 60% at 50% -18%, rgba(255, 255, 255, 0.34), rgba(255, 255, 255, 0.06) 55%, rgba(255, 255, 255, 0) 70%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0.02) 60%, rgba(60, 48, 30, 0.04));
  box-shadow:
    inset 0 1.5px 0 rgba(255, 255, 255, 0.75),          /* top edge */
    inset 1px 0 0 rgba(255, 255, 255, 0.35),            /* left edge */
    inset 0 -1px 0 rgba(60, 48, 30, 0.16),              /* bottom edge */
    inset 0 0 0 1px rgba(255, 255, 255, 0.22),          /* the pane's rim */
    inset 0 0 22px rgba(255, 255, 255, 0.22);           /* light caught inside thick glass */
  -webkit-backdrop-filter: saturate(118%) contrast(104%);
  backdrop-filter: saturate(118%) contrast(104%);
  animation: glint 7s ease-in-out infinite;
}
.wave::after {
  background:
    radial-gradient(120% 70% at 50% -30%, rgba(255, 255, 255, 0.34), rgba(255, 255, 255, 0.05) 55%, rgba(255, 255, 255, 0) 72%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0.02) 60%, rgba(60, 48, 30, 0.04));
}
.plate::before, .wave::before {
  inset: -25% 0;
  background: linear-gradient(115deg, rgba(255, 255, 255, 0) 40%, rgba(255, 255, 255, 0.22) 48%, rgba(255, 255, 255, 0.07) 52%, rgba(255, 255, 255, 0) 60%);
  animation: glare 7s ease-in-out infinite;
  will-change: transform;
}

/* ONE LIGHT for the whole card. A single beam (always at 115deg) drifts from just left of
   the card (x = -15%) to just short of the middle (x = 45%) while the card rises, and back
   while it sinks — a slow, subtle sweep, never a full pass —
   with the float's own timing (7 s ease-in-out). Each piece moves its own highlight to
   wherever that beam is over it, so the logo, the title, the display glass and the
   waveform glass all catch the same light at the same moment.
   Offsets come from where each piece sits on the card (measured at phone and desktop
   widths): logo 6-25%, title 29-59%, display and waveform 6-94%. */
@keyframes glare {
  0%, 100% { transform: translate3d(-74%, 0, 0); }
  50%      { transform: translate3d(-6%, 0, 0); }
}
@keyframes glint {
  0%, 100% { opacity: 0.8; }
  50%      { opacity: 1; }
}
.is-turning .plate::before, .is-turning .wave::before,
.is-turning .plate::after, .is-turning .wave::after { animation-play-state: paused; }
body.dark-mode .plate::before, body.dark-mode .wave::before { opacity: 0.4; }
body.dark-mode .plate::after, body.dark-mode .wave::after { animation-name: glint-dark; }
@keyframes glint-dark { 0%, 100% { opacity: 0.35; } 50% { opacity: 0.5; } }
@media (prefers-reduced-motion: reduce) {
  .plate::before, .wave::before, .plate::after, .wave::after { animation: none; }
}
body.lite .plate::before, body.lite .wave::before, body.lite .plate::after, body.lite .wave::after { display: none; }

.glass-scratch {
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: inherit;
  pointer-events: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='300' viewBox='0 0 420 300' fill='none' stroke-linecap='round'%3E%3Cpath d='M83.9 153.3Q75.6 155.4 65.8 153.9' stroke='%235a5246' stroke-opacity='0.19' stroke-width='0.83' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M83.9 153.3Q75.6 155.4 65.8 153.9' stroke='%23ffffff' stroke-opacity='0.66' stroke-width='0.83'/%3E%3Cpath d='M395.9 193.1Q413.7 178.2 430.1 167.5' stroke='%235a5246' stroke-opacity='0.18' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M395.9 193.1Q413.7 178.2 430.1 167.5' stroke='%23ffffff' stroke-opacity='0.64' stroke-width='0.68'/%3E%3Cpath d='M140.5 175.5Q152.9 163.3 168.9 154.3' stroke='%235a5246' stroke-opacity='0.21' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M140.5 175.5Q152.9 163.3 168.9 154.3' stroke='%23ffffff' stroke-opacity='0.75' stroke-width='0.68'/%3E%3Cpath d='M293.1 98.3Q299.6 96.6 309.3 97.4' stroke='%235a5246' stroke-opacity='0.18' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M293.1 98.3Q299.6 96.6 309.3 97.4' stroke='%23ffffff' stroke-opacity='0.65' stroke-width='0.68'/%3E%3Cpath d='M348.9 10.2Q358.4 9.6 371.4 4.2' stroke='%235a5246' stroke-opacity='0.23' stroke-width='0.83' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M348.9 10.2Q358.4 9.6 371.4 4.2' stroke='%23ffffff' stroke-opacity='0.83' stroke-width='0.83'/%3E%3Cpath d='M144.8 97.1Q163.8 122.4 188.6 148.8' stroke='%235a5246' stroke-opacity='0.29' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M144.8 97.1Q163.8 122.4 188.6 148.8' stroke='%23ffffff' stroke-opacity='1.0' stroke-width='0.68'/%3E%3Cpath d='M81.1 166.6Q100.4 147.5 120.3 132.2' stroke='%235a5246' stroke-opacity='0.26' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M81.1 166.6Q100.4 147.5 120.3 132.2' stroke='%23ffffff' stroke-opacity='0.95' stroke-width='0.68'/%3E%3Cpath d='M10.2 252.0Q5.6 252.9 -4.7 252.7' stroke='%235a5246' stroke-opacity='0.30' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M10.2 252.0Q5.6 252.9 -4.7 252.7' stroke='%23ffffff' stroke-opacity='1.0' stroke-width='0.68'/%3E%3Cpath d='M95.3 82.3Q73.4 87.9 48.2 95.6' stroke='%235a5246' stroke-opacity='0.21' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M95.3 82.3Q73.4 87.9 48.2 95.6' stroke='%23ffffff' stroke-opacity='0.75' stroke-width='0.68'/%3E%3Cpath d='M158.7 136.9Q178.3 144.1 192.3 151.5' stroke='%235a5246' stroke-opacity='0.25' stroke-width='0.83' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M158.7 136.9Q178.3 144.1 192.3 151.5' stroke='%23ffffff' stroke-opacity='0.88' stroke-width='0.83'/%3E%3Cpath d='M300.2 54.4Q278.1 50.3 254.5 45.6' stroke='%235a5246' stroke-opacity='0.26' stroke-width='0.83' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M300.2 54.4Q278.1 50.3 254.5 45.6' stroke='%23ffffff' stroke-opacity='0.93' stroke-width='0.83'/%3E%3Cpath d='M25.5 279.6Q33.0 278.2 43.7 274.5' stroke='%235a5246' stroke-opacity='0.21' stroke-width='0.83' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M25.5 279.6Q33.0 278.2 43.7 274.5' stroke='%23ffffff' stroke-opacity='0.74' stroke-width='0.83'/%3E%3Cpath d='M168.8 73.7A50.2 50.2 0 0 1 151.7 94.0' stroke='%235a5246' stroke-opacity='0.18' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M168.8 73.7A50.2 50.2 0 0 1 151.7 94.0' stroke='%23ffffff' stroke-opacity='0.64' stroke-width='0.68'/%3E%3Cpath d='M388.2 167.0A34.8 34.8 0 0 1 392.8 184.4' stroke='%235a5246' stroke-opacity='0.14' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M388.2 167.0A34.8 34.8 0 0 1 392.8 184.4' stroke='%23ffffff' stroke-opacity='0.5' stroke-width='0.68'/%3E%3Cpath d='M125.2 158.0A27.1 27.1 0 0 1 108.8 160.5' stroke='%235a5246' stroke-opacity='0.18' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M125.2 158.0A27.1 27.1 0 0 1 108.8 160.5' stroke='%23ffffff' stroke-opacity='0.64' stroke-width='0.68'/%3E%3C/svg%3E") center / cover no-repeat;
  /* faint everywhere (15%), lit inside the travelling band */
  -webkit-mask-image: linear-gradient(115deg, rgba(0, 0, 0, 0.12) 0%, rgba(0, 0, 0, 0.12) 34%, #000 44%, #000 52%, rgba(0, 0, 0, 0.12) 62%, rgba(0, 0, 0, 0.12) 100%);
  mask-image: linear-gradient(115deg, rgba(0, 0, 0, 0.12) 0%, rgba(0, 0, 0, 0.12) 34%, #000 44%, #000 52%, rgba(0, 0, 0, 0.12) 62%, rgba(0, 0, 0, 0.12) 100%);
  -webkit-mask-size: 260% 100%;
  mask-size: 260% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  animation: catch-light 7s ease-in-out infinite;
}
.wave .glass-scratch { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='90' viewBox='0 0 420 90' fill='none' stroke-linecap='round'%3E%3Cpath d='M269.6 73.1Q225.1 64.2 185.3 55.6' stroke='%235a5246' stroke-opacity='0.21' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M269.6 73.1Q225.1 64.2 185.3 55.6' stroke='%23ffffff' stroke-opacity='0.74' stroke-width='0.68'/%3E%3Cpath d='M376.5 63.6Q333.7 67.6 295.0 68.1' stroke='%235a5246' stroke-opacity='0.19' stroke-width='0.83' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M376.5 63.6Q333.7 67.6 295.0 68.1' stroke='%23ffffff' stroke-opacity='0.69' stroke-width='0.83'/%3E%3Cpath d='M394.1 21.6Q371.7 24.1 353.3 28.8' stroke='%235a5246' stroke-opacity='0.20' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M394.1 21.6Q371.7 24.1 353.3 28.8' stroke='%23ffffff' stroke-opacity='0.71' stroke-width='0.68'/%3E%3Cpath d='M129.5 35.3Q148.7 23.7 171.8 16.4' stroke='%235a5246' stroke-opacity='0.18' stroke-width='0.83' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M129.5 35.3Q148.7 23.7 171.8 16.4' stroke='%23ffffff' stroke-opacity='0.65' stroke-width='0.83'/%3E%3Cpath d='M337.4 43.7Q344.7 47.5 354.2 51.5' stroke='%235a5246' stroke-opacity='0.26' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M337.4 43.7Q344.7 47.5 354.2 51.5' stroke='%23ffffff' stroke-opacity='0.94' stroke-width='0.68'/%3E%3Cpath d='M71.2 129.9A58.2 58.2 0 0 1 51.2 99.0' stroke='%235a5246' stroke-opacity='0.18' stroke-width='0.68' transform='translate%280.4 0.5%29'/%3E%3Cpath d='M71.2 129.9A58.2 58.2 0 0 1 51.2 99.0' stroke='%23ffffff' stroke-opacity='0.64' stroke-width='0.68'/%3E%3C/svg%3E"); }
/* The lit band follows the reflection: left at rest, right at the top of the float */
@keyframes catch-light {
  0%, 100% { -webkit-mask-position: 92.9% 0; mask-position: 92.9% 0; }
  50%      { -webkit-mask-position: 50.3% 0; mask-position: 50.3% 0; }
}
.is-turning .glass-scratch { animation-play-state: paused; }
/* Night: the scratches stay faintly visible everywhere, and still light up in the band */
body.dark-mode .glass-scratch {
  opacity: 0.55;
  -webkit-mask-image: linear-gradient(115deg, rgba(0, 0, 0, 0.32) 0%, rgba(0, 0, 0, 0.32) 34%, #000 44%, #000 52%, rgba(0, 0, 0, 0.32) 62%, rgba(0, 0, 0, 0.32) 100%);
  mask-image: linear-gradient(115deg, rgba(0, 0, 0, 0.32) 0%, rgba(0, 0, 0, 0.32) 34%, #000 44%, #000 52%, rgba(0, 0, 0, 0.32) 62%, rgba(0, 0, 0, 0.32) 100%);
}
@media (prefers-reduced-motion: reduce) { .glass-scratch { animation: none; } }
body.lite .glass-scratch { display: none; }

/* ---------- Now playing: plain type on the card, like a station name ---------- */
.song-card {
  padding: 2px 8px 0;
  text-align: center;
  transition: transform 0.25s var(--ease);
}
.song-card.nudge { transform: translate3d(-10px, 0, 0); }
.song-name {
  margin: 0 0 4px;
  font-family: var(--ui);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.artist-name {
  margin: 0;
  font-family: var(--digit);
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The waveform window: sunken, light, thin bars (script.js draws them) */
.wave {
  border-radius: 18px;
  padding: 10px 14px;
  background: var(--well);
  box-shadow: var(--press), var(--edge);
}
body.lite .wave { box-shadow: inset 0 0 0 1px var(--line); }
#wave { display: block; width: 100%; height: 100%; }

/* ---------- Buttons: soft raised keys ---------- */
.neu-btn {
  position: relative;
  border: 0;
  border-radius: 16px;
  background: var(--cream);
  color: var(--ink);
  min-height: 48px;
  padding: 0 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  cursor: pointer;
  font-family: var(--ui);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0;
  box-shadow: var(--raise), var(--edge);
  transition: transform 0.15s var(--ease), box-shadow 0.15s var(--ease), color 0.15s;
}
.neu-btn:active,
.neu-btn[aria-pressed="true"] {
  transform: scale(0.97);
  box-shadow: var(--press), var(--edge);
}
.neu-btn:disabled { opacity: 0.5; cursor: default; transform: none; }
.neu-btn:focus-visible,
.corner-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

.neu-btn--accent { color: var(--gold-deep); }
.neu-btn--wide { width: 100%; }

/* Dislike | Play | Save: play stays in the middle even while Save is hidden */
.controls {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
}
.controls #skip-btn { justify-self: end; }
.controls #save-btn { justify-self: start; }

/* Front-page keys, as in the reference: a bevelled near-white face (light from the
   top left), a wide faint shadow, and small grey icons. Pressing still sinks the key in. */

.controls .neu-btn:active,
.controls .neu-btn[aria-pressed="true"] {
  background: var(--btn-pressed);
  box-shadow: var(--press), var(--edge);
}

/* Play: a raised outer ring with a slightly dished inner disc, like a dial cap.
   The press is the same as before (it sinks in), and the icon stays caramel. */
.neu-btn--hero {
  border-radius: 50%;
  color: var(--gold-deep);
  padding: 0;
}
.neu-btn--hero::before {
  content: "";
  position: absolute;
  inset: 7px;
  border-radius: 50%;
  background: linear-gradient(145deg, var(--key-dish-top), var(--key-dish-bottom));
  box-shadow: inset 0 2px 5px var(--key-shadow), 0 0 0 1px rgba(90, 76, 55, 0.06);
}
/* While playing: the whole key, ring included, sinks to the display's tone */
.is-live .neu-btn--hero,
.is-connecting .neu-btn--hero {
  background: var(--well);
  box-shadow: inset 0 3px 8px var(--key-shadow), inset 0 0 0 1px rgba(90, 76, 55, 0.06), var(--edge);
}
.is-live .neu-btn--hero::before,
.is-connecting .neu-btn--hero::before {
  background: var(--well);
  box-shadow: inset 0 2px 6px var(--key-shadow);
}
.neu-btn--hero:active::before { box-shadow: none; background: transparent; }
.neu-btn--hero .icon { position: relative; width: 30px; height: 30px; }

/* Dislike and save: rounded-square keys like the skip keys in the photo */
.neu-btn--round {
  width: 60px;
  height: 60px;
  border-radius: 18px;
  color: var(--key-icon);
  padding: 0;
}
.neu-btn--round .icon { width: 22px; height: 22px; }
.neu-btn--round, .neu-btn--small, #skip-btn, #skip-btn[aria-pressed="true"] { color: var(--gold-deep); }
.neu-btn--small { width: 60px; height: 60px; border-radius: 18px; }

body.lite .controls .neu-btn { background: var(--cream); box-shadow: var(--edge); }
#save-btn.is-busy .icon { animation: blink 0.9s steps(2, jump-none) infinite; }
#skip-btn.is-busy .icon { opacity: 0.45; }

.vote-badge {
  position: absolute;
  top: -6px;
  right: -8px;
  min-width: 30px;
  padding: 2px 6px;
  border-radius: 8px;
  background: var(--gold-fill);
  color: #fffaf1;
  font-family: var(--digit);
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 1.3;
}

.attribution {
  text-align: right;
  font-family: var(--digit);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  color: var(--ink-soft);
  opacity: 0.8;
}
/* "made by Hootan" links to Hootan's site: looks like plain text, no underline.
   (The padding makes it easier to tap; the negative margin keeps it where it was.) */
.made-by { color: inherit; text-decoration: none; display: inline-block; padding: 8px 0; margin: -8px 0; -webkit-tap-highlight-color: transparent; }
.made-by:focus-visible { outline: 1px solid currentColor; outline-offset: 2px; border-radius: 3px; }

/* ---------- Studio (flat: borders and tone only, no shadows) ---------- */
.studio {
  font-family: var(--sans);
  letter-spacing: 0.012em;
  display: flex;
  flex-direction: column;
  gap: 22px;
}
body.lite .studio { box-shadow: none; }
.studio .corner-btn { box-shadow: none; border: 1.5px solid var(--line); opacity: 1; background: var(--btn-face); }
.studio .corner-btn:active { transform: none; background: var(--btn-pressed); box-shadow: none; }

.studio-head { margin-right: 52px; }
.studio-title {
  margin: 0;
  font-family: var(--sans);
  font-size: 1.75rem;
  line-height: 1.15;
}
.studio-greeting { margin: 4px 0 0; color: var(--ink-soft); font-size: 0.95rem; }
.studio-section { margin: 0 0 6px; font-size: 0.95rem; font-weight: 700; color: var(--ink-soft); }

/* Two primary actions, same size, side by side */
.actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.action {
  display: grid;
  justify-items: start;
  align-content: end;
  gap: 2px;
  min-height: 132px;
  padding: 16px;
  border: 1.5px solid var(--line);
  border-radius: 18px;
  background: var(--btn-face);
  color: var(--ink);
  font-family: var(--sans);
  text-align: left;
  cursor: pointer;
  transition: background-color 0.12s, border-color 0.12s;
}
.action-icon { width: 34px; height: 34px; color: var(--gold-deep); margin-bottom: auto; }
.action-label { font-size: 1.15rem; font-weight: 700; }
.action-sub { font-size: 0.8rem; color: var(--ink-soft); }
.action:hover { border-color: var(--gold); }
.action:active, .action.is-busy { background: var(--btn-pressed); border-color: var(--gold-deep); }
.action:disabled { opacity: 0.5; cursor: default; }
.action:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* Scheduled list */
.queue-list { list-style: none; margin: 0; padding: 0; border-top: 1.5px solid var(--line); }
.queue-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 40px 40px;
  align-items: center;
  gap: 6px;
  min-height: 56px;
  padding: 6px 0;
  border-bottom: 1px solid var(--line);
}
.queue-time { font-weight: 700; color: var(--gold-deep); font-variant-numeric: tabular-nums; }
.queue-body { min-width: 0; display: grid; }
.queue-name { display: block; width: 100%; padding: 0; border: 0; background: none; color: inherit; font-family: inherit; text-align: left; cursor: text; font-size: 1.02rem; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.queue-meta { font-size: 0.82rem; color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.queue-name:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 4px; }
.queue-rename {
  width: 100%;
  min-width: 0;
  padding: 3px 6px;
  border: 1.5px solid var(--gold);
  border-radius: 8px;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.02rem;
  font-weight: 700;
  outline: none;
}
.queue-empty { padding: 14px 0; color: var(--ink-soft); font-size: 0.92rem; border-bottom: 1px solid var(--line); }
.queue-del, .queue-edit {
  width: 40px;
  height: 40px;
  border: 1.5px solid var(--line);
  border-radius: 12px;
  background: var(--btn-face);
  color: var(--ink-soft);
  display: grid;
  place-items: center;
  cursor: pointer;
}
.queue-del:hover, .queue-edit:hover { border-color: var(--gold); }
.queue-del:active, .queue-edit:active { background: var(--btn-pressed); }
.queue-edit { color: var(--gold-deep); }
.queue-del.confirm { border-color: var(--danger); }
.queue-del:focus-visible, .queue-edit:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* Server status: a small piece of the black display, three lines, no scrolling */
.status-strip {
  padding: 10px 14px 11px;
  border-radius: 22px;
  background: var(--display);
  color: var(--display-ink);
}
.status-strip .plate-label { margin-bottom: 5px; }
.status-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-rows: repeat(3, 1.35rem);
  height: calc(3 * 1.35rem);
  overflow: hidden;
}
.status-list li { display: flex; align-items: baseline; gap: 10px; min-width: 0; line-height: 1.35rem; }
.status-list time { flex: none; font-size: 0.72rem; }
.status-list span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.88rem; }

.studio-foot { margin-top: auto; display: flex; justify-content: space-between; align-items: center; font-size: 0.8rem; color: var(--ink-soft); }
.studio-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 40px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--gold-deep);
  font-family: var(--sans);
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
}
.studio-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* ---------- Curator tools (flat, same type as the studio) ---------- */
.curator { grid-template-columns: minmax(0, 1fr); gap: 22px; }

/* Tiers */
.tiers { display: grid; gap: 8px; }

.tiers-search {
  width: 150px;
  min-height: 34px;
  padding: 0 10px;
  border: 1.5px solid var(--line);
  border-radius: 10px;
  background: transparent;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 0.85rem;
}
.tiers-search:focus { outline: 2px solid var(--gold); outline-offset: 1px; }
.tiers-bar { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.tiers-bar span {
  padding: 6px 4px;
  border: 1.5px solid var(--line);
  border-radius: 10px;
  text-align: center;
  font-size: 0.72rem;
  color: var(--ink-soft);
}
.tiers-bar b { display: block; font-size: 1.05rem; color: var(--ink); font-variant-numeric: tabular-nums; }
.tiers-list { display: grid; gap: 4px; max-height: 420px; overflow-y: auto; overscroll-behavior: contain; }

.tier-row {
  /* Rows off screen are skipped when the browser draws: long lists stay fast */
  content-visibility: auto;
  contain-intrinsic-size: auto 45px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) repeat(3, 36px);
  align-items: center;
  gap: 4px;
  min-height: 44px;
  border-bottom: 1px solid var(--line);
}
.tier-row-body { min-width: 0; display: grid; }
.tier-more {
  width: 100%;
  min-height: 44px;
  margin: 2px 0 6px;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--gold-deep);
  cursor: pointer;
}
.tier-more:hover { text-decoration: underline; }
.tier-more:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; border-radius: 10px; }
.tier-title { font-size: 0.92rem; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tier-btn {
  width: 36px;
  height: 36px;
  border: 1.5px solid var(--line);
  border-radius: 10px;
  background: var(--btn-face);
  color: var(--ink-soft);
  display: grid;
  place-items: center;
  cursor: pointer;
  position: relative;
}
.tier-btn:hover { border-color: var(--gold); }
.tier-btn:active { background: var(--btn-pressed); }
.tier-btn:disabled { background: transparent; border-color: transparent; }
.tier-btn:disabled { opacity: 0.25; cursor: default; }
.tier-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
.tier-btn.is-on { color: var(--gold-deep); }
.tier-btn small { position: absolute; right: 3px; bottom: 1px; font-size: 0.6rem; font-weight: 700; }
.tiers-empty { padding: 10px 0; font-size: 0.88rem; color: var(--ink-soft); }

/* ---------- Dialogs ---------- */
.sheet {
  width: min(440px, calc(100vw - 24px));
  max-height: calc(100dvh - 32px);
  padding: 22px 18px 18px;
  border: 0;
  border-radius: var(--radius);
  background: var(--cream);
  color: var(--ink);
  box-shadow: var(--raise-lg), var(--edge);
  overflow: auto;
  overscroll-behavior: contain;
}
.sheet--compact { width: min(320px, calc(100vw - 24px)); padding-top: 56px; }
.sheet::backdrop, .flow::backdrop { background: rgba(28, 24, 18, 0.55); }
body.lite .sheet { box-shadow: var(--edge); }

.input {
  width: 100%;
  min-width: 0;
  max-width: 100%;
  min-height: 46px;
  padding: 10px 12px;
  border: 0;
  border-radius: 12px;
  background: var(--cream-deep);
  color: var(--ink);
  font-size: 1.02rem;
  box-shadow: var(--press-sm), var(--edge);
  outline: none;
}
.input:focus { box-shadow: var(--press-sm), 0 0 0 2px var(--gold); }
.input::placeholder { color: var(--ink-soft); opacity: 0.7; }

.login-form { display: grid; gap: 14px; }
/* Labels sit above the boxes, small mono caps like the display's labels */
.field { display: grid; gap: 6px; }
.field-label {
  padding-left: 4px;
  font-family: var(--digit);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--gold-deep);
}
/* Password with a show/hide key inside the right edge */
.pw-wrap { position: relative; }
.pw-wrap .input { padding-right: 56px; }
.pw-toggle {
  position: absolute;
  top: 50%;
  right: 6px;
  width: 40px;
  height: 36px;
  margin-top: -18px;
  border: 0;
  border-radius: 10px;
  background: linear-gradient(145deg, var(--key-top), var(--key-bottom));
  color: var(--ink-soft);
  display: grid;
  place-items: center;
  cursor: pointer;
  box-shadow: var(--raise-xs), var(--edge);
}
.pw-toggle:active { background: var(--btn-pressed); box-shadow: var(--press-sm), var(--edge); }
.pw-toggle[aria-pressed="true"] { color: var(--gold-deep); }
.pw-toggle:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.form-error { margin: 0; color: var(--danger); font-size: 0.95rem; text-align: center; }

/* ---------- Scheduling flow (flat, same type as the studio) ---------- */
.flow {
  width: min(400px, calc(100vw - 24px));
  max-height: calc(100dvh - 24px);
  padding: 18px 18px 20px;
  border-radius: 24px;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  letter-spacing: 0.012em;
  overflow: auto;
  overscroll-behavior: contain;
}
.flow-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.flow-title { margin: 0; font-size: 1.3rem; font-weight: 700; line-height: 1.2; }
.flow-close {
  flex: none;
  width: 40px;
  height: 40px;
  border: 1.5px solid var(--line);
  border-radius: 50%;
  background: none;
  color: var(--ink-soft);
  display: grid;
  place-items: center;
  cursor: pointer;
}

.flow-file {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px 10px;
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
  font-size: 0.85rem;
}
.flow-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; }
.flow-file-state { color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.flow-file-state.is-error { color: var(--danger); }
.flow-bar { grid-column: 1 / -1; height: 3px; background: var(--line); overflow: hidden; }
.flow-bar i { display: block; height: 100%; background: var(--gold); transform-origin: left; transform: scaleX(0); transition: transform 0.2s linear; }

.step { display: grid; gap: 12px; }
.step-lead { margin: 0; font-size: 1.1rem; font-weight: 700; }
.step-note { margin: 0; font-size: 0.88rem; color: var(--ink-soft); }
.step-error { margin: 0; font-size: 0.88rem; color: var(--danger); }
.step-actions { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 10px; margin-top: 4px; }

.btn {
  min-height: 48px;
  padding: 0 16px;
  border: 1.5px solid var(--line);
  border-radius: 14px;
  background: var(--btn-face);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1rem;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  cursor: pointer;
}
.btn:active { background: var(--btn-pressed); border-color: var(--gold-deep); }
.btn--primary { background: var(--gold); border-color: var(--gold); color: #1f1d19; }
.btn--primary:active { border-color: var(--gold-deep); }
.btn:disabled { opacity: 0.45; cursor: default; }
.btn--wide { width: 100%; }
.btn:focus-visible, .flow-close:focus-visible, .icon-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* Recording */
.rec-clock {
  margin: 8px 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  font-size: 3rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}
.rec-dot { width: 14px; height: 14px; border-radius: 50%; background: var(--danger); animation: blink 1.2s steps(2, jump-none) infinite; }
.step[data-step="record"] .step-note { text-align: center; margin-bottom: 6px; }

/* When: summary, calendar, tuner */
.when-summary { margin: 0; font-size: 1.05rem; font-weight: 700; }

.cal { border: 1.5px solid var(--line); border-radius: 16px; padding: 4px 6px 6px; }
.cal-bar { display: grid; grid-template-columns: 36px 1fr 36px; align-items: center; margin-bottom: 0; }
.cal-month { text-align: center; font-weight: 700; font-size: 0.95rem; }
.icon-btn {
  width: 36px;
  height: 34px;
  border: 0;
  border-radius: 12px;
  background: var(--btn-face);
  color: var(--ink);
  display: grid;
  place-items: center;
  cursor: pointer;
}
.icon-btn:active { background: var(--btn-pressed); }
.icon-btn:disabled { opacity: 0.25; cursor: default; }
.cal-week, .cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px 2px; }
.cal-week span { text-align: center; font-size: 0.7rem; color: var(--ink-soft); padding: 0 0 2px; }
.cal-day {
  height: 30px;
  border: 1.5px solid transparent;
  border-radius: 10px;
  background: none;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 0.92rem;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.cal-day.is-out { color: var(--ink-soft); opacity: 0.5; }
.cal-day.is-today { font-weight: 700; }
.cal-day[aria-pressed="true"] { background: var(--gold); border-color: var(--gold); color: #1f1d19; font-weight: 700; opacity: 1; }
.cal-day:disabled { opacity: 0.22; cursor: default; }
.cal-day:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }

/* The tuner: hour and minute wheels behind one gold window, like a radio dial */
.tuner {
  --row: 34px;
  position: relative;
  display: flex;
  justify-content: center;
  align-items: stretch;
  gap: 0;
  height: calc(var(--row) * 3);
  padding: 0 10px;
  border: 1.5px solid var(--line);
  border-radius: 16px;
  overflow: hidden;
  /* tick marks down both edges, one per row */
  background:
    repeating-linear-gradient(to bottom, var(--tick) 0 1.5px, transparent 1.5px var(--row)) left 0 top calc(var(--row) / 2 - 0.75px) / 8px 100% no-repeat,
    repeating-linear-gradient(to bottom, var(--tick) 0 1.5px, transparent 1.5px var(--row)) right 0 top calc(var(--row) / 2 - 0.75px) / 8px 100% no-repeat;
}
.tuner::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: var(--row);
  height: var(--row);
  border-top: 1.5px solid var(--gold);
  border-bottom: 1.5px solid var(--gold);
  background: var(--gold-soft);
  pointer-events: none;
}
.tuner-sep { align-self: center; font-size: 1.4rem; font-weight: 700; position: relative; }
.wheel {
  position: relative;
  width: 64px;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  outline: none;
}
.wheel::-webkit-scrollbar { display: none; }
.wheel--ampm { width: 56px; }
.wheel-list { padding: var(--row) 0; }
.wheel-item {
  height: var(--row);
  line-height: var(--row);
  text-align: center;
  scroll-snap-align: center;
  font-size: 1.3rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
  opacity: 0.45;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  transition: opacity 0.12s, color 0.12s;
}
.wheel--ampm .wheel-item { font-size: 1rem; }
.wheel-item.on { opacity: 1; color: var(--ink); font-weight: 700; font-size: 1.4rem; }
.wheel:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; border-radius: 10px; }

/* Repeat: today + the next six days */
.day-row { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.day-btn {
  display: grid;
  justify-items: center;
  gap: 1px;
  padding: 8px 0 7px;
  border: 1.5px solid var(--line);
  border-radius: 12px;
  background: var(--btn-face);
  color: var(--ink);
  font-family: var(--sans);
  cursor: pointer;
}
.day-btn:active { background: var(--btn-pressed); }
.day-btn small { font-size: 0.68rem; color: var(--ink-soft); }
.day-btn b { font-size: 1rem; font-variant-numeric: tabular-nums; }
.day-btn[aria-pressed="true"] { background: var(--gold); border-color: var(--gold); color: #1f1d19; }

.day-btn.is-first { cursor: default; }
.day-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* Done */
.step--done { justify-items: center; text-align: center; padding: 10px 0 6px; }
.done-mark {
  width: 64px;
  height: 64px;
  border: 1.5px solid var(--gold);
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: var(--gold-deep);
}
.done-mark .icon { width: 34px; height: 34px; }

/* =====================================================================
   One look everywhere: the front page's language applied to the studio,
   charts, tiers, dialogs and the scheduling flow.
   - Buttons are raised keys: a face a touch brighter than the card, a dark
     drop shadow; pressed they sink in and turn darker than the card.
   - Information panels (status, numbers, charts, calendar, tuner) are sunken
     wells, like the station display.
   - Chosen options are filled caramel with light text, no shadow.
   ===================================================================== */
.studio { border: 0; box-shadow: var(--raise-lg), var(--edge); }
.flow { border: 0; box-shadow: var(--raise-lg), var(--edge); }
.studio-title { font-weight: 700; letter-spacing: -0.02em; }

/* Keys */
.studio .corner-btn,
.action, .btn, .queue-del, .queue-edit, .tier-btn, .icon-btn, .day-btn, .flow-close {
  border: 0;
  background: linear-gradient(145deg, var(--key-top), var(--key-bottom));
  color: var(--ink);
  box-shadow: var(--raise-xs), var(--edge);
  transition: background-color 0.12s, box-shadow 0.12s, transform 0.12s var(--ease);
}
.action { box-shadow: var(--raise), var(--edge); }
.btn, .studio .corner-btn, .flow-close { box-shadow: var(--raise-sm), var(--edge); }
.queue-del, .tier-btn { color: var(--ink-soft); }
.queue-edit, .tier-btn.is-on, .studio .corner-btn { color: var(--gold-deep); }

.studio .corner-btn:active,
.action:active, .action.is-busy, .btn:active, .queue-del:active, .queue-edit:active, .tier-btn:active,
.icon-btn:active, .day-btn:active, .flow-close:active {
  background: var(--btn-pressed);
  box-shadow: var(--press-sm), var(--edge);
  transform: none;
}
.queue-del.confirm { color: var(--danger); box-shadow: var(--raise-xs), inset 0 0 0 1.5px var(--danger); }
.tier-btn:disabled, .icon-btn:disabled { background: transparent; box-shadow: none; }

/* Chosen options: filled caramel, flat */
.btn--primary,
.day-btn[aria-pressed="true"], .cal-day[aria-pressed="true"] {
  background: var(--gold-fill);
  color: #fffaf1;
  box-shadow: none;
}
.btn--primary { box-shadow: var(--raise-sm), var(--edge); }
.btn--primary:active { background: #7c562a; color: #fffaf1; box-shadow: var(--press-sm), var(--edge); }
.day-btn[aria-pressed="true"] small { color: rgba(255, 250, 241, 0.8); }
.cal-day.is-today { border-color: var(--scale); }

/* Wells */
.status-strip, .tiers-bar span, .cal, .tuner {
  border: 0;
  background-color: var(--well);
  color: var(--well-ink);
  box-shadow: var(--press-sm), var(--edge);
}
.input, .tiers-search, .queue-rename {
  border: 0;
  background: var(--well);
  color: var(--well-ink);
  box-shadow: var(--press-sm), var(--edge);
}
.tiers-search:focus, .queue-rename:focus { outline: 2px solid var(--gold); outline-offset: 1px; }
.status-strip .plate-label { color: var(--gold-deep); }
.status-list time { color: var(--gold-deep); font-family: var(--digit); }
.status-list .log-error { color: var(--danger); }
.status-list .log-warn { color: var(--ink-soft); opacity: 1; }

body.lite .studio, body.lite .flow { box-shadow: var(--edge); }

/* ---------- Small screens (3.6" 1280x720 ≈ 280–360 css px wide) ---------- */
@media (max-width: 360px) {
  .stage { padding-left: 10px; padding-right: 10px; }
  .deck { padding: 20px 14px 14px; border-radius: 24px; }
  .brand { gap: 12px; margin-bottom: 14px; }

  h1 { font-size: 1.85rem; }
  .corner-btn.brand-btn { margin-right: -4px; }   /* the display is 4 px wider here */
  .plate { margin: 0 -4px 14px; padding: 14px 14px 12px; min-height: 186px; }
  .plate-status { font-size: 0.98rem; }
  .song-name { font-size: 1.5rem; }
  .neu-btn--hero { width: 80px; height: 80px; border-radius: 26px; }
  .neu-btn--hero .icon--xl { width: 38px; height: 38px; }
  .neu-btn--round { width: 56px; height: 56px; }
  .action { min-height: 116px; padding: 12px; }
  .flow { padding: 14px 12px 16px; }
}

@media (max-width: 300px) {
  h1 { font-size: 1.6rem; }

  .plate-status { font-size: 1.15rem; }
  .news-list li { font-size: 0.92rem; }
  .song-name { font-size: 1.25rem; }
  .artist-name { font-size: 0.74rem; }

  .day-row { gap: 4px; }
  .day-btn small { font-size: 0.6rem; }
  .wheel { width: 54px; }
  .input { font-size: 0.92rem; padding: 10px 8px; }
  .actions { gap: 8px; }
  .queue-item { grid-template-columns: minmax(0, 1fr) 38px 38px; gap: 4px; }
}

/* Short portrait screens */
@media (max-height: 640px) and (orientation: portrait) {
  .face--front { min-height: calc(100dvh - 32px); }
  .stage { padding-top: 12px; padding-bottom: calc(12px + env(safe-area-inset-bottom)); }
  .brand { margin-bottom: 12px; }
  .plate { min-height: 170px; }
  .song-card { padding: 0 8px; margin-bottom: 10px; }

}

/* Phone in landscape (e.g. 1280x720 turned sideways): two columns */
@media (orientation: landscape) and (max-height: 520px) {
  .stage { padding: 10px max(14px, env(safe-area-inset-right)) 10px max(14px, env(safe-area-inset-left)); }
  .float-wrap { max-width: 860px; animation: none; }
  .face--front {
    display: grid;
    grid-template-columns: 1.1fr 1fr;
    grid-template-rows: auto 1fr auto auto auto;
    column-gap: 18px;
    padding: 16px 18px 12px;
  }
  .face--front .brand { grid-column: 1; grid-row: 1; margin-bottom: 10px; }
  .face--front .plate { grid-column: 1; grid-row: 2 / span 4; margin: 0; min-height: 0; }
  .face--front .song-card { grid-column: 2; grid-row: 2; align-self: end; margin: 52px 0 10px; }
  .face--front .wave { grid-column: 2; grid-row: 3; height: 40px; margin-bottom: 12px; }
  .face--front .controls { grid-column: 2; grid-row: 4; }

  .face--front .attribution { grid-column: 2; grid-row: 5; margin-top: 8px; }

  h1 { font-size: 1.7rem; }
  .neu-btn--hero { width: 76px; height: 76px; }
  .neu-btn--hero::before { inset: 6px; }
  .neu-btn--round, .neu-btn--small { width: 52px; height: 52px; border-radius: 16px; }
  .plate-scale { margin: 4px 2px 2px; }
}

@media (min-width: 720px) and (min-height: 700px) {
  .deck { padding: 32px 30px 22px; }
}

@media (prefers-reduced-motion: reduce) {
  .float-wrap { animation: none; }
  .rec-dot { animation: none; }
  .song-card, .neu-btn, .corner-btn { transition: none; }
  .face { transition: none !important; }
  .flip, .float-wrap { transition: none; }
  .is-live .onair::before, .is-connecting .dots i, .is-live .plate-scale i { animation: none; }
}

/* Lite: drop the remaining motion */
body.lite .neu-btn, body.lite .corner-btn, body.lite .song-card { transition: none; }
body.lite .is-live .onair::before, body.lite .is-connecting .dots i, body.lite .is-live .plate-scale i { animation: none; }
body.lite .song-card.nudge { transform: none; }

/* Login / studio button sits in the header row, not in the card's corner */
.face--front .brand { margin-right: 0; }
.corner-btn.brand-btn {
  position: relative;
  top: auto;
  right: auto;
  margin-left: auto;
  align-self: center;
  flex: none;
}

/* Login / studio button: just the icon, no box, with the same dark drop shadow as
   everything raised. Pressed, it settles down and the shadow tightens. */
.corner-btn.brand-btn {
  width: 40px;
  height: 40px;
  background: none;
  box-shadow: none;
  border-radius: 12px;
  color: var(--gold-deep);
  opacity: 1;
}
.corner-btn.brand-btn .icon {
  width: 26px;
  height: 26px;
  filter: drop-shadow(1.5px 3px 3px var(--drop-wide)) drop-shadow(0.5px 1px 1px var(--drop-near));
  transition: transform 0.15s var(--ease), filter 0.15s var(--ease);
}
.corner-btn.brand-btn:active { transform: none; background: none; box-shadow: none; }
.corner-btn.brand-btn:active .icon {
  transform: translateY(1.5px);
  filter: drop-shadow(0.5px 1px 1px var(--drop-near));
}
body.lite .corner-btn.brand-btn .icon { filter: none; }
.corner-btn.brand-btn { place-items: center end; }   /* the icon itself lines up with the display edge */

/* ---------- Bottom icons: brushed caramel metal, many fine scratches ----------
   The shine and the scratch glints come from the card's one light: each icon's band moves
   to where the shared beam is over that icon (dislike 20%, play 46%, save 73% across the
   card; the beam turns back just before the middle, so play is only grazed), on the float's own 7 s ease-in-out cycle. */
.metal-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.k-s1 { stop-color: #c79d5c; } .k-s2 { stop-color: #8f6630; } .k-s3 { stop-color: #d2aa69; }
.k-s4 { stop-color: #7c5626; } .k-s5 { stop-color: #a87b3f; }
body.dark-mode .k-s1 { stop-color: #f0d39c; } body.dark-mode .k-s2 { stop-color: #c08f50; }
body.dark-mode .k-s3 { stop-color: #f2d8a4; } body.dark-mode .k-s4 { stop-color: #a87a3e; }
body.dark-mode .k-s5 { stop-color: #d0a466; }
.k-shine { animation: 7s ease-in-out infinite; }
.k-shine-1 { animation-name: k-shine-1; }
.k-shine-2 { animation-name: k-shine-2; }
.k-shine-3 { animation-name: k-shine-3; }
@keyframes k-shine-1 { 0%, 100% { transform: translate(-134px, 0); } 50% { transform: translate(106px, 0); } }
@keyframes k-shine-2 { 0%, 100% { transform: translate(-177px, 0); } 50% { transform: translate(3px, 0); } }
@keyframes k-shine-3 { 0%, 100% { transform: translate(-347px, 0); } 50% { transform: translate(-106px, 0); } }
.is-turning .k-shine { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .k-shine { animation: none; } }
body.lite .metal-icon .k-layer { display: none; }
body.lite .k-shine { animation: none; }

/* ---------- Fits a phone screen: no scrolling on the radio side ----------
   The card fills the visible height (browser bars included) and never goes past it. */
/* the radio sits in the middle of the screen; when a flamingo skywrites across the top,
   it floats down out of the way for a while and comes back (body.is-skywriting) */
.stage { padding-top: calc(38px + env(safe-area-inset-top)); padding-bottom: calc(38px + env(safe-area-inset-bottom)); }
/* (the glide itself is animated from the script, only while it happens: a transition left
   on the card all the time made some browsers redraw the page endlessly) */
.face--front { min-height: min(660px, calc(100dvh - 76px - env(safe-area-inset-top) - env(safe-area-inset-bottom))); }
.face--front.deck { padding: 20px 20px 14px; }
.face--front .brand { margin-bottom: 14px; }

.plate { min-height: 0; margin-bottom: 14px; }
.song-card { margin-bottom: 10px; }
.wave { height: 54px; margin-bottom: 16px; }
.neu-btn--hero { width: 80px; height: 80px; }
.neu-btn--round, .neu-btn--small { width: 54px; height: 54px; border-radius: 16px; }
.attribution { margin-top: 10px; }
@media (max-height: 640px) and (orientation: portrait) {
  .face--front.deck { padding: 16px 16px 10px; }
  .face--front .brand { margin-bottom: 10px; }

  .plate-status { font-size: 1.2rem; }
  .plate-scale { margin: 4px 2px 2px; }
  .wave { height: 46px; margin-bottom: 12px; }
  .neu-btn--hero { width: 70px; height: 70px; }
  .neu-btn--round, .neu-btn--small { width: 48px; height: 48px; border-radius: 14px; }
  .attribution { margin-top: 6px; }
}
@media (min-width: 720px) and (min-height: 700px) {
  .face--front.deck { padding: 28px 28px 18px; }
}

/* ---------- The three keys: matte and a little worn ----------
   Matte: an even face (no gloss gradient, no bright rim), so the light doesn't glint off
   them; the dark drop shadow stays. Worn: a fixed layer of fine dust specks and soft
   thumb smudges, a touch darker toward the edges, under the icons. */
.controls .neu-btn {
  background: linear-gradient(180deg, var(--key-top), var(--key-bottom) 140%);
  box-shadow: 5px 12px 24px var(--drop-wide), 1px 3px 7px var(--drop-near), var(--edge);
}
.controls .neu-btn::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='s' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' seed='3'/%3E%3CfeColorMatrix values='0 0 0 0 0.32 0 0 0 0 0.26 0 0 0 0 0.17 0 0 0 -3.2 0.89'/%3E%3C/filter%3E%3Cfilter id='m' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.035' numOctaves='3' seed='10'/%3E%3CfeColorMatrix values='0 0 0 0 0.32 0 0 0 0 0.26 0 0 0 0 0.17 0 0 0 1.20 -0.53'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url%28%23m%29'/%3E%3Crect width='160' height='160' filter='url%28%23s%29'/%3E%3C/svg%3E") 0 0 / 160px 160px,
    radial-gradient(120% 95% at 45% 35%, rgba(70, 55, 35, 0) 55%, rgba(70, 55, 35, 0.10) 100%);
}
body.dark-mode .controls .neu-btn::after {
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='s' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' seed='3'/%3E%3CfeColorMatrix values='0 0 0 0 0.85 0 0 0 0 0.8 0 0 0 0 0.7 0 0 0 -3.2 0.57'/%3E%3C/filter%3E%3Cfilter id='m' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.035' numOctaves='3' seed='10'/%3E%3CfeColorMatrix values='0 0 0 0 0.85 0 0 0 0 0.8 0 0 0 0 0.7 0 0 0 0.72 -0.32'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url%28%23m%29'/%3E%3Crect width='160' height='160' filter='url%28%23s%29'/%3E%3C/svg%3E") 0 0 / 160px 160px,
    radial-gradient(120% 95% at 45% 35%, rgba(0, 0, 0, 0) 55%, rgba(0, 0, 0, 0.18) 100%);
}
.controls .neu-btn .icon { position: relative; z-index: 1; }
.controls .neu-btn:active { box-shadow: var(--press), var(--edge); }
body.lite .controls .neu-btn::after { display: none; }

/* Wear only where a thumb goes: on the icon and just around it, fading out before the
   key's edge (and over the icon itself, so the metal looks handled too) */
.controls .neu-btn::after {
  z-index: 2;
  opacity: 0.8;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 0, #000 14px, rgba(0, 0, 0, 0) 24px);
  mask-image: radial-gradient(circle at 50% 50%, #000 0, #000 14px, rgba(0, 0, 0, 0) 24px);
}
/* Play: dirtier than the small keys, but still only on and just around the icon */
.controls .neu-btn--hero::after {
  opacity: 0.95;
  -webkit-mask-image: radial-gradient(circle closest-side at 50% 50%, #000 0, #000 50%, rgba(0, 0, 0, 0) 78%);
  mask-image: radial-gradient(circle closest-side at 50% 50%, #000 0, #000 50%, rgba(0, 0, 0, 0) 78%);
}
body.dark-mode .controls .neu-btn--hero::after { opacity: 0.75; }

/* ---------- Header: one rusted bronze nameplate (logo + name engraved) ---------- */
.face--front .brand { gap: 12px; }
.nameplate { flex: 1 1 auto; min-width: 0; max-width: 300px; filter: drop-shadow(3px 6px 8px var(--drop-wide)) drop-shadow(1px 1px 2px var(--drop-near)); }
.np { display: block; width: 100%; height: auto; }
body.lite .nameplate { filter: none; }
/* the shared light: the plate spans about 6-80% of the card */
.np-shine { animation: np-shine 7s ease-in-out infinite; }
@keyframes np-shine { 0%, 100% { transform: translate(-39px, 0); } 50% { transform: translate(204px, 0); } }
.is-turning .np-shine { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .np-shine { animation: none; transform: translate(90px, 0); } }
body.lite .np-shine { animation: none; transform: translate(90px, 0); }

/* Play key while playing: the ring sinks a shade darker than the display's tone */
.is-live .controls .neu-btn--hero,
.is-connecting .controls .neu-btn--hero {
  background: linear-gradient(rgba(70, 55, 32, 0.09), rgba(70, 55, 32, 0.09)), var(--well);
  box-shadow: inset 0 3px 9px var(--key-shadow), inset 0 0 0 1px rgba(90, 76, 55, 0.1), var(--edge);
}
body.dark-mode.is-live .controls .neu-btn--hero,
body.dark-mode .is-live .controls .neu-btn--hero,
body.dark-mode .is-connecting .controls .neu-btn--hero {
  background: linear-gradient(rgba(0, 0, 0, 0.22), rgba(0, 0, 0, 0.22)), var(--well);
}

/* Studio side up: the radio side's animations (float light, glass, metal shine) stop,
   since nobody can see them */
.is-flipped .face--front,
.is-flipped .face--front *,
.is-flipped .face--front *::before,
.is-flipped .face--front *::after { animation-play-state: paused !important; }

/* The waveform redraws every frame: a backdrop filter on its glass would re-filter what's
   behind it each time (heavy on phones), so its pane is drawn without one */
.wave::after { -webkit-backdrop-filter: none; backdrop-filter: none; }

/* Dirt where this listener actually taps (script: setupWear): the grime texture shows
   only through the smudges, which build up with repeated taps and fade over days.
   A key nobody has touched is clean. */
.controls .neu-btn::after,
.controls .neu-btn--hero::after {
  opacity: calc(0.4 + 0.55 * var(--wear, 0));        /* grime deepens with wear (setupWear) */
  transition: opacity 4s ease;
  -webkit-mask-image: var(--smudge, linear-gradient(transparent, transparent));
  mask-image: var(--smudge, linear-gradient(transparent, transparent));
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
body.dark-mode .controls .neu-btn::after { opacity: calc(0.34 + 0.46 * var(--wear, 0)); }
/* the icon's scratch layers fade in slowly as the key wears */
.controls .metal-icon .k-layer { transition: opacity 4s ease; }
/* under the grain, a faint greasy film, so a print reads as a print */
.controls .neu-btn::after { background-color: rgba(84, 64, 38, 0.13); }
body.dark-mode .controls .neu-btn::after { background-color: rgba(235, 222, 198, 0.07); }

/* ---------- Studio analytics: square tiles (script: curator) ----------
   Two framed groups of four squares, in the app's own colours: raised paper cards,
   a night card and a caramel card. Each tile leans towards the finger (3D), tap one to
   open it across the group with the details; three tiles draw in WebGL. */

.an-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.an-head .studio-section { margin: 0; }
.an-range { display: inline-flex; padding: 3px; border-radius: 999px; background: var(--well); box-shadow: inset 0 1px 3px var(--key-shadow); }
.an-range button {
  border: 0; background: none; color: var(--ink-soft); font: 600 0.72rem/1 var(--ui);
  padding: 7px 11px; border-radius: 999px; cursor: pointer;
}
.an-range button[aria-pressed="true"] { background: linear-gradient(180deg, var(--key-top), var(--key-bottom)); color: var(--ink); box-shadow: var(--raise-xs); }

.an-group {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  background: var(--cream-deep);
  box-shadow: inset 0 1px 4px var(--key-shadow), inset 0 -1px 0 var(--rim);
  perspective: 900px;
  grid-auto-flow: row dense;           /* an open tile never leaves a hole */
}

.an-tile { position: relative; aspect-ratio: 1; cursor: pointer; outline: none; transform-style: preserve-3d; }
.an-tile:focus-visible .an-face { box-shadow: 0 0 0 2px var(--gold), var(--raise-sm); }
.an-face {
  --rx: 0deg; --ry: 0deg; --gx: 50%; --gy: 0%;
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  border-radius: inherit;
  transform: rotateX(var(--rx)) rotateY(var(--ry));
  transform-style: preserve-3d;
  transition: transform 0.6s var(--ease), box-shadow 0.3s;
  box-shadow: 4px 10px 20px var(--drop-wide), 1px 2px 5px var(--drop-near), inset 0 1px 0 var(--rim);
}
.an-tile.is-tilting .an-face { transition: transform 0.12s linear, box-shadow 0.3s; box-shadow: 7px 18px 30px var(--drop-wide), 2px 4px 8px var(--drop-near), inset 0 1px 0 var(--rim); }
/* the light on the card follows the finger */
.an-face::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(70% 60% at var(--gx) var(--gy), rgba(255, 255, 255, 0.28), rgba(255, 255, 255, 0) 70%);
  opacity: 0; transition: opacity 0.4s;
}
.an-tile.is-tilting .an-face::after { opacity: 1; }
.an-tile--paper .an-face { background: linear-gradient(180deg, var(--key-top), var(--key-bottom)); color: var(--ink); }
.an-tile--night .an-face { background: linear-gradient(165deg, #2a2722, var(--display)); color: var(--display-ink); }
.an-tile--caramel .an-face { background: linear-gradient(160deg, #c39456, #966a34 80%); color: #fff6e6; }
body.dark-mode .an-tile--night .an-face { background: linear-gradient(165deg, #1b1916, #0b0a09); }

.an-title { display: flex; align-items: center; justify-content: space-between; font: 600 0.72rem/1.2 var(--ui); letter-spacing: 0.01em; opacity: 0.82; transform: translateZ(10px); }
.an-live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--flamingo); box-shadow: 0 0 0 3px rgba(240, 119, 156, 0.2); animation: an-pulse 2s ease-in-out infinite; }
@keyframes an-pulse { 50% { box-shadow: 0 0 0 6px rgba(240, 119, 156, 0); } }
.an-big { font: 700 2.7rem/1 var(--ui); letter-spacing: -0.04em; transform: translateZ(34px); }
.an-big--sm { font-size: 1.55rem; }
.an-sub { font: 500 0.68rem/1.3 var(--ui); opacity: 0.7; transform: translateZ(20px); }
.an-flags { font-size: 0.95rem; letter-spacing: 2px; transform: translateZ(26px); }
.an-3d, .an-flow { display: block; width: 100%; flex: 1 1 auto; min-height: 0; transform: translateZ(22px); }
.an-tile[data-tile="globe"] .an-3d { width: calc(100% + 12px); }
.an-chip {
  position: absolute; max-width: calc(100% - 20px);
  padding: 4px 8px; border-radius: 9px; background: rgba(30, 20, 8, 0.38); color: #fff6e6;
  font: 700 0.62rem/1.2 var(--digit); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transform: translateZ(30px);
}
.an-heat { flex: 1 1 auto; display: grid; grid-template-columns: repeat(var(--cols, 12), minmax(0, 1fr)); gap: 3px; transform: translateZ(18px); }
.an-cell { display: block; aspect-ratio: 1; border-radius: 2px; background: rgba(184, 137, 75, var(--a, 0.1)); }
.an-gauge { display: block; width: 100%; flex: 1 1 auto; min-height: 0; color: inherit; transform: translateZ(22px); }
.an-gauge-num { font: 700 26px var(--ui); fill: currentColor; letter-spacing: -1px; }
.an-gauge-cap { font: 500 9px var(--ui); fill: currentColor; opacity: 0.6; }
.an-curves { display: block; width: 100%; flex: 1 1 auto; min-height: 0; margin-top: 6px; color: inherit; transform: translateZ(22px); }

/* open: across the whole group, as tall as the details need */
.an-more { display: none; }
.an-tile.is-open { grid-column: 1 / -1; aspect-ratio: auto; cursor: default; }
.an-tile.is-open .an-face { position: relative; inset: auto; min-height: 320px; }
.an-tile.is-open .an-title { font-size: 0.82rem; cursor: pointer; }
.an-tile.is-open .an-title::after { content: "×"; font: 400 1.3rem/1 var(--ui); opacity: 0.6; margin-left: 10px; }
.an-tile.is-open .an-live-dot { margin-left: auto; }
.an-tile.is-open .an-more { display: block; margin-top: 14px; transform: translateZ(8px); }
.an-tile.is-open .an-3d { flex: none; height: 260px; }
.an-tile.is-open[data-tile="globe"] .an-3d { height: 300px; touch-action: none; cursor: grab; }
.an-tile.is-open .an-flow, .an-tile.is-open .an-gauge, .an-tile.is-open .an-curves { flex: none; height: 150px; }
.an-tile.is-open .an-heat { grid-template-columns: auto repeat(24, minmax(0, 1fr)); gap: 2px; }
.an-tile.is-open .an-big { margin-top: 8px; }
.an-tile.is-open .an-chip { position: static; display: inline-block; align-self: flex-start; }
.an-heat-day, .an-heat-hour { font: 600 0.55rem/1 var(--ui); opacity: 0.6; white-space: nowrap; align-self: center; }
.an-heat-day { padding-right: 4px; }
.an-heat-hour { overflow: visible; }

.an-h { margin: 14px 0 6px; font: 700 0.7rem/1.2 var(--ui); letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.65; }
.an-h:first-child { margin-top: 0; }
.an-note, .an-empty { margin: 0; font: 500 0.78rem/1.45 var(--ui); opacity: 0.75; }
.an-list { list-style: none; margin: 0; padding: 0; }
.an-list li { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 8px; padding: 7px 0; border-top: 1px solid rgba(127, 110, 85, 0.18); font: 500 0.8rem/1.3 var(--ui); }
.an-list li:first-child { border-top: 0; }
.an-list--songs li { grid-template-columns: minmax(0, 1.4fr) minmax(40px, 1fr) auto; }
.an-list .an-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.an-list b { font: 700 0.78rem var(--digit); }
.an-flag { font-size: 1rem; }
.an-share { position: relative; display: block; min-width: 0; }
.an-share i { display: block; height: 6px; border-radius: 3px; background: var(--gold); }
.an-tile--caramel .an-share i { background: #fff1d6; }
.an-share small { display: block; margin-top: 3px; font: 600 0.62rem/1 var(--digit); opacity: 0.75; }
.an-table { display: grid; gap: 0; font: 500 0.78rem/1.3 var(--ui); }
.an-tr { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1.3fr) 0.7fr 0.7fr; gap: 8px; align-items: center; padding: 7px 0; border-top: 1px solid rgba(255, 255, 255, 0.2); }
.an-tile--paper .an-tr { border-top-color: rgba(127, 110, 85, 0.18); }
.an-table--3 .an-tr { grid-template-columns: 1.4fr 1fr 1fr; }
.an-tr--head { border-top: 0; font: 700 0.6rem/1.2 var(--ui); letter-spacing: 0.06em; text-transform: uppercase; opacity: 0.7; }
.an-tr .an-name { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; overflow: hidden; }
.an-num { font: 700 0.78rem var(--digit); text-align: right; }
.an-now-pill { font: 700 0.56rem/1 var(--digit); font-style: normal; padding: 3px 5px; border-radius: 6px; background: var(--flamingo); color: #fff; }
.an-legend { list-style: none; margin: 0 0 6px; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 12px; }
.an-legend li { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 6px; font: 500 0.76rem var(--ui); }
.an-legend i { width: 8px; height: 8px; border-radius: 50%; }
.an-legend b { font: 700 0.74rem var(--digit); }
.an-credit { margin: 4px 4px 0; font: 500 0.62rem/1.3 var(--ui); opacity: 0.55; }
.an-credit a { color: inherit; }
/* the tier list keeps its own look inside the open Rotation tile */
.an-tile--night .an-more .step-note { color: inherit; opacity: 0.7; }
/* open Rotation: back to paper, so the tier list reads like the rest of the studio */
.an-tile[data-tile="tiers"].is-open .an-face { background: linear-gradient(180deg, var(--key-top), var(--key-bottom)); color: var(--ink); }

body.lite .an-face, body.lite .an-tile.is-tilting .an-face { transform: none; transition: none; }
body.lite .an-face::after { display: none; }
@media (prefers-reduced-motion: reduce) { .an-face { transform: none !important; } .an-live-dot { animation: none; } }

/* ---------- Analytics tiles: one consistent layout ----------
   Every tile: title at the top, the picture filling the middle, one footer line at the
   bottom, all on the same 12 px inset. Depth (translateZ) only while a finger tilts the
   card, so at rest everything lines up to the pixel. */
.curator { display: block; margin-top: 0; }
.an-head { margin-bottom: 12px; }
.an-group { gap: 10px; padding: 10px; margin-bottom: 12px; border-radius: 28px; }
.an-tile { border-radius: 18px; }
.an-face { padding: 12px; }
.an-tile.is-open .an-face { padding: 14px; }

.an-title, .an-big, .an-sub, .an-flags, .an-3d, .an-flow, .an-chip, .an-heat, .an-gauge, .an-curves {
  transform: translateZ(calc(var(--d, 0) * var(--z, 14px)));
  transition: transform 0.6s var(--ease);
}
.an-tile.is-tilting .an-face { --d: 1; }
.an-title { --z: 8px; flex: none; min-height: 16px; line-height: 16px; }
.an-big { --z: 30px; line-height: 0.95; }
.an-big--sm { margin-top: 4px; }
.an-sub, .an-chip { --z: 18px; }
.an-flags { --z: 22px; }
.an-3d, .an-flow, .an-gauge, .an-curves, .an-heat { --z: 16px; }

/* the footer line: always one line, always at the bottom */
.an-sub { flex: none; margin-top: 6px; line-height: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.an-tile[data-tile="now"] .an-sub { margin-top: auto; }
.an-flags { flex: none; margin-top: 4px; min-height: 18px; line-height: 18px; white-space: nowrap; overflow: hidden; }

.an-heat { align-content: center; }
.an-tile[data-tile="globe"] .an-3d { margin: 4px -6px 0; }
.an-chip { left: 12px; bottom: 12px; }
.an-tile.is-open .an-chip { margin-top: 10px; }
.an-big { margin-top: 4px; }
.an-3d, .an-flow, .an-gauge, .an-curves { margin-top: 4px; }
.an-heat { margin-top: 4px; }

/* ---------- Rotation tile ----------
   Closed: the radar and one footer line, like every other tile.
   Open: radar beside a tier breakdown, then tools and the song list with its numbers. */
.an-rot-top { flex: 1 1 auto; min-height: 0; display: flex; margin-top: 4px; }
.an-rot-top .an-3d { margin-top: 0; }
.an-rot-tiers { display: none; list-style: none; margin: 0; padding: 0; }
.an-tile[data-tile="tiers"].is-open .an-rot-top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: 14px; align-items: center; flex: none; }
.an-tile[data-tile="tiers"].is-open .an-rot-top .an-3d { height: 180px; }
.an-tile[data-tile="tiers"].is-open .an-rot-tiers { display: grid; gap: 7px; }
.an-rot-tiers li { display: grid; grid-template-columns: 58px minmax(0, 1fr) auto; align-items: center; gap: 8px; font: 600 0.72rem/1.2 var(--ui); }
.an-rot-tiers b { font: 700 0.74rem var(--digit); min-width: 3ch; text-align: right; }
.an-rot-tiers .an-share i { height: 7px; }
.an-rot-boost { color: var(--gold-deep); }
.an-tile[data-tile="tiers"].is-open .an-sub { display: none; }

.rot-tools { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; margin-bottom: 10px; }
.rot-tools .tiers-search { width: 100%; min-width: 0; }
.rot-sort {
  border: 0; border-radius: 12px; padding: 0 30px 0 12px; height: 40px;
  font: 600 0.78rem var(--ui); color: var(--ink);
  background: var(--well) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23835d2a' stroke-width='1.6'/%3E%3C/svg%3E") no-repeat right 11px center;
  box-shadow: inset 0 1px 3px var(--key-shadow);
  -webkit-appearance: none; appearance: none;
}
.rot-sort:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
.rot-chips { display: flex; gap: 6px; overflow-x: auto; padding: 2px 1px 6px; margin-bottom: 4px; scrollbar-width: none; }
.rot-chips::-webkit-scrollbar { display: none; }
.rot-chip {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  border: 0; border-radius: 999px; padding: 7px 11px; cursor: pointer;
  font: 600 0.74rem/1 var(--ui); color: var(--ink-soft);
  background: var(--well); box-shadow: inset 0 1px 2px var(--key-shadow);
}
.rot-chip b { font: 700 0.68rem var(--digit); opacity: 0.75; }
.rot-chip[aria-pressed="true"] { color: #fff6e6; background: var(--gold-fill); box-shadow: 1px 3px 8px var(--drop-near); }
.rot-key { display: flex; flex-wrap: wrap; gap: 4px 12px; margin: 2px 0 8px; font: 600 0.64rem/1 var(--ui); color: var(--ink-soft); }
.rot-key span { display: inline-flex; align-items: center; gap: 4px; }
.rot-key .icon, .rot-stats .icon { width: 11px; height: 11px; opacity: 0.7; }

.an-tile[data-tile="tiers"] .tiers-list { max-height: 460px; gap: 0; }
.an-tile[data-tile="tiers"] .tier-row { padding: 9px 2px; border-top: 1px solid rgba(127, 110, 85, 0.16); gap: 6px; }
.an-tile[data-tile="tiers"] .tier-row:first-child { border-top: 0; }

.rot-stats { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 11px; font: 700 0.68rem/1 var(--digit); color: var(--ink-soft); }
.rot-stats i { display: inline-flex; align-items: center; gap: 4px; font-style: normal; }
.rot-tier { font: 700 0.6rem/1 var(--ui); font-style: normal; padding: 3px 6px; border-radius: 6px; background: var(--gold-soft); color: var(--gold-deep); }
.rot-tier--5 { background: rgba(201, 64, 108, 0.14); color: var(--live); }
.rot-rate { display: block; height: 3px; border-radius: 2px; background: rgba(127, 110, 85, 0.14); overflow: hidden; }
.rot-rate b { display: block; height: 100%; background: var(--live); opacity: 0.7; }
.rot-note { margin: 10px 0 0; font: 500 0.68rem/1.4 var(--ui); color: var(--ink-soft); }
.an-tile[data-tile="tiers"] .tier-more { margin-top: 6px; }
.rot-head { display: flex; align-items: center; gap: 7px; min-width: 0; }
.rot-head .tier-title { min-width: 0; }
.rot-head .rot-tier { flex: none; }
.an-rot-tiers .an-share { background: rgba(127, 110, 85, 0.12); border-radius: 4px; }
.an-tile[data-tile="tiers"] .tier-row-body { gap: 5px; }

/* ---------- Glass drawn by three.js (script: glass) ----------
   (the body says "glass-on"; the canvases are canvas.glass-gl, never the same name) */
canvas.glass-gl { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 4; pointer-events: none; border-radius: inherit; }
body.glass-on .plate::before, body.glass-on .wave::before,
body.glass-on .plate::after, body.glass-on .wave::after,
body.glass-on .glass-scratch { display: none; }
body.lite canvas.glass-gl { display: none; }

/* ---------- Guide (script: setupGuide) ----------
   Plain warm paper, pencil sketches that move a little on a slow loop, easy-to-read text
   with room to breathe. The paper scrolls when it's taller than the screen. */
.guide {
  position: fixed; inset: 0; z-index: 60;
  display: grid; grid-template-rows: minmax(0, 1fr) auto; justify-items: center; align-items: center;
  padding: 16px 14px max(20px, env(safe-area-inset-bottom));
  background: rgba(24, 19, 12, 0.6);
}
.guide[hidden] { display: none; }
/* a blurred backdrop is costly to keep repainting on phones: desktops only */
@media (hover: hover) and (pointer: fine) { body:not(.lite) .guide { background: rgba(24, 19, 12, 0.55); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); } }
.guide-sheet {
  position: relative; z-index: 1; width: min(92vw, 760px); transform-style: flat; perspective: 1800px;
  filter: drop-shadow(7px 18px 26px rgba(10, 6, 2, 0.4)) drop-shadow(1px 2px 4px rgba(10, 6, 2, 0.25));
}
/* while it folds and flies, one cheap shadow (a filter on moving paper is redrawn every frame) */
.guide.is-folding .guide-sheet, .guide-sheet.is-flying { filter: drop-shadow(3px 8px 12px rgba(10, 6, 2, 0.3)); }

.guide-page, .guide-face--plain, .guide-layer {
  background-color: #efebe3;
  background-image:
    radial-gradient(130% 120% at 50% 35%, rgba(255, 255, 255, 0.42), rgba(130, 108, 72, 0.1)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' seed='7'/%3E%3CfeColorMatrix values='0 0 0 0 0.35 0 0 0 0 0.3 0 0 0 0 0.22 0 0 0 0.12 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}
.guide-face--plain, .guide-layer { background-color: #e9e4da; }
.guide-page {
  position: relative; border-radius: 4px; color: #3d372f;
  max-height: calc(100vh - 116px); max-height: calc(100dvh - 116px);
  overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: rgba(90, 75, 50, 0.3) transparent;
  padding: 1.6em 2.1em 2.1em; outline: none;
}
.guide-page--copy { position: absolute; border-radius: 0; max-height: none; overflow: hidden; }
/* more below: a soft fade at the bottom edge while there's still paper to scroll */
.guide-sheet::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 46px; border-radius: 0 0 4px 4px; pointer-events: none;
  background: linear-gradient(rgba(239, 235, 227, 0), rgba(233, 228, 218, 0.95)); opacity: 0; transition: opacity 0.25s;
}
.guide-sheet.can-scroll::after { opacity: 1; }
.guide.is-folding .guide-sheet::after { opacity: 0; transition: none; }

/* Everything on the paper is sized from its font size. The sketch of the radio sits big on
   top; the paper scrolls if it's taller than the screen. */
.guide-page { font-size: 16px; }
.guide-head { display: block; margin-bottom: 2em; text-align: center; }
.guide-hero { display: block; width: min(100%, 19em); margin: 0 auto 0.6em; }
.guide-title {
  margin: 0 0 0.35em;
  font: 700 2em/1 var(--serif); letter-spacing: 0.06em; text-transform: uppercase;
  color: #5d564c; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7), 0 -1px 0 rgba(60, 45, 25, 0.22);
}
.guide-intro { max-width: 38ch; margin: 0 auto; font: 500 1em/1.55 var(--ui); color: #4a443b; }
.guide-entries { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 1.5em 1.6em; }
.guide-entries li { display: grid; grid-template-columns: 4.6em 1fr; gap: 0.9em; align-items: center; }
.guide-vg { width: 4.6em; height: 4.6em; overflow: visible; }
.guide-entries b { display: block; margin-bottom: 0.15em; font: 700 1.04em/1.25 var(--ui); color: #3d372f; }
.guide-entries p { margin: 0; font: 400 0.94em/1.5 var(--ui); color: #4f493f; }
.guide-sign { margin: 1.7em auto 0; max-width: 40ch; text-align: center; font: italic 500 1.05em/1.4 var(--serif); color: #6a6257; }

@media (max-width: 640px) {
  .guide { padding-top: 10px; }
  .guide-sheet { width: min(94vw, 440px); }
  .guide-page { padding: 1.1em 1.1em 1.2em; max-height: calc(100vh - 100px); max-height: calc(100dvh - 100px); }
  .guide-head { margin-bottom: 1.7em; }
  .guide-hero { width: min(80%, 16em); }
  .guide-title { font-size: 1.7em; }
  .guide-intro { font-size: 0.9em; }
  .guide-entries { grid-template-columns: 1fr; gap: 1.4em; }
  .guide-entries li { grid-template-columns: 3.6em 1fr; gap: 0.8em; }
  .guide-vg { width: 3.6em; height: 3.6em; }
  .guide-entries b { font-size: 0.98em; }
  .guide-entries p { font-size: 0.89em; line-height: 1.42; }
  .guide-sign { margin-top: 1.6em; font-size: 0.98em; }
}

/* ---- pencil sketch ---- */
.sk { filter: none; }
/* the pencil wobble is a live SVG filter: desktops only (phones skip it, the lines stay) */
@media (hover: hover) and (pointer: fine) { body:not(.lite) .sk { filter: url(#gd-pencil); } }
.sk path, .sk circle, .sk rect, .sk ellipse { fill: none; stroke: #6f675c; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.guide-vg .sk path, .guide-vg .sk circle, .guide-vg .sk rect, .guide-vg .sk ellipse { stroke-width: 1.7; }
.sk .sk-soft { stroke-opacity: 0.4; stroke-width: 1; }
.sk .sk-fill { fill: #e4dfd5; }
.sk .sk-fill2 { fill: #d9d2c5; }
.sk .sk-paper { fill: #efebe4; stroke-opacity: 0.6; }
.sk .sk-dots { stroke-dasharray: 0.1 5.2; stroke-width: 3; stroke: #8a8174; }
.sk .sk-dark { fill: #5d564c; stroke: #4c463e; }
.sk .sk-ink { fill: #6f675c; }
.sk .sk-skin { fill: #f4eee4; }
.sk .sk-inside { fill: #5d564c; stroke: #4c463e; }
.sk .sk-tick { stroke: #e9e4da; stroke-width: 1; }
.sk .sk-needle { stroke: #d8c08a; stroke-width: 2; }
.sk .sk-neck { stroke: #e4dfd5; stroke-width: 7; }
.sk-plaque { fill: none; stroke: #8a8174; stroke-width: 1.1; }
.sk-plaque--in { stroke-opacity: 0.4; }
.sk-script { font: italic 600 13px var(--serif); fill: #6f675c; }
.ga-lbl { font: 700 9.5px var(--ui); letter-spacing: 0.04em; }

/* ---- the slow loops ----
   Rest pose first (what shows with reduced motion and while folding), then the motion. */
.guide [class*="ga-"] { transform-box: fill-box; transform-origin: center; }
.ga-finger, .ga-ring, .ga-after, .ga-skip, .ga-drop { opacity: 0; }
.sk .ga-vote { fill: none; }
.ga-lbl--hq { fill: #efebe3; }
.ga-lbl--sv { fill: #6f675c; }
.guide .ga-bars, .guide .ga-bar { transform-origin: 50% 100%; }
.guide .ga-door { transform-origin: 0 50%; }

@media (prefers-reduced-motion: no-preference) {
  .guide-entries li { --cycle: 4.2s; }
  .guide-entries li:nth-child(2) { --lag: -1.4s; }
  .guide-entries li:nth-child(3) { --lag: -2.8s; }
  .ga-finger { animation: ga-finger var(--cycle) ease-in-out var(--lag, 0s) infinite; }
  .ga-press { animation: ga-press var(--cycle) ease-in-out var(--lag, 0s) infinite; }
  .ga-ring { animation: ga-ring var(--cycle) ease-out var(--lag, 0s) infinite; }
  .ga-after { animation: ga-after var(--cycle) ease-in-out var(--lag, 0s) infinite; }
  .ga-vote { animation: ga-vote var(--cycle) step-end var(--lag, 0s) infinite; }
  .ga-skip { animation: ga-skip var(--cycle) ease-out var(--lag, 0s) infinite; }
  .ga-drop { animation: ga-drop var(--cycle) ease-in var(--lag, 0s) infinite; }
  .ga-tray { animation: ga-tray var(--cycle) ease-out var(--lag, 0s) infinite; }
  .ga-knob2 { animation: ga-slide 6s cubic-bezier(0.6, 0, 0.3, 1) infinite; }
  .ga-lbl--hq { animation: ga-lbl-hq 6s step-end infinite; }
  .ga-lbl--sv { animation: ga-lbl-sv 6s step-end infinite; }
  .ga-bars { animation: ga-bars 6s cubic-bezier(0.6, 0, 0.3, 1) infinite; }
  .ga-bar { animation: ga-eq 1.1s ease-in-out infinite alternate; }
  .ga-bar--2 { animation-duration: 0.8s; } .ga-bar--3 { animation-duration: 1.3s; } .ga-bar--4 { animation-duration: 0.95s; } .ga-bar--5 { animation-duration: 1.2s; }
  .ga-door { animation: ga-door 6s ease-in-out infinite; }
  .ga-arrow { animation: ga-arrow 6s ease-in-out infinite; }
  .ga-needle { animation: ga-needle 7s ease-in-out infinite alternate; }
  .ga-knob { animation: ga-turn 7s ease-in-out infinite alternate; }
  .ga-wave { animation: ga-wave 2.6s ease-in-out infinite; }
  .ga-wave--2 { animation-delay: 0.45s; }
  .ga-note { animation: ga-note 5.2s ease-in-out infinite; }
  .ga-note--2 { animation-delay: 2.6s; }
  .ga-float { animation: ga-float 4.6s ease-in-out infinite alternate; }
  .ga-ripple { animation: ga-ripple 4.6s ease-in-out infinite alternate; }
}
/* a tap: the finger comes in, presses, lets go */
@keyframes ga-finger {
  0%, 26% { opacity: 0; transform: translate(14px, 16px); }
  38% { opacity: 1; transform: translate(5px, 6px); }
  46%, 50% { opacity: 1; transform: translate(0, 0); }
  58% { opacity: 1; transform: translate(4px, 5px); }
  72%, 100% { opacity: 0; transform: translate(14px, 16px); }
}
@keyframes ga-press { 0%, 45% { transform: scale(1); } 49%, 52% { transform: scale(0.91); } 60%, 100% { transform: scale(1); } }
@keyframes ga-ring { 0%, 47% { opacity: 0; transform: scale(0.94); stroke-width: 3; } 50% { opacity: 0.75; transform: scale(0.96); stroke-width: 3; } 78%, 100% { opacity: 0; transform: scale(1.32); stroke-width: 1; } }
@keyframes ga-after { 0%, 55% { opacity: 0; } 64%, 88% { opacity: 0.8; } 100% { opacity: 0; } }
@keyframes ga-vote { 0% { fill: transparent; } 50% { fill: #6f675c; } 94% { fill: transparent; } }
@keyframes ga-skip { 0%, 60% { opacity: 0; transform: translateX(-8px); } 70%, 88% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateX(6px); } }
@keyframes ga-drop {
  0%, 52% { opacity: 0; transform: translateY(-20px); }
  56% { opacity: 1; transform: translateY(-18px); }
  70% { opacity: 1; transform: translateY(0); }
  75% { transform: translateY(-3px); }
  80%, 90% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(0); }
}
@keyframes ga-tray { 0%, 69% { transform: none; } 73% { transform: translateY(1.6px); } 80%, 100% { transform: none; } }
@keyframes ga-slide { 0%, 38% { transform: none; } 50%, 88% { transform: translateX(34px); } 100% { transform: none; } }
@keyframes ga-lbl-hq { 0% { fill: #efebe3; } 44% { fill: #6f675c; } 94% { fill: #efebe3; } }
@keyframes ga-lbl-sv { 0% { fill: #6f675c; } 44% { fill: #efebe3; } 94% { fill: #6f675c; } }
@keyframes ga-bars { 0%, 38% { transform: none; } 50%, 88% { transform: scaleY(0.45); } 100% { transform: none; } }
@keyframes ga-eq { from { transform: scaleY(1); } to { transform: scaleY(0.55); } }
@keyframes ga-door { 0%, 18% { transform: none; } 34%, 70% { transform: scaleX(0.42) skewY(-7deg); } 86%, 100% { transform: none; } }
@keyframes ga-arrow { 0%, 28% { opacity: 0; transform: translateX(-10px); } 44%, 66% { opacity: 1; transform: translateX(6px); } 80%, 100% { opacity: 0; transform: translateX(14px); } }
@keyframes ga-needle { from { transform: translateX(-20px); } to { transform: translateX(12px); } }
@keyframes ga-turn { from { transform: rotate(-30deg); } to { transform: rotate(25deg); } }
@keyframes ga-wave { 0%, 100% { opacity: 0.15; } 50% { opacity: 0.75; } }
@keyframes ga-note { 0% { opacity: 0; transform: translateY(8px) rotate(-6deg); } 25% { opacity: 1; } 70% { opacity: 0.8; } 100% { opacity: 0; transform: translateY(-30px) rotate(8deg); } }
@keyframes ga-float { from { transform: translateY(-2px) rotate(-1.5deg); } to { transform: translateY(3px) rotate(1.5deg); } }
@keyframes ga-ripple { from { transform: scaleX(0.92); opacity: 0.5; } to { transform: scaleX(1.06); opacity: 0.9; } }
/* only the sketches on screen move */
.guide-entries li:not(.is-seen) [class*="ga-"], .guide-hero:not(.is-seen) [class*="ga-"] { animation-play-state: paused !important; }
/* still while folding (the copies on the folding paper would restart out of step) */
.guide.is-folding svg * { animation: none !important; }
body.lite .guide svg * { animation: none !important; }

.guide-ok {
  position: relative; z-index: 2; margin-top: 14px; min-width: 200px; height: 50px; padding: 0 30px; border: 0; border-radius: 999px; cursor: pointer;
  font: 700 0.98rem/1 var(--ui); letter-spacing: 0.06em; color: #3d372f;
  background: linear-gradient(180deg, #f6f2ea, #e2dccf);
  box-shadow: 0 10px 22px rgba(0, 0, 0, 0.35), 0 2px 5px rgba(0, 0, 0, 0.25), inset 0 1px 0 #fff;
}
.guide-ok:active { transform: translateY(1px); }
.guide-ok:focus-visible { outline: 2px solid rgba(236, 232, 224, 0.7); outline-offset: 3px; }
.guide-ok:focus:not(:focus-visible) { outline: none; }

/* ---- folding ---- */
.guide-flap { position: absolute; transform-style: preserve-3d; }
.guide-flap--y { transform-origin: 0 50%; }
.guide-flap--x { transform-origin: 50% 0; }
.guide-face { position: absolute; inset: 0; overflow: hidden; -webkit-backface-visibility: hidden; backface-visibility: hidden; }
.guide-flap--y .guide-face--back { transform: rotateY(180deg); }
.guide-flap--x .guide-face--back { transform: rotateX(180deg); }
/* light on the turning paper: barely there */
.guide-shade { position: absolute; inset: 0; opacity: 0; pointer-events: none; background: linear-gradient(90deg, rgba(60, 45, 25, 0.35), rgba(60, 45, 25, 0.05) 70%, rgba(255, 252, 245, 0.2)); }
.guide-flap--x .guide-shade { background: linear-gradient(180deg, rgba(60, 45, 25, 0.35), rgba(60, 45, 25, 0.05) 70%, rgba(255, 252, 245, 0.2)); }
/* the shadow the flap throws on the paper as it comes down */
.guide-cast { position: absolute; opacity: 0; pointer-events: none; }
.guide-cast--y { background: linear-gradient(270deg, rgba(40, 30, 15, 0.16), rgba(40, 30, 15, 0.03) 75%, rgba(40, 30, 15, 0)); }
.guide-cast--x { background: linear-gradient(0deg, rgba(40, 30, 15, 0.16), rgba(40, 30, 15, 0.03) 75%, rgba(40, 30, 15, 0)); }
.guide-layer { position: absolute; }
.guide-layer--y { box-shadow: inset -1px 0 0 rgba(90, 70, 40, 0.1), -1px 0 3px rgba(40, 30, 15, 0.12); }
.guide-layer--x { box-shadow: inset 0 -1px 0 rgba(90, 70, 40, 0.1), 0 -1px 3px rgba(40, 30, 15, 0.12); }
body.dark-mode .guide { background: rgba(0, 0, 0, 0.62); }

/* fold lines: a valley (shadow, then a lit edge) or a mountain (the other way round) */
.guide-creases { position: absolute; top: 0; left: 0; right: 0; height: 100%; z-index: 1; overflow: hidden; pointer-events: none; opacity: 0; transition: opacity 0.6s ease; }
.guide-sheet.is-creased .guide-creases { opacity: 1; }
.gc { position: absolute; display: block; }
.gc--v { top: 0; bottom: 0; width: 16px; margin-left: -8px;
  background: linear-gradient(90deg, rgba(70, 52, 28, 0) 0%, rgba(70, 52, 28, 0.05) 38%, rgba(70, 52, 28, 0.15) 49%, rgba(255, 253, 248, 0.6) 53%, rgba(255, 253, 248, 0.12) 68%, rgba(255, 253, 248, 0) 100%); }
.gc--v.gc--m { transform: scaleX(-1); }
.gc--h { left: 0; right: 0; height: 16px; margin-top: -8px;
  background: linear-gradient(180deg, rgba(255, 253, 248, 0) 0%, rgba(255, 253, 248, 0.12) 32%, rgba(255, 253, 248, 0.6) 47%, rgba(70, 52, 28, 0.15) 51%, rgba(70, 52, 28, 0.05) 62%, rgba(70, 52, 28, 0) 100%); }

/* the guide key on the radio, beside "made by Hootan": the same as the login button, just
   the icon on the card, gold, with the same drop shadow as everything raised. The row is
   only as tall as the icon; the touch area reaches past it invisibly. */
.face--front .attribution { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 24px; }
.face--front .attribution > span { margin-left: auto; line-height: 1; }
.guide-icon {
  position: relative; display: block; flex: none; width: 24px; height: 24px; margin: 0; padding: 0; border: 0; border-radius: 6px; cursor: pointer;
  background: none; box-shadow: none; outline: none;
  -webkit-tap-highlight-color: transparent;
}
.guide-icon::before { content: ""; position: absolute; inset: -12px -12px -10px -10px; border-radius: 14px; } /* ~46px touch area */
.guide-icon[hidden] { display: none; }
.guide-icon .icon {
  width: 24px; height: 24px;
  transition: transform 0.15s var(--ease), filter 0.15s var(--ease);
}
.guide-icon:active .icon { transform: translateY(1.5px); filter: drop-shadow(0.5px 1px 1px var(--drop-near)); }
body.lite .guide-icon .icon { filter: none; }
.guide-icon:focus-visible { box-shadow: 0 0 0 2px var(--gold); }

/* ---------- The radio never scrolls (script: fitRadio) ----------
   Short screens get the radio a step more compact (fit-1 .. fit-3) until it fits, and
   then the page itself is locked so it can't be dragged around. (The studio side scrolls
   inside its own card.) Only a screen too small even for fit-3 is left to scroll. */
html.no-scroll, html.no-scroll body { overflow: hidden; overscroll-behavior: none; }
html.no-scroll .stage { overflow: hidden; }
html.fit-1 .face--front.deck { padding: 14px 14px 10px; }
html.fit-1 .face--front .brand { margin-bottom: 8px; }
html.fit-1 .plate { margin-bottom: 10px; }
html.fit-1 .song-card { margin-bottom: 6px; }
html.fit-1 .wave { height: 40px; margin-bottom: 10px; }
html.fit-1 .attribution { margin-top: 6px; }
html.fit-2 .plate { padding: 10px 12px; }
html.fit-2 .plate-status { font-size: 1.05rem; }
html.fit-2 .song-name { font-size: 1.25rem; }
html.fit-2 .neu-btn--hero { width: 64px; height: 64px; border-radius: 50%; }
html.fit-2 .neu-btn--round, html.fit-2 .neu-btn--small { width: 46px; height: 46px; border-radius: 14px; }
html.fit-2 .wave { height: 34px; margin-bottom: 8px; }
html.fit-3 .plate-news { display: none; }
html.fit-3 .face--front .brand { margin-bottom: 6px; }
html.fit-3 .nameplate { max-width: 230px; }
html.fit-3 .song-card { margin-bottom: 4px; }

/* ---------- Station display: an old computer terminal's lettering ----------
   VT323 (after the DEC VT320 terminal) for everything on the display. It's drawn smaller
   than most faces at the same size, so font-size-adjust brings it up to the same height. */
.plate, .plate * { font-family: var(--crt); }
.plate { font-size-adjust: 0.5; }
.plate .plate-status { letter-spacing: 0.03em; font-weight: 400; }
.plate .onair, .plate .q-chip, .plate .plate-label, .plate .news-time { letter-spacing: 0.1em; font-weight: 400; }
.plate .news-text { font-weight: 400; }
@supports not (font-size-adjust: 0.5) {
  .plate .plate-status { font-size: 1.9rem; }
  .plate .onair, .plate .q-chip, .plate .plate-label { font-size: 0.9rem; }
  .plate .news-list { font-size: 1.15rem; }
}

/* the guide key: grey, like "made by Hootan" beside it */
.guide-icon { color: var(--ink-soft); opacity: 0.8; }
.guide-icon:hover { opacity: 1; }
.guide-icon .icon { filter: drop-shadow(1px 2px 2px var(--drop-wide)) drop-shadow(0.5px 1px 1px var(--drop-near)); }

/* ---------- The three keys: round keycaps, like a calculator's ----------
   A round cap standing up out of the card on a short wall, lit from the top left, with
   the same dirt, scratches and shadows as before. In CSS (the wall is a solid shadow under
   the cap; pressing sinks the cap and the wall shrinks) until Three.js draws them properly
   (script: keys3d), and in the lighter mode. */
body { --key-wall: #cec5b5; --key-wall-live: #c8c0b2; }
body.dark-mode { --key-wall: #1c1a16; --key-wall-live: #0d0c0a; }
.face--front .controls .neu-btn {
  --wall: 6px;
  border-radius: 50%;
  background: radial-gradient(120% 120% at 30% 25%, var(--key-top), var(--key-bottom) 70%);
  box-shadow: 0 var(--wall) 0 var(--key-wall), 6px calc(var(--wall) + 9px) 20px var(--drop-wide), 2px calc(var(--wall) + 2px) 4px var(--drop-near);
  transition: transform 0.09s ease-out, box-shadow 0.09s ease-out;
}
.face--front .controls .neu-btn--hero { --wall: 7px; }
.face--front .controls .neu-btn--hero::before { inset: 0; border-radius: 50%; box-shadow: none;
  background: radial-gradient(70% 70% at 50% 45%, rgba(0, 0, 0, 0.035), transparent 70%); }  /* a hint of a dish */
.face--front .controls .neu-btn:active,
.face--front .controls .neu-btn[aria-pressed="true"],
.face--front.is-live .controls .neu-btn--hero,
.face--front.is-connecting .controls .neu-btn--hero,
.is-live .controls .neu-btn--hero, .is-connecting .controls .neu-btn--hero {
  transform: translateY(calc(var(--wall) - 2px));
  box-shadow: 0 2px 0 var(--key-wall), 2px 5px 10px var(--drop-wide), 1px 1px 2px var(--drop-near);
}
.face--front.is-live .controls .neu-btn--hero, .is-live .controls .neu-btn--hero,
.is-connecting .controls .neu-btn--hero { background: radial-gradient(120% 120% at 30% 25%, var(--well), var(--btn-pressed) 80%); }
body.lite .face--front .controls .neu-btn { box-shadow: 0 3px 0 var(--key-wall); background: var(--key-top); }

/* drawn in 3D: the canvas is the whole keycap (cap, wall, shadow); the button is only the
   top of the cap, a touch oval because we see it from slightly in front */
.key-cap { position: absolute; z-index: 0; pointer-events: none; }
body.keys-3d .face--front .controls .neu-btn,
body.keys-3d .face--front .controls .neu-btn:active,
body.keys-3d .face--front .controls .neu-btn[aria-pressed="true"],
body.keys-3d .is-live .controls .neu-btn--hero,
body.keys-3d .is-connecting .controls .neu-btn--hero {
  background: transparent; box-shadow: none; transform: none; transition: none;
  height: auto; aspect-ratio: 1 / 0.927; overflow: visible;
}
body.keys-3d .face--front .controls .neu-btn--hero::before { display: none; }
body.keys-3d .face--front .controls .neu-btn .icon,
body.keys-3d .face--front .controls .neu-btn::after { transform: translateY(var(--sink, 0px)); }
body.keys-3d .face--front .controls .neu-btn::after { border-radius: 50%; }
body.lite .key-cap { display: none; }

/* The bottom row lines up with the display window: the book's left edge on the window's
   left edge, the end of "made by Hootan" on its right edge (optically: the book's drawing
   starts 1px inside its box, and the text's letter spacing trails after the last letter) */
.face--front .attribution > span { margin-right: -0.12em; }
.guide-icon .icon { margin-left: -1px; }   /* (fitRadio fine-tunes this to the pixel) */
@media (max-width: 360px) {
  .face--front .attribution { margin-left: -4px; margin-right: -4px; }   /* the display is 4px wider here */
  .face--front .nameplate { margin-left: -4px; }                          /* and so is the name plate's line */
}

/* a little more room around the song title */
.face--front .song-card { margin-top: 8px; margin-bottom: 18px; }
.face--front .song-name { margin-bottom: 6px; }
html.fit-1 .face--front .song-card { margin-top: 2px; margin-bottom: 10px; }
html.fit-3 .face--front .song-card { margin-top: 0; margin-bottom: 6px; }

/* The display window and the wave window share both side edges, on every screen */
@media (max-width: 360px) {
  .face--front .wave { margin-left: -4px; margin-right: -4px; }
}
/* Nothing below the display moves when the song changes: the song card always keeps room
   for the title and the artist line (even when there's no artist), and the "coming up" box
   always keeps room for its two rows (the display shows two at most) */
.face--front .song-name, .face--front .artist-name { min-height: 1.2em; }
.face--front .artist-name:empty::before { content: "\00a0"; }
.face--front .news-list { min-height: calc(2 * 0.95rem * 1.25 + 5px); align-content: start; }
.sk-script { font-style: italic; }

/* Folding stays smooth: while the paper folds, nothing on it is filtered or animated, the
   moving flaps are their own layers, and the paper's big soft shadow (a filter, redrawn
   every frame on moving paper) swaps for none until the folded paper flies off */
.guide.is-folding .guide-sheet { filter: none; }
.guide.is-folding .guide-sheet.is-flying { filter: drop-shadow(3px 8px 12px rgba(10, 6, 2, 0.3)); }
.guide.is-folding .sk { filter: none !important; }
.guide-flap { will-change: transform; }
.guide-cast { will-change: opacity; }

/* The sheet is flat on purpose: in a shared 3D space Safari sorts the paper, the folded
   layers and the copies on a turning flap by depth, and things at the same depth swap
   order from frame to frame (that flicker showed the printed page through the folds).
   Flat, they simply stack in order; only the turning flap itself is 3D. */
.guide-layer, .guide-cast { transform: none; }

/* ---------- Flamingos (script: flamingoArt, flamingos) ----------
   Low-poly line drawings in the same thin gold as the lines of the sky behind the radio:
   a smooth outline (.fl-rim) around a fainter net of even triangles (.fl-net), a darker
   beak tip and a clear eye. Everything a flamingo does is in this section. */
body { --fl-line: rgba(184, 137, 75, 0.62); }
body.dark-mode { --fl-line: rgba(214, 174, 106, 0.55); }
.fl { display: block; width: 100%; height: 100%; overflow: visible; }
.fl .fl-net, .fl .fl-rim { fill: none; stroke: var(--fl-line); vector-effect: non-scaling-stroke; stroke-linejoin: round; stroke-linecap: round; }
.fl .fl-net { stroke-width: 0.8px; stroke-opacity: 0.72; }
.fl .fl-rim { stroke-width: 1.25px; }
.fl .fl-tip { fill: var(--fl-line); fill-opacity: 0.55; }
.fl .fl-eyering { fill: none; stroke: var(--fl-line); stroke-width: 1.1px; vector-effect: non-scaling-stroke; }
.fl .fl-pupil { fill: var(--fl-line); fill-rule: evenodd; }
.fl .fl-eyeshut { fill: none; stroke: var(--fl-line); stroke-width: 1.1px; vector-effect: non-scaling-stroke; stroke-linecap: round; }
.fl .fl-eye { transform-box: view-box; animation: fl-blink 4.2s infinite; }       /* (each eye's pivot is set where it's drawn) */
@keyframes fl-blink { 0%, 46%, 50%, 100% { transform: scaleY(1); } 48% { transform: scaleY(0.1); } }

/* The wingbeat: a quick downstroke and a slower recovery, as birds fly; the body lifts a
   little on each downstroke. Faster when braking or flailing, slow when dazed, and wings
   held out, barely moving, while it glides down. */
.fl .fl-wing { transform-box: view-box; transform-origin: 66px 31px; animation: fl-flap 0.52s infinite; }
.fl .fl-wing--far { animation-delay: -0.07s; opacity: 0.55; }
@keyframes fl-flap {
  0% { transform: scaleY(1); animation-timing-function: cubic-bezier(0.5, 0, 0.75, 0.6); }
  38% { transform: scaleY(-0.8); animation-timing-function: cubic-bezier(0.3, 0.3, 0.5, 1); }
  100% { transform: scaleY(1); }
}
.fl .fl-flybody { transform-box: view-box; transform-origin: 70px 36px; animation: fl-heave 0.52s infinite; }
@keyframes fl-heave { 0%, 100% { transform: none; } 30% { transform: translateY(-1.6px) rotate(-0.6deg); } 62% { transform: translateY(0.4px); } }
.fl-bird.is-flaring .fl .fl-wing, .fl-bird.is-flaring .fl .fl-flybody { animation-duration: 0.22s; }
.fl-bird.is-tumbling .fl .fl-wing, .fl-bird.is-tumbling .fl .fl-flybody { animation-duration: 0.12s; }
.fl-bird.is-dazed .fl .fl-wing, .fl-bird.is-dazed .fl .fl-flybody { animation-duration: 0.9s; }
.fl-bird.is-gliding .fl .fl-wing { animation: fl-glide 2.4s ease-in-out infinite alternate; }
.fl-bird.is-gliding .fl .fl-flybody { animation: none; }
@keyframes fl-glide { from { transform: scaleY(0.3); } to { transform: scaleY(0.12); } }

/* The wandering ones. A layer over the radio, and one behind it for the half of a circle
   that goes round its back; only the drawing itself catches taps. Each bird is a 100 x 100
   box with its feet at the bottom middle, holding both drawings: landing, the flying one
   folds its wings away as the standing one appears. --s scales it (further away). */
.fl-layer { position: fixed; inset: 0; z-index: 40; pointer-events: none; overflow: hidden; }
.fl-layer--back { z-index: 0; }
.fl-bird {
  --fl-line: rgba(172, 124, 58, 0.92);                       /* a little stronger than the flock far off, so you notice it */
  position: absolute; left: 0; top: 0; width: 100px; height: 100px; padding: 0; border: 0; background: none;
  cursor: pointer; pointer-events: none; will-change: transform; transform-origin: 50% 76%; -webkit-tap-highlight-color: transparent;
}
body.dark-mode .fl-bird { --fl-line: rgba(226, 192, 130, 0.88); }
.fl-bird:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; border-radius: 8px; }
.fl-bird .fl-pose { position: absolute; bottom: 0; display: block; transform-origin: 50% 100%; scale: var(--s, 1);
  transition: opacity 0.22s ease, transform 0.26s ease; pointer-events: auto; }
.fl-bird .fl-pose::before { content: ""; position: absolute; inset: -12px; }      /* easy to tap */
.fl-bird .fl-pose--fly { left: -10px; width: 120px; height: 60px; }     /* (the same scale as the standing drawing) */
.fl-bird .fl-pose--stand { left: 20px; width: 60px; height: 95px; opacity: 0; transform: translateY(5px) scaleY(0.9); pointer-events: none; }
.fl-bird.is-standing .fl-pose--fly { opacity: 0; transform: scale(0.92, 0.6); pointer-events: none; }
.fl-bird.is-standing .fl-pose--stand { opacity: 1; transform: none; pointer-events: auto; }
.fl-layer--back .fl-bird .fl-pose { pointer-events: none; }

/* standing: a slow shift of weight; touching down it settles; before take-off it crouches */
.fl-bird.is-standing .fl-pose--stand .fl { transform-origin: 50% 100%; animation: fl-idle 5s ease-in-out infinite; }
@keyframes fl-idle { 0%, 100% { transform: none; } 30% { transform: rotate(-1deg); } 65% { transform: rotate(1.2deg) translateY(0.5px); } }
.fl-bird.is-landing .fl-pose--stand .fl { animation: fl-settle 0.45s ease-out; }
/* breathing, gently, whenever it's on its feet (deeper asleep, below); touching down, it
   fluffs its feathers */
.fl-bird.is-standing .fl-pose--stand .fl-body { transform-box: view-box; transform-origin: 30px 62px; animation: fl-breathe-s 4.4s ease-in-out infinite; }
@keyframes fl-breathe-s { 0%, 100% { transform: none; } 50% { transform: scale(1.012, 0.992); } }
.fl-bird.is-landing .fl-pose--stand .fl-body { animation: fl-fluff 0.5s ease-out; }
@keyframes fl-fluff { 0%, 100% { transform: none; } 30% { transform: scale(1.05, 0.95); } 55% { transform: scale(0.98, 1.03); } 78% { transform: scale(1.015, 0.99); } }
/* a fish in its beak wriggles */
.fl.has-fish .fl-fish path { transform-box: fill-box; transform-origin: 60% 50%; animation: fl-wiggle 0.26s ease-in-out infinite alternate; }
@keyframes fl-wiggle { from { transform: rotate(-10deg); } to { transform: rotate(10deg); } }
.fl-bird.is-standing.is-sleeping .fl-pose--stand .fl-body { transform-box: view-box; transform-origin: 30px 62px; animation: fl-breathe 3.6s ease-in-out infinite; }   /* (asleep: slower, deeper) */
@keyframes fl-settle { 0% { transform: translateY(-7px) scale(0.97, 1.05); } 55% { transform: translateY(0) scale(1.04, 0.93); } 100% { transform: none; } }
.fl-bird.is-crouching .fl-pose--stand .fl { animation: none; transform: scale(1.05, 0.88); transition: transform 0.3s ease-in; }

/* bobbing to the music */
.fl-bird.is-dancing .fl-pose--stand .fl { animation: fl-bounce 0.5s ease-in-out infinite alternate; }
.fl .fl-wingup { transform-box: view-box; transform-origin: 34px 37px; }
.fl .fl-wingup-far { transform: translate(4px, -1.5px); opacity: 0.55; }
.fl-bird.is-dancing .fl-wingup { animation: fl-salute 2s ease-in-out infinite; }
@keyframes fl-salute { 0%, 100% { opacity: 0; transform: scale(0.9, 0.1); } 14% { opacity: 1; transform: none; } 38% { opacity: 1; transform: rotate(-5deg); } 56% { opacity: 0; transform: scale(0.9, 0.1); } }
@keyframes fl-bounce { from { transform: scaleY(1); } to { transform: scaleY(0.975); } }

/* asleep: the neck folds back and the head comes down to lie on its back, eyes shut,
   breathing slowly, z's drifting up (the neck itself bends: flamingoArt.act in script.js) */
.fl .fl-wingup { opacity: 0; }
.fl .fl-eyeshut { opacity: 0; }
.fl.is-shut .fl-eye { opacity: 0; animation: none; }
.fl.is-shut .fl-eyeshut { opacity: 1; }

.fl-zz { position: absolute; left: 46px; top: 24px; width: 0; height: 0; pointer-events: none; display: none; }
.fl-bird[data-left="1"] .fl-zz { transform: scaleX(-1); }
.fl-bird.is-sleeping .fl-zz { display: block; }
.fl-zz i { position: absolute; left: 0; top: 0; font: italic 600 11px/1 var(--ui); color: var(--fl-line); opacity: 0;
  animation: fl-z 2.6s ease-out 1.5s infinite; }
.fl-zz i:nth-child(2) { font-size: 9px; animation-delay: 2.4s; }
.fl-zz i:nth-child(3) { font-size: 8px; animation-delay: 3.3s; }
@keyframes fl-z { 0% { opacity: 0; transform: translate(0, 0); } 20% { opacity: 0.95; } 100% { opacity: 0; transform: translate(-14px, -28px); } }

/* fishing: head right down to the ground, a little dabbling, up with a fish, which goes
   down in one gulp (head thrown back) */
.fl .fl-fish { opacity: 0; }
.fl.has-fish .fl-fish { opacity: 1; }

/* on the radio's screen: drawn in the screen's own ink, bobbing as it walks */
.fl-bird.is-on-display { --fl-line: var(--well-ink); opacity: 0.88; }   /* (drawn in the screen's own ink, like its text) */
.fl-bird.is-walking .fl-pose--stand .fl { animation: fl-walk 0.46s ease-in-out infinite; }
@keyframes fl-walk { 0%, 100% { transform: translateY(0) rotate(0); } 25% { transform: translateY(-2px) rotate(-2deg); } 50% { transform: translateY(0) rotate(0); } 75% { transform: translateY(-2px) rotate(2deg); } }

/* the crash: a ring, a burst of short lines and a few feathers drifting down, turning;
   stars going round the dazed birds' heads */
.fl-puff { position: absolute; left: 0; top: 0; width: 0; height: 0; pointer-events: none; }
.fl-puff i { position: absolute; left: -1.5px; top: -12px; width: 3px; height: 24px; border-radius: 2px; background: var(--fl-line, #b8894b);
  transform-origin: 1px 9px; animation: fl-burst 0.6s ease-out forwards; }
.fl-puff i, .fl-puff b { filter: drop-shadow(0 0 1px rgba(255, 250, 240, 0.9)); }
.fl-puff i:nth-child(1) { rotate: 0deg; } .fl-puff i:nth-child(2) { rotate: 45deg; } .fl-puff i:nth-child(3) { rotate: 90deg; }
.fl-puff i:nth-child(4) { rotate: 135deg; } .fl-puff i:nth-child(5) { rotate: 180deg; } .fl-puff i:nth-child(6) { rotate: 225deg; }
.fl-puff i:nth-child(7) { rotate: 270deg; } .fl-puff i:nth-child(8) { rotate: 315deg; }
@keyframes fl-burst { 0% { scale: 1 0.3; opacity: 1; } 100% { scale: 1 1; opacity: 0; transform: translateY(-26px); } }
.fl-puff b { position: absolute; left: -16px; top: -16px; width: 32px; height: 32px; border-radius: 50%;
  border: 1.5px solid var(--fl-line, #b8894b); animation: fl-ring 0.5s ease-out forwards; }
@keyframes fl-ring { from { scale: 0.2; opacity: 1; } to { scale: 1.8; opacity: 0; } }
.fl-puff u { position: absolute; left: -9px; top: -4px; width: 18px; height: 8px; opacity: 0; animation: fl-feather var(--d, 1.4s) ease-out 0.05s forwards; }
.fl-puff u svg { display: block; width: 100%; height: 100%; overflow: visible; fill: none; stroke: var(--fl-line, #b8894b); stroke-width: 1.1; stroke-linecap: round; }
@keyframes fl-feather {
  0% { opacity: 1; transform: translate(0, 0) rotate(var(--r)); }
  25% { transform: translate(calc(var(--dx) * 0.8), -18px) rotate(calc(var(--r) + 70deg)); }
  100% { opacity: 0; transform: translate(var(--dx), 48px) rotate(calc(var(--r) + 220deg)); }
}
.fl-stars { position: absolute; left: 0; top: 0; width: 44px; height: 16px; pointer-events: none; }
.fl-stars span { position: absolute; inset: 0; animation: fl-orbit 0.9s linear infinite; transform-style: preserve-3d; }
.fl-stars i { position: absolute; top: 0; font-style: normal; font-size: 15px; line-height: 1; color: var(--gold, #b8894b); }
.fl-stars i:nth-child(1) { left: 0; } .fl-stars i:nth-child(2) { left: 16px; top: 6px; } .fl-stars i:nth-child(3) { left: 32px; }
@keyframes fl-orbit { from { transform: rotateY(0deg); } to { transform: rotateY(360deg); } }

/* sunglasses (worn on the eye, or held in the beak to begin with) */
.fl .fl-shades { display: none; }
.fl.has-shades .fl-shades { display: inline; }
.fl .fl-lens { fill: #1c1915; fill-opacity: 0.92; stroke: var(--fl-line); stroke-width: 0.9px; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.fl .fl-frame { fill: none; stroke: var(--fl-line); stroke-width: 1.1px; vector-effect: non-scaling-stroke; stroke-linecap: round; }
.fl .fl-glint { fill: none; stroke: #fff; stroke-opacity: 0.75; stroke-width: 0.7px; vector-effect: non-scaling-stroke; stroke-linecap: round; }
.fl.shades-on .fl-eye, .fl.shades-on .fl-eyeshut { opacity: 0; }

/* tapped: a fright (a jump, the eye wide) before it's caught */
.fl-bird.is-startled .fl-pose { animation: fl-jump 0.5s cubic-bezier(0.3, 0, 0.4, 1); }
@keyframes fl-jump { 0% { translate: 0 0; } 35% { translate: 0 -12px; scale: calc(var(--s, 1) * 0.96) calc(var(--s, 1) * 1.06); } 70% { translate: 0 0; scale: calc(var(--s, 1) * 1.05) calc(var(--s, 1) * 0.94); } 100% { translate: 0 0; } }
.fl-bird.is-startled .fl-eye { animation: fl-wide 0.55s ease-out forwards; }
@keyframes fl-wide { 0% { transform: scale(1); } 30% { transform: scale(1.9); } 100% { transform: scale(1.55); } }

/* little things that come off a bird: notes, a feather, a glint, a heart, a "!", the ball */
.fl-fx { position: absolute; left: 0; top: 0; pointer-events: none; color: var(--gold); line-height: 1; }
.fx-note { font: 700 15px/1 var(--ui); animation: fx-note 2s ease-out forwards; }
@keyframes fx-note { 0% { opacity: 0; transform: translate(0, 4px) scale(0.6); } 15% { opacity: 1; transform: translate(0, 0) scale(1); }
  100% { opacity: 0; transform: translate(var(--dx, 10px), -40px) rotate(-12deg) scale(1.05); } }
.fx-feather { width: 22px; animation: fx-feather 3.2s ease-in-out forwards; }
.fx-feather svg { display: block; width: 100%; fill: none; stroke: var(--gold); stroke-width: 1; }
@keyframes fx-feather { 0% { opacity: 0; transform: translate(0, 0) rotate(0); } 12% { opacity: 1; }
  50% { transform: translate(calc(var(--dx, 20px) * 0.6), 22px) rotate(40deg); } 100% { opacity: 0; transform: translate(var(--dx, 20px), 52px) rotate(-20deg); } }
.fx-spark { font-size: 13px; animation: fx-spark 0.9s ease-out forwards; }
@keyframes fx-spark { 0% { opacity: 0; transform: scale(0.2) rotate(0); } 35% { opacity: 1; transform: scale(1.3) rotate(45deg); } 100% { opacity: 0; transform: scale(0.6) rotate(90deg); } }
.fx-heart { width: 18px; animation: fx-heart 3.6s ease-out forwards; }
.fx-heart svg { display: block; width: 100%; fill: var(--gold-soft); stroke: var(--gold); stroke-width: 1.6; }
@keyframes fx-heart { 0% { opacity: 0; transform: scale(0.2); } 12% { opacity: 1; transform: scale(1.25); } 20%, 30%, 40% { transform: scale(1); } 25%, 35% { transform: scale(1.15); }
  100% { opacity: 0; transform: translateY(-34px) scale(0.9); } }
.fx-bang { font: 800 22px/1 var(--ui); animation: fx-bang 0.9s cubic-bezier(0.3, 1.5, 0.5, 1) forwards; }
@keyframes fx-bang { 0% { opacity: 0; transform: scale(0.2) translateY(8px); } 25% { opacity: 1; transform: scale(1.15); } 80% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: translateY(-6px); } }
.fx-ball { width: 14px; height: 14px; }
.fx-shadow { height: 4px; border-radius: 50%; background: var(--well-ink); opacity: 0.4; filter: blur(0.6px); }
.fx-ball svg { display: block; width: 100%; height: 100%; fill: var(--gold-soft); stroke: var(--gold); stroke-width: 1.4; }

/* the pool float drifting across the waveform window */
#wave { position: relative; z-index: 1; }                /* (the bars in front of the float) */
.wave-float { position: absolute; left: 0; bottom: 4%; height: 86%; aspect-ratio: 1; z-index: 0; pointer-events: none; opacity: 0.9;
  will-change: transform; clip-path: inset(0 0 9% 0); filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.2)); }
.wave-float img { display: block; width: 100%; height: 100%; }

/* what a flamingo says: a little raised key of a bubble, in the radio's caramel, coming out
   of its beak (the point touches the beak; --tail-x is set where it sits) */
.fl-say {
  position: absolute; left: 0; top: 0; max-width: min(180px, 52vw); padding: 5px 10px 6px;
  border-radius: 12px; background: linear-gradient(145deg, var(--key-top), var(--key-bottom)); color: var(--gold-deep);
  font: 700 0.68rem/1.25 var(--ui); letter-spacing: 0.01em;
  box-shadow: var(--raise-sm), var(--edge), inset 0 0 0 1px var(--gold-soft);
  pointer-events: none; opacity: 0; scale: 0.15;
  transition: opacity 0.25s ease, scale 0.42s cubic-bezier(0.3, 1.45, 0.5, 1);
}
.fl-say span { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fl-say::after {                                    /* the point, down to the beak */
  content: ""; position: absolute; bottom: -4px; left: calc(var(--tail-x, 14px) - 5px); width: 10px; height: 10px;
  background: var(--key-bottom); border-radius: 0 0 3px 0; transform: rotate(45deg);
  box-shadow: inset -1px -1px 0 var(--gold-soft), 2px 2px 3px var(--drop-near);
}
.fl-say.is-in { opacity: 1; scale: 1; }
@media (prefers-reduced-motion: reduce) { .fl-say { transition: opacity 0.25s; scale: 1; } }

/* skywriting: a flamingo crosses the sky, the note appears behind it and drifts away */
.sky-layer { position: fixed; inset: 0; z-index: 35; pointer-events: none; overflow: hidden; }
.sky-layer[hidden] { display: none; }
.sky-text { position: absolute; left: 0; right: 0; top: max(8px, calc(env(safe-area-inset-top) + 4px)); text-align: center; white-space: nowrap;
  font: italic 800 30px/1.2 var(--ui); letter-spacing: 0.02em; color: var(--fl-line);
  text-shadow: 0 0 6px rgba(255, 255, 255, 0.85), 0 0 18px rgba(255, 250, 240, 0.7); transition: opacity 4s ease, filter 4s ease, transform 4s ease; }
body.dark-mode .sky-text { text-shadow: 0 0 6px rgba(0, 0, 0, 0.8), 0 0 18px rgba(214, 174, 106, 0.35); }
.sky-text span { --p: 0px; display: inline-block; white-space: pre;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(var(--p) - 46px), transparent var(--p));
  mask-image: linear-gradient(90deg, #000 calc(var(--p) - 46px), transparent var(--p)); }
.sky-text[dir="rtl"] span { -webkit-mask-image: linear-gradient(270deg, #000 calc(var(--p) - 46px), transparent var(--p));
  mask-image: linear-gradient(270deg, #000 calc(var(--p) - 46px), transparent var(--p)); }
.sky-text.is-gone { opacity: 0; filter: blur(6px); transform: translateY(-14px) scale(1.04); }
.sky-bird { position: absolute; left: 0; top: 0; width: 80px; height: 40px; will-change: transform; }

/* the catch window: a simple box with your note; the caught flamingo, side on, peeks over
   its top edge (breathing, looking about, blinking, and now and then swinging its neck
   round to look at you with the other eye); taking the note, it turns to face it */
.catch { width: min(380px, calc(100vw - 32px)); padding: 20px 16px 16px; overflow: visible; margin-top: max(120px, 18vh); }
.catch .fl { --fl-line: rgba(232, 204, 158, 0.95); }              /* stronger, over the dimmed page */
.catch-peek { position: absolute; right: 56px; bottom: 100%; width: 112px; height: 92px; overflow: hidden; pointer-events: none; }
.catch-bird { position: absolute; left: 6px; top: 2px; width: 100px; height: 157px; }
.catch-flyer { position: absolute; right: 52px; bottom: calc(100% + 18px); width: 110px; height: 55px; opacity: 0; pointer-events: none; }
.catch.is-flying .catch-peek { opacity: 0; transition: opacity 0.15s; }
.catch.is-flying .catch-flyer { opacity: 1; }
.catch-form { display: grid; gap: 10px; min-width: 0; }
.catch-title { margin: 0 2px; font: 800 1.08rem/1.2 var(--ui); color: var(--ink); }
.catch-row { display: grid; grid-template-columns: minmax(0, 1fr) 48px; gap: 8px; align-items: center; }
.catch-note { position: relative; border-radius: 14px; background: var(--well); box-shadow: var(--press), var(--edge); transform-origin: 70% 50%; }
.catch-input { width: 100%; min-width: 0; height: 48px; padding: 0 14px; border: 0; background: none; color: var(--ink); font: 600 1rem/1 var(--ui); outline: none; }
.catch-note:focus-within { box-shadow: var(--press), 0 0 0 1.5px var(--gold); }
.catch-send { width: 48px; height: 48px; border: 0; border-radius: 14px; display: grid; place-items: center; cursor: pointer;
  background: linear-gradient(145deg, var(--key-top), var(--key-bottom)); color: var(--gold-deep); box-shadow: var(--raise-sm), var(--edge); }
.catch-send:active { transform: translateY(1px); box-shadow: var(--press-sm), var(--edge); }
.catch-send:disabled { opacity: 0.5; }
.catch-send .icon { width: 20px; height: 20px; }
.catch.is-sent .catch-title, .catch.is-sent .catch-send { opacity: 0.35; transition: opacity 0.3s; }
.catch.is-sent .catch-form > :not(.catch-note) { opacity: 0.35; transition: opacity 0.3s; }
.fl-side .fl-breathe { transform-box: view-box; transform-origin: 30px 62px; animation: fl-breathe 3.2s ease-in-out infinite; }
@keyframes fl-breathe { 0%, 100% { transform: none; } 50% { transform: scale(1.02, 0.985); } }

/* the guide's sketch of a flamingo: it flaps, its note bobs, the skywriting trail draws itself */
.guide-vg .sk .guide-lowpoly .fl-net { stroke-width: 0.7; stroke-opacity: 0.6; }
.guide-vg .sk .guide-lowpoly .fl-rim { stroke-width: 1.1; }
.guide-vg .sk .guide-lowpoly .fl-eyering { stroke-width: 0.9; }
.guide-vg .sk .guide-lowpoly .fl-pupil, .guide-vg .sk .guide-lowpoly .fl-tip { fill: #6f675c; fill-rule: evenodd; stroke: none; }
.guide-vg .sk .guide-lowpoly .fl-tip { fill-opacity: 0.5; }
.guide .ga-flap { transform-box: view-box; transform-origin: 66px 31px; }
.guide .ga-trail { stroke-dasharray: 120; stroke-dashoffset: 120; stroke-opacity: 0.5; }
@media (prefers-reduced-motion: no-preference) {
  .ga-flap { animation: ga-flap 0.9s ease-in-out infinite alternate; }
  .ga-note-scroll { animation: ga-scroll 2.4s ease-in-out infinite alternate; }
  .ga-trail { animation: ga-trail 4.2s ease-in-out infinite; }
}
@keyframes ga-flap { from { transform: scaleY(1); } to { transform: scaleY(-0.7); } }
@keyframes ga-scroll { from { transform: translateY(0) rotate(-3deg); } to { transform: translateY(-4px) rotate(3deg); } }
@keyframes ga-trail { 0% { stroke-dashoffset: 120; } 60%, 80% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: -120; } }

@media (prefers-reduced-motion: reduce) { .fl *, .fl-zz i { animation: none !important; } }

/* studio: the flamingo notes and the blocked words */
.notes-panel { margin-top: 18px; }
/* inside the open "Flamingo notes" tile: below the numbers, after a thin line (the tile's
   title already says what it is) */
.notes-panel.is-in-tile { margin-top: 16px; padding-top: 12px; border-top: 1px solid rgba(90, 70, 40, 0.16); text-align: start; }
.notes-panel.is-in-tile > .studio-section { display: none; }
.an-tile:not(.is-open) .an-notes { display: none; }
.notes-help { margin: 0 0 8px; font-size: 0.84rem; line-height: 1.45; color: var(--ink-soft); }
.note-item.is-flagged .queue-meta { color: var(--danger); }
.notes-add { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; margin-top: 10px; }
.notes-btn { height: 44px; padding: 0 16px; border-radius: 12px; font-weight: 700; color: var(--gold-deep); }
.words { margin-top: 12px; }
.words summary { cursor: pointer; font-weight: 700; color: var(--ink-soft); padding: 6px 0; }
.words summary span { font-weight: 500; opacity: 0.8; margin-left: 4px; }
.words-list { display: flex; flex-wrap: wrap; gap: 6px; }
.word-chip { display: inline-flex; align-items: center; gap: 4px; padding: 5px 8px 5px 10px; border: 1.5px solid var(--line); border-radius: 999px; background: var(--btn-face);
  color: var(--ink); font: 600 0.82rem/1 var(--ui); cursor: pointer; }
.word-chip .icon { width: 12px; height: 12px; opacity: 0.6; }
.word-chip:hover { border-color: var(--danger); }
.word-chip:hover .icon { opacity: 1; color: var(--danger); }

/* phones on their side: no room for a sky band */
@media (orientation: landscape) and (max-height: 520px) {
  .stage { padding-top: 10px; }
  .face--front { min-height: calc(100dvh - 20px); }
}

/* Big screens: a wider sheet of paper, the six entries in three columns, a touch larger type */
@media (min-width: 1100px) and (min-height: 640px) {
  .guide-sheet { width: min(88vw, 1080px); }
  .guide-page { font-size: 17px; padding: 1.8em 2.6em 2.3em; }
  .guide-entries { grid-template-columns: repeat(3, 1fr); gap: 1.7em 2em; }
  .guide-hero { width: min(100%, 21em); }
}

/* floating down for skywriting, the radio moves under the room's light: the light now
   catches its top edge and falls away toward the bottom (the glass beam and the keys'
   highlights shift with it in 3D) */
.face--front::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index: 5;
  background: linear-gradient(180deg, rgba(255, 248, 232, 0.16), rgba(255, 248, 232, 0) 28%, rgba(60, 42, 18, 0) 55%, rgba(60, 42, 18, 0.09));
  opacity: 0; transition: opacity 1.6s cubic-bezier(0.45, 0, 0.25, 1);
}
body.dark-mode .face--front::after {
  background: linear-gradient(180deg, rgba(255, 226, 170, 0.07), rgba(255, 226, 170, 0) 30%, rgba(0, 0, 0, 0) 55%, rgba(0, 0, 0, 0.18));
}
body.is-skywriting .face--front::after { opacity: 1; }

/* the guide in Farsi: right to left, a Persian typeface, no capitals or letter spacing
   (they would break up the joined letters) */
.guide[lang="fa"] .guide-page, .guide[lang="fa"] .guide-ok { font-family: "Vazirmatn", Tahoma, sans-serif; }
.guide[lang="fa"] .guide-title { font-family: "Vazirmatn", Tahoma, sans-serif; text-transform: none; letter-spacing: 0; font-weight: 800; }
.guide[lang="fa"] .guide-intro, .guide[lang="fa"] .guide-entries p { line-height: 1.85; }
.guide[lang="fa"] .guide-entries b, .guide[lang="fa"] .guide-entries p, .guide[lang="fa"] .guide-sign, .guide[lang="fa"] .guide-intro { font-family: inherit; }
.guide[lang="fa"] .guide-sign { font-style: normal; }
.guide-lang {
  position: absolute; top: 10px; inset-inline-end: 12px; z-index: 2; padding: 3px 9px; border: 1px solid rgba(90, 75, 50, 0.3);
  border-radius: 999px; background: rgba(255, 255, 255, 0.4); color: #5d564c; font: 600 12px/1.4 "Vazirmatn", var(--ui); cursor: pointer;
}
.guide-lang:hover { background: rgba(255, 255, 255, 0.7); }
.guide.is-folding .guide-lang { visibility: hidden; }

/* The studio on a big screen: the card opens out wider (not just a little taller), and the
   charts sit four to a row */
@media (min-width: 1100px) and (min-height: 700px) {
  .float-wrap.is-grown { max-width: min(980px, 90vw); }
  .flip.is-grown { height: min(calc(var(--front-h) * 1.45), calc(100dvh - 32px)) !important; }
  .flip.is-grown .an-group { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---------- Live from the studio (script: liveChat, liveStudio) ---------- */
/* the station display while a host is live: the tuner scale makes way, "Coming up" becomes
   the chat (lines in the display's own type, names like the times in "Coming up"), with a
   line to write on, and the display grows to hold it */
.plate.is-chat .plate-scale { display: none; }
.plate.is-chat .plate-status { display: none; }
.plate.is-chat .plate-news { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; margin-top: 10px; }
html.fit-3 .plate-news.is-chat { display: flex; }
.plate-news.is-chat .plate-label { color: var(--live); }
.plate-news.is-chat .plate-label::before { content: ""; display: inline-block; width: 6px; height: 6px; margin-right: 6px; border-radius: 50%;
  background: var(--flamingo); vertical-align: 1px; animation: blink 1.6s steps(2, jump-none) infinite; }
.plate-chat { flex: 1 1 auto; display: flex; flex-direction: column; gap: 8px; min-height: 0; }
.plate-chat[hidden] { display: none; }
.plate-chat-list { flex: 1 1 auto; height: 9.6em; min-height: 0; margin: 0; padding: 2px 2px 0; list-style: none; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 6px; font-size: 0.95rem; line-height: 1.3; scrollbar-width: thin;
  -webkit-mask-image: linear-gradient(transparent, #000 14px); mask-image: linear-gradient(transparent, #000 14px); }
.plate-chat-list .chat-line { margin-top: 0; overflow-wrap: anywhere; color: var(--well-ink); }
.plate-chat-list .chat-line:first-child { margin-top: auto; }
.plate-chat-list .chat-who { margin-right: 8px; color: var(--gold-deep); font-weight: 400; }
.plate-chat-list .is-host .chat-who { color: var(--live); }
.plate-chat-list .chat-empty { margin-top: auto; color: var(--ink-soft); }
.plate-chat-form { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 10px; align-items: center; padding-top: 8px; border-top: 1px solid var(--scale); }
.plate-chat-name { grid-column: 1 / -1; justify-self: start; padding: 0; border: 0; background: none; color: var(--gold-deep); font-size: 0.85rem; cursor: pointer; }
.plate-chat-name[hidden] { display: none; }
.plate-chat-input { width: 100%; min-width: 0; height: 34px; padding: 0 2px; border: 0; border-bottom: 1px dashed var(--scale); border-radius: 0; background: none;
  color: var(--well-ink); font-size: 1rem; caret-color: var(--gold); outline: none; }
.plate-chat-input::placeholder { color: var(--ink-soft); opacity: 0.8; }
.plate-chat-input:focus { border-bottom: 1px solid var(--gold); }
.plate-chat-rename { grid-column: 1 / -1; height: 26px; font-size: 0.8rem; }
.plate-chat-send { min-width: 58px; }
.plate-chat-send:disabled { opacity: 0.5; }
.plate-chat-msg { margin: 0; font-size: 0.78rem; color: var(--live); }
.plate-chat-msg[hidden] { display: none; }
@media (min-width: 900px) { .plate-chat-list { height: 12em; } .plate .plate-chat-list { font-size: 1.1rem; } }

/* the studio: "Go live" across the full width under Record and Upload */
.action--live { grid-column: 1 / -1; min-height: 0; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 12px; align-items: center; }
.action--live .action-icon { grid-row: 1 / 3; margin: 0; color: var(--live); }
.action--live .action-label, .action--live .action-sub { grid-column: 2; }
.action[hidden] { display: none; }
.live-panel { padding: 14px; border: 1.5px solid var(--line); border-radius: 18px; background: var(--btn-face); display: grid; gap: 10px; }
.live-panel[hidden] { display: none; }
.live-panel[data-state="live"], .live-panel[data-state="watch"] { border-color: rgba(201, 64, 108, 0.45); }
.live-top { display: flex; align-items: center; gap: 10px; }
.live-h { margin: 0; flex: 1; font: 700 1.1rem/1.2 var(--sans); }
.live-panel[data-state="ready"] .live-dot { animation: none; background: var(--line); box-shadow: none; }
.live-clock { font: 700 1rem var(--digit); color: var(--live); font-variant-numeric: tabular-nums; }
.live-ready, .live-on, .live-chat { display: none; }
.live-panel[data-state="ready"] .live-ready { display: grid; gap: 10px; }
.live-panel[data-state="live"] .live-on, .live-panel[data-state="watch"] .live-on { display: grid; gap: 10px; }
.live-panel[data-state="watch"] .live-meter { display: none; }
.live-panel[data-state="live"] .live-chat, .live-panel[data-state="watch"] .live-chat { display: grid; gap: 8px; }
.live-hint { margin: 0; font-size: 0.82rem; line-height: 1.45; color: var(--ink-soft); }
.live-btns { display: flex; gap: 8px; justify-content: flex-end; }
.live-room { margin: 0; font-size: 0.85rem; color: var(--ink-soft); }
.live-meter { height: 8px; border-radius: 4px; background: var(--well); box-shadow: var(--press-sm); overflow: hidden; }
.live-meter i { display: block; height: 100%; background: linear-gradient(90deg, var(--gold), var(--live)); transform-origin: left; transform: scaleX(0); transition: transform 0.08s linear; }
.live-end { justify-self: start; border-color: var(--live); color: var(--live); }
.live-end[hidden] { display: none; }
.live-chat .chat-list { list-style: none; margin: 0; padding: 8px 10px; max-height: 260px; min-height: 120px; overflow-y: auto; overscroll-behavior: contain;
  border-radius: 14px; background: var(--well); box-shadow: var(--press), var(--edge); display: grid; align-content: start; gap: 7px; }
.live-chat .chat-line { font-size: 0.92rem; line-height: 1.35; overflow-wrap: anywhere; }
.live-chat .chat-who { font-weight: 700; color: var(--gold-deep); margin-right: 6px; }
.live-chat .is-host .chat-who { color: var(--live); }
.live-chat .chat-empty { color: var(--ink-soft); font-size: 0.88rem; padding: 6px 0; }
.live-chat .chat-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }

/* notes on a scheduled show */
.queue-notes-btn { justify-self: start; margin-top: 2px; padding: 0; border: 0; background: none; color: var(--gold-deep); font: 600 0.8rem/1.3 var(--ui); cursor: pointer; }
.queue-notes-btn::before { content: "\270E  "; }
.queue-notes-btn.is-open { color: var(--ink); }
.queue-notes { grid-column: 1 / -1; display: grid; gap: 8px; padding: 4px 0 6px; }
.qn-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.qn-list li { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 8px; align-items: start; padding: 8px 10px; border-radius: 12px; background: var(--well); font-size: 0.88rem; line-height: 1.4; }
.qn-list b { color: var(--gold-deep); }
.qn-text { overflow-wrap: anywhere; }
.qn-del { width: 24px; height: 24px; padding: 0; border: 0; border-radius: 8px; background: none; color: var(--ink-soft); display: grid; place-items: center; cursor: pointer; }
.qn-del .icon { width: 14px; height: 14px; }
.qn-add { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }

/* the "Who posts music" tile */
.an-podium { list-style: none; margin: auto 0 0; padding: 0; display: grid; gap: 5px; transform: translateZ(20px); }
.an-podium li { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr); gap: 8px; align-items: center; font: 600 0.72rem/1.2 var(--ui); }
.an-podium-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.an-podium i { display: block; height: 6px; border-radius: 3px; background: var(--gold); transform-origin: left; transform: scaleX(var(--v, 0.1)); opacity: 0.85; }
.an-podium .an-podium-1 i { background: var(--live); }
.an-tile.is-open .an-podium { display: none; }
.an-list--posters li { grid-template-columns: minmax(0, 1.6fr) repeat(4, minmax(34px, auto)); text-align: right; }
.an-list--posters li > :first-child { text-align: left; }
.an-list--posters .an-list-head { font-size: 0.66rem; letter-spacing: 0.06em; text-transform: uppercase; opacity: 0.6; }
.an-list--posters .an-list-best { display: block; padding-top: 0; border-top: 0; text-align: left; font-size: 0.72rem; opacity: 0.65; }
.an-note { margin: 10px 0 0; font: 500 0.72rem/1.45 var(--ui); opacity: 0.7; }

/* ---------- Cobwebs (script: cobwebs): an installed app left alone for a week ---------- */
.webs { position: absolute; inset: 0; z-index: 6; pointer-events: none; overflow: hidden; border-radius: inherit; transition: opacity 3s ease; }
.webs.is-clear { opacity: 0; }
.webs-svg { position: absolute; left: 0; top: 0; overflow: visible; }
.webs-svg path { fill: none; stroke: url(#web-sheen); stroke-linecap: round; stroke-linejoin: round; transition: opacity 2.5s ease; }
.webs-svg .web-c { stop-color: rgba(118, 110, 98, 0.34); }
.webs-svg .web-hi { stop-color: rgba(255, 255, 255, 0.95); }
body.dark-mode .webs-svg .web-c { stop-color: rgba(232, 224, 208, 0.26); }
body.dark-mode .webs-svg .web-hi { stop-color: rgba(255, 252, 244, 0.75); }
.webs-svg .web-frame { stroke-width: 0.75; }
.webs-svg .web-moor { stroke-width: 0.7; }
.webs-svg .web-spoke { stroke-width: 0.6; }
.webs-svg .web-spiral { stroke-width: 0.45; }
.webs-svg .web-hub { stroke-width: 0.5; }
.webs-svg .web-loose { stroke-width: 0.5; }
.webs-svg .web-dew { fill: rgba(255, 255, 255, 0.85); stroke: rgba(118, 110, 98, 0.3); stroke-width: 0.3; transition: opacity 2.5s ease; }
.webs-svg .is-gone { opacity: 0; }
/* a light breeze: each web gives a little, at its own pace */
.web-sway { transform-box: view-box; animation: web-sway 6s ease-in-out infinite alternate; }
@keyframes web-sway { 0% { transform: translate(0, 0) skewX(0deg); } 40% { transform: translate(0.6px, 0.3px) skewX(0.6deg); } 100% { transform: translate(-0.4px, -0.2px) skewX(-0.5deg); } }
.web-spider { fill: rgba(62, 54, 45, 0.82); stroke: rgba(62, 54, 45, 0.82); transition: opacity 2s ease 0.8s; }
.web-spider .web-spider-legs path { fill: none; stroke-width: 0.55; stroke: rgba(62, 54, 45, 0.82); }
.web-spider .web-spider-mark { fill: none; stroke: rgba(235, 225, 205, 0.6); stroke-width: 0.5; }
body.dark-mode .web-spider, body.dark-mode .web-spider .web-spider-legs path { fill: rgba(212, 202, 182, 0.75); stroke: rgba(212, 202, 182, 0.75); }
.web-spider.is-gone { opacity: 0; }
.webs-svg .web-silk { stroke: rgba(118, 110, 98, 0.45); stroke-width: 0.45; }
body.dark-mode .webs-svg .web-silk { stroke: rgba(232, 224, 208, 0.4); }
/* a hanging spider turns a little on its thread, and climbs back up as the webs clear */
.web-hanging { transform-box: view-box; animation: web-dangle 5s ease-in-out infinite alternate; transition: opacity 2s ease 1.2s, translate 2.4s ease-in; }
.web-hanging.is-gone { translate: 0 -40px; }
@keyframes web-dangle { from { rotate: -4deg; } to { rotate: 4deg; } }
/* dust on the radio */
.webs-svg .web-speck { fill: rgba(96, 88, 76, 1); transition: opacity 3s ease; }
.webs-svg .web-lint { fill: none; stroke: rgba(96, 88, 76, 0.4); stroke-width: 0.45; }
body.dark-mode .webs-svg .web-speck { fill: rgba(225, 216, 198, 0.8); }
body.dark-mode .webs-svg .web-lint { stroke: rgba(225, 216, 198, 0.35); }
.webs-svg .web-speck.is-gone, .webs-svg .web-lint.is-gone { opacity: 0 !important; }
/* dust and fluff carried through by the breeze */
.web-mote { position: absolute; left: -12px; width: 2.5px; height: 2.5px; border-radius: 50%; background: rgba(255, 252, 244, 0.85);
  box-shadow: 0 0 3px rgba(255, 252, 244, 0.7); animation: web-drift 14s linear infinite; transition: opacity 2s ease; }
.web-mote--seed { width: 7px; height: 7px; background: none; box-shadow: none;
  background-image: radial-gradient(circle at 50% 50%, rgba(120, 104, 80, 0.55) 0 1px, transparent 1.4px),
                    repeating-conic-gradient(rgba(255, 255, 255, 0.75) 0 4deg, transparent 4deg 30deg); }
body.dark-mode .web-mote { background-color: rgba(255, 248, 230, 0.5); }
.web-mote.is-gone { opacity: 0; }
@keyframes web-drift {
  0% { left: -12px; transform: translateY(0) rotate(0); opacity: 0; }
  8% { opacity: 0.9; }
  30% { transform: translateY(-10px) rotate(70deg); }
  55% { transform: translateY(6px) rotate(160deg); }
  80% { transform: translateY(-6px) rotate(240deg); opacity: 0.8; }
  100% { left: calc(100% + 12px); transform: translateY(4px) rotate(320deg); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .web-sway, .web-mote, .web-hanging { animation: none; } .web-mote { display: none; } }
@media (prefers-reduced-motion: reduce) { .live-dot, .plate-news.is-chat .plate-label::before { animation: none; } }
/* the channel link in the guide: ink on the paper, kept left-to-right inside Farsi */
.guide .guide-link { color: inherit; font-weight: 600; text-decoration: underline; text-decoration-color: rgba(111, 103, 92, 0.5); text-decoration-thickness: 1px; text-underline-offset: 3px; direction: ltr; unicode-bidi: isolate; white-space: nowrap; }
.guide .guide-link:visited { color: inherit; }
/* signed in: "For hootan", the tools they have, in the paper's ink */
.guide-host { margin: 6px 0 18px; padding-top: 14px; border-top: 1px dashed rgba(111, 103, 92, 0.35); }
.guide-host[hidden] { display: none; }
.guide-host-title { margin: 0 0 10px; font: italic 600 1.15rem/1.2 var(--sans); color: #4c463e; }
.guide-tools { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.guide-tools li { display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: 10px; align-items: start; font-size: 0.92rem; line-height: 1.4; color: #5d564c; }
.guide-tools .icon { width: 20px; height: 20px; margin-top: 1px; color: #6f675c; }
.guide-tools b { color: #3f3a33; }
.live-dot { flex: none; width: 10px; height: 10px; border-radius: 50%; background: var(--flamingo); box-shadow: 0 0 0 3px rgba(240, 119, 156, 0.22); animation: blink 1.6s steps(2, jump-none) infinite; }
/* short screens: the chat keeps fewer lines in view, so the radio still fits without scrolling */
html.fit-1 .plate-chat-list { height: 7.8em; }
html.fit-2 .plate-chat-list { height: 5.6em; }
html.fit-3 .plate-chat-list { height: 3.9em; }
