/*!
 * Fluid Sonata — stage styling.
 * Aesthetic: concert hall, lights down. The fluid is the performer; the
 * chrome is an usher — present when you need it, gone when you don't.
 * System type stack only: the app fetches no fonts at runtime.
 *
 * © 2026 djEnterprises · Daniel J. Ehrlich
 */

:root {
  --bg: #05060a;
  --text: #e8e6f2;
  --dim: rgba(232, 230, 242, 0.52);
  --dimmer: rgba(232, 230, 242, 0.34);
  --hair: rgba(255, 255, 255, 0.15);
  --glass: rgba(255, 255, 255, 0.06);
  --glass-2: rgba(255, 255, 255, 0.12);
  --gold: #d9a441;
  /* the orrery reads these — each orbit ring wears its planet's colour */
  --mercury: #c9b39a;
  --venus: #f2cd6e;
  --earth: #5fb2ff;
  --moon: #d6dbe8;
  --mars: #ff7a4d;
  --jupiter: #e5a95f;
  --saturn: #eed9a0;
  --uranus: #8fe0ef;
  --neptune: #7f9cff;
  --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  /* motion tokens — every duration/easing below comes from here */
  --quick: 0.18s;
  --settle: 0.6s;
  --ease-out: cubic-bezier(0.22, 0.9, 0.3, 1);
  --spring: cubic-bezier(0.34, 1.4, 0.44, 1);
  --press: scale(0.965);
}

* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  width: 100%; height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

/* the stage eases in on load instead of popping (reduced motion: instant) */
@keyframes stageIn { from { opacity: 0; } }
html { touch-action: manipulation; }  /* taps fire instantly — no double-tap-zoom wait */

#orrery, canvas#stage { animation: stageIn 0.9s var(--ease-out) both; }

/* Layer order: orrery (0) → fluid (1) → chrome (5+) → gate (10) → sheet (20) */
#orrery {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  transition: opacity 0.9s ease;
}
#orrery.off { opacity: 0 !important; }

canvas#stage {
  position: fixed; inset: 0; z-index: 1;
  display: block; width: 100vw; height: 100vh;
  touch-action: none; cursor: crosshair;
}

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }

:focus-visible { outline: 1px solid var(--gold); outline-offset: 3px; }

/* ── chrome: fades out when the audience goes still ─────────────────── */
.chrome { position: fixed; z-index: 5; transition: opacity 0.7s ease; }
body.idle .chrome { opacity: 0; }
/* George's rule (2026-07-31): EVERYTHING — top rail included — yields to
   the stage after ~5 s; any touch or mouse move brings it back. Two
   exceptions: an OPEN settings sheet never fades from under a reader,
   and the music player ghosts at 25% instead of vanishing — a player
   that disappears mid-listen reads as a crash, not as cinema. */
body.idle #settings { opacity: 1; }
body:not(.started) #hud,
body:not(.started) #dock { opacity: 0; pointer-events: none; }
body.started #hud,
body.started #dock { opacity: 1; }
/* SPECIFICITY LAW (found 2026-08-01, Daniel's phone): the started rules
   above carry an ID, so class-only `body.idle .chrome` NEVER beat them —
   the dock/HUD/simdock could not fade once playing, on any platform.
   These ID-level rules come AFTER, so idle finally wins.

   IDLE IS NOT "HIDE EVERYTHING" (settled 2026-08-01): what you OPERATE
   fades — the top rail, the pills, the player dims. What you WATCH stays:
   the equalizer, the track text and the capsule with its live epoch, which
   ticks a day at a time and is meant to be watched. #simdock was already
   staying (its `body.started` rule outranked the idle one), but the HUD was
   fading out of the same group — that half-dressed look is what Daniel
   photographed. */
body.idle #dock { opacity: 0; }
body.idle #player { opacity: 0.25; }

/* top rail */
#top {
  top: 0; left: 0; right: 0;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 18px 20px;
  font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--dim);
  background: linear-gradient(180deg, rgba(3, 4, 8, 0.55), transparent);
  pointer-events: none;
}
#top { flex-wrap: nowrap; }
#top .mark, #top nav a { white-space: nowrap; }
#top .mark { font-weight: 300; letter-spacing: 0.22em; }
#top .mark em { font-style: italic; color: var(--text); opacity: 0.9; }
#top nav { display: flex; align-items: center; gap: 18px; pointer-events: auto; }
#top nav a { transition: color 0.2s ease; }
#top nav a:hover { color: var(--text); }
#top .home { display: inline-flex; align-items: center; gap: 7px; pointer-events: auto; }
#top nav .home { display: inline-flex; align-items: center; gap: 7px; }
#top .home img { width: 20px; height: 20px; opacity: 0.85; }
#top .home:hover img { opacity: 1; }
#top nav .home img { width: 20px; height: 20px; opacity: 0.85; }
#top nav .home:hover img { opacity: 1; }

/* the settings gear + its popover */
#top nav .gear {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--hair); background: var(--glass);
  color: var(--dim);
  transition: color 0.2s ease, background 0.2s ease, transform 0.5s var(--ease-out);
}
#top nav .gear:hover { color: var(--text); background: var(--glass-2); transform: rotate(40deg); }
#top nav .gear.on { color: var(--gold); border-color: rgba(217, 164, 65, 0.5); transform: rotate(90deg); }

#settings {
  top: 56px; right: 16px; z-index: 9; width: 250px;
  max-height: calc(100vh - 76px - env(safe-area-inset-bottom, 0px));
  overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
  padding: 16px 18px 14px; border-radius: 16px;
  border: 1px solid var(--hair);
  background: linear-gradient(180deg, rgba(16, 18, 30, 0.74), rgba(8, 9, 16, 0.78));
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
}
#settings::-webkit-scrollbar { width: 7px; }
#settings::-webkit-scrollbar-track { background: transparent; }
#settings::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.18); border-radius: 4px; }
#settings::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.3); }
#settings[hidden] { display: none; }
#settings .set-brand {
  display: flex; align-items: center; gap: 9px;
  padding-bottom: 13px; margin-bottom: 13px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 13px; font-weight: 300; letter-spacing: 0.03em; color: var(--dim);
  transition: color 0.2s ease;
}
#settings .set-brand em { font-style: italic; color: var(--text); }
#settings .set-brand img { width: 22px; height: 22px; opacity: 0.9; }
#settings .set-brand:hover { color: var(--text); }
#settings .set-brand:hover img { opacity: 1; }

#settings .set-k {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--dimmer); margin-bottom: 9px;
}
#settings .set-row { display: flex; gap: 7px; flex-wrap: wrap; }
#settings .set-row.wrap { flex-wrap: wrap; }
#settings .set-row.wrap button { flex: 1 1 calc(50% - 4px); }
#settings .set-k + .set-k, #settings .set-note + .set-k { margin-top: 14px; }
#settings .set-note + .set-k { border-top: 1px solid rgba(255, 255, 255, 0.08); padding-top: 13px; }
#settings .set-row button {
  flex: 1; padding: 8px 10px; border-radius: 11px;
  border: 1px solid var(--hair); background: var(--glass);
  color: var(--dim); font-size: 12px;
  transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease, transform var(--quick) var(--spring);
}
#settings .set-row button:hover { color: var(--text); background: var(--glass-2); }
#settings .set-row button:active { transform: var(--press); }
#settings .set-row button.on { color: var(--gold); border-color: rgba(217, 164, 65, 0.55); background: rgba(217, 164, 65, 0.1); }
#settings .set-note { margin-top: 11px; font-size: 11px; line-height: 1.6; color: var(--dimmer); }
#settings .set-col { display: flex; flex-direction: column; gap: 6px; }
#settings .file-btn {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  padding: 8px 12px; border-radius: 11px;
  border: 1px solid rgba(217, 164, 65, 0.4); background: rgba(217, 164, 65, 0.08);
  color: var(--text); font-size: 12px;
  transition: background 0.15s ease, border-color 0.15s ease;
}
#settings .file-btn:hover { background: rgba(217, 164, 65, 0.16); border-color: rgba(217, 164, 65, 0.6); }
#settings .file-btn .lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#settings .set-col button {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; border-radius: 11px; text-align: left;
  border: 1px solid var(--hair); background: var(--glass);
  color: var(--dim); font-size: 12px;
  transition: color 0.15s ease, background 0.15s ease, transform var(--quick) var(--spring);
}
#settings .set-col button:hover { color: var(--text); background: var(--glass-2); }
#settings .set-col button:active { transform: var(--press); }
#top nav .gear.rec { color: #ff6b6b; border-color: rgba(255, 107, 107, 0.55); }

