/* cptmg v2 — "haute-kinetic" look for The Midnight Girl, with every cptmg.com feature.
   Colour tokens are the owner's (inline :root in _includes/v2/head.njk). Text contrast against --bg
   is gated at release (tools/lib/contrast.mjs, 7:1); over the moving particle scene a scrim + per-
   glyph halo keep it there (see .vignette / --halo).

   PER-OBJECT STYLE. Every selectable element may carry --o-* variables from the owner's style set
   (objstyle.js — the same function the editor preview uses). They are registered NON-inheriting,
   so a style on a slide never leaks into the title inside it. Components declare their defaults as
   --d-*; the shared .o rule resolves  --o-X (owner)  →  --d-X (component)  →  base. */

@property --o-color   { syntax: '*'; inherits: false; }
@property --o-bg      { syntax: '*'; inherits: false; }
@property --o-border  { syntax: '*'; inherits: false; }
@property --o-size    { syntax: '*'; inherits: false; }
@property --o-weight  { syntax: '*'; inherits: false; }
@property --o-tracking{ syntax: '*'; inherits: false; }
@property --o-leading { syntax: '*'; inherits: false; }
@property --o-case    { syntax: '*'; inherits: false; }
@property --o-font    { syntax: '*'; inherits: false; }
@property --o-style   { syntax: '*'; inherits: false; }
@property --o-align   { syntax: '*'; inherits: false; }
@property --o-glow    { syntax: '*'; inherits: false; }
@property --o-radius  { syntax: '*'; inherits: false; }
@property --o-opacity { syntax: '*'; inherits: false; }
@property --o-scale   { syntax: '*'; inherits: false; }
@property --o-gap     { syntax: '*'; inherits: false; }
@property --o-fx       { syntax: '*'; inherits: false; }
@property --o-fx-speed { syntax: '*'; inherits: false; }
@property --o-fx-repeat { syntax: '*'; inherits: false; }
@property --o-react    { syntax: '*'; inherits: false; }

:root {
  --font-display: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-body: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;
  --mono: var(--font-mono);
  --glass: rgb(10 14 26 / 0.75);
  --glass-sheet: rgb(13 19 35 / 0.92);
  --border: rgb(255 255 255 / 0.12);
  --border-spec: rgb(255 255 255 / 0.24);
  --accent-glow: rgb(var(--accent-rgb) / 0.45);
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --pulse: 0;
  --scrim: 0.7;
  --gutter: clamp(16px, 3vw, 36px);
  --halo: 0 0 2px rgb(3 4 8 / 0.95), 0 0 7px rgb(3 4 8 / 0.9);
}

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body { font-family: var(--font-body); background: var(--bg); color: var(--txt); min-height: 100vh; min-height: 100dvh; -webkit-font-smoothing: antialiased; overflow-x: hidden; }
button { font: inherit; color: inherit; }
a { color: inherit; }
ul { list-style: none; }
img { max-width: 100%; display: block; }
.ico { width: 1em; height: 1em; flex: none; }

.visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
.skip-link { position: fixed; left: var(--gutter); top: 12px; z-index: 200; background: var(--txt); color: #000; padding: 10px 16px; border-radius: 4px; font-family: var(--mono); font-weight: 700; font-size: 12px; transform: translateY(-200%); transition: transform 0.2s var(--ease); text-shadow: none; }
.skip-link:focus { transform: none; }
:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; border-radius: 4px; }

/* ── the shared per-object resolver ─────────────────────────────────────────────── */
.o {
  color: var(--o-color, var(--d-color, currentColor));
  font-size: calc(var(--d-size, 1em) * var(--o-size, 1));
  font-weight: var(--o-weight, var(--d-weight, 400));
  letter-spacing: var(--o-tracking, var(--d-tracking, normal));
  line-height: var(--o-leading, var(--d-leading, 1.35));
  text-transform: var(--o-case, var(--d-case, none));
  font-family: var(--o-font, var(--d-font, var(--font-body)));
  font-style: var(--o-style, var(--d-style, normal));
  text-align: var(--o-align, var(--d-align, start));
  opacity: var(--o-opacity, 1);
  text-shadow: 0 0 calc(var(--o-glow, 0) * 28px) currentColor, var(--halo);
}
/* React to music, for anything that isn't the title: a swell and a glow on each kick (--pulse, v2.js).
   fx.js only sets .fx-react when motion is allowed; the calm / reduced-motion rules below still apply. */
.fx-react { scale: calc(1 + var(--pulse) * 0.04); transform-origin: left center;
  filter: drop-shadow(0 0 calc(var(--pulse) * 14px) rgb(var(--accent-rgb) / calc(var(--pulse) * 0.8)));
  transition: scale 0.12s ease, filter 0.12s ease; }
.slide-media.fx-react, .cta.fx-react { transform-origin: center; }
body.calm .fx-react, body.reduce-motion .fx-react { scale: none; filter: none; }

/* ── particle layer + legibility scrim ──────────────────────────────────────────── */
#bgfx { position: fixed; inset: 0; z-index: 0; pointer-events: none; width: 100vw; height: 100vh; background: var(--bg);
  opacity: var(--particle-opacity); filter: brightness(calc(1 + var(--pulse) * 0.35)) saturate(calc(1 + var(--pulse) * 0.25));
  transition: filter 0.12s ease-out, opacity 0.6s var(--ease); }
#bgfx > canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
body.particles-off #bgfx > canvas { visibility: hidden; }
/* The scene paints its own background (Galaxy cycles to a purple ~#5f1e6e; #94a3b8 on that is
   ~4.3:1). The scrim darkens where the text sits; the halo gives each glyph its own dark edge. */
.vignette { position: fixed; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(90deg, rgb(3 4 8 / var(--scrim)) 0%, rgb(3 4 8 / calc(var(--scrim) * 0.8)) 50%, rgb(3 4 8 / calc(var(--scrim) * 0.2)) 85%),
    linear-gradient(to top, rgb(3 4 8 / calc(var(--scrim) + 0.15)), transparent 30%),
    linear-gradient(to bottom, rgb(3 4 8 / var(--scrim)), transparent 20%); }