/* ── the top-bar switches: Tilt and Haptics (2026-08-06) ────────────
   Same chip as the gear, minus the gear's rotate — these are switches, not
   a panel, and a spinning switch reads as a spinner. ON is the house gold.
   They sit in the top bar because the phone dock's rows are deterministic
   by design; a button added there brings the sometimes-wrapping back. */
#top nav .gear.tgl:hover { transform: none; background: var(--glass-2); color: var(--text); }
#top nav .gear.tgl.on {
  transform: none; color: var(--gold);
  border-color: rgba(217, 164, 65, 0.55);
  background: rgba(217, 164, 65, 0.12);
  box-shadow: 0 0 10px rgba(217, 164, 65, 0.22);
}
#top nav .gear.tgl:active { transform: scale(0.94); }
#top nav .gear.tgl[hidden] { display: none; }
#top nav .gear.rec svg { animation: blink 1s steps(2, end) infinite; }
#settings .set-note kbd {
  font-family: var(--mono); font-size: 9.5px; padding: 1px 5px;
  border: 1px solid var(--hair); border-radius: 4px; color: var(--dim);
}

/* HUD, bottom-left */
/* Deliberately NOT uppercased: catalogue numbers carry their own casing
   ("WoO 59" is Werke ohne Opuszahl — "WOO 59" would be wrong). */
/* The text rides ON the equalizer, not above it (Daniel, 2026-08-01): the
   negative margin pulls the canvas up under these three lines, and
   position+z-index keeps them painted over the bars. */
#hud {
  position: relative; z-index: 1; margin-bottom: -184px;
  font-family: var(--mono);
  font-size: 11px; letter-spacing: 0.14em;
  color: var(--dim); pointer-events: none; line-height: 1.7;
  text-shadow: 0 1px 2px rgba(6, 8, 14, 0.95), 0 0 12px rgba(6, 8, 14, 0.8);
}
#hudSub { color: var(--dimmer); text-transform: none; letter-spacing: 0.06em; }
#hudLine, #hudSub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@keyframes hudSwap { from { opacity: 0.15; } to { opacity: 1; } }
#hudLine.swap, #hudSub.swap { animation: hudSwap 0.5s var(--ease-out); }
/* the LOOK pill nods when the rotation hands it a new palette */
@keyframes pillNod { 35% { transform: scale(1.06); } }
.ctl.nod { animation: pillNod 0.4s var(--spring); }

/* the one-line "what is this" caption, sitting above the control bar */
#dock {
  right: 20px; bottom: 16px;
  display: flex; flex-direction: column; align-items: flex-end; gap: 10px;
  /* wide enough that the gold Your-music bar rides the SAME row as the
     pills instead of wrapping to a line of its own (Daniel, 2026-08-01) */
  max-width: min(790px, calc(100vw - 40px));
}
.sheet-in .kicker img { width: 18px; height: 18px; vertical-align: -4px; margin-right: 4px; opacity: 0.95; }
.sheet-in .kicker em { font-style: italic; }

/* phones: the stage speaks for itself — no caption at all */
@media (max-width: 700px) {
  #blurb .blurb-full { display: none; }
}
/* the REC pill: quiet until armed, then unmistakably live */
#ctlRec.rec { color: #ff6b6b; border-color: rgba(255, 107, 107, 0.55); }
#ctlRec.rec svg { animation: blink 1s steps(2, end) infinite; }

.ctl-brk { display: none; }   /* desktop: one bar, no break */
/* ── the observatory (bottom-LEFT): equalizer above the sim pod ─────
   Daniel's split (2026-07-31): left = what you watch (eq, epoch, track
   text, ORBIT/SPEED), right = what you operate (pills, the player). */
#simdock {
  left: 20px; bottom: 16px; z-index: 4;
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
}
#spectrum {
  display: block; width: min(44vw, 560px); height: 190px;
  pointer-events: none; opacity: 0.78;
}
body:not(.started) #simdock { opacity: 0; pointer-events: none; }
body.started #simdock { opacity: 1; }
/* the pod goes glassier still (Daniel: 'slightly greater translucency') */
#simdock .pod {
  background: rgba(255, 255, 255, 0.035);
  border-color: rgba(255, 255, 255, 0.10);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
}
#blurb {
  max-width: 430px; text-align: right;
  font-size: 10.5px; line-height: 1.75; letter-spacing: 0.03em;
  color: var(--dimmer); pointer-events: none;
}
#blurb b { font-weight: 500; color: var(--dim); }
#blurb .blurb-short { display: none; }
#blurb button {
  pointer-events: auto; color: var(--dim); font-size: 10.5px;
  letter-spacing: 0.06em; border-bottom: 1px solid rgba(255, 255, 255, 0.22);
  transition: color 0.2s ease, border-color 0.2s ease;
}
#blurb button:hover { color: var(--text); border-color: var(--gold); }

/* ── the your-music player: a real transport on the stage ──────────── */
/* ── the Corner Deck: the audience's player, bottom-LEFT (D1) ────────
   Translucent so the stage reads through it; the dock keeps the right
   corner. On phones it collapses to a mini-bar + pull-up sheet (M1). */
#player {
  right: 20px; bottom: 16px; z-index: 6;
  width: 340px; max-width: calc(100vw - 40px);
}
#player[hidden] { display: none; }
.p-deck {
  position: relative;
  padding: 13px 16px 12px; border-radius: 18px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  background: rgba(10, 12, 20, 0.20);
  backdrop-filter: blur(26px) saturate(1.25); -webkit-backdrop-filter: blur(26px) saturate(1.25);
}
/* the deck says whose music this is — the power button beside SCORES is
   the way back to the written programme (Daniel, 2026-08-01) */
.p-kicker {
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--gold); opacity: 0.75;
  margin-bottom: 6px;
}
.p-grab { display: none; }
.p-mini { display: none; }
.p-head { display: flex; align-items: baseline; gap: 9px; }
.p-kbps {
  flex-shrink: 0; font-family: var(--mono); font-size: 9px;
  letter-spacing: 0.08em; color: var(--dimmer);
}
.p-name {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12.5px; letter-spacing: 0.03em; color: var(--text);
}
/* the power switch back to the written programme. No label: the deck says
   YOUR MUSIC at the top, and the word "Scores" on this button kept reading
   as the panel's own title (Daniel, twice, 2026-08-01). A power glyph on a
   player is unambiguous — it's how every stereo has ever worked. */
#pEject {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--hair); color: var(--dim);
  transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease, transform var(--quick) var(--spring);
}
#pEject:hover { border-color: rgba(217, 164, 65, 0.5); }
#pEject:hover { color: var(--text); background: var(--glass-2); }
#pEject:active { transform: var(--press); }

.p-scrub { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.p-time {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.04em;
  color: var(--dim); font-variant-numeric: tabular-nums; min-width: 34px;
}
.p-time:last-child { text-align: right; }
.p-barwrap { position: relative; flex: 1; display: flex; align-items: center; }
#pBar {
  -webkit-appearance: none; appearance: none; width: 100%; height: 26px;
  background: transparent; cursor: pointer;
  --fill: 0%;   /* the played portion, driven from JS */
}
#pBar::-webkit-slider-runnable-track {
  height: 4px; border-radius: 2px;
  background: linear-gradient(90deg, var(--gold) var(--fill), rgba(255, 255, 255, 0.14) var(--fill));
}
#pBar::-webkit-slider-thumb {
  -webkit-appearance: none; width: 13px; height: 13px; border-radius: 50%;
  background: var(--text); margin-top: -4.5px;
  box-shadow: 0 0 8px rgba(217, 164, 65, 0.6);
  transition: transform var(--quick) var(--spring);
}
#pBar:active::-webkit-slider-thumb { transform: scale(1.35); }
#pBar::-moz-range-track { height: 4px; border-radius: 2px; background: rgba(255, 255, 255, 0.14); }
#pBar::-moz-range-progress { height: 4px; border-radius: 2px; background: var(--gold); }
#pBar::-moz-range-thumb {
  width: 13px; height: 13px; border: 0; border-radius: 50%;
  background: var(--text); box-shadow: 0 0 8px rgba(217, 164, 65, 0.6);
}
.p-bubble {
  position: absolute; bottom: 26px; transform: translateX(-50%);
  padding: 3px 8px; border-radius: 7px;
  border: 1px solid var(--hair); background: rgba(8, 9, 16, 0.95);
  font-family: var(--mono); font-size: 10.5px; color: var(--text);
  pointer-events: none; white-space: nowrap;
}

.p-transport { display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 6px; }
.p-transport button[hidden], .p-toggles button[hidden] { display: none; }   /* [hidden] must beat the display rules */
.p-transport button {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 50%;
  color: var(--dim);
  transition: color 0.15s ease, background 0.15s ease, transform var(--quick) var(--spring);
}
.p-transport button:hover { color: var(--text); background: rgba(255, 255, 255, 0.08); }
.p-transport button:active { transform: scale(0.9); }
.p-ten {
  position: absolute; bottom: -1px; left: 50%; transform: translateX(-50%);
  font-family: var(--mono); font-size: 7.5px; letter-spacing: 0.08em; color: var(--dimmer);
}
.p-play {
  width: 54px !important; height: 54px !important;
  border: 1px solid rgba(217, 164, 65, 0.55); background: rgba(217, 164, 65, 0.12);
  color: var(--text) !important;
  box-shadow: 0 0 18px rgba(217, 164, 65, 0.22);
}
.p-play:hover { background: rgba(217, 164, 65, 0.2) !important; }
@keyframes playPop { 40% { transform: scale(1.12); } }
.p-play.pop { animation: playPop 0.32s var(--spring); }

/* the toggles row: shuffle · repeat · queue — and the door back out */
.p-toggles { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.p-toggles button {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  width: 32px; height: 32px; border-radius: 50%;
  color: var(--dim);
  transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease, transform var(--quick) var(--spring);
}
.p-toggles button:hover { color: var(--text); background: rgba(255, 255, 255, 0.08); }
.p-toggles button:active { transform: scale(0.9); }
.p-toggles button.on { color: var(--gold); background: rgba(217, 164, 65, 0.12); }
#pList { width: auto; padding: 0 10px; border-radius: 16px; }
.p-count { font-family: var(--mono); font-size: 9px; letter-spacing: 0.06em; }
.p-flex { flex: 1; }
.p-mobile-only { display: none !important; }

/* the queue: floats ABOVE the deck on desktop, Winamp-drawer style */
#playlist {
  position: absolute; left: 0; right: 0; bottom: calc(100% + 8px);
  max-height: 236px; overflow-y: auto; overscroll-behavior: contain;
  padding: 8px; border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  background: rgba(10, 12, 20, 0.38);
  backdrop-filter: blur(22px) saturate(1.2); -webkit-backdrop-filter: blur(22px) saturate(1.2);
  scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
}
#playlist[hidden] { display: none; }
#playlist .q-row {
  display: flex; align-items: center; gap: 9px;
  width: 100%; padding: 7px 9px; border-radius: 9px;
  color: var(--dim); font-size: 12px; text-align: left;
  transition: color 0.15s ease, background 0.15s ease;
}
#playlist .q-row:hover { color: var(--text); background: rgba(255, 255, 255, 0.06); }
#playlist .q-num { font-family: var(--mono); font-size: 9.5px; color: var(--dimmer); min-width: 16px; }
#playlist .q-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#playlist .q-dur { font-family: var(--mono); font-size: 9.5px; color: var(--dimmer); font-variant-numeric: tabular-nums; }
#playlist .q-row.now { color: var(--gold); background: rgba(217, 164, 65, 0.1); }
#playlist .q-row.now .q-num, #playlist .q-row.now .q-dur { color: rgba(217, 164, 65, 0.75); }

/* file mode slims the dock: the deck owns transport and identity */
/* In file mode the deck IS the instrument — mute and record live inside it
   now, so nothing is left floating in the corner (Daniel, 2026-08-01). */
#dock.filemode #controls [data-act="play"],
#dock.filemode #controls [data-act="mute"],
#dock.filemode #controls #ctlRec,
#dock.filemode #controls .ctl-brk { display: none; }
/* [data-act="track"] STAYS in file mode — it is no longer the score
   cycler there, it is the labelled door back to the programme (Daniel,
   2026-08-05). Hiding it is what made the way home invisible. */
#dock.filemode #controls [data-act="track"] { border-color: rgba(217, 164, 65, 0.4); }
#dock.filemode #controls [data-act="track"] .v { color: var(--gold); }
/* file mode on desktop: the deck stacks ABOVE the slimmed dock row
   (mute + REC), both on the right — the cockpit side. The HUD keeps its
   track text now — it lives on the LEFT, no collision possible. */
/* The deck used to be lifted 74px to clear the mute/record circles below
   it. Those moved INSIDE the deck (v84), so it sits flush with the rest of
   the bottom rail again. */
/* ── the build log: measured, never estimated ──────────────────────── */
.build-log { display: flex; flex-direction: column; gap: 5px; margin: 2px 0 4px; }
.bl-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.06em;
}
.bl-row span { color: var(--dimmer); text-transform: uppercase; letter-spacing: 0.12em; }
.bl-row b { color: var(--text); font-weight: 500; text-align: right; }
.link-b {
  color: var(--gold); border-bottom: 1px solid rgba(217, 164, 65, 0.4);
  font-size: inherit; letter-spacing: inherit;
}
.stat-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px; margin: 14px 0 16px;
}
.stat {
  padding: 11px 12px; border-radius: 12px;
  border: 1px solid var(--hair); background: rgba(255, 255, 255, 0.025);
}
.stat b {
  display: block; font-family: var(--mono); font-size: 17px; font-weight: 500;
  color: var(--gold); letter-spacing: 0.02em; margin-bottom: 3px;
}
.stat span { display: block; font-size: 10.5px; line-height: 1.5; color: var(--dim); }

/* the deck owns its corner: the caption yields in file mode */
body.filemode #blurb { display: none; }

/* The observatory and the cockpit share the bottom rail only when there is
   genuinely room for both. The capsule runs to ~547px and the dock to 790,
   so under ~1380px they collide (Daniel photographed the pills sitting on
   top of the ORBIT slider). Below that, the pills take their own line above
   the capsule — the same stacking phones already use. */
@media (max-width: 1380px) and (min-width: 701px) {
  #dock { bottom: 66px; }
}

/* control bar, bottom-right */
#controls {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  justify-content: flex-end;
}
#controls .ctl { flex-shrink: 0; }
.ctl[hidden] { display: none; }   /* the author display below would beat [hidden] */
.ctl {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 34px; padding: 0 12px;
  border: 1px solid var(--hair); border-radius: 17px;
  background: var(--glass); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  color: var(--dim);
  font-size: 11px; letter-spacing: 0.12em;
  transition: color 0.2s ease, background 0.2s ease, border-color 0.2s ease, transform 0.12s ease;
}
.ctl:hover { color: var(--text); background: var(--glass-2); border-color: rgba(255, 255, 255, 0.28); }
.ctl:active { transform: var(--press); transition-duration: 0.06s; }
.ctl .k { color: var(--dimmer); font-size: 10px; letter-spacing: 0.16em; }
.ctl .v { color: var(--text); text-transform: none; letter-spacing: 0.02em; }
/* the orrery pod: two steppers (zoom, speed) inside one glass pill */
.ctl.pod { gap: 4px 6px; padding: 0 10px; cursor: default; flex-wrap: wrap; }
.ctl.pod.hide { display: none; }
.ctl.pod button {
  width: 22px; height: 24px; border-radius: 8px; color: var(--dim);
  font-size: 13px; line-height: 1; display: inline-flex;
  align-items: center; justify-content: center;
  transition: color 0.15s ease, background 0.15s ease;
}
.ctl.pod button:hover { color: var(--text); background: rgba(255, 255, 255, 0.12); }
.ctl.pod button:active { transform: scale(0.9); }
.ctl.pod button { transition: color 0.15s ease, background 0.15s ease, transform var(--quick) var(--spring); }
.ctl.pod .v { min-width: 42px; text-align: center; font-family: var(--mono); font-size: 10px; }
.ctl.pod .sep { width: 1px; height: 16px; background: var(--hair); margin: 0 4px; }
.ctl.pod .pod-k { margin-right: 2px; }
.ctl.pod .pod-grp { display: inline-flex; align-items: center; gap: 7px; }
.ctl.pod .names {
  padding: 3px 9px; border-radius: 9px; font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--dim);
  transition: color 0.15s ease, background 0.15s ease;
}
.ctl.pod .names:hover { color: var(--text); background: rgba(255, 255, 255, 0.1); }
.ctl.pod .names.on { color: var(--gold); background: rgba(217, 164, 65, 0.14); }