.build-flag { pointer-events: none; position: fixed; left: 50%; top: 10px; transform: translateX(-50%); z-index: 90; font-family: var(--mono); font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: #000; background: var(--cyan); padding: 5px 12px; border-radius: 99px; text-shadow: none; }

/* ── frame ──────────────────────────────────────────────────────────────────────── */
.frame { position: relative; z-index: 10; min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; gap: 18px;
  padding: 24px var(--gutter) max(18px, env(safe-area-inset-bottom)); text-shadow: var(--halo); zoom: var(--a-scale, 1); }

/* ── header ─────────────────────────────────────────────────────────────────────── */
.top { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 20px; border-radius: var(--o-radius, 0);
  background: var(--o-bg, transparent); box-shadow: inset 0 0 0 1px var(--o-border, transparent); }
.brand { display: flex; align-items: center; gap: 12px; min-width: 0; }
.logo-link { display: inline-flex; text-decoration: none; }
.logo { height: calc(40px * var(--logo-scale, 1)); width: auto; opacity: var(--logo-opacity, 1); }
.logo--mask { display: inline-block; aspect-ratio: 1 / 1; height: calc(40px * var(--logo-scale, 1)); opacity: var(--logo-opacity, 1); background: var(--logo-tint);
  -webkit-mask-position: center; mask-position: center; -webkit-mask-size: contain; mask-size: contain; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; }
.logo--rainbow { background: var(--logo-rainbow); background-size: 300% 100%; animation: logoRainbow var(--logo-rainbow-speed, 3s) linear infinite; }
@keyframes logoRainbow { to { background-position: 300% 0; } }
.brand-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.brand-title { --d-size: 14px; --d-weight: 800; --d-tracking: 3px; --d-case: uppercase; --d-font: var(--font-display); --d-color: var(--txt); --d-leading: 1.2; }
.brand-sub { --d-size: 11px; --d-font: var(--font-mono); --d-color: var(--txt-dim); --d-leading: 1.2; }

.socials { justify-self: center; display: flex; position: relative; }
/* The gap is set on the <nav> (header.socialsStyle), but --o-* never inherit (registered inherits:false) —
   so it is handed to the <ul> through an ordinary, inheriting custom property. */
.socials { --socials-gap: var(--o-gap, 8px); }
.socials ul { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--socials-gap); }
.socials-toggle { display: none; }
.social { --d-size: 11px; --d-weight: 600; --d-tracking: 0.4px; --d-case: uppercase; --d-font: var(--font-mono); --d-color: var(--txt-dim);
  display: inline-flex; align-items: center; gap: 7px; min-height: 34px; padding: 7px 14px; border-radius: var(--o-radius, 99px); text-decoration: none;
  background: var(--o-bg, var(--glass)); border: 1px solid var(--o-border, var(--border)); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease), box-shadow 0.2s var(--ease); }
.social:hover { border-color: var(--border-spec); transform: translateY(-1px); box-shadow: 0 0 14px rgb(var(--accent-rgb) / 0.25); }
.social .ico { width: 14px; height: 14px; }
.socials--icon .social-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.socials--icon .social { padding: 8px; border-radius: 50%; }
.socials--text .social { background: none; border: 0; backdrop-filter: none; padding: 4px 6px; }
.social--nolink { opacity: 0.7; }