/* the zoom slider — logarithmic AU, gold-lit track */
#zoomSlider, #tiltSlider, #speedSlider { -webkit-appearance: none; appearance: none; width: 86px; height: 24px; background: transparent; cursor: pointer; }
#zoomSlider::-webkit-slider-runnable-track, #tiltSlider::-webkit-slider-runnable-track, #speedSlider::-webkit-slider-runnable-track {
  height: 3px; border-radius: 2px;
  background: linear-gradient(90deg, rgba(217, 164, 65, 0.75), rgba(255, 255, 255, 0.16));
}
#zoomSlider::-webkit-slider-thumb, #tiltSlider::-webkit-slider-thumb, #speedSlider::-webkit-slider-thumb {
  -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%;
  background: var(--text); margin-top: -5.5px;
  box-shadow: 0 0 8px rgba(217, 164, 65, 0.55);
  transition: transform var(--quick) var(--spring);
}
#zoomSlider:active::-webkit-slider-thumb, #speedSlider:active::-webkit-slider-thumb { transform: scale(1.3); }
#zoomSlider::-moz-range-track, #tiltSlider::-moz-range-track, #speedSlider::-moz-range-track {
  height: 3px; border-radius: 2px;
  background: linear-gradient(90deg, rgba(217, 164, 65, 0.75), rgba(255, 255, 255, 0.16));
}
#zoomSlider::-moz-range-thumb, #tiltSlider::-moz-range-thumb, #speedSlider::-moz-range-thumb {
  width: 14px; height: 14px; border: 0; border-radius: 50%;
  background: var(--text); box-shadow: 0 0 8px rgba(217, 164, 65, 0.55);
}

/* the epoch counter Daniel loves — gold, and on every screen size */
/* the date moved onto the ORBIT/SPEED capsule (Daniel, 2026-08-01) — one
   home for it, and the one band phones never bury under the control rows */
#hudEpoch { display: none; }
.pod-epoch .v { min-width: 78px; color: var(--gold); letter-spacing: 0.06em; }
/* desktop keeps the date inline in the capsule; the standalone line is the
   phone's answer, so the capsule there stays a single row */
#simEpoch { display: none; }

/* the drag coach: one gentle banner until the first real stir */
#dragHint {
  position: fixed; left: 50%; bottom: 118px; z-index: 6;
  transform: translate(-50%, 10px);
  padding: 10px 18px; border-radius: 21px;
  border: 1px solid var(--hair); background: rgba(10, 12, 20, 0.78);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  font-size: 12px; letter-spacing: 0.08em; color: var(--dim);
  opacity: 0; pointer-events: none;
  transition: opacity 0.5s ease, transform 0.5s var(--ease-out);
}
#dragHint.show { opacity: 1; transform: translate(-50%, 0); }
#dragHint .dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--gold); margin-right: 9px; vertical-align: 1px;
  animation: hintPulse 1.6s ease-in-out infinite;
}
@keyframes hintPulse { 50% { transform: scale(1.55); opacity: 0.45; } }

/* the your-music pill reads as the special door it is */
.ctl.gold { border-color: rgba(217, 164, 65, 0.45); color: var(--text); }
.ctl.gold svg { color: var(--gold); }
.ctl.gold:hover { border-color: rgba(217, 164, 65, 0.7); background: rgba(217, 164, 65, 0.1); }
/* the SOUND pill lights up while the EDM remix is playing */
.ctl.on { border-color: rgba(217, 164, 65, 0.65); background: rgba(217, 164, 65, 0.12); color: var(--text); }
.ctl.on svg { color: var(--gold); }

.ctl.rec.on { color: #ff6b6b; border-color: rgba(255, 107, 107, 0.5); background: rgba(255, 107, 107, 0.12); }
.ctl.rec.on svg { animation: blink 1s steps(2, end) infinite; }
@keyframes blink { 50% { opacity: 0.25; } }

/* ── the title gate ────────────────────────────────────────────────── */
#overlay {
  position: fixed; inset: 0; z-index: 10;
  display: flex;   /* .ov-in centers via margin:auto — overflow stays reachable */
  padding: 88px 20px 96px;
  /* Light enough that the prelude swirls read through it, dark enough that
     the title copy stays legible over whatever the fluid is doing. */
  background: radial-gradient(ellipse at center, rgba(8, 10, 18, 0.62), rgba(3, 4, 8, 0.88));
  cursor: pointer; user-select: none;
  transition: opacity 0.6s ease, visibility 0.6s ease;
  overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
}
#overlay::-webkit-scrollbar { width: 8px; }
#overlay::-webkit-scrollbar-track { background: transparent; }
#overlay::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.16); border-radius: 4px; }
#overlay.hidden { opacity: 0; visibility: hidden; pointer-events: none; }
/* Reading the About sheet from the title screen: pull the title copy right
   down so it can't compete with the text on top of it. */
body.sheet-open #overlay { opacity: 0.1; pointer-events: none; }

.ov-in { text-align: center; max-width: 940px; width: 100%; margin: auto; }
/* staggered entrance: eyebrow → title → sub → scores → play → hints */
@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}
.ov-in > * { animation: rise var(--settle) var(--ease-out) both; }
.ov-in .ov-brand { animation-delay: 0.02s; }
.ov-in .eyebrow { animation-delay: 0.1s; }
.ov-in h1 { animation-delay: 0.14s; }
.ov-in .sub { animation-delay: 0.24s; }
.ov-in .play { animation-delay: 0.34s; }
.ov-in .gate-music { animation-delay: 0.44s; }
.ov-in .hint { animation-delay: 0.52s; }
.ov-in #scores { animation-delay: 0.6s; }
.ov-in .ov-more { animation-delay: 0.7s; }
/* the house lockup, above the title — clicking it goes home */
.ov-brand {
  display: inline-flex; align-items: center; gap: 10px;
  margin-bottom: 20px; padding: 6px 4px;
  font-size: 16px; font-weight: 300; letter-spacing: 0.04em; color: var(--dim);
  transition: color 0.2s ease;
}
.ov-brand em { font-style: italic; color: var(--text); }
.ov-brand img { width: 30px; height: 30px; opacity: 0.9; transition: opacity 0.2s ease, transform 0.4s var(--spring); }
.ov-brand:hover { color: var(--text); }
.ov-brand:hover img { opacity: 1; transform: scale(1.06); }

.ov-in .eyebrow {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.28em;
  text-transform: uppercase; color: var(--gold); opacity: 0.85; margin-bottom: 18px;
}
.ov-in h1 {
  font-weight: 250; font-size: clamp(30px, 5.4vw, 58px);
  letter-spacing: 0.14em; line-height: 1.05;
}
.ov-in h1 em { font-style: italic; opacity: 0.82; }
.ov-in .sub {
  margin-top: 14px; font-size: 13px; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--dim);
}

/* score picker */
#scores {
  margin: 34px auto 0; display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  max-width: 780px; text-align: left;
}
.score {
  display: block; padding: 15px 16px 16px;
  border: 1px solid var(--hair); border-radius: 14px;
  background: var(--glass); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  transition: border-color 0.2s ease, background 0.2s ease, transform var(--quick) var(--spring);
}
.score:active { transform: var(--press); }
.score:hover { transform: translateY(-2px); background: var(--glass-2); border-color: rgba(255, 255, 255, 0.3); }
.score.on { border-color: rgba(217, 164, 65, 0.6); background: rgba(217, 164, 65, 0.09); }
.score-composer {
  display: block; font-family: var(--mono); font-size: 9.5px;
  letter-spacing: 0.22em; text-transform: uppercase; color: var(--gold);
  opacity: 0.8; margin-bottom: 5px;
}
.score-n { display: block; font-size: 16px; font-weight: 400; letter-spacing: 0.03em; }
.score-w { display: block; margin-top: 5px; font-size: 12px; color: var(--dim); }
.score-c { display: block; margin-top: 2px; font-family: var(--mono); font-size: 10px; letter-spacing: 0.12em; color: var(--dimmer); }
.score-b { display: block; margin-top: 10px; font-size: 12px; line-height: 1.5; color: var(--dim); }

/* the your-music front door on the gate */
.gate-music {
  margin: 16px auto 0; display: inline-flex; align-items: center; gap: 10px;
  padding: 10px 18px; border-radius: 19px;
  border: 1px solid var(--hair); background: var(--glass);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  font-size: 12.5px; letter-spacing: 0.04em; color: var(--dim);
  transition: color 0.2s ease, background 0.2s ease, border-color 0.2s ease, transform var(--quick) var(--spring);
}
.gate-music:hover { color: var(--text); background: var(--glass-2); border-color: rgba(217, 164, 65, 0.45); }
.gate-music:active { transform: var(--press); }
.gate-music b { color: var(--gold); font-weight: 500; }
.gate-music svg { color: var(--gold); }

/* play */
.play {
  margin: 30px auto 0; width: 84px; height: 84px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: var(--glass); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  transition: transform 0.2s ease, background 0.2s ease;
}
#overlay:hover .play, .play:hover { transform: scale(1.08); background: var(--glass-2); }
.play:active { transform: scale(0.98); }
.play { transition: transform var(--quick) var(--spring), background 0.2s ease; }
.play svg { margin-left: 6px; }

.ov-in .hint { margin-top: 20px; font-size: 11px; letter-spacing: 0.12em; color: var(--dimmer); }
.ov-in .hint b { font-weight: 400; color: var(--dim); }
.ov-more { margin-top: 14px; }
.ov-more button {
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--dim); border-bottom: 1px solid rgba(255, 255, 255, 0.22); padding-bottom: 2px;
  transition: color 0.2s ease, border-color 0.2s ease;
}
.ov-more button:hover { color: var(--text); border-color: var(--gold); }

/* ── the About sheet ───────────────────────────────────────────────── */
#about {
  position: fixed; inset: 0; z-index: 20;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(3, 4, 8, 0.72);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  opacity: 0; transition: opacity 0.26s ease;
}
/* An author `display` rule beats the UA's [hidden] rule — without this the
   closed sheet stays in the hit-test layer and eats every click. */
#about[hidden] { display: none; }
#about.in { opacity: 1; }
.sheet-in {
  position: relative; width: 100%; max-width: 720px; max-height: calc(100vh - 48px);
  overflow-y: auto; overscroll-behavior: contain; padding: 30px 32px 34px;
  scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
  border: 1px solid var(--hair); border-radius: 18px;
  background: linear-gradient(180deg, rgba(16, 18, 30, 0.96), rgba(7, 8, 14, 0.97));
  transform: translateY(12px); transition: transform 0.3s cubic-bezier(0.2, 0.9, 0.25, 1);
}
#about.in .sheet-in { transform: none; }
.sheet-in::-webkit-scrollbar { width: 8px; }
.sheet-in::-webkit-scrollbar-track { background: transparent; }
.sheet-in::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.18); border-radius: 4px; }
.sheet-in::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.3); }
.sheet-close {
  position: absolute; top: 14px; right: 16px; width: 32px; height: 32px;
  border-radius: 50%; border: 1px solid var(--hair); color: var(--dim);
  display: flex; align-items: center; justify-content: center; font-size: 15px;
}
.sheet-close:hover { color: var(--text); border-color: rgba(255, 255, 255, 0.35); }
.sheet-in h2 {
  font-size: 21px; font-weight: 300; letter-spacing: 0.06em; margin-bottom: 4px;
}
.sheet-in h2 em { font-style: italic; }
.sheet-in .kicker {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.24em;
  text-transform: uppercase; color: var(--gold); margin-bottom: 16px;
}
.sheet-in h3 {
  margin: 24px 0 8px; font-size: 11px; font-weight: 500;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--dim);
}
.sheet-in p, .sheet-in li { font-size: 13.5px; line-height: 1.72; color: rgba(232, 230, 242, 0.82); }
.sheet-in p + p { margin-top: 10px; }
.sheet-in ul { margin: 6px 0 0 18px; }
.sheet-in li { margin-top: 5px; }
.sheet-in a { color: var(--gold); border-bottom: 1px solid rgba(217, 164, 65, 0.4); }
.sheet-in a:hover { border-color: var(--gold); }
.sheet-in code {
  font-family: var(--mono); font-size: 12px;
  background: rgba(255, 255, 255, 0.07); padding: 1px 5px; border-radius: 4px;
}
.keys { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 6px 18px; margin-top: 8px; }
.keys div { font-size: 12.5px; color: rgba(232, 230, 242, 0.78); }
.keys kbd {
  font-family: var(--mono); font-size: 10.5px; padding: 2px 6px; margin-right: 8px;
  border: 1px solid var(--hair); border-radius: 5px; color: var(--text);
  background: rgba(255, 255, 255, 0.05);
}
.sheet-foot {
  margin-top: 26px; padding-top: 16px; border-top: 1px solid rgba(255, 255, 255, 0.1);
  display: flex; flex-wrap: wrap; gap: 8px 18px; justify-content: space-between; align-items: center;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.1em; color: var(--dimmer);
}
.sheet-foot .foot-brand { display: inline-flex; align-items: center; gap: 9px; }
.sheet-foot .foot-brand img { width: 22px; height: 22px; opacity: 0.9; }
.sheet-foot .foot-brand em { font-style: italic; }

/* graceful audio failure: the visuals still run, and we say so */
#noaudio {
  position: fixed; left: 50%; top: 18px; transform: translateX(-50%);
  z-index: 8; padding: 8px 16px; border-radius: 12px;
  border: 1px solid var(--hair); background: rgba(10, 12, 20, 0.85);
  font-size: 11.5px; letter-spacing: 0.06em; color: var(--dim);
  opacity: 0; pointer-events: none; transition: opacity 0.4s ease;
}
#noaudio.show { opacity: 1; }

/* ── no-WebGL fallback ─────────────────────────────────────────────── */
#nogl { display: none; }
body.no-gl #nogl {
  display: flex; position: fixed; inset: 0; z-index: 30;
  align-items: center; justify-content: center; padding: 28px; text-align: center;
}
body.no-gl #nogl p { max-width: 460px; font-size: 14px; line-height: 1.7; color: var(--dim); }
body.no-gl #nogl a { color: var(--gold); }

/* ── safe areas (notched iPhones) ──────────────────────────────────── */
@supports (padding: env(safe-area-inset-bottom)) {
  #dock { bottom: calc(16px + env(safe-area-inset-bottom)); }
  /* hud height handled by the observatory rules above */
}

/* ── touch: bigger targets, bigger thumb ───────────────────────────── */
@media (pointer: coarse) {
  .ctl { min-height: 42px; border-radius: 21px; padding: 0 14px; }
  .ctl.pod button { width: 30px; height: 34px; }
  #zoomSlider { height: 34px; }
  #zoomSlider::-webkit-slider-thumb, #tiltSlider::-webkit-slider-thumb, #speedSlider::-webkit-slider-thumb { width: 19px; height: 19px; margin-top: -8px; }
  #zoomSlider::-moz-range-thumb, #tiltSlider::-moz-range-thumb, #speedSlider::-moz-range-thumb { width: 19px; height: 19px; }
}