.top-right { display: flex; align-items: center; gap: 20px; justify-self: end; }
.live { --d-size: 10px; --d-weight: 700; --d-tracking: 1px; --d-case: uppercase; --d-font: var(--font-mono); --d-color: var(--txt);
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 11px; border-radius: var(--o-radius, 99px); text-decoration: none; border: 1px solid var(--o-border, var(--border)); background: var(--o-bg, var(--glass)); }
.live .ico { width: 13px; height: 13px; }
.live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--txt-dim); }
.live--on { border-color: #16c925; }
.live--on .live-dot { background: #23e03a; box-shadow: 0 0 10px #23e03a; animation: livePulse 1.6s ease-in-out infinite; }
@keyframes livePulse { 50% { opacity: 0.35; } }
.telemetry { display: flex; gap: 20px; font-family: var(--mono); font-size: 11px; }
.tel { display: flex; flex-direction: column; gap: 2px; }
.tel dt { color: var(--txt-dim); font-size: 10px; text-transform: uppercase; letter-spacing: 0.8px; }
.tel dd { font-weight: 700; font-variant-numeric: tabular-nums; }
.tel-clock { color: var(--amber); }

.sheet-nav ul { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.sheet-link { background: none; border: 0; border-bottom: 1px solid transparent; cursor: pointer; padding: 6px 0; min-height: 32px; font-family: var(--mono); font-size: 11px; font-weight: 700;
  letter-spacing: 1.2px; text-transform: uppercase; color: var(--txt-dim); transition: color 0.2s, border-color 0.2s; }
.sheet-link:hover, .sheet-link[aria-expanded='true'] { color: var(--txt); border-bottom-color: var(--accent); }
.pill-num { color: var(--accent-ink); margin-right: 4px; }

/* ── stage + carousel ───────────────────────────────────────────────────────────── */
.stage { flex: 1; display: flex; flex-direction: column; justify-content: center; width: 100%; max-width: 1400px; margin: 0 auto; outline: none; }
.carousel { display: flex; flex-direction: column; gap: 22px; }
/* minmax(0,1fr) + min-width:0: a grid item defaults to min-width:auto and grows to its content —
   measured, the kinetic words ran off the right edge instead of wrapping. */
.slides { display: grid; grid-template-columns: minmax(0, 1fr); }
.slide { grid-area: 1 / 1; min-width: 0; position: relative; display: flex; flex-direction: column; justify-content: center; gap: 30px; min-height: 50vh; }
/* The entrance animates the slide's CONTENTS, never the slide: a transform on .slide makes it the containing
   block of the fixed .slide-bg, so for the 0.6 s the glow snapped to the slide's box — scaled 1.15, poking past
   the screen edge (the page went 11–54 px too wide) — then jumped back to full screen (regression C3). */
/* …and not over an owner's own effect (the picture is a direct child and can carry one — fx.js data-fx). */
.slide > :not(.slide-bg):not([data-fx]) { animation: slideIn 0.6s var(--ease); }
.slide-bg { animation: bgIn 0.6s var(--ease); }
@keyframes bgIn { from { opacity: 0; } }
.slide[hidden] { display: none; }
@keyframes slideIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.slide--hidden { outline: 1px dashed var(--amber); outline-offset: 8px; }
.hidden-flag { position: absolute; top: -6px; right: 0; font-family: var(--mono); font-size: 10px; font-weight: 700; text-transform: uppercase; color: #000; background: var(--amber); padding: 3px 8px; border-radius: 99px; z-index: 3; text-shadow: none; }
.slide-copy { min-width: 0; position: relative; z-index: 2; display: flex; flex-direction: column; gap: 14px; }

/* artwork background effects (cptmg.com bgEffect: cover | diffuse) */
.slide-bg { position: fixed; inset: 0; z-index: -1; pointer-events: none; background-position: center; background-size: cover; background-repeat: no-repeat; opacity: var(--slide-img-opacity, 1); }
.slide--bg-diffuse .slide-bg { filter: blur(40px) saturate(1.3); transform: scale(1.15); opacity: calc(var(--slide-img-opacity, 1) * 0.6); }
.slide--bg-cover .slide-bg { opacity: calc(var(--slide-img-opacity, 1) * 0.45); }

.kicker { --d-size: 11px; --d-weight: 700; --d-tracking: 2px; --d-case: uppercase; --d-font: var(--font-mono); --d-color: var(--accent-ink); }
.kinetic { --d-size: calc(clamp(52px, 8.5vw, 124px) * var(--title-scale)); --d-weight: 800; --d-case: uppercase; --d-font: var(--font-display); --d-color: var(--txt); --d-leading: 0.92;
  letter-spacing: var(--o-tracking, var(--title-tracking));
  text-shadow: 0 0 calc(var(--o-glow, 0) * 30px) var(--accent-glow), var(--halo);
  transform-origin: left center;
  transition: letter-spacing 0.2s var(--ease), text-shadow 0.12s ease, scale 0.12s ease; overflow-wrap: anywhere; }
/* React to music (fx.js .fx-react; the title reacts unless the owner switches it off). `scale`, not
   `transform`, so an effect's keyframes (which animate transform) and the beat add up instead of
   one cancelling the other. */
.kinetic.fx-react { letter-spacing: calc(var(--o-tracking, var(--title-tracking)) + var(--pulse) * 2px);
  text-shadow: 0 0 calc(var(--pulse) * 35px + var(--o-glow, 0) * 30px) var(--accent-glow), var(--halo);
  scale: calc(1 + var(--pulse) * 0.015); filter: none; }
.subtext { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; }
.subtitle { --d-size: 18px; --d-style: italic; --d-color: var(--txt-dim); }
.badge { --d-size: 10px; --d-weight: 700; --d-tracking: 0.6px; --d-case: uppercase; --d-font: var(--font-mono); --d-color: var(--cyan);
  border: 1px solid var(--o-border, currentColor); background: var(--o-bg, transparent); padding: 3px 9px; border-radius: var(--o-radius, 99px); }
.badge:empty { display: none; }
.description { --d-size: 17px; --d-color: var(--txt); --d-leading: 1.55; max-width: 62ch; }

/* layouts */
.slide--split { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); align-items: center; gap: clamp(20px, 4vw, 64px); }
.slide--split .slide-media { order: 2; }
.slide--split .kinetic { --d-size: calc(clamp(42px, 6vw, 92px) * var(--title-scale)); }
.slide--centered { align-items: center; --d-align: center; }
.slide--centered .slide-copy { align-items: center; }
.slide--centered .subtext, .slide--centered .ctas, .slide--centered .score-words, .slide--centered .score-head { justify-content: center; }
.slide--centered .kinetic { transform-origin: center; }
.slide--centered .slide-media { width: min(320px, 60vw); }
.slide--banner { justify-content: flex-end; min-height: 58vh; }
.slide--banner .slide-media { position: absolute; inset: 0; z-index: 0; margin: 0; }
.slide--banner .slide-media img { width: 100%; height: 100%; max-height: none; border-radius: 16px; }
.slide--banner .slide-media::after { content: ''; position: absolute; inset: 0; border-radius: 16px; background: linear-gradient(to top, rgb(3 4 8 / 0.88), rgb(3 4 8 / 0.2) 70%); }
.slide--banner .slide-copy { padding: clamp(16px, 3vw, 40px); }
.slide-media { margin: 0; }
.slide-media img { width: 100%; max-height: 62vh; border-radius: 16px; box-shadow: 0 30px 80px rgb(0 0 0 / 0.55), 0 0 60px rgb(var(--accent-rgb) / 0.18); }
/* The artwork's Opacity dims the picture itself, not only the glow behind the page (regression 2026-09-28 E8). */
.slide-media img { opacity: var(--slide-img-opacity, 1); }

/* the kinetic score */
.score { display: flex; flex-direction: column; gap: 14px; }
.score-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.score-hint { font-family: var(--mono); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1.5px; color: var(--txt-dim); }
.score-toggle { font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; background: var(--glass); color: var(--txt-dim); border: 1px solid var(--border); border-radius: 99px; padding: 4px 10px; min-height: 28px; cursor: pointer; }
.score-toggle:hover { color: var(--txt); border-color: var(--border-spec); }
.score-words { --d-size: clamp(20px, 2.2vw, 28px); --d-weight: 800; --d-case: uppercase; --d-font: var(--font-display); --d-color: var(--word-idle); --d-tracking: -0.6px;
  display: flex; flex-wrap: wrap; gap: 14px 22px; align-items: baseline; }
.word { position: relative; background: none; border: 0; padding: 0; color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit; transition: color 0.25s var(--ease), transform 0.25s var(--ease), text-shadow 0.25s var(--ease); }
button.word { cursor: pointer; }
button.word:hover { color: var(--cyan); transform: translateY(-2px); }
.word.is-active { color: #fff; transform: scale(1.08) translateY(-3px); text-shadow: 0 0 24px var(--accent-glow), var(--halo); }
.word.is-active::after { content: ''; position: absolute; left: 0; right: 0; bottom: -6px; height: 2px; background: var(--accent); box-shadow: 0 0 12px var(--accent); }

/* CTA buttons — v2's look by default; any of the 21 looks / 17 fx in the shared effects.css
   (cptmg.com's button set) apply through .cta-look--X / .cta-fx--X on the row. */
.ctas { display: flex; flex-wrap: wrap; gap: var(--cta-gap, 12px); align-items: center; margin-top: 4px; }
.cta { --d-size: 12px; --d-weight: 700; --d-tracking: 1px; --d-case: uppercase; --d-font: var(--font-mono); --d-color: var(--cta-secondary-text-color, var(--txt));
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 12px calc(22px * var(--cta-scale, 1)); text-decoration: none; cursor: pointer;
  font-size: calc(12px * var(--cta-scale, 1) * var(--o-size, 1)); border-radius: var(--o-radius, var(--cta-radius, 4px));
  background: var(--o-bg, var(--glass)); border: 1px solid var(--o-border, var(--border-spec)); text-shadow: none;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), box-shadow 0.2s var(--ease), transform 0.2s var(--ease); }
.cta--primary { --d-color: var(--cta-primary-text-color, #000); background: var(--o-bg, var(--cta-primary-bg-color, var(--txt))); border-color: transparent; }
.cta-look--auto .cta:hover, .cta-look--solid .cta:hover { box-shadow: 0 0 25px var(--accent-glow); }
.cta-look--auto .cta--primary:hover { background: var(--o-bg, var(--accent-ink)); }
.cta--nolink { cursor: default; opacity: 0.75; }
/* A button's OWN colour, fill and border (its style set; objstyle.js data-o) beat its look — effects.css paints
   .preview-cta with higher specificity, so they did nothing under Holo, Glass… (regression 2026-09-28 E9).
   Calm mode still wins over both (below). */
.ctas .cta.o[data-o~="color"] { color: var(--o-color) !important; }
.ctas .cta.o[data-o~="bg"] { background: var(--o-bg) !important; }
.ctas .cta.o[data-o~="border"] { border-color: var(--o-border) !important; }
body.calm .ctas .cta.o[data-o] { color: var(--calm-fg) !important; background: var(--calm-bg) !important; border-color: var(--calm-border) !important; }
body.calm .ctas .cta--primary.o[data-o] { color: var(--calm-bg) !important; background: var(--calm-fg) !important; }
.cta--ghost { --d-color: var(--txt-dim); background: transparent; }

/* carousel controls */
.carousel-ctrl { display: flex; align-items: center; gap: 10px; }
.carousel-ctrl[hidden] { display: none; }
.c-btn { width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; cursor: pointer; font-size: 16px; line-height: 1; background: var(--glass); border: 1px solid var(--border); color: var(--txt); }
.c-btn:hover { border-color: var(--border-spec); }
.c-pause[aria-pressed='true'] { color: var(--accent-ink); border-color: var(--accent); }
.c-dots { display: flex; gap: 4px; }
.c-dot { width: 28px; height: 28px; border-radius: 50%; border: 0; cursor: pointer; background: transparent; position: relative; }
.c-dot::before { content: ''; position: absolute; inset: 10px; border-radius: 50%; background: var(--txt-dim); transition: transform 0.2s, background 0.2s; }
.c-dot[aria-current='true']::before { background: var(--accent); transform: scale(1.4); box-shadow: 0 0 10px var(--accent); }
.c-dot--hidden::before { background: transparent; border: 1px dashed var(--amber); }

/* ── footer bar ─────────────────────────────────────────────────────────────────── */
.bottom { display: flex; flex-direction: column; gap: 14px; border-top: 1px solid var(--border); padding-top: 16px; }
.foot-bar { display: flex; align-items: center; gap: 12px 22px; flex-wrap: wrap; }
.legal { --d-size: 11px; --d-font: var(--font-mono); --d-color: var(--txt-dim); }
.foot-links { display: flex; gap: 12px; align-items: center; }
.foot-link { --d-size: 11px; --d-font: var(--font-mono); --d-color: var(--txt-dim); display: inline-flex; align-items: center; text-decoration: none; min-height: 28px; }
.foot-link:hover { color: var(--txt); }
.foot-icon { height: 22px; width: auto; }
.contact { --d-size: 11px; --d-weight: 700; --d-tracking: 0.6px; --d-case: uppercase; --d-font: var(--font-mono); --d-color: var(--txt);
  display: inline-flex; align-items: center; gap: 7px; min-height: 32px; padding: 6px 12px; border-radius: var(--o-radius, 99px); border: 1px solid var(--o-border, var(--border)); background: var(--o-bg, var(--glass)); text-decoration: none; cursor: pointer; }
.contact:hover { border-color: var(--cyan); }
.contact-addr { color: var(--cyan); text-transform: none; font-weight: 400; }
.badges { display: flex; gap: 10px; }
.badge-item { position: relative; }
.badge-btn { display: grid; place-items: center; width: var(--badge-size); height: var(--badge-size); border-radius: var(--badge-radius); overflow: hidden; background: transparent; border: 1px solid var(--border); padding: 0; cursor: pointer; text-decoration: none; }
.badge-btn img { width: 100%; height: 100%; object-fit: contain; }
.bubble { position: absolute; bottom: calc(100% + 10px); left: 0; z-index: 50; width: max-content; max-width: min(340px, calc(100vw - 32px));
  padding: 12px 14px; border-radius: 14px; border: 1px solid rgb(var(--accent-rgb) / 0.3); background: rgb(10 8 22 / 0.97); color: var(--txt);
  font-size: 12px; line-height: 1.5; white-space: pre-line; text-shadow: none; box-shadow: 0 12px 40px rgb(0 0 0 / 0.6);
  /* display:none when hidden, not just invisible: an invisible bubble still takes layout space, and
     on a phone it widened the page to 477px (measured) — the whole site zoomed out. */
  display: none; opacity: 0; transition: opacity 0.15s, display 0.15s allow-discrete; }
.badge-item:hover .bubble, .badge-item:focus-within .bubble { display: block; opacity: 1; }
@starting-style { .badge-item:hover .bubble, .badge-item:focus-within .bubble { opacity: 0; } }
.badge-item.is-dismissed .bubble { display: none; }
.foot-tools { margin-left: auto; display: flex; align-items: center; gap: 14px; }
/* The calm-mode switch (v2/calm.njk). NOT .calm — that class lands on <body> in calm mode, and this rule restyled the
   whole page with it (mono 11px, a flex row; measured 2026-10-01). Both the words and the switch take a click, and
   each is a 44px-tall target (WCAG 2.5.5) without growing the switch itself. */
.calm-tog { display: flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 11px; color: var(--txt-dim); }
.calm-tog label { display: inline-flex; align-items: center; min-height: 44px; cursor: pointer; }
.calm-tog .switch::before { content: ''; position: absolute; inset: -11px -4px; }
/* The privacy & notices link — fixed in every footer (v2/footer.njk, coming-soon, privacy page). */
.foot-notices { display: inline-flex; align-items: center; min-height: 44px; font-family: var(--font-mono); font-size: 11px; color: var(--txt-dim);
  text-decoration: underline; text-underline-offset: 3px; }
.foot-notices:hover { color: var(--txt); }
.foot-notices:focus-visible, .calm-tog .switch:focus-visible { outline: 2px solid var(--lime); outline-offset: 3px; }
/* The footer of a standalone page (coming-soon, privacy): legal line · privacy & notices · calm switch, one centred
   row that wraps. The site itself has the full footer (.bottom, v2/footer.njk). */
.page-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0 22px; text-align: center;
  padding: 10px var(--gutter) max(14px, env(safe-area-inset-bottom)); text-shadow: var(--halo); }
.page-legal { margin: 0; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.4px; color: var(--txt-dim); }


/* ── the player DOCK (High Frequency's bar, cptmg colours) ───────────────────────── */
/* In the page flow directly ABOVE the footer (owner: "footer at the bottom, the music player above
   it"), sticky so it holds the bottom of the screen while there is more page below it. It bleeds out
   of the frame's side gutters to span the window. --dock-clear (v2.js) is the live distance from the
   window's bottom edge to the dock's top — the playlist menu and phone tooltips open above it. */
:root { --dock-h: 92px; }
.dock { position: sticky; bottom: 0; z-index: 60; flex: none; height: var(--dock-h); margin: 0 calc(-1 * var(--gutter)); padding: 0 28px;
  display: grid; grid-template-columns: minmax(200px, 1fr) minmax(300px, 640px) minmax(200px, 1fr); gap: 24px; align-items: center;
  background: var(--o-bg, rgb(8 10 20 / 0.78)); backdrop-filter: blur(36px) saturate(190%); -webkit-backdrop-filter: blur(36px) saturate(190%);
  border-top: 1px solid var(--o-border, var(--border)); text-shadow: none; }
/* the pulse line: brightens on every detected kick */
.dock::before { content: ''; position: absolute; left: 0; right: 0; top: -1px; height: 1px; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--lime), var(--accent), var(--cyan), transparent); opacity: calc(0.4 + var(--pulse) * 0.6); }
.dock-now { display: flex; align-items: center; gap: 14px; min-width: 0; }
.dock-cover { position: relative; flex: none; width: 54px; height: 54px; border-radius: 10px; overflow: hidden;
  background: linear-gradient(135deg, rgb(var(--accent-rgb) / 0.55), color-mix(in srgb, var(--cyan) 45%, transparent)); }
.dock-cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.dock-cover canvas { position: absolute; inset: -2px; width: calc(100% + 4px); height: calc(100% + 4px); mix-blend-mode: screen; pointer-events: none; }
.dock-bpm { position: absolute; left: 6px; bottom: 4px; font-family: var(--mono); font-size: 13px; font-weight: 800; color: #fff; text-shadow: 0 1px 6px rgb(0 0 0 / 0.7); }
.dock-meta { min-width: 0; }
.dock-title { font-weight: 800; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--o-color, var(--txt)); }
.dock-artist { font-size: 13px; color: var(--txt-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dock-mid { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
.dock-btns { display: flex; align-items: center; gap: 18px; }
.dock-icon { width: 36px; height: 36px; display: grid; place-items: center; border-radius: 50%; border: 0; background: transparent; color: var(--txt-dim); cursor: pointer; transition: color 0.2s, background 0.2s; }
.dock-icon:hover:not(:disabled) { color: var(--txt); background: rgb(255 255 255 / 0.06); }
.dock-icon svg { width: 16px; height: 16px; fill: currentColor; }
.dock-icon:disabled { opacity: 0.35; cursor: default; }
.dock-play { width: 46px; height: 46px; border-radius: 50%; border: 0; display: grid; place-items: center; cursor: pointer; color: #05060b;
  background: linear-gradient(135deg, var(--accent-ink), var(--cyan)); box-shadow: 0 0 calc(12px + var(--pulse) * 26px) var(--accent-glow); transition: transform 0.2s; }
.dock-play:hover:not(:disabled) { transform: scale(1.07); }
.dock-play:disabled { opacity: 0.4; cursor: default; box-shadow: none; }
.dock-play svg { width: 17px; height: 17px; fill: currentColor; }
.dock-prog { width: 100%; display: flex; align-items: center; gap: 12px; font-family: var(--mono); font-size: 11.5px; font-variant-numeric: tabular-nums; color: var(--txt-dim); }
/* The waveform IS the timer/scrubber (player-draw.js wave): a role=slider — ←/→ ±5 s, PgUp/PgDn ±30 s,
   Home/End, click or drag. The played part is the site gradient; a plain bar when a track has no map. */
.dock-wave { flex: 1; min-width: 0; height: 32px; border-radius: 6px; cursor: pointer; touch-action: none; }
.dock-wave canvas { display: block; width: 100%; height: 100%; }
.dock-wave[aria-disabled='true'] { cursor: default; }
/* The equalizer skyline: the live analyzer across the full width of the screen, rising off the player's top
   edge while music plays (owner 2026-09-26: "the equalizers popping off playing across the bottom of the
   screen"). Decorative; it falls away when the music stops. */
.dock-eq { position: absolute; left: 0; right: 0; bottom: 100%; height: 76px; width: 100%; pointer-events: none;
  opacity: 0; transition: opacity 0.6s ease; }
.dock.is-playing .dock-eq { opacity: 0.92; }
body.reduce-motion .dock-eq, body.calm .dock-eq { display: none; }
@media (prefers-reduced-motion: reduce) { .dock-eq { display: none; } }   /* same test as A11Y.still(): the OS setting counts too */
.dock-right { display: flex; align-items: center; justify-content: flex-end; gap: 12px; }
.dock-list { display: inline-flex; align-items: center; gap: 8px; min-height: 38px; padding: 7px 14px; border-radius: 99px; cursor: pointer;
  background: var(--glass); border: 1px solid var(--border); color: var(--txt); font-family: var(--mono); font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; }
.dock-list:hover, .dock-list[aria-expanded='true'] { border-color: var(--accent); box-shadow: 0 0 16px var(--accent-glow); }
.dock-list svg { width: 16px; height: 16px; fill: currentColor; }
.dock-count { min-width: 20px; padding: 1px 6px; border-radius: 99px; background: rgb(var(--accent-rgb) / 0.25); color: var(--accent-ink); text-align: center; }
.vol { -webkit-appearance: none; appearance: none; width: 96px; height: 4px; border-radius: 4px; cursor: pointer;
  background: linear-gradient(90deg, var(--accent), var(--cyan)) 0 / calc(var(--v, 0.8) * 100%) 100% no-repeat, rgb(255 255 255 / 0.18); }
.vol::-webkit-slider-thumb { -webkit-appearance: none; width: 13px; height: 13px; border-radius: 50%; background: var(--accent-ink); box-shadow: 0 0 10px var(--accent); }
.vol::-moz-range-thumb { width: 13px; height: 13px; border: 0; border-radius: 50%; background: var(--accent-ink); }

/* the playlist menu — opens up out of the dock */
.playlist { position: fixed; inset: auto 16px var(--dock-clear, calc(var(--dock-h) + 10px)) auto; margin: 0; width: min(400px, calc(100vw - 32px)); max-height: min(62vh, 560px);
  padding: 0; border: 1px solid var(--border-spec); border-radius: 18px; overflow: hidden; color: var(--txt);
  background: rgb(10 12 24 / 0.94); backdrop-filter: blur(30px) saturate(180%); -webkit-backdrop-filter: blur(30px) saturate(180%);
  box-shadow: 0 30px 80px rgb(0 0 0 / 0.7), 0 0 40px rgb(var(--accent-rgb) / 0.15);
  opacity: 0; transform: translateY(12px); transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), overlay 0.22s allow-discrete, display 0.22s allow-discrete; }
.playlist:popover-open { opacity: 1; transform: none; display: flex; flex-direction: column; }
@starting-style { .playlist:popover-open { opacity: 0; transform: translateY(12px); } }
.pl-head { padding: 16px 18px 12px; border-bottom: 1px solid var(--border); }
.pl-title { font-family: var(--mono); font-size: 12px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; }
.pl-sub { font-size: 12px; color: var(--txt-dim); margin-top: 3px; }
.pl-list { list-style: none; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 2px; }
.pl-item { width: 100%; display: grid; grid-template-columns: 44px 1fr auto; align-items: center; gap: 12px; padding: 8px 10px; border-radius: 12px; border: 0;
  background: transparent; color: var(--txt); text-align: left; text-decoration: none; cursor: pointer; transition: background 0.15s; }
.pl-item:hover, .pl-item:focus-visible { background: rgb(255 255 255 / 0.07); }
.pl-item[aria-current='true'] { background: rgb(var(--accent-rgb) / 0.14); }
.pl-item--off { cursor: default; opacity: 0.7; }
.pl-art { position: relative; width: 44px; height: 44px; border-radius: 8px; overflow: hidden; display: grid; place-items: center; font-family: var(--mono); font-size: 12px; font-weight: 800;
  background: linear-gradient(135deg, rgb(var(--accent-rgb) / 0.45), color-mix(in srgb, var(--cyan) 35%, transparent)); }
.pl-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.pl-eq { position: absolute; inset: 0; display: none; align-items: flex-end; justify-content: center; gap: 3px; padding-bottom: 10px; background: rgb(0 0 0 / 0.45); }
.pl-eq i { width: 3px; height: 40%; background: var(--lime); border-radius: 2px; animation: eq 0.9s ease-in-out infinite; }
.pl-eq i:nth-child(2) { animation-delay: -0.3s; } .pl-eq i:nth-child(3) { animation-delay: -0.6s; }
@keyframes eq { 50% { height: 85%; } }
.pl-item[aria-current='true'] .pl-eq { display: flex; }
.dock:not(.is-playing) .pl-eq i { animation-play-state: paused; }
.pl-text { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pl-name { font-weight: 800; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pl-with { font-size: 12px; font-style: italic; color: var(--txt-dim); }
.pl-meta { font-family: var(--mono); font-size: 10.5px; color: var(--accent-ink); text-transform: uppercase; white-space: nowrap; }
.dock--noaudio .dock-prog { opacity: 0.4; }

/* ── switches, sheets ───────────────────────────────────────────────────────────── */
.switch { flex: none; width: 40px; height: 22px; border-radius: 20px; border: 0; cursor: pointer; position: relative; background: #334155; transition: background 0.25s, box-shadow 0.25s; }
.switch::after { content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: transform 0.2s var(--ease); }
.switch[aria-checked='true'] { background: var(--accent); box-shadow: 0 0 12px var(--accent); }
.switch[aria-checked='true']::after { transform: translateX(18px); }

.sheet { position: fixed; inset: 0 0 0 auto; margin: 0; border: 0; padding: 0; width: min(520px, 100vw); max-width: 100vw; height: 100vh; height: 100dvh; max-height: none;
  background: var(--glass-sheet); color: var(--txt); border-left: 1px solid var(--border-spec); box-shadow: -20px 0 60px rgb(0 0 0 / 0.8); zoom: var(--a-scale, 1);
  transform: translateX(100%); transition: transform 0.4s var(--ease), overlay 0.4s allow-discrete, display 0.4s allow-discrete; }
.sheet[open] { transform: none; }
@starting-style { .sheet[open] { transform: translateX(100%); } }
.sheet::backdrop { background: rgb(3 4 8 / 0.65); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); opacity: 0; transition: opacity 0.35s var(--ease), overlay 0.35s allow-discrete, display 0.35s allow-discrete; }
.sheet[open]::backdrop { opacity: 1; }
@starting-style { .sheet[open]::backdrop { opacity: 0; } }
.sheet-inner { height: 100%; overflow-y: auto; padding: 32px 36px; display: flex; flex-direction: column; gap: 24px; }
.sheet-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; border-bottom: 1px solid var(--border); padding-bottom: 16px; }
.sheet-title { font-family: var(--mono); font-size: 13px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; }
.btn-close { width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; cursor: pointer; background: rgb(255 255 255 / 0.06); border: 1px solid var(--border); font-size: 15px; transition: background 0.2s, transform 0.2s; }
.btn-close:hover { background: rgb(255 255 255 / 0.15); transform: rotate(90deg); }
.sheet-note { font-family: var(--mono); font-size: 12.5px; color: var(--txt-dim); line-height: 1.6; }

.catalog { display: flex; flex-direction: column; gap: 14px; }
.catalog-item { border-radius: 12px; background: rgb(255 255 255 / 0.03); border: 1px solid var(--border); transition: background 0.25s, border-color 0.25s, box-shadow 0.25s; }
.catalog-item:hover { background: rgb(255 255 255 / 0.07); border-color: var(--accent); }
.catalog-item.is-current { border-color: var(--accent); background: rgb(var(--accent-rgb) / 0.08); box-shadow: 0 0 20px rgb(var(--accent-rgb) / 0.2); }
.catalog-pick { display: flex; align-items: center; gap: 14px; width: 100%; text-align: left; background: none; border: 0; padding: 16px 20px 8px; cursor: pointer; }
.cat-cover { width: 56px; height: 56px; border-radius: 8px; object-fit: cover; flex: none; }
.cat-text { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 0; }
.cat-top { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.cat-name { font-size: 16px; font-weight: 800; letter-spacing: -0.3px; }
.cat-bpm { font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--accent-ink); }
.cat-with { font-size: 13px; font-style: italic; color: var(--txt-dim); }
.cat-desc { padding: 0 20px 8px; font-size: 13px; line-height: 1.55; color: var(--txt); }
.cat-meta { display: flex; justify-content: space-between; gap: 12px; margin: 0 20px; padding: 8px 0 14px; font-family: var(--mono); font-size: 11px; color: var(--txt-dim); border-top: 1px solid rgb(255 255 255 / 0.06); text-transform: uppercase; }
.cat-links { display: flex; gap: 12px; flex-wrap: wrap; }
.cat-links a { color: var(--cyan); text-decoration: none; }
.cat-links a:hover { text-decoration: underline; }
.cat-transcript { margin: 0 20px 14px; font-size: 13px; color: var(--txt-dim); }
.cat-transcript summary { cursor: pointer; font-family: var(--mono); font-size: 11px; text-transform: uppercase; }
.cat-transcript p { white-space: pre-line; margin-top: 8px; line-height: 1.6; }

.rack { display: flex; flex-direction: column; gap: 12px; border: 0; }
.rack legend { font-family: var(--mono); font-size: 11px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: var(--txt-dim); margin-bottom: 12px; }
.preset { display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-radius: 12px; cursor: pointer; background: rgb(255 255 255 / 0.03); border: 1px solid var(--border); font-weight: 700; font-size: 14px; }
.preset:has(input:checked) { border-color: var(--accent); background: rgb(var(--accent-rgb) / 0.1); }
.preset:has(input:focus-visible) { outline: 2px solid var(--cyan); outline-offset: 2px; }
.preset input { accent-color: var(--accent); width: 16px; height: 16px; }
.rack-row { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding: 14px 20px; border-radius: 14px; background: rgb(255 255 255 / 0.03); border: 1px solid var(--border); font-size: 14px; font-weight: 700; }
.stepper { display: flex; align-items: center; gap: 10px; }
.step { min-width: 44px; min-height: 36px; border-radius: 8px; border: 1px solid var(--border); background: var(--glass); cursor: pointer; font-weight: 800; }
.stepper output { font-family: var(--mono); min-width: 48px; text-align: center; }
.shortcuts summary { cursor: pointer; font-family: var(--mono); font-size: 11px; text-transform: uppercase; color: var(--txt-dim); }
.shortcuts dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; margin-top: 10px; font-size: 13px; }
.shortcuts dt { font-family: var(--mono); color: var(--cyan); }

.dossier-bio { --d-size: 15px; --d-leading: 1.65; --d-color: var(--txt); }
.dossier { display: flex; flex-direction: column; }
.dossier-row { display: flex; justify-content: space-between; gap: 16px; padding: 13px 0; border-bottom: 1px solid rgb(255 255 255 / 0.06); font-size: 13px; }
.dossier-row dt { color: var(--txt-dim); }
.dossier-row dd { font-family: var(--mono); font-weight: 700; color: var(--cyan); text-align: right; }
.dossier-row a { text-decoration: none; }

/* ── visitor accessibility choices (a11y.js) — the visitor's choice wins, hence !important ── */
body.sp-comfortable .frame *, body.sp-comfortable .sheet * { letter-spacing: 0.04em !important; word-spacing: 0.1em !important; line-height: 1.7 !important; }
body.sp-spacious .frame *, body.sp-spacious .sheet * { letter-spacing: 0.08em !important; word-spacing: 0.18em !important; line-height: 1.9 !important; }
body.rf-lexend :is(.frame, .sheet) :not(svg, svg *) { font-family: 'Lexend', system-ui, sans-serif !important; }
body.rf-atkinson :is(.frame, .sheet) :not(svg, svg *) { font-family: 'Atkinson Hyperlegible Next', system-ui, sans-serif !important; }
body.rf-opendyslexic :is(.frame, .sheet) :not(svg, svg *) { font-family: 'OpenDyslexic', system-ui, sans-serif !important; }
/* Calm mode (cptmg.com parity): no particles, no pulse, no moving words, steady high-contrast colours. */
body.calm { --bg: var(--calm-bg); --txt: var(--calm-fg); --txt-dim: var(--calm-fg); --word-idle: var(--calm-fg); --accent: var(--calm-accent); --accent-ink: var(--calm-accent); --cyan: var(--calm-link); --border: var(--calm-border); --halo: none; }
body.calm #bgfx, body.calm .vignette, body.calm .slide-bg { display: none; }
body.calm .o { color: var(--calm-fg) !important; text-shadow: none !important; }
body.calm .kinetic.fx-react { scale: none !important; }
body.calm .cta, body.calm .social, body.calm .dock, body.calm .playlist, body.calm .live { background: var(--calm-bg) !important; border-color: var(--calm-border) !important; }
body.calm .cta--primary { background: var(--calm-fg) !important; color: var(--calm-bg) !important; }
body.calm *, body.reduce-motion * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }

/* ── small screens ──────────────────────────────────────────────────────────────── */
@media (max-width: 960px) {
  .top { grid-template-columns: 1fr auto; }
  .socials { grid-column: 1 / -1; grid-row: 2; justify-self: stretch; }
  .socials ul { justify-content: flex-start; }
  .slide--split { grid-template-columns: 1fr; }
  .slide--split .slide-media { order: 0; max-width: 420px; }
  .dock { grid-template-columns: minmax(0, 1fr) auto auto; gap: 14px; padding: 20px 16px 0; height: calc(var(--dock-h) + 20px); }
  /* The waveform stays the scrubber on small screens: a full-width band along the top edge of the bar. */
  .dock-prog { position: absolute; left: 16px; right: 16px; top: 5px; width: auto; gap: 0; }   /* width:auto — the base width:100% would void right:16px (#728) */
  .dock-prog > span { display: none; }
  .dock-wave { height: 16px; }
  .dock-eq { height: 52px; }
  .dock-right .vol, .dock-right #p-mute { display: none; }
}
@media (max-width: 600px) {
  .frame { padding-top: 16px; gap: 16px; }
  .vignette { background: rgb(3 4 8 / var(--scrim)); }
  .top { grid-template-columns: 1fr; }
  .top-right { justify-self: start; flex-wrap: wrap; }
  /* socials collapse behind a Links button (cptmg.com's mobile menu) */
  .socials-toggle { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 6px 14px; border-radius: 99px; border: 1px solid var(--border);
    background: var(--glass); font-family: var(--mono); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; cursor: pointer; }
  .socials ul { display: none; }
  .socials.is-open ul { display: flex; position: absolute; top: calc(100% + 8px); left: 0; z-index: 40; flex-direction: column; align-items: stretch; padding: 10px; border-radius: 14px; background: var(--glass-sheet); border: 1px solid var(--border-spec); min-width: 220px; }
  .slide { min-height: 0; gap: 22px; }
  .kinetic { --d-size: calc(clamp(40px, 13vw, 84px) * var(--title-scale)); letter-spacing: calc(var(--o-tracking, var(--title-tracking)) * 0.6); }
  .kinetic.fx-react { letter-spacing: calc(var(--o-tracking, var(--title-tracking)) * 0.6 + var(--pulse) * 2px); }
  .subtitle { --d-size: 16px; }
  :root { --dock-h: 72px; }
  .dock-btns .dock-icon { display: none; }
  /* The word stays for screen readers — display:none left an unnamed button (axe button-name, WCAG 4.1.2;
     regression 2026-09-28). Same technique as .visually-hidden. */
  .dock-list span:not(.dock-count) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .foot-tools { margin-left: 0; }
  .sheet-inner { padding: 24px 20px; }
  .bubble { position: fixed; z-index: 70; left: 16px; right: 16px; bottom: var(--dock-clear, calc(var(--dock-h) + 16px)); width: auto; max-width: none; }
}

/* ── NOW PLAYING — HighFrequency's expanded player, in cptmg's colours (now-playing.js) ─────────── */
.dock-now { cursor: pointer; }
.np { width: min(1100px, calc(100vw - 32px)); max-height: calc(100dvh - 32px); margin: auto; padding: 0; color: var(--txt); text-shadow: none;
  border: 1px solid var(--border-spec); border-radius: 22px; overflow: auto; overscroll-behavior: contain;
  background: rgb(8 10 20 / 0.9); backdrop-filter: blur(40px) saturate(180%); -webkit-backdrop-filter: blur(40px) saturate(180%);
  box-shadow: 0 40px 120px rgb(0 0 0 / 0.7), 0 0 60px rgb(var(--accent-rgb) / 0.18); }
.np::backdrop { background: rgb(3 4 8 / 0.72); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.np-inner { display: flex; flex-direction: column; gap: 22px; padding: 22px 26px 26px; }
.np-top { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.np-kicker { margin: 0; display: flex; align-items: center; gap: 8px; font-family: var(--mono); font-size: 11px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; color: var(--accent-ink); }
.np-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--txt-dim); }
.np.is-playing .np-dot { background: var(--lime); box-shadow: 0 0 10px var(--lime); animation: np-blink 1.6s ease-in-out infinite; }
@keyframes np-blink { 50% { opacity: 0.35; } }
.np-close, .np-icon { display: grid; place-items: center; border-radius: 50%; border: 1px solid var(--border); background: var(--glass); color: var(--txt); cursor: pointer; }
.np-close { width: 44px; height: 44px; }
.np-icon { width: 46px; height: 46px; }
.np-close svg, .np-icon svg { width: 18px; height: 18px; fill: currentColor; }
.np-stage { display: grid; grid-template-columns: minmax(160px, 240px) minmax(0, 1fr); gap: 28px; align-items: center; }
.np-art { position: relative; aspect-ratio: 1; border-radius: 18px; overflow: hidden; border: 1px solid var(--border-spec);
  background: linear-gradient(135deg, rgb(var(--accent-rgb) / 0.35), rgb(0 229 255 / 0.18));
  box-shadow: 0 0 calc(20px + var(--pulse, 0) * 40px) rgb(var(--accent-rgb) / calc(0.25 + var(--pulse, 0) * 0.45)); transition: box-shadow 0.12s ease; }
.np-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.np-art-empty { position: absolute; inset: 0; display: grid; place-items: center; font-family: var(--font-display); font-size: 72px; font-weight: 800; color: var(--txt); }
.np-title { margin: 0; font-family: var(--font-display); font-weight: 800; text-transform: uppercase; font-size: clamp(34px, 5vw, 72px); line-height: 0.92; letter-spacing: -1px; overflow-wrap: anywhere; color: var(--txt); }
.np-with { margin: 10px 0 0; color: var(--txt-dim); font-size: 16px; }
.np-chips { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 16px 0 0; padding: 0; }
.np-chips li { font-family: var(--mono); font-size: 12px; font-weight: 700; padding: 4px 10px; border-radius: 6px; border: 1px solid var(--border); color: var(--cyan); background: var(--glass); }
.np-btns { display: flex; align-items: center; gap: 16px; margin-top: 22px; }
.np-play { width: 64px; height: 64px; border-radius: 50%; border: 0; display: grid; place-items: center; cursor: pointer; color: #05060b;
  background: linear-gradient(135deg, var(--cyan), var(--accent)); box-shadow: 0 0 calc(14px + var(--pulse, 0) * 26px) rgb(var(--accent-rgb) / 0.55); }
.np-play svg { width: 24px; height: 24px; fill: currentColor; }
.np-score { display: flex; flex-direction: column; gap: 10px; padding: 16px 18px; border: 1px solid var(--border); border-radius: 16px; background: rgb(255 255 255 / 0.03); }
.np-score-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.np-label { margin: 0; font-family: var(--mono); font-size: 11px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: var(--txt-dim); }
.np-now, .np-listen { margin: 0; font-family: var(--mono); font-size: 12px; color: var(--cyan); font-variant-numeric: tabular-nums; }
.np-sections { list-style: none; display: flex; gap: 4px; margin: 0; padding: 0; }
.np-sections li { flex: 1 1 0; min-width: 0; }
.np-sec { width: 100%; min-height: 32px; padding: 4px 6px; border-radius: 6px; border: 1px solid var(--border); background: transparent; color: var(--txt-dim); cursor: pointer;
  font-family: var(--mono); font-size: 11px; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.np-sections li.is-now .np-sec { color: var(--txt); border-color: var(--accent); box-shadow: inset 0 -2px 0 var(--accent); }
.np-wave { position: relative; height: 84px; border-radius: 8px; cursor: pointer; touch-action: none; }
.np-wave canvas, .np-spec { display: block; width: 100%; height: 100%; }
.np-spec { height: 56px; }
.np-times { display: flex; justify-content: space-between; margin: 0; font-family: var(--mono); font-size: 12px; color: var(--txt-dim); font-variant-numeric: tabular-nums; }
.np-lyrics summary { display: flex; align-items: center; min-height: 36px; cursor: pointer; font-family: var(--mono); font-size: 12px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: var(--txt-dim); }
.np-lyrics-text { max-width: 70ch; margin-top: 8px; white-space: pre-line; line-height: 1.7; font-size: 15px; color: var(--txt); }
.np-links { list-style: none; display: flex; flex-wrap: wrap; gap: 10px; margin: 0; padding: 0; }
.np-link { display: inline-flex; align-items: center; min-height: 36px; padding: 7px 14px; border-radius: 99px; border: 1px solid var(--border); background: var(--glass);
  color: var(--txt); text-decoration: none; font-family: var(--mono); font-size: 12px; font-weight: 700; }
.np-link:hover, .np-sec:hover, .np-icon:hover, .np-close:hover { border-color: var(--cyan); }
@media (max-width: 700px) {
  .np-inner { padding: 16px; gap: 16px; }
  .np-stage { grid-template-columns: 1fr; gap: 16px; }
  .np-art { max-width: 180px; }
  .np-sec { font-size: 10px; padding: 4px 3px; }
}
body.reduce-motion .np.is-playing .np-dot { animation: none; }
body.reduce-motion .np-art, body.reduce-motion .np-play { box-shadow: none; transition: none; }
body.calm .np { background: var(--calm-bg) !important; border-color: var(--calm-border) !important; backdrop-filter: none; }
@media (prefers-reduced-motion: reduce) { .np.is-playing .np-dot { animation: none; } .np-art, .np-play { transition: none; } }

/* ── motion ─────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
  #bgfx { opacity: calc(var(--particle-opacity) * 0.6); filter: none; }
  .kinetic.fx-react { scale: none; text-shadow: 0 0 calc(var(--o-glow, 0) * 30px) var(--accent-glow), var(--halo); letter-spacing: var(--o-tracking, var(--title-tracking)); }
  .fx-react { scale: none; filter: none; }
}
/* Motion/pulse off drops the BEAT's glow, never the owner's own (styles.title.glow). */
body[data-no-pulse] .kinetic.fx-react, body.pulse-off .kinetic.fx-react { scale: none; text-shadow: 0 0 calc(var(--o-glow, 0) * 30px) var(--accent-glow), var(--halo); letter-spacing: var(--o-tracking, var(--title-tracking)); }
body[data-no-pulse] .fx-react, body.pulse-off .fx-react { scale: none; filter: none; }
body[data-no-pulse] #bgfx, body.pulse-off #bgfx { filter: none; }