/* ── mobile ────────────────────────────────────────────────────────── */
@media (max-width: 700px) {
  #top { padding: 12px 12px; font-size: 9px; gap: 10px; }
  #top .mark { letter-spacing: 0.14em; }
  #top nav { gap: 10px; flex-shrink: 0; }
  #top nav .home img { width: 16px; height: 16px; }
  #overlay { padding: 76px 16px 92px; }
  #scores { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; max-width: 460px; }
  .score { padding: 12px 12px 13px; text-align: center; }
  .score-b { display: none; }
  .score-n { font-size: 14px; }
  .score-w { font-size: 11px; }
  .play { width: 72px; height: 72px; margin-top: 24px; }
  /* HUD sits ABOVE the whole dock on a phone — side by side they collide */
  /* On a phone the eq deliberately sits BEHIND the control rows (the v68
     look), so any text at its foot is buried — Daniel photographed exactly
     that. The pills already name the score and the sound, and the capsule
     now carries the date, so the HUD has nothing left to say here. */
  #hud { display: none; }
  #dock { right: 10px; left: 10px; bottom: 12px; align-items: center; gap: 8px; max-width: none; }
  /* the description STAYS visible on a phone — the SHORT variant, so it
     never truncates mid-sentence (the clamp is only a safety net) */
  #blurb {
    max-width: none; text-align: center; font-size: 10px; line-height: 1.6;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  #blurb .blurb-full { display: none; }
  #blurb .blurb-short { display: inline; }
  #blurb button { display: inline; }
  #controls { gap: 6px; justify-content: center; }
  .ctl .k { display: none; }
  /* the orrery pod becomes its own full row, slider stretched */
  .ctl.pod {
    flex: 1 1 100%; order: 2; justify-content: center; gap: 6px 8px;
    padding: 7px 12px; flex-wrap: wrap; border-radius: 18px;
  }
  .ctl.pod .sep { display: none; }
  .ctl.pod .pod-k { display: inline; font-size: 9px; letter-spacing: 0.14em; }
  /* DETERMINISTIC rows on phones — no sometimes-wrapping. Flex places
     items by natural width BEFORE growing, so which row the SOUND pill
     landed on depended on the mode name and the phone (Daniel caught it
     switching lines in the field). The .ctl-brk element is a hard line
     break: row one is always play · mute · SCORE (stretched), row two is
     always SOUND + the gold Your-music bar. */
  #controls [data-act="track"] { flex: 1 1 auto; min-width: 0; min-height: 44px; border-radius: 22px; }
  #controls .ctl-brk { display: block; flex-basis: 100%; height: 0; }
  #ctlFile {
    flex: 1 1 auto; min-width: 0; justify-content: center;
    min-height: 44px; border-radius: 22px;
  }
  #ctlMode { flex: 0 0 auto; min-height: 44px; border-radius: 22px; }
  #ctlPMode { flex: 0 0 auto; min-height: 44px; min-width: 44px; border-radius: 22px; }
  #ctlMode .k { display: none; }   /* icon + mode name is enough at phone width */

  /* ONE compact row: both steppers share it instead of stacking */
  .ctl.pod { gap: 8px; padding: 0 10px; }
  .ctl.pod .pod-grp { flex: 1 1 0; min-width: 0; justify-content: center; }
  /* three sliders will not fit one phone row legibly: ORBIT and SPEED
     share the top line, TILT — the signature control — takes the whole
     second row, full width under the thumb. Deterministic, never a
     sometimes-wrap. Matches v2. */
  .ctl.pod .pod-orbit { order: 1; }
  .ctl.pod .pod-speed { order: 2; }
  .ctl.pod .pod-tilt  { order: 3; flex: 1 1 100%; }
  .ctl.pod .pod-epoch { order: 4; }
  #zoomSlider, #tiltSlider, #speedSlider { flex: 1; min-width: 0; max-width: none; }
  .ctl.pod .v { min-width: 46px; font-size: 9.5px; }
  #dragHint { bottom: 226px; }
  /* phones: the observatory stacks under everything — eq behind the
     dock rows (the v68 look), pod at the very bottom */
  #simdock { left: 10px; right: 10px; bottom: calc(8px + env(safe-area-inset-bottom, 0px)); align-items: stretch; gap: 6px; }
  #spectrum { width: 100%; height: 76px; }
  /* the capsule is inline-flex, so on a WIDE phone-band window (a resized
     desktop browser) it kept its intrinsic width while the equalizer went
     full-bleed — the two stopped matching. It fills the rail here. */
  #simpod { display: flex; }
  #simpod .ctl.pod { width: 100%; }
  /* the capsule stays ONE row here (Daniel, 2026-08-01) — the date sits on
     its own line just above it, in the gap the control rows leave clear */
  .ctl.pod .pod-epoch { display: none; }
  #simEpoch {
    display: block; text-align: center;
    font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.14em;
    color: var(--gold); pointer-events: none;
    text-shadow: 0 1px 2px rgba(6, 8, 14, 0.95), 0 0 12px rgba(6, 8, 14, 0.8);
  }
  #simEpoch .k { color: var(--dimmer); margin-right: 6px; }
  /* COMPACT STACK (Daniel, 2026-08-06: "these controls are blocking the fluid
     sim — nothing should be taking up extra space"). Each layer now clears
     only the MEASURED height of the one below it, with a tight 8px seam, so
     the chrome shrinks whenever its content does instead of reserving a fixed
     band. The equalizer is deliberately excluded from --pod-h: it is scenery
     and belongs behind the rows. */
  #dock { bottom: calc(8px + var(--pod-h, 64px) + 8px + env(safe-area-inset-bottom, 0px)); }
  /* M1: a 52px mini-bar; the deck becomes a pull-up sheet */
  /* The band is DERIVED, never guessed. #dock is fixed at 132px and its
     height is content-driven — the blurb wraps, file mode empties it, a long
     track name reflows it — so any hardcoded number here eventually collides
     with it. It did: 240px left an 18px overlap on the dock's blurb line at
     375x812, which is the third time this bug class has landed (a retired
     206px override, then the 68px specificity fight, now this).
     ui.js publishes the dock's MEASURED height as --dock-h via a
     ResizeObserver; the deck rides 12px clear of whatever that turns out to
     be. The fallback keeps it sane for the frame before JS runs. */
  #player, body.filemode #player {
    left: 10px; right: 10px; width: auto; max-width: none;
    bottom: calc(8px + var(--pod-h, 64px) + 8px + var(--dock-h, 96px) + 6px + env(safe-area-inset-bottom, 0px));
  }
  .p-mini {
    display: flex; align-items: center; gap: 10px;
    min-height: 52px; padding: 6px 8px 6px 14px; border-radius: 26px;
    border: 1px solid rgba(255, 255, 255, 0.10);
    background: rgba(10, 12, 20, 0.34);
    backdrop-filter: blur(20px) saturate(1.2); -webkit-backdrop-filter: blur(20px) saturate(1.2);
    cursor: pointer;
  }
  .pm-eq { display: flex; align-items: flex-end; gap: 2px; height: 14px; flex-shrink: 0; }
  .pm-eq i { width: 3px; background: var(--gold); border-radius: 1.5px; animation: pmEq 0.9s ease-in-out infinite; }
  .pm-eq i:nth-child(1) { height: 60%; animation-delay: 0s; }
  .pm-eq i:nth-child(2) { height: 100%; animation-delay: 0.22s; }
  .pm-eq i:nth-child(3) { height: 45%; animation-delay: 0.41s; }
  @keyframes pmEq { 50% { transform: scaleY(0.4); } }
  body.paused .pm-eq i { animation-play-state: paused; }
  .pm-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; }
  .pm-time { font-family: var(--mono); font-size: 10.5px; color: var(--dim); font-variant-numeric: tabular-nums; }
  #pmPlay {
    display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
    width: 40px; height: 40px; border-radius: 50%;
    border: 1px solid rgba(217, 164, 65, 0.55); background: rgba(217, 164, 65, 0.12);
    color: var(--text);
  }
  .p-deck {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 12;
    border-radius: 22px 22px 0 0; border-bottom: 0;
    background: rgba(10, 12, 20, 0.44);
    backdrop-filter: blur(26px) saturate(1.2); -webkit-backdrop-filter: blur(26px) saturate(1.2);
    padding: 10px 18px calc(16px + env(safe-area-inset-bottom, 0px));
    transform: translateY(104%);
    transition: transform var(--settle) var(--ease-out);
  }
  #player.open .p-deck { transform: translateY(0); }
  #player.open .p-mini { display: none; }
  .p-grab {
    display: block; width: 38px; height: 4px; border-radius: 2px;
    background: rgba(255, 255, 255, 0.22); margin: 0 auto 10px;
  }
  .p-transport { gap: 14px; margin-top: 10px; }
  .p-transport button { width: 44px; height: 44px; }
  .p-toggles { margin-top: 10px; }
  .p-toggles button { width: 38px; height: 38px; }
  .p-mobile-only { display: inline-flex !important; }
  /* the queue joins the sheet's flow */
  #playlist { position: static; margin-top: 10px; max-height: 30dvh; background: rgba(255, 255, 255, 0.04); backdrop-filter: none; -webkit-backdrop-filter: none; }
  /* file mode: the mini-bar + pod are the whole story */
  #dock.filemode #controls [data-act="mute"],
  #dock.filemode #controls #ctlRec,
  #dock.filemode #controls .ctl-brk { display: none; }
  #dock.filemode #blurb { display: none; }
  .p-transport { gap: 30px; }
  .p-transport button { width: 44px; height: 44px; }
  #settings { right: 10px; left: auto; top: 52px; }
  /* Recording and the Fullscreen API are desktop-grade features; iOS Safari
     has no element fullscreen and a WebM download is a dead end there. */
  #settings [data-app="rec"], #settings [data-app="full"] { display: none; }
  .sheet-in { padding: 26px 20px 28px; }
}

/* ── reduced motion ────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation: none !important; }
  .score:hover, .play:hover, #overlay:hover .play { transform: none; }
}

/* ── the mathematics (About sheet) ─────────────────────────────────── */
#about .eq {
  display: block; text-align: center; margin: 14px 0 6px;
  font-family: Georgia, 'Times New Roman', serif; font-style: italic;
  font-size: 16px; letter-spacing: 0.02em; color: var(--text);
  overflow-x: auto; padding: 2px 0;
  white-space: nowrap;   /* an equation scrolls; it never breaks mid-formula */
}

/* ── the first-run tour ──────────────────────────────────────────────
   A REAL spotlight: the frame itself is transparent and casts a huge
   shadow outward, so the target stays lit and everything else dims.
   Drawing a dark box with a hole punched in it would fight the fluid. */
#tour { position: fixed; inset: 0; z-index: 30; }
#tour[hidden] { display: none; }
#tourSpot {
  position: absolute; border-radius: 16px;
  box-shadow: 0 0 0 9999px rgba(4, 5, 9, 0.74), 0 0 0 1px var(--gold, #d9a340) inset;
  transition: left .42s cubic-bezier(.2,.9,.3,1.15), top .42s cubic-bezier(.2,.9,.3,1.15),
              width .42s cubic-bezier(.2,.9,.3,1.15), height .42s cubic-bezier(.2,.9,.3,1.15);
  pointer-events: none;
}
#tourCard {
  position: absolute; left: 50%; transform: translateX(-50%);
  width: min(430px, calc(100vw - 32px));
  background: rgba(14, 16, 24, 0.97); border: 1px solid rgba(217, 163, 64, 0.28);
  border-radius: 16px; padding: 16px 18px 13px;
  box-shadow: 0 18px 48px rgba(0,0,0,.6);
  transition: top .42s cubic-bezier(.2,.9,.3,1.15);
}
#tourTitle { font-size: 15px; letter-spacing: .01em; color: var(--gold, #d9a340); margin-bottom: 6px; }
#tourBody { font-size: 13.5px; line-height: 1.55; color: rgba(233,230,221,.86); }
#tourFoot { display: flex; align-items: center; justify-content: space-between; margin-top: 14px; gap: 12px; }
#tourDots { display: flex; gap: 6px; }
#tourDots i { width: 5px; height: 5px; border-radius: 50%; background: rgba(233,230,221,.26); }
#tourDots i.on { background: var(--gold, #d9a340); }
#tourBtns { display: flex; gap: 8px; }
#tourBtns button {
  font: inherit; font-size: 13px; padding: 8px 15px; border-radius: 999px;
  border: 1px solid rgba(233,230,221,.16); color: rgba(233,230,221,.72);
  background: transparent; min-height: 34px;
}
#tourBtns #tourNext { background: var(--gold, #d9a340); color: #0a0b10; border-color: transparent; font-weight: 600; }
#tourBtns button:active { transform: var(--press, scale(.97)); }
/* the chrome must stay lit while the tour points at it */
body.tour-open.idle .chrome { opacity: 1; }
body.tour-open #dragHint { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  #tourSpot, #tourCard { transition: none; }
}

/* ── in-app brand: the mark stays, the wordmark becomes the product ── */
.app-brand { cursor: default; }
#top .home.app-brand { letter-spacing: 0.14em; text-transform: uppercase; font-size: 11px; }
#settings .set-brand.app-brand span { font-style: normal; color: var(--text); letter-spacing: 0.06em; }

/* ── Settings on a phone: a real bottom sheet, not a desktop panel ──
   The 250px top-right panel is right on a wide screen — you keep watching
   the fluid react while you change a look. On a phone it bought nothing:
   two thirds of the width, every line of prose wrapping five times, and a
   dead strip of stage you cannot touch anyway because the sheet swallows
   taps. Full width, rising from the bottom, with a grabber. */
@media (max-width: 560px) {
  #settings {
    top: auto; right: 0; left: 0; bottom: 0; width: auto;
    max-height: min(80vh, calc(100vh - 72px));
    border-radius: 22px 22px 0 0;
    border-left: 0; border-right: 0; border-bottom: 0;
    padding: 20px 20px calc(20px + env(safe-area-inset-bottom, 0px));
    background: linear-gradient(180deg, rgba(16, 18, 30, 0.93), rgba(8, 9, 16, 0.96));
    animation: sheetUp 0.34s cubic-bezier(.2,.9,.3,1.05) both;
  }
  #settings::before {
    content: ''; display: block; width: 38px; height: 4px; margin: -6px auto 14px;
    border-radius: 999px; background: rgba(233, 230, 221, 0.22);
  }
}
@keyframes sheetUp { from { transform: translateY(14px); opacity: 0; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { #settings { animation: none; } }

/* ── the brand, now a footer credit rather than a header ───────────── */
#settings .set-foot {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin-top: 18px; padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  font-size: 12px; font-weight: 300; letter-spacing: 0.03em;
  color: var(--dimmer); transition: color 0.2s ease;
}
#settings .set-foot em { font-style: italic; color: var(--dim); }
#settings .set-foot img { width: 20px; height: 20px; opacity: 0.75; }
#settings .set-foot:hover, #settings .set-foot:active { color: var(--gold); }
#settings .set-foot:active { transform: var(--press); }
/* the second Your-music capsule is a way BACK, not a peer of the picker */
#settings .set-col .set-secondary { opacity: 0.72; font-size: 12.5px; }
#settings .set-col .set-secondary:active { transform: var(--press); }
/* ── one player, two sources: the deck now shows for scores too ──────
   In score mode the dock still carries the programme capsules, so the
   deck steps up a row instead of landing on top of them. In file mode
   the dock empties and the deck keeps its old flush seat.
   DESKTOP-SCOPED: unscoped, this late rule (specificity 111) beat the
   phone block's 240px band (100) and parked the mini bar ON the EPOCH
   line and SPEED row — the same fight the retired 206px override lost,
   one selector over. Phones keep their band. */
@media (min-width: 701px) {
  body:not(.filemode) #player { bottom: 68px; }
}
/* phones take the universal 240px band set in the main phone block — the
   206px override that lived here fought it and re-buried the EPOCH line */
/* the deck's haptics toggle dims when off, like its neighbours */
.p-toggles #pHaptics:not(.on) { opacity: 0.38; }

/* ── the tilt (2026-08-05) ────────────────────────────────────────
   TILT is the signature control, so its thumb wears the house gold and
   on phones it takes a full row of its own rather than a squeezed half.
   The master switch in Settings removes the row entirely when off —
   a slider that cannot move is worse than no slider. */
#tiltSlider::-webkit-slider-thumb { background: var(--gold); box-shadow: 0 0 10px rgba(217, 164, 65, 0.75); }
#tiltSlider::-moz-range-thumb { background: var(--gold); box-shadow: 0 0 10px rgba(217, 164, 65, 0.75); }
body.no-tilt .pod-tilt { display: none !important; }

/* an OPEN deck is being read — idle never ghosts it (George's rule) */
body.idle #player.open { opacity: 1; }

/* ── settings goes to glass (Daniel, 2026-08-05: "the settings page does
   not look premium") ─────────────────────────────────────────────────
   Same ink, same gold — what changes is DEPTH. Every control becomes a
   small pane of lit glass: a vertical light-from-above gradient, a 1px
   inner top highlight, and a soft shadow it appears to cast. Selected
   states glow instead of merely tinting, and a press physically sinks
   (deeper than the shared --press, because these read as objects now).
   Appended last on purpose: it OVERRIDES the flat fills above without
   forking the base rules the dock still shares. */
#settings .set-row button,
#settings .set-col button,
#settings .file-btn {
  background: linear-gradient(180deg, rgba(255,255,255,0.085), rgba(255,255,255,0.028) 46%, rgba(10,12,20,0.32));
  border: 1px solid rgba(255,255,255,0.13);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.16),
              inset 0 -1px 0 rgba(0,0,0,0.28),
              0 2px 7px rgba(0,0,0,0.32);
  border-radius: 12px;
  min-height: 38px;
  color: var(--dim);
}
#settings .set-row button:hover,
#settings .set-col button:hover {
  background: linear-gradient(180deg, rgba(255,255,255,0.12), rgba(255,255,255,0.05) 46%, rgba(10,12,20,0.30));
  color: var(--text);
}
#settings .set-row button:active,
#settings .set-col button:active,
#settings .file-btn:active {
  transform: translateY(1px) scale(0.985);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07),
              inset 0 2px 6px rgba(0,0,0,0.32),
              0 1px 3px rgba(0,0,0,0.25);
}
#settings .set-row button.on {
  color: var(--gold);
  border-color: rgba(217, 164, 65, 0.62);
  background: linear-gradient(180deg, rgba(217,164,65,0.20), rgba(217,164,65,0.08) 50%, rgba(120,84,20,0.10));
  box-shadow: inset 0 1px 0 rgba(255,224,160,0.30),
              inset 0 -1px 0 rgba(0,0,0,0.25),
              0 2px 10px rgba(217,164,65,0.15);
}
#settings .file-btn {
  border-color: rgba(217, 164, 65, 0.45);
  background: linear-gradient(180deg, rgba(217,164,65,0.16), rgba(217,164,65,0.06) 50%, rgba(120,84,20,0.08));
  box-shadow: inset 0 1px 0 rgba(255,224,160,0.26),
              inset 0 -1px 0 rgba(0,0,0,0.25),
              0 2px 8px rgba(0,0,0,0.30);
  color: var(--text);
}
#settings .file-btn:hover { background: linear-gradient(180deg, rgba(217,164,65,0.22), rgba(217,164,65,0.10) 50%, rgba(120,84,20,0.10)); }
/* the panel itself: a touch more body, so the glass has something behind it */
#settings {
  background: linear-gradient(180deg, rgba(18, 20, 33, 0.88), rgba(8, 9, 16, 0.92));
  border-color: rgba(255,255,255,0.12);
  box-shadow: 0 18px 50px rgba(0,0,0,0.55);
}
/* section keys pick up the gold, so the sections read as chapters */
#settings .set-k { color: rgba(217,164,65,0.75); }
/* switches read as switches: the ON state carries a small gold dot */
#settings .set-row button[role="switch"][aria-checked="true"]::before {
  content: ''; display: inline-block; width: 5px; height: 5px;
  border-radius: 50%; background: var(--gold); margin-right: 7px;
  box-shadow: 0 0 6px rgba(217,164,65,0.8);
  vertical-align: 1px;
}

/* rights line: present, quiet, and honest about what "open" means here */
.sheet-rights { font-size: 10.5px; color: var(--dimmer); margin-bottom: 10px; letter-spacing: 0.02em; }

/* ══ COMPACT + GLASS, phones (Daniel, 2026-08-06) ═══════════════════
   "Minimalist, slick, compact, premium, 3D Apple Glass. I do not want extra
   space. These controls are blocking the fluid sim."

   The stage is the product; the chrome is an instrument panel laid over it.
   So every band below either earns its height or goes, and what remains reads
   as lit glass rather than flat ink. */
@media (max-width: 700px) {

  /* 1. The blurb is a duplicate once the show is running — "How it works"
        already lives in Settings (setApp data-app="about"). It was costing a
        whole band of stage to say something the gear says better. */
  body.started #blurb { display: none; }

  /* 2. ONE control row instead of two. The score pill keeps its name because
        that is what you steer by; Your-music collapses to its gold glyph,
        which still reads as "bring a file in" and is spelled out in full both
        on the title screen and in Settings. */
  body.started #controls .ctl-brk { display: none; }
  body.started #ctlFile {
    flex: 0 0 auto; min-width: 44px; width: 44px; padding: 0;
    justify-content: center; gap: 0;
  }
  body.started #ctlFile .lbl,
  body.started #ctlFile span:not([aria-hidden]) { display: none; }

  /* 3. The date rejoins the instrument row instead of floating on its own
        line — one band saved, and it belongs with the readouts anyway. */
  body.started #simEpoch { display: none; }
  body.started .ctl.pod .pod-epoch { display: flex; flex: 0 0 auto; }
  body.started .ctl.pod .pod-epoch .k { display: none; }

  /* 4. Tighter seams everywhere the eye does not need air. */
  #controls { gap: 6px; }
  .ctl.pod { padding: 0 8px; }
  #dock { gap: 6px; }
}

/* ── the glass, on every surface the finger meets ──────────────────
   The Settings panel already reads as lit glass; the deck, the pills and the
   instrument capsule were still flat. Same recipe: a light-from-above
   gradient, a 1px inner top highlight, a soft cast shadow, and a press that
   physically sinks. Depth is what makes it read as an OBJECT over the fluid
   rather than a rectangle painted on it. */
.p-mini,
#controls .ctl,
#simdock .ctl.pod {
  background: linear-gradient(180deg, rgba(255,255,255,0.10), rgba(255,255,255,0.032) 46%, rgba(10,12,20,0.34));
  border: 1px solid rgba(255,255,255,0.13);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.17),
              inset 0 -1px 0 rgba(0,0,0,0.30),
              0 6px 18px rgba(0,0,0,0.34);
  backdrop-filter: blur(22px) saturate(1.25);
  -webkit-backdrop-filter: blur(22px) saturate(1.25);
}
#controls .ctl:active,
.p-mini:active {
  transform: translateY(1px) scale(0.988);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07),
              inset 0 2px 6px rgba(0,0,0,0.34),
              0 2px 6px rgba(0,0,0,0.26);
}
/* the gold surfaces keep the gold, but gain the same lit edge */
#ctlFile, .file-btn {
  background: linear-gradient(180deg, rgba(217,164,65,0.20), rgba(217,164,65,0.075) 50%, rgba(120,84,20,0.12));
  border-color: rgba(217,164,65,0.50);
  box-shadow: inset 0 1px 0 rgba(255,224,160,0.30),
              inset 0 -1px 0 rgba(0,0,0,0.26),
              0 6px 16px rgba(0,0,0,0.30);
}

/* ── narrow phones: one control row, no wrap ────────────────────────
   At 375pt the score pill's name pushed it onto a second row. That name is
   already on the deck one band above ("Moonlight · Presto — Beethoven"), so
   here the pill keeps its glyph and drops the words — it is a way INTO the
   queue, not a label. Nothing is lost and a whole band of stage comes back.
   Scoped to <=430px so the roomier phones keep the words. */
@media (max-width: 430px) {
  body.started #controls [data-act="track"] {
    flex: 0 0 auto; min-width: 44px; width: 44px;
    padding: 0; gap: 0; justify-content: center;
  }
  body.started #controls [data-act="track"] .k,
  body.started #controls [data-act="track"] .v { display: none; }
  /* the sound pill takes the freed room instead of leaving a gap */
  body.started #ctlMode { flex: 1 1 auto; min-width: 0; justify-content: center; }
  body.started #ctlMode .v { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* ── idle now clears the WHOLE panel (Daniel, 2026-08-06) ───────────
   The 2026-08-01 split kept the equalizer and the instrument capsule on
   screen while the pills faded — "what you watch stays". On a phone those are
   the two widest objects in the frame, and the verdict is that they are
   covering the simulation, which is the thing people came for. So idle now
   clears everything; one touch brings it all back.

   The old behaviour survives as a CHOICE, not a regression: Settings →
   Controls → Auto-hide. With it off, `chrome-lock` is set and the idle class
   is never applied at all — these rules simply never fire. */
body.idle #simdock { opacity: 0; }
body.idle #player { opacity: 0; }
body.chrome-lock #simdock,
body.chrome-lock #dock,
body.chrome-lock #player,
body.chrome-lock .chrome { opacity: 1; }

/* ── the app's own mark on the opening screen (Daniel, 2026-08-06) ──
   The gate carried only the djEnterprises wordmark; the app icon is the thing
   people tapped to get here, so it belongs above the title. Rounded to the
   iOS continuous-corner ratio (~22.4% of the side) so it reads as the icon
   they just came from rather than a floating picture. */
.ov-icon {
  display: block; margin: 0 auto 18px;
  width: 96px; height: 96px;
  border-radius: 22px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.55),
              inset 0 1px 0 rgba(255,255,255,0.16);
  border: 1px solid rgba(255,255,255,0.10);
}
@media (max-width: 700px) { .ov-icon { width: 78px; height: 78px; border-radius: 18px; margin-bottom: 14px; } }
@media (prefers-reduced-motion: no-preference) {
  .ov-icon { animation: ovIconIn 0.7s cubic-bezier(.2,.9,.3,1.05) both; }
}
@keyframes ovIconIn { from { opacity: 0; transform: translateY(8px) scale(0.94); } to { opacity: 1; transform: none; } }


/* ── TAP TARGETS ───────────────────────────────────────────────────
   Apple's 44 pt floor, met without moving a single pixel. Ported from the
   fluid-click prototype, where the shortfall was found by probing what
   elementFromPoint actually returns around each control's edges rather than
   by reading the rules.

   The sliders needed HEIGHT, not padding: box-sizing is border-box globally,
   so padding shrinks a range input instead of growing it. The negative block
   margins hand the extra height straight back to the layout, so the capsule
   keeps its measurements and the 3 px track stays on the pixel it was drawn
   on. ID selectors because the base rule sets these heights by ID — a class
   selector loses the cascade silently. */
#zoomSlider, #tiltSlider, #speedSlider {
  position: relative; z-index: 1; height: 44px; margin-block: -10px;
}
/* zoom is drawn 34 px tall on a phone, so it gives back 5, not 10 */
@media (max-width: 700px) { #zoomSlider { height: 44px; margin-block: -5px; } }

#top nav .gear { position: relative; }
#top nav .gear::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
/* the two header buttons sit 10 px apart, so two centred 44 px areas would
   overlap and the later one in the DOM would quietly eat the other's edge */
#top nav .gear.tgl::after { transform: translate(-58%, -50%); }
#top nav #gearBtn::after  { transform: translate(-42%, -50%); }
#top nav .gear > * { position: relative; z-index: 1; }
