/* ==========================================================
   soundb-shared.css  –  Global styles for all pages
   ========================================================== */

/* ── RESET & TOKENS ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Universal anchor-scroll clearance: .topbar is position:sticky, top:0,
   62px tall (+1px border) — without this, jumping to any #id (a native
   <a href="#...">, or a JS scrollIntoView() call, both respect
   scroll-margin-top identically) lands that element's top edge flush
   against the viewport top, hidden behind the bar. Applied to every
   element with an id rather than per-page, since anchor targets are
   scattered across many different pages/components (TOC sidebars, "jump to
   section" buttons, glossary entries, admin dashboard back-links) with no
   single shared class to hang this off instead — and an element that's
   never actually scrolled to as an anchor target is completely unaffected
   by having this property, so there's no real cost to it being universal.
   Two pre-existing page-specific values (78px podcast-shelf, 90px glossary
   terms) already established this exact pattern before this rule existed;
   this just makes it comprehensive instead of ad hoc. */
[id] { scroll-margin-top: 80px; }
:root {
  --bg: #0D0B08; --bg2: #171310; --bg3: #1E1812; --card: #171310;
  --border: #2A2119; --border2: rgba(255,255,255,0.13);
  --text: #F0EDE6; --muted: #A69C8C;
  --amber: #FF8C00; --amber2: #FFB347;
  --green: #4ADE80; --red: #F87171; --blue: #60A5FA;
  --font-display: 'Barlow Condensed', sans-serif;
  --font-body: 'Barlow', sans-serif;
  --font-mono: 'DM Mono', monospace;
}

/* Wordmark treatment used wherever "soundb" appears as live text (not the
   assets/logo SVG image) — sound lowercase, B uppercase, tight tracking.
   text-transform: none overrides ancestor headings that force uppercase. */
.text-logo { font-family: 'Plus Jakarta Sans', var(--font-display), sans-serif; font-weight: 800; letter-spacing: -0.09em; text-transform: none; }

/* ── AD SLOT — real sponsor content (window.renderAdSlot), shared visual
   across every ad placement site-wide. Image-only by design (clients
   supply artwork, not copy) — fills exactly whatever box the placement
   provides via object-fit:cover rather than a fixed aspect-ratio, since
   each of the 4 slots (Gear Launch card, Go Deeper column, Learn sidebar,
   Transfer cell) has a different fixed height set on its mount div. ── */
.ad-slot-sponsor { display: block; width: 100%; height: 100%; overflow: hidden; }
.ad-slot-sponsor-img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── SERVER-UNREACHABLE OVERLAY (soundb-cms.js) ── */
.cms-offline-overlay { position: fixed; inset: 0; z-index: 99999; background: var(--bg); display: flex; align-items: center; justify-content: center; padding: 24px; animation: cms-offline-fade 0.3s ease; }
@keyframes cms-offline-fade { from { opacity: 0; } to { opacity: 1; } }
.cms-offline-inner { max-width: 380px; text-align: center; }
.cms-offline-mark { width: 48px; height: auto; margin: 0 auto 28px; opacity: 0.92; }
.cms-offline-eyebrow { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--amber); margin-bottom: 18px; display: flex; align-items: center; justify-content: center; gap: 8px; }
.cms-offline-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--amber); animation: cms-offline-pulse 1.6s ease-in-out infinite; }
@keyframes cms-offline-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.3; transform: scale(0.7); } }
.cms-offline-title { font-family: var(--font-display); font-size: 34px; font-weight: 900; text-transform: uppercase; letter-spacing: -0.5px; line-height: 1.02; color: var(--text); margin-bottom: 16px; }
.cms-offline-text { font-size: 14px; color: var(--muted); line-height: 1.65; margin-bottom: 30px; }
.cms-offline-btn { background: var(--amber); color: #000; font-family: var(--font-display); font-size: 13px; font-weight: 900; text-transform: uppercase; letter-spacing: 0.04em; padding: 13px 34px; border: none; cursor: pointer; }
.cms-offline-btn:hover { background: var(--amber2); }

/* ── AUTH LOADING OVERLAY (soundb-components.js) ──
   Covers the gap between "credentials submitted" and "page has finished
   reacting to the login" (nav re-render, any page-level re-fetch via
   onAuthSuccess, and — if that logic redirects — the navigation itself),
   so a visitor never sees a stale logged-out gate for a beat after a
   successful login. */
.auth-loading-overlay { position: fixed; inset: 0; z-index: 10000; background: rgba(10,10,11,0.92); backdrop-filter: blur(14px); display: flex; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: opacity 0.18s ease; }
.auth-loading-overlay.visible { opacity: 1; pointer-events: all; }
.auth-loading-inner { text-align: center; }
.auth-loading-spinner { width: 34px; height: 34px; margin: 0 auto 16px; border: 3px solid var(--border2); border-top-color: var(--amber); border-radius: 50%; animation: auth-loading-spin 0.8s linear infinite; }
@keyframes auth-loading-spin { to { transform: rotate(360deg); } }
.auth-loading-text { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
/* Replaces a protected page's entire content region the moment authentication
   is not valid — see SoundbAuth.protectPage() in soundb-cms.js. Shared by the
   account, invoice and admin pages so every one of them presents the same
   thing, instead of each inventing its own inline-styled message. */
.auth-gate { padding: 80px 24px; text-align: center; }
.auth-gate-title { font-family: var(--font-display); font-size: 28px; font-weight: 900; text-transform: uppercase; color: var(--text); margin-bottom: 12px; }
.auth-gate-copy { font-family: var(--font-mono); font-size: 12px; color: var(--muted); line-height: 1.7; max-width: 420px; margin: 0 auto 22px; }
/* overscroll-behavior-x:none is what actually stops the page from being
   horizontally rubber-banded/dragged (body's overflow-x:hidden below
   already prevents real overflow, this stops the *gesture* itself).
   Deliberately NOT adding overflow-x:hidden here too, even though html
   is iOS Safari's real scrolling root: doing so made every .topbar
   position:sticky element stop sticking site-wide (confirmed via a
   direct A/B scroll test) — setting overflow-x on html forces overflow-y
   to compute to auto per spec, which changes what "nearest scrolling
   ancestor" sticky resolves against. Not worth trading a fixed nav for a
   fixed rubber-band. */
html { scroll-behavior: smooth; overscroll-behavior-x: none; }
body { background: var(--bg); color: var(--text); font-family: var(--font-body); font-size: 16px; line-height: 1.6; overflow-x: hidden; overscroll-behavior-x: none; }
a { color: inherit; text-decoration: none; }

/* ── UTILITIES ── */
.hidden { display: none; }

/* Loading placeholder for a text value still being fetched — shown
   instead of blank/"—" so a page refresh reads as "still loading" rather
   than empty/broken. Remove the class (and any inline width override)
   the moment the real value is set. Sizes are per-instance via inline
   width since the values they stand in for vary a lot (a plan name vs.
   an email address) — the class only owns shape/color/animation. */
.sb-skeleton {
  display: inline-block;
  width: 80px;
  height: 0.85em;
  border-radius: 4px;
  background: var(--border2);
  vertical-align: middle;
  animation: sb-skeleton-pulse 1.3s ease-in-out infinite;
}
@keyframes sb-skeleton-pulse {
  0%, 100% { opacity: 0.5; }
  50% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .sb-skeleton { animation: none; opacity: 0.75; }
}
.link-amber { cursor: pointer; color: var(--amber); }
.link-amber.underline { text-decoration: underline; }
.text-muted-mono { font-family: var(--font-mono); font-size: 12px; color: var(--muted); }
.empty-state-text { padding: 16px 0; font-family: var(--font-mono); font-size: 10px; color: var(--muted); }

/* "Load more" reveal button — shared here so pages don't each need their
   own copy (soundb-news.html/soundb-reviews.html/soundb-music-reviews.html
   already had this exact block duplicated in their own page-local <style>
   blocks; kept those as-is rather than risk touching working pages, this
   is just the one copy every newly-added page reuses). */
.load-more-wrap { padding: 32px 0 0; display: flex; justify-content: center; }
.load-more-btn { background: var(--bg3); border: 1px solid var(--border2); color: var(--muted); font-family: var(--font-display); font-size: 14px; font-weight: 700; text-transform: uppercase; padding: 12px 36px; cursor: pointer; transition: all 0.2s; letter-spacing: 0.06em; }
.load-more-btn:hover { color: var(--text); border-color: var(--amber); }

/* ── SCROLL REVEAL — driven by window.initScrollReveal() in soundb-utils.js.
   Add class="reveal" to any element; it fades/slides in the first time it
   crosses into the viewport. Respects reduced-motion. ── */
.reveal { opacity: 0; transform: translateY(28px); transition: opacity 0.7s cubic-bezier(.16,.8,.3,1), transform 0.7s cubic-bezier(.16,.8,.3,1); }
.reveal.is-visible { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* ── SHARED: modal content (label/title/field/button) ── */
.modal-eyebrow { font-family: var(--font-mono); font-size: 10px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.14em; margin-bottom: 12px; }
.modal-eyebrow.danger { color: var(--red); }
.modal-title { font-family: var(--font-display); font-size: 30px; font-weight: 900; text-transform: uppercase; line-height: 1; margin-bottom: 20px; }
.modal-title-lg { font-family: var(--font-display); font-size: 36px; font-weight: 900; text-transform: uppercase; line-height: 1; margin-bottom: 8px; }
.modal-accent { color: var(--amber); }
.modal-desc { font-size: 13px; color: var(--muted); line-height: 1.7; margin-bottom: 24px; }
.modal-field-group { margin-bottom: 10px; }
.modal-field { width: 100%; background: var(--bg3); border: 1px solid var(--border2); color: var(--text); font-family: var(--font-body); font-size: 14px; padding: 13px 14px; outline: none; box-sizing: border-box; }
.modal-submit-btn { width: 100%; background: var(--amber); color: #000; font-family: var(--font-display); font-weight: 900; text-transform: uppercase; padding: 13px; border: none; cursor: pointer; letter-spacing: 0.04em; }
.modal-submit-btn:disabled { background: var(--bg3); color: var(--muted); cursor: not-allowed; }
.modal-error-text { display: none; font-family: var(--font-mono); font-size: 11px; color: var(--red); margin-bottom: 12px; }
.modal-success-text { display: none; text-align: center; padding: 16px 0 0; font-family: var(--font-body); font-size: 13px; color: var(--text); line-height: 1.65; }
.modal-footnote { font-family: var(--font-mono); font-size: 10px; color: var(--muted); margin-top: 14px; text-align: center; }
.modal-typo-hint { font-family: var(--font-mono); font-size: 11px; color: var(--amber); margin: -6px 0 10px; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.modal-resend-link { display: block; margin-top: 10px; font-size: 11px; color: var(--amber); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }

/* ── SHARED: subscribe modal (soundb-components.js) ── */
.subscribe-modal-overlay { display: none; position: fixed; inset: 0; z-index: 600; background: rgba(10,10,11,0.92); backdrop-filter: blur(14px); align-items: center; justify-content: center; }
.subscribe-modal-box { background: var(--bg2); border: 1px solid var(--border2); max-width: 440px; width: 90%; padding: 40px; position: relative; }
.subscribe-modal-close { position: absolute; top: 16px; right: 16px; background: none; border: none; color: var(--muted); font-size: 20px; cursor: pointer; line-height: 1; }
.subscribe-modal-box .modal-field { margin-bottom: 10px; transition: border-color 0.2s; }
.subscribe-modal-box .modal-submit-btn { font-size: 16px; transition: background 0.2s; }

/* ── SHARED: nav account slot (soundb-components.js) ── */
.icon-btn-row { display: flex; align-items: center; gap: 8px; }
.icon-btn-text { width: auto; padding: 0 10px; font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; }

/* ── SHARED: search overlay extras (soundb-components.js) ── */
.trending-article-num { font-family: var(--font-mono); font-size: 13px; color: var(--amber); min-width: 22px; }
.search-results-count { font-family: var(--font-mono); font-size: 11px; color: var(--muted); margin-bottom: 24px; }
.no-results-title { font-family: var(--font-display); font-size: 32px; font-weight: 900; text-transform: uppercase; margin-bottom: 8px; }
.result-body { flex: 1; min-width: 0; }
.result-badge-row { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.result-type-badge { font-family: var(--font-mono); font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; padding: 2px 7px; color: #000; background: var(--badge-bg); }
.tag-badge-amber { display: inline-block; font-family: var(--font-mono); font-size: 9px; text-transform: uppercase; letter-spacing: .1em; padding: 2px 8px; background: rgba(255,140,0,0.15); color: var(--amber); border: 1px solid rgba(255,140,0,0.35); margin-left: 8px; vertical-align: middle; }
.release-thumb-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.release-thumb-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.release-score-den { font-size: 11px; color: var(--muted); }

/* ── TOPBAR ── */
.topbar { background: rgba(10,10,11,0.96); backdrop-filter: blur(12px); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 200; }
/* justify-content:space-between (not the default flex-start) matters once
   .primary-nav collapses to display:none below the hamburger breakpoint:
   with only logo + nav-controls left as flex children, flex-start left them
   sitting bunched together right after the logo with a large dead gap
   stretching to the true right edge. space-between pushes them to opposite
   ends regardless — a no-op at wider widths since .primary-nav's flex:1
   already fills the middle there. */
.topbar-inner { max-width: 1320px; margin: 0 auto; padding: 0 24px; display: flex; align-items: center; justify-content: space-between; height: 62px; gap: 0; }
.logo { height: 38px; width: auto; display: block; flex-shrink: 0; margin-right: 40px; user-select: none; cursor: pointer; position: relative; top: -4px; }

/* ── NAV ── */
.primary-nav { display: flex; align-items: stretch; height: 100%; flex: 1; }
.nav-item { position: relative; display: flex; align-items: center; }
.nav-link { display: flex; align-items: center; gap: 5px; font-size: 13px; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); padding: 0 16px; height: 100%; transition: color 0.2s; white-space: nowrap; cursor: pointer; border: none; background: none; font-family: var(--font-body); position: relative; }
.nav-link:hover, .nav-link.active { color: var(--text); }
.nav-link svg { transition: transform 0.2s; flex-shrink: 0; }
.nav-item:hover .nav-link svg { transform: rotate(180deg); }
.nav-link::after { content: ''; position: absolute; bottom: 0; left: 16px; right: 16px; height: 2px; background: var(--amber); transform: scaleX(0); transform-origin: left; transition: transform 0.2s; }
.nav-link:hover::after, .nav-link.active::after { transform: scaleX(1); }

/* ── DROPDOWNS ── */
.dropdown { position: absolute; top: 100%; left: -20px; background: var(--bg2); border: 1px solid var(--border2); min-width: 520px; opacity: 0; pointer-events: none; transform: translateY(8px); transition: opacity 0.2s, transform 0.2s; z-index: 300; }
.dropdown-narrow { min-width: 280px; }
.dropdown-narrow .dropdown-inner { grid-template-columns: 1fr; }
.nav-item:hover .dropdown { opacity: 1; pointer-events: all; transform: translateY(0); }
.dropdown-inner { display: grid; grid-template-columns: 1fr 1fr; }
.dropdown-col { padding: 24px; border-right: 1px solid var(--border); }
.dropdown-col:last-child { border-right: none; }
.dropdown-col-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-bottom: 14px; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
.dropdown-link { display: flex; align-items: flex-start; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border); cursor: pointer; transition: opacity 0.15s; }
.dropdown-link:last-child { border-bottom: none; padding-bottom: 0; }
.dropdown-link:hover { opacity: 0.7; }
.dropdown-icon { width: 32px; height: 32px; flex-shrink: 0; background: var(--bg3); display: flex; align-items: center; justify-content: center; color: var(--amber); font-size: 14px; }
.dropdown-text strong { font-family: var(--font-display); font-size: 15px; font-weight: 800; text-transform: uppercase; color: var(--text); display: block; margin-bottom: 2px; line-height: 1.1; }
.dropdown-text span { font-family: var(--font-mono); font-size: 10px; color: var(--muted); }
.dropdown-featured { padding: 20px 24px; background: var(--bg3); grid-column: span 2; border-top: 1px solid var(--border); display: flex; align-items: center; gap: 16px; cursor: pointer; transition: opacity 0.2s; }
.dropdown-featured:hover { opacity: 0.8; }
.dropdown-featured-img { width: 72px; height: 50px; background: var(--bg2); flex-shrink: 0; overflow: hidden; }
.dropdown-featured-eyebrow { font-family: var(--font-mono); font-size: 10px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 4px; }
.dropdown-featured-title { font-family: var(--font-display); font-size: 16px; font-weight: 800; text-transform: uppercase; color: var(--text); line-height: 1.1; }

/* ── NAV CONTROLS ── */
.nav-controls { display: flex; align-items: center; gap: 8px; margin-left: 20px; flex-shrink: 0; }
.icon-btn { width: 38px; height: 38px; background: none; border: none; color: var(--muted); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: color 0.2s; }
.icon-btn:hover { color: var(--text); }
.icon-btn.icon-btn-text { width: auto; gap: 6px; }
.btn-subscribe { background: var(--amber); color: #000; font-family: var(--font-body); font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; padding: 8px 18px; border: none; cursor: pointer; transition: background 0.2s, transform 0.1s; white-space: nowrap; }
.btn-subscribe:hover { background: var(--amber2); transform: translateY(-1px); }
.hamburger { display: none; flex-direction: column; gap: 5px; cursor: pointer; background: none; border: none; padding: 6px; margin-left: 8px; }
.hamburger span { display: block; width: 22px; height: 1.5px; background: var(--muted); transition: all 0.3s; }
.hamburger.open span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); background: var(--text); }
.hamburger.open span:nth-child(2) { opacity: 0; }
.hamburger.open span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); background: var(--text); }

/* ── ACCOUNT MENU (click-toggled, rendered into #nav-account-slot) ──
   Deliberately NOT the .dropdown pattern above. That one is hover-driven
   and belongs to the primary nav's category panels, which are purely
   informational. This menu contains Log Out, so it opens on an explicit
   click and closes on outside click / Escape — the same convention
   window.openShareMenu already uses for an actions popover.

   .acct-menu carries its own position:relative rather than adding one to
   the shared .nav-controls: the panel then anchors to the trigger button,
   and no other control in the topbar inherits a new containing block. */
.acct-menu { position: relative; display: flex; align-items: center; }
.acct-panel {
  position: absolute; top: calc(100% + 8px); right: 0;
  min-width: 240px; background: var(--bg2); border: 1px solid var(--border2);
  box-shadow: 0 12px 40px rgba(0,0,0,.5);
  padding: 6px 0; z-index: 300;
  /* visibility, not just opacity: an opacity:0 panel is still in the tab
     order and the accessibility tree — the .dropdown rules above have that
     bug and it should not be copied here. */
  opacity: 0; visibility: hidden; pointer-events: none; transform: translateY(-6px);
  transition: opacity .18s, transform .18s, visibility .18s;
}
.acct-menu.open .acct-panel { opacity: 1; visibility: visible; pointer-events: all; transform: translateY(0); }
.acct-panel-label {
  font-family: var(--font-mono); font-size: 9px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted);
  padding: 12px 18px 8px; margin-bottom: 2px; border-bottom: 1px solid var(--border);
}
.acct-item {
  display: block; width: 100%; text-align: left; background: none; border: none;
  font-family: var(--font-body); font-size: 13px; letter-spacing: .03em;
  color: var(--text); padding: 10px 18px; cursor: pointer;
  transition: color .15s, background .15s;
}
.acct-item:hover, .acct-item:focus-visible { color: var(--amber); background: var(--bg3); outline: none; }
.acct-divider { height: 1px; background: var(--border); margin: 6px 0; }
.acct-item-danger { color: var(--muted); }
.acct-item-danger:hover, .acct-item-danger:focus-visible { color: var(--red); background: var(--bg3); }
.acct-caret { transition: transform .2s; flex-shrink: 0; }
.acct-menu.open .acct-caret { transform: rotate(180deg); }

/* Live open-issue count next to "System Health" in the account menu (both
   desktop and mobile copies — see accountMenuGroups/paintAccountSlot in
   soundb-components.js). Zero is shown muted rather than hidden entirely,
   so its absence never reads as "hasn't loaded yet". */
.nav-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; height: 17px; padding: 0 5px; margin-left: 4px;
  border-radius: 999px; vertical-align: middle;
  background: var(--amber); color: #000;
  font-family: var(--font-mono); font-size: 10px; font-weight: 700;
}
.nav-badge.zero { background: var(--border2); color: var(--muted); }

/* ── TICKER ── */
.ticker { background: var(--amber); overflow: hidden; height: 34px; display: flex; align-items: center; }
.ticker-label { font-family: var(--font-display); font-size: 11px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: #000; padding: 0 18px; white-space: nowrap; border-right: 1px solid rgba(0,0,0,0.2); background: rgba(0,0,0,0.1); height: 100%; display: flex; align-items: center; flex-shrink: 0; }
.ticker-track { display: flex; animation: ticker 40s linear infinite; white-space: nowrap; }
@keyframes ticker { 0%{transform:translateX(0)} 100%{transform:translateX(-50%)} }
.ticker-item { font-family: var(--font-body); font-size: 12px; font-weight: 500; color: #000; padding: 0 36px; border-right: 1px solid rgba(0,0,0,0.15); }

/* ── SEARCH OVERLAY ── */
.search-overlay { position: fixed; inset: 0; background: rgba(10,10,11,0.97); backdrop-filter: blur(20px); z-index: 500; display: flex; flex-direction: column; opacity: 0; pointer-events: none; transition: opacity 0.25s; }
.search-overlay.open { opacity: 1; pointer-events: all; }
.search-header { padding: 24px 40px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 20px; }
.search-back { background: none; border: none; color: var(--muted); cursor: pointer; display: flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.06em; transition: color 0.2s; padding: 0; flex-shrink: 0; }
.search-back:hover { color: var(--text); }
.search-input-wrap { flex: 1; position: relative; display: flex; align-items: center; }
.search-icon { position: absolute; left: 0; color: var(--amber); pointer-events: none; }
.search-input { width: 100%; background: none; border: none; font-family: var(--font-display); font-size: 42px; font-weight: 800; text-transform: uppercase; color: var(--text); outline: none; padding: 0 0 0 52px; letter-spacing: -0.5px; caret-color: var(--amber); }
.search-input::placeholder { color: rgba(240,237,230,0.15); }
.search-clear { background: var(--bg3); border: none; color: var(--muted); cursor: pointer; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; transition: all 0.2s; flex-shrink: 0; opacity: 0; pointer-events: none; }
.search-clear.visible { opacity: 1; pointer-events: all; }
.search-clear:hover { color: var(--text); }
.search-body { flex: 1; overflow-y: auto; padding: 0 40px 40px; }
.search-default { padding-top: 40px; display: grid; grid-template-columns: 1fr 1fr; gap: 48px; }
.search-section-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-bottom: 16px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.recent-list { list-style: none; }
.recent-item { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--border); cursor: pointer; transition: opacity 0.15s; }
.recent-item:last-child { border-bottom: none; }
.recent-item:hover { opacity: 0.7; }
.recent-icon { color: var(--muted); flex-shrink: 0; }
.recent-text { font-size: 15px; color: var(--text); flex: 1; }
.recent-remove { color: var(--muted); background: none; border: none; cursor: pointer; font-size: 18px; line-height: 1; padding: 2px 4px; transition: color 0.2s; }
.recent-remove:hover { color: var(--text); }
.trending-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 24px; }
.chip { font-family: var(--font-mono); font-size: 11px; color: var(--muted); border: 1px solid var(--border); padding: 7px 14px; cursor: pointer; transition: all 0.2s; letter-spacing: 0.04em; }
.chip:hover { color: var(--amber); border-color: var(--amber); }
.chip.hot { color: var(--amber); border-color: rgba(255,140,0,0.3); }
.trending-article { display: flex; gap: 16px; padding: 14px 0; border-bottom: 1px solid var(--border); cursor: pointer; transition: opacity 0.15s; align-items: flex-start; }
.trending-article:last-child { border-bottom: none; }
.trending-article:hover { opacity: 0.7; }
.trending-num { font-family: var(--font-mono); font-size: 13px; color: var(--amber); min-width: 24px; flex-shrink: 0; padding-top: 2px; }
.trending-article-title { font-family: var(--font-display); font-size: 18px; font-weight: 800; text-transform: uppercase; color: var(--text); line-height: 1.1; margin-bottom: 4px; }
.trending-article-meta { font-family: var(--font-mono); font-size: 10px; color: var(--muted); }
.search-results { display: none; padding-top: 32px; }
.search-results.visible { display: block; }
.search-results.no-results-box { padding-top: 60px; text-align: center; }
.search-default.hidden { display: none; }
.results-count { font-family: var(--font-mono); font-size: 11px; color: var(--muted); margin-bottom: 24px; padding-bottom: 14px; border-bottom: 1px solid var(--border); }
.results-count strong { color: var(--amber); }
.result-item { display: flex; gap: 20px; padding: 20px 0; border-bottom: 1px solid var(--border); cursor: pointer; transition: opacity 0.15s; align-items: flex-start; }
.result-item:last-child { border-bottom: none; }
.result-item:hover { opacity: 0.75; }
.result-thumb { width: 80px; height: 56px; background: var(--bg3); flex-shrink: 0; overflow: hidden; }
.result-cat { font-family: var(--font-mono); font-size: 10px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 6px; }
.result-title { font-family: var(--font-display); font-size: 22px; font-weight: 800; text-transform: uppercase; color: var(--text); line-height: 1.05; margin-bottom: 6px; }
.result-title mark { background: rgba(255,140,0,0.2); color: var(--amber); }
.result-excerpt { font-size: 13px; color: var(--muted); line-height: 1.5; }
.result-meta { font-family: var(--font-mono); font-size: 10px; color: #5a5856; margin-top: 6px; }
.no-results { text-align: center; padding: 80px 0; display: none; }
.no-results.visible { display: block; }
.no-results-icon { color: var(--border2); margin-bottom: 20px; }
.no-results h3 { font-family: var(--font-display); font-size: 28px; font-weight: 900; text-transform: uppercase; color: var(--muted); margin-bottom: 10px; }
.no-results p { font-family: var(--font-mono); font-size: 12px; color: var(--muted); }

/* ── MOBILE NAV ── */
.mobile-nav { position: fixed; top: 62px; left: 0; right: 0; bottom: 0; background: var(--bg2); border-top: 1px solid var(--border); z-index: 190; overflow-y: auto; transform: translateX(-100%); transition: transform 0.3s cubic-bezier(0.4,0,0.2,1); }
.mobile-nav.open { transform: translateX(0); }
.mobile-nav-inner { padding: 24px; }
.mobile-section { margin-bottom: 32px; }
.mobile-section-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
.mobile-link { display: flex; align-items: center; justify-content: space-between; padding: 14px 0; border-bottom: 1px solid var(--border); font-family: var(--font-display); font-size: 24px; font-weight: 800; text-transform: uppercase; color: var(--text); cursor: pointer; transition: color 0.2s; }
.mobile-link:hover, .mobile-link.active { color: var(--amber); }
.mobile-link:last-child { border-bottom: none; }
.mobile-sub-links { display: flex; flex-wrap: wrap; gap: 8px; padding: 12px 0; }
.mobile-sub-link { font-family: var(--font-mono); font-size: 11px; color: var(--muted); border: 1px solid var(--border); padding: 6px 12px; cursor: pointer; transition: all 0.2s; }
.mobile-sub-link:hover { color: var(--amber); border-color: var(--amber); }
.mobile-subscribe { width: 100%; background: var(--amber); color: #000; font-family: var(--font-display); font-size: 18px; font-weight: 900; letter-spacing: 0.06em; text-transform: uppercase; padding: 16px; border: none; cursor: pointer; margin-top: 8px; }

/* ── FOOTER ── */
footer { background: var(--bg2); border-top: 1px solid var(--border); padding: 60px 0 32px; }
.footer-grid { display: grid; grid-template-columns: 280px 1fr 1fr 1fr; gap: 48px; margin-bottom: 48px; }
.footer-logo { height: 32px; width: auto; display: block; margin-bottom: 14px; }
.footer-desc { font-size: 13px; color: var(--muted); line-height: 1.7; }
.footer-col h4 { font-family: var(--font-mono); font-size: 10px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-bottom: 16px; }
.footer-col a { display: block; font-size: 13px; color: var(--muted); margin-bottom: 10px; transition: color 0.2s; cursor: pointer; }
.footer-col a:hover { color: var(--text); }
.footer-bottom { padding-top: 24px; border-top: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
.footer-bottom a { cursor: pointer; color: var(--muted); transition: color 0.2s; }
.footer-bottom a:hover { color: var(--text); }
/* .footer-grid used to get redefined across six separate scattered
   breakpoints throughout this file — since equal-specificity CSS rules
   resolve by source order rather than by which max-width is narrower, the
   LAST one in the file (a max-width:600px rule collapsing everything to a
   single column) always won regardless of actual viewport width, which is
   why mobile always looked fully stacked no matter what the "closer"
   breakpoints tried to set. Consolidated into this one rule instead — the
   logo/description block spans the full width on top, and the three link
   columns (Coverage/Company/Follow) sit in a tidy 2-column grid below it. */
@media (max-width: 768px) {
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 28px 20px; }
  .footer-grid > div:first-child { grid-column: 1 / -1; }
}
.container { max-width: 1320px; margin: 0 auto; padding: 0 24px; }

.section-title { font-family: var(--font-display); font-size: 13px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); display: flex; align-items: center; gap: 10px; }
.section-title::before { content: ''; width: 16px; height: 2px; background: var(--amber); }
.section-link { font-family: var(--font-mono); font-size: 11px; color: var(--amber); letter-spacing: 0.06em; transition: opacity 0.2s; cursor: pointer; }
.section-link:hover { opacity: 0.7; }

/* ── RESPONSIVE ── */
/* 1250px, not 1024px: below ~1150px the full nav-link row plus search/account/
   subscribe genuinely runs out of room and overflows the topbar's own right
   padding (confirmed by measuring subscribe-btn's right edge pinned flush to
   the viewport edge between ~1025-1149px) — moving the hamburger breakpoint
   up clears that dead zone entirely instead of trying to squeeze content
   into a range that doesn't fit it. #nav-account-slot (Log In/username/
   Mentor Queue/Studio Uploads) hides here too since its content moves into
   the mobile-nav drawer's own #mobile-nav-account-slot below this width. */
@media (max-width: 1250px) { .primary-nav { display: none; } .hamburger { display: flex; } #nav-account-slot { display: none; } }
@media (max-width: 900px) { .search-input { font-size: 28px; } .search-default { grid-template-columns: 1fr; } .search-header { padding: 20px; } .search-body { padding: 0 20px 32px; } }
@media (max-width: 768px) { .container { padding: 0 16px; } }
@media (max-width: 480px) { .container { padding: 0 14px; } .btn-subscribe { display: none; } .topbar-inner { padding: 0 14px; } .search-input { font-size: 20px; } }

/* ══════════════════════════════════════════════════════════════
   PAGE-SPECIFIC STYLES — consolidated from all pages
   ══════════════════════════════════════════════════════════════ */

/* ── SHARED: container, section-header, section-link, tags ── */
.container { max-width: 1320px; margin: 0 auto; padding: 0 24px; }
.section-header { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 24px; padding-bottom: 14px; border-bottom: 1px solid var(--border); }
.section-title { font-family: var(--font-display); font-size: 13px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); display: flex; align-items: center; gap: 10px; }
.section-title::before { content: ''; width: 16px; height: 2px; background: var(--amber); }
.section-link { font-family: var(--font-mono); font-size: 11px; color: var(--amber); letter-spacing: 0.06em; transition: opacity 0.2s; cursor: pointer; }
.section-link:hover { opacity: 0.7; }
.tag { font-family: var(--font-mono); font-size: 11px; color: var(--muted); border: 1px solid var(--border); padding: 6px 12px; cursor: pointer; transition: all 0.2s; letter-spacing: 0.04em; }
.tag:hover { color: var(--amber); border-color: var(--amber); }

/* ── SHARED: read progress bar ── */
.read-progress { position: fixed; top: 62px; left: 0; right: 0; height: 2px; background: var(--border); z-index: 199; }
.read-progress-fill { height: 100%; background: var(--amber); width: 0; transition: width 0.1s linear; }

/* ── SHARED: breadcrumb ── */
.breadcrumb { font-family: var(--font-mono); font-size: 11px; color: var(--muted); margin-bottom: 28px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.breadcrumb a { color: var(--muted); transition: color 0.2s; cursor: pointer; }
.breadcrumb a:hover { color: var(--amber); }
.breadcrumb-sep { opacity: 0.4; }

/* ── SHARED: badges ── */
.badge-editors { background: var(--amber); color: #000; }
.badge-new { background: var(--blue); color: #000; }
.badge-budget { background: var(--green); color: #000; }

/* ── SHARED: page hero (gear, specs) ── */
.page-hero { padding: 48px 0 40px; border-bottom: 1px solid var(--border); }
.page-hero-inner { display: flex; align-items: flex-end; justify-content: space-between; gap: 32px; flex-wrap: wrap; }
.page-eyebrow { font-family: var(--font-mono); font-size: 11px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.14em; margin-bottom: 12px; display: flex; align-items: center; gap: 10px; }
.page-eyebrow::before { content: ''; width: 20px; height: 1px; background: var(--amber); }
.page-title { font-family: var(--font-display); font-size: 80px; font-weight: 900; text-transform: uppercase; line-height: 0.9; letter-spacing: -2px; color: var(--text); }
.page-title em { color: var(--amber); font-style: normal; }
.page-desc { font-size: 14px; color: var(--muted); max-width: 340px; line-height: 1.7; margin-top: 16px; }
.page-stats { display: flex; gap: 32px; flex-shrink: 0; }
.page-stat-num { font-family: var(--font-display); font-size: 40px; font-weight: 900; color: var(--amber); line-height: 1; }
.page-stat-label { font-family: var(--font-mono); font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; margin-top: 4px; }

/* ── SHARED: article/review body typography ── */
.review-body p, .article-body p { font-family: var(--font-serif); font-size: 17px; line-height: 1.85; color: #D8D5CE; margin-bottom: 26px; }
.review-body h2, .article-body h2 { font-family: var(--font-display); font-size: 34px; font-weight: 900; text-transform: uppercase; color: var(--text); margin: 48px 0 18px; line-height: 1; }
.review-body h3, .article-body h3 { font-family: var(--font-display); font-size: 22px; font-weight: 700; text-transform: uppercase; color: var(--text); margin: 32px 0 14px; }
.review-body strong, .article-body strong { color: var(--text); font-weight: 600; }

/* ── SHARED: meta bar ── */
.meta-bar { display: flex; align-items: center; gap: 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 14px 0; margin-bottom: 40px; flex-wrap: wrap; row-gap: 12px; }
.meta-author { display: flex; align-items: center; gap: 10px; }
.author-av { width: 38px; height: 38px; background: var(--bg3); border-radius: 50%; border: 1px solid var(--border2); display: flex; align-items: center; justify-content: center; font-family: var(--font-display); font-size: 15px; font-weight: 700; color: var(--amber); flex-shrink: 0; }
.author-name { font-size: 14px; font-weight: 600; }
.author-role { font-family: var(--font-mono); font-size: 10px; color: var(--muted); }
.meta-div { width: 1px; height: 36px; background: var(--border); margin: 0 20px; }
.meta-info { font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
.meta-info strong { color: var(--text); display: block; font-weight: 500; }

/* ── Mobile-only meta layout (see .meta-bar-mobile markup in
   soundb-review.html) — hidden on desktop, swapped in at ≤900px in place
   of .meta-bar. Author gets its own row; date/read-time/tested read as
   one muted byline sentence instead of separate boxed stats; price and
   badge/score are pulled into their own bordered "verdict strip" since
   that's the at-a-glance info a reader scans for on a review. ── */
.meta-bar-mobile { display: none; }
.mb-author { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
/* 48px = .author-av's 38px width + .mb-author's 10px gap, so the byline
   lines up under the author's name rather than under the avatar. */
.mb-byline { font-family: var(--font-mono); font-size: 11px; color: var(--muted); line-height: 1.7; margin-bottom: 16px; margin-left: 48px; }
.mb-sep { margin: 0 6px; color: var(--border2); }
/* Guards against a dangling separator when a field is missing content
   (e.g. an empty date on an older review record) — CMS content should
   still be filled in, but a stray leading "·" isn't a good fallback. */
.mb-byline span:empty + .mb-sep { display: none; }
.mb-verdict { display: flex; align-items: center; justify-content: space-between; gap: 12px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 14px 0; }
.mb-verdict-price { font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
.mb-verdict-price strong { display: block; color: var(--text); font-family: var(--font-display); font-size: 16px; font-weight: 700; margin-bottom: 2px; }
.mb-verdict-badge { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }

/* ── SHARED: pullquote ── */
.pullquote { border-left: 3px solid var(--amber); padding: 8px 0 8px 26px; margin: 36px 0; }
.pullquote p { font-family: var(--font-display); font-size: 28px; font-weight: 700; text-transform: uppercase; line-height: 1.1; color: var(--text); margin-bottom: 10px; }
.pullquote cite { font-family: var(--font-mono); font-size: 11px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; font-style: normal; }

/* ── SHARED: cover image ── */
.cover-img { width: 100%; height: 500px; background: var(--bg3); margin-bottom: 12px; overflow: hidden; }
.cover-caption { font-family: var(--font-mono); font-size: 11px; color: var(--muted); margin-bottom: 48px; padding-left: 14px; border-left: 2px solid var(--border); }

/* ── SHARED: article/review hero labels ── */
.review-cat, .article-cat { font-family: var(--font-mono); font-size: 11px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.14em; margin-bottom: 18px; display: flex; align-items: center; gap: 10px; }
.review-cat::before, .article-cat::before { content: ''; width: 20px; height: 1px; background: var(--amber); }

/* ── SHARED: TOC sidebar ── */
.toc-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.toc-list { list-style: none; }
.toc-item a { font-size: 13px; color: var(--muted); padding: 7px 0 7px 14px; display: block; border-left: 2px solid var(--border); transition: all 0.2s; line-height: 1.4; }
.toc-item a:hover, .toc-item.active a { color: var(--text); border-left-color: var(--amber); }

/* ── SHARED: sticky sidebar ── */
.sticky-sidebar { position: sticky; top: 80px; display: flex; flex-direction: column; gap: 28px; }

/* ── SHARED: author bio ── */
.author-bio { margin-top: 48px; padding: 28px; background: var(--card); border: 1px solid var(--border); display: flex; gap: 20px; }
.author-bio-av { width: 56px; height: 56px; background: var(--bg3); border-radius: 50%; border: 1px solid var(--border2); display: flex; align-items: center; justify-content: center; font-family: var(--font-display); font-size: 22px; font-weight: 700; color: var(--amber); flex-shrink: 0; }
.author-bio-name { font-family: var(--font-display); font-size: 18px; font-weight: 900; text-transform: uppercase; margin-bottom: 4px; }
.author-bio-role { font-family: var(--font-mono); font-size: 10px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 10px; }
.author-bio-text { font-size: 13px; color: var(--muted); line-height: 1.6; }

/* ── SHARED: article tags ── */
.article-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 40px; padding-top: 28px; border-top: 1px solid var(--border); }

/* ── SHARED: newsletter (sidebar + inline) ── */
.sidebar-newsletter { background: var(--card); border: 1px solid var(--border2); padding: 22px; }
.sidebar-newsletter h4 { font-family: var(--font-display); font-size: 20px; font-weight: 900; text-transform: uppercase; line-height: 1.1; margin-bottom: 8px; }
.sidebar-newsletter h4 span { color: var(--amber); }
.sidebar-newsletter p { font-family: var(--font-mono); font-size: 10px; color: var(--muted); margin-bottom: 14px; line-height: 1.6; }
.sidebar-newsletter input { width: 100%; background: var(--bg3); border: 1px solid var(--border2); color: var(--text); font-family: var(--font-body); font-size: 13px; padding: 10px 12px; outline: none; margin-bottom: 8px; }
.sidebar-newsletter input:focus { border-color: var(--amber); }
.sidebar-newsletter button { width: 100%; background: var(--amber); color: #000; font-family: var(--font-display); font-size: 14px; font-weight: 900; text-transform: uppercase; padding: 11px; border: none; cursor: pointer; }
.sidebar-newsletter button:hover { background: var(--amber2); }
.inline-newsletter { background: var(--card); border: 1px solid var(--border2); border-left: 3px solid var(--amber); padding: 28px 32px; margin: 48px 0; display: flex; align-items: center; gap: 32px; flex-wrap: wrap; }
.inline-newsletter h4 { font-family: var(--font-display); font-size: 22px; font-weight: 900; text-transform: uppercase; white-space: nowrap; }
.inline-newsletter h4 span { color: var(--amber); }
.inline-newsletter p { font-family: var(--font-mono); font-size: 11px; color: var(--muted); flex: 1; min-width: 160px; }
.inline-newsletter-form { display: flex; gap: 0; flex-shrink: 0; }
.inline-newsletter input { background: var(--bg3); border: 1px solid var(--border2); border-right: none; color: var(--text); font-family: var(--font-body); font-size: 13px; padding: 10px 16px; outline: none; width: 200px; }
.inline-newsletter input::placeholder { color: var(--muted); }
.inline-newsletter input:focus { border-color: var(--amber); }
.inline-newsletter button { background: var(--amber); color: #000; font-family: var(--font-display); font-size: 14px; font-weight: 900; text-transform: uppercase; padding: 10px 18px; border: none; cursor: pointer; white-space: nowrap; transition: background 0.2s; }
.inline-newsletter button:hover { background: var(--amber2); }

/* ── SHARED: data callout ── */
.data-callout { background: var(--card); border: 1px solid var(--border); padding: 28px 32px; margin: 36px 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.data-num { font-family: var(--font-display); font-size: 52px; font-weight: 900; color: var(--amber); line-height: 1; }
.data-label { font-family: var(--font-mono); font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin-top: 6px; }
.inline-graphic { width: 100%; background: var(--bg3); border: 1px solid var(--border); margin: 36px 0; overflow: hidden; }

/* ── SHARED: spec table ── */
.spec-table { width: 100%; border-collapse: collapse; margin: 36px 0; }
.spec-table th { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); text-align: left; padding: 10px 16px; border-bottom: 1px solid var(--border); background: var(--bg3); }
.spec-table td { font-size: 13px; padding: 12px 16px; border-bottom: 1px solid var(--border); vertical-align: top; }
.spec-table tr:last-child td { border-bottom: none; }
.spec-table td:first-child { font-family: var(--font-mono); font-size: 11px; color: var(--muted); width: 40%; }
.spec-table td:last-child { color: var(--text); }
.spec-table tr:hover td { background: var(--card); }

/* ── SHARED: verdict box ── */
.verdict-box { background: var(--card); border: 1px solid var(--border2); border-left: 3px solid var(--amber); padding: 32px; margin: 48px 0; }
.verdict-box-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--amber); margin-bottom: 14px; }
.verdict-box p { font-family: var(--font-serif); font-size: 16px; line-height: 1.8; color: var(--muted); }
.verdict-box-score { display: flex; align-items: baseline; gap: 4px; margin-top: 20px; }
.verdict-box-score-num { font-family: var(--font-display); font-size: 56px; font-weight: 900; color: var(--amber); line-height: 1; }
.verdict-box-score-den { font-family: var(--font-mono); font-size: 16px; color: var(--muted); }
.verdict-box-score-label { font-family: var(--font-mono); font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; margin-left: 12px; align-self: center; }

/* ── SHARED: comparison table ── */
.comparison-wrap { margin: 48px 0; }
.comparison-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-bottom: 16px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.comparison-table { width: 100%; border-collapse: collapse; }
.comparison-table th { font-family: var(--font-display); font-size: 14px; font-weight: 800; text-transform: uppercase; text-align: left; padding: 14px 16px; border-bottom: 2px solid var(--border); color: var(--muted); }
.comparison-table th.winner { color: var(--amber); border-bottom-color: var(--amber); }
.comparison-table td { font-size: 13px; padding: 12px 16px; border-bottom: 1px solid var(--border); color: var(--muted); vertical-align: middle; }
.comparison-table tr:last-child td { border-bottom: none; }
.comparison-table td:first-child { font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
.comparison-table td.highlight { color: var(--text); font-weight: 500; }
.comparison-table td.winner-col { background: rgba(255,140,0,0.04); }
.comparison-table tr:hover td { background: var(--card); }
.badge-best { background: var(--amber); color: #000; font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; padding: 2px 7px; margin-left: 6px; vertical-align: middle; }
.badge-good { background: rgba(74,222,128,0.15); color: var(--green); font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; padding: 2px 7px; margin-left: 6px; }
.badge-avg { background: rgba(255,140,0,0.12); color: var(--amber); font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; padding: 2px 7px; margin-left: 6px; }

/* ── SHARED: score card (review) ── */
.score-card { background: var(--card); border: 1px solid var(--border2); padding: 32px; margin: 40px 0; }
.score-card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 28px; padding-bottom: 20px; border-bottom: 1px solid var(--border); }
.score-card-title { font-family: var(--font-display); font-size: 14px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.score-overall { text-align: right; }
.score-overall-num { font-family: var(--font-display); font-size: 72px; font-weight: 900; color: var(--amber); line-height: 1; }
.score-overall-label { font-family: var(--font-mono); font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; }
.score-rows { display: flex; flex-direction: column; gap: 14px; }
.score-row { display: flex; align-items: center; gap: 16px; }
.score-row-label { font-family: var(--font-mono); font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; min-width: 120px; }
/* score-bar-track/fill → defined in SPECS PAGE section below */
.score-row-val { font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--text); min-width: 32px; text-align: right; }

/* ── SHARED: pros/cons (review) ── */
.pros-cons { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--border); border: 1px solid var(--border); margin: 36px 0; }
.pros, .cons { background: var(--bg); padding: 24px; }
.pros-cons-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; margin-bottom: 16px; font-weight: 500; }
.pros .pros-cons-label { color: var(--green); }
.cons .pros-cons-label { color: var(--red); }
.pros-cons-list { list-style: none; display: flex; flex-direction: column; gap: 10px; }
.pros-cons-list li { font-size: 14px; color: var(--muted); display: flex; gap: 10px; align-items: flex-start; line-height: 1.5; }
.pros-cons-list li::before { flex-shrink: 0; font-family: var(--font-mono); font-size: 12px; margin-top: 1px; }
.pros .pros-cons-list li::before { content: '+'; color: var(--green); }
.cons .pros-cons-list li::before { content: '−'; color: var(--red); }

/* ── SHARED: buy box (review sidebar) ── */
.buy-box { background: var(--card); border: 1px solid var(--border2); }
.buy-box-header { padding: 16px 20px; border-bottom: 1px solid var(--border); font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.buy-box-body { padding: 20px; }
.buy-product-name { font-family: var(--font-display); font-size: 22px; font-weight: 900; text-transform: uppercase; margin-bottom: 4px; }
.buy-product-sub { font-family: var(--font-mono); font-size: 10px; color: var(--muted); margin-bottom: 16px; }
.buy-price { font-family: var(--font-display); font-size: 36px; font-weight: 900; color: var(--amber); margin-bottom: 4px; }
.buy-price-note { font-family: var(--font-mono); font-size: 10px; color: var(--muted); margin-bottom: 16px; }
.buy-btn { display: block; width: 100%; background: var(--amber); color: #000; font-family: var(--font-display); font-size: 16px; font-weight: 900; text-transform: uppercase; letter-spacing: 0.06em; padding: 13px; text-align: center; border: none; cursor: pointer; transition: background 0.2s; margin-bottom: 8px; }
.buy-btn:hover { background: var(--amber2); }
.buy-btn-sec { display: block; width: 100%; background: transparent; color: var(--muted); font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em; padding: 11px; text-align: center; border: 1px solid var(--border); cursor: pointer; transition: all 0.2s; }
.buy-btn-sec:hover { color: var(--text); border-color: var(--border2); }

/* ── SHARED: sidebar score widget ── */
.sidebar-score { background: var(--bg3); border: 1px solid var(--border); padding: 20px; }
.ss-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); margin-bottom: 14px; }
.ss-row { display: flex; align-items: center; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid var(--border); font-family: var(--font-mono); font-size: 11px; }
.ss-row:last-child { border-bottom: none; }
.ss-name { color: var(--muted); }
.ss-val { color: var(--text); font-weight: 500; }
.ss-val.green { color: var(--green); }
.ss-val.amber { color: var(--amber); }
.ss-val.red   { color: var(--red); }

/* ── SHARED: related sidebar items ── */
.related-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.related-item { display: flex; gap: 12px; padding: 14px 0; border-bottom: 1px solid var(--border); cursor: pointer; transition: opacity 0.2s; align-items: flex-start; }
.related-item:last-child { border-bottom: none; }
.related-item:hover { opacity: 0.7; }
.related-thumb { width: 56px; height: 40px; background: var(--bg3); flex-shrink: 0; }
.related-cat { font-family: var(--font-mono); font-size: 9px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 4px; }
.related-title { font-family: var(--font-display); font-size: 14px; font-weight: 700; text-transform: uppercase; color: var(--text); line-height: 1.15; }

/* ── SHARED: "more" grids ── */
.more-section { border-top: 1px solid var(--border); padding: 56px 0; }
.more-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); }
.more-card { background: var(--bg); padding: 20px; cursor: pointer; transition: background 0.2s; }
.more-card:hover { background: var(--card); }
/* Default (article "more stories") is 16:9 — soundb-review.html overrides
   this to square locally, since it reuses the same class for gear items. */
.more-card-img { width: 100%; aspect-ratio: 16/9; background: var(--bg3); margin-bottom: 14px; overflow: hidden; }
.more-card-img svg, .more-card-img img { display: block; width: 100%; height: 100%; object-fit: cover; }
.more-score { font-family: var(--font-display); font-size: 28px; font-weight: 900; color: var(--amber); margin-bottom: 6px; }
.more-name { font-family: var(--font-display); font-size: 16px; font-weight: 800; text-transform: uppercase; color: var(--text); line-height: 1.1; margin-bottom: 4px; }
.more-sub { font-family: var(--font-mono); font-size: 10px; color: var(--muted); }
.more-cat { font-family: var(--font-mono); font-size: 10px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 8px; }
.more-title { font-family: var(--font-display); font-size: 20px; font-weight: 800; text-transform: uppercase; color: var(--text); line-height: 1.1; margin-bottom: 8px; }
.more-meta { font-family: var(--font-mono); font-size: 10px; color: var(--muted); }

/* ── GEAR PAGE ── */
.filter-bar { padding: 20px 0; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.filter-label { font-family: var(--font-mono); font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.12em; flex-shrink: 0; }
.filter-chips { display: flex; gap: 8px; flex-wrap: wrap; flex: 1; }
.chip { font-family: var(--font-mono); font-size: 11px; color: var(--muted); border: 1px solid var(--border); padding: 7px 14px; cursor: pointer; transition: all 0.2s; letter-spacing: 0.04em; background: none; white-space: nowrap; }
.chip:hover { color: var(--text); border-color: var(--border2); }
.chip.active { color: #000; background: var(--amber); border-color: var(--amber); }
.filter-right { display: flex; gap: 8px; align-items: center; margin-left: auto; flex-shrink: 0; }
.sort-select { background: var(--bg3); border: 1px solid var(--border); color: var(--muted); font-family: var(--font-mono); font-size: 11px; padding: 7px 12px; outline: none; cursor: pointer; appearance: none; -webkit-appearance: none; padding-right: 28px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%238A8880' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 10px center; }
.sort-select:focus { border-color: var(--amber); }
.view-toggle { display: flex; border: 1px solid var(--border); overflow: hidden; }
.view-btn { background: none; border: none; color: var(--muted); cursor: pointer; padding: 7px 10px; display: flex; align-items: center; transition: all 0.2s; border-right: 1px solid var(--border); }
.view-btn:last-child { border-right: none; }
.view-btn.active, .view-btn:hover { background: var(--bg3); color: var(--text); }
.gear-layout { display: grid; grid-template-columns: 220px 1fr; gap: 40px; padding: 40px 0 80px; }
.filter-sidebar { display: flex; flex-direction: column; gap: 28px; }
.filter-group-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
.filter-option { display: flex; align-items: center; justify-content: space-between; padding: 8px 0; cursor: pointer; transition: opacity 0.2s; border-bottom: 1px solid var(--border); }
.filter-option:last-child { border-bottom: none; }
.filter-option:hover { opacity: 0.75; }
.filter-option-left { display: flex; align-items: center; gap: 10px; }
.filter-checkbox { width: 14px; height: 14px; border: 1px solid var(--border2); background: none; display: flex; align-items: center; justify-content: center; flex-shrink: 0; transition: all 0.2s; }
.filter-checkbox.checked { background: var(--amber); border-color: var(--amber); }
.filter-checkbox.checked::after { content: ''; width: 6px; height: 4px; border-left: 1.5px solid #000; border-bottom: 1.5px solid #000; transform: rotate(-45deg) translateY(-1px); display: block; }
.filter-option-name { font-size: 13px; color: var(--muted); }
.filter-option-count { font-family: var(--font-mono); font-size: 10px; color: var(--muted); opacity: 0.6; }
/* Brand list grows with the catalog (25+ brands as of the 2026-07-27 gear
   expansion) — cap its height and scroll internally instead of pushing the
   Price/Score/Badge groups further down the sidebar on every new brand. */
#brand-filters { max-height: 260px; overflow-y: auto; padding-right: 6px; }
#brand-filters::-webkit-scrollbar { width: 6px; }
#brand-filters::-webkit-scrollbar-track { background: transparent; }
#brand-filters::-webkit-scrollbar-thumb { background: var(--border2); }
#brand-filters::-webkit-scrollbar-thumb:hover { background: var(--muted); }
#brand-filters { scrollbar-width: thin; scrollbar-color: var(--border2) transparent; }
.price-range { display: flex; flex-direction: column; gap: 10px; }
.price-inputs { display: flex; gap: 8px; align-items: center; }
.price-input { background: var(--bg3); border: 1px solid var(--border); color: var(--text); font-family: var(--font-mono); font-size: 11px; padding: 8px 10px; width: 100%; outline: none; }
.price-input:focus { border-color: var(--amber); }
.price-sep { font-family: var(--font-mono); font-size: 11px; color: var(--muted); flex-shrink: 0; }
.score-filter { display: flex; gap: 6px; flex-wrap: wrap; }
.score-btn { background: var(--bg3); border: 1px solid var(--border); color: var(--muted); font-family: var(--font-display); font-size: 14px; font-weight: 700; padding: 6px 12px; cursor: pointer; transition: all 0.2s; }
.score-btn:hover, .score-btn.active { background: var(--amber); color: #000; border-color: var(--amber); }
.clear-filters { font-family: var(--font-mono); font-size: 11px; color: var(--amber); cursor: pointer; padding: 10px 0; transition: opacity 0.2s; background: none; border: none; text-align: left; }
.clear-filters:hover { opacity: 0.7; }
.gear-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); align-content: start; }
.gear-grid.list-view { grid-template-columns: 1fr; }
.gear-card { background: var(--bg); padding: 0; position: relative; display: flex; flex-direction: column; user-select: none; -webkit-user-select: none; transition: background 0.2s; }
.gear-card:hover { background: var(--card); }
.gear-card-img { width: 100%; aspect-ratio: 1/1; background: var(--bg3); overflow: hidden; position: relative; flex-shrink: 0; cursor: zoom-in; }
.gear-card-img-media { width: 100%; height: 100%; }
.gear-card-img svg, .gear-card-img img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Horizontal fader for the multi-angle gallery, sitting right below the
   image — only actually mounted (by mountGearFaders in soundb-gear.html)
   when a product has 2+ photos; otherwise this slot just stays empty. */
.gear-card-fader-slot { padding: 10px 14px; background: var(--bg2); border-bottom: 1px solid var(--border); }
.gear-card-fader-slot .sb-fader-track { height: 3px; }
.gear-card-img svg { transition: transform 0.5s; }
.gear-card-img img { transition: transform 0.5s; }
.gear-card-img:hover svg, .gear-card-img:hover img { transform: scale(1.05); }
.gear-card-badge { position: absolute; top: 12px; left: 12px; font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; padding: 3px 8px; }
.gear-card-body { padding: 18px; flex: 1; display: flex; flex-direction: column; cursor: pointer; }
.gear-card-cat { font-family: var(--font-mono); font-size: 10px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 6px; }
.gear-card-name { font-family: var(--font-display); font-size: 20px; font-weight: 800; text-transform: uppercase; color: var(--text); line-height: 1.05; margin-bottom: 4px; }
.gear-card-brand { font-family: var(--font-mono); font-size: 10px; color: var(--muted); margin-bottom: 12px; }
.gear-card-desc { font-size: 12px; color: var(--muted); line-height: 1.5; margin-bottom: 14px; flex: 1; }
.gear-card-footer { display: flex; align-items: center; justify-content: space-between; margin-top: auto; padding-top: 12px; border-top: 1px solid var(--border); }
.gear-card-price { font-family: var(--font-display); font-size: 22px; font-weight: 900; color: var(--text); }
.gear-card-score { display: flex; align-items: baseline; gap: 2px; }
.score-num { font-family: var(--font-display); font-size: 22px; font-weight: 900; color: var(--amber); }
.score-den { font-family: var(--font-mono); font-size: 10px; color: var(--muted); }
.gear-card-action { display: flex; gap: 6px; margin-top: 12px; }
.btn-review { flex: 1; background: var(--amber); color: #000; font-family: var(--font-display); font-size: 13px; font-weight: 900; text-transform: uppercase; padding: 9px; text-align: center; border: none; cursor: pointer; transition: background 0.2s; }
.btn-review:hover { background: var(--amber2); }
.btn-save { background: var(--bg3); border: 1px solid var(--border); color: var(--muted); font-family: var(--font-mono); font-size: 11px; padding: 9px 12px; cursor: pointer; transition: all 0.2s; }
.btn-save:hover { color: var(--text); border-color: var(--border2); }
.gear-grid.list-view .gear-card { flex-direction: row; }
.gear-grid.list-view .gear-card-img { width: 200px; aspect-ratio: 1/1; flex-shrink: 0; }
.gear-grid.list-view .gear-card-body { padding: 20px 24px; }
.gear-grid.list-view .gear-card-action { margin-top: 0; }
.no-results-msg { grid-column: span 3; padding: 80px 0; text-align: center; color: var(--muted); }
.no-results-msg h3 { font-family: var(--font-display); font-size: 28px; font-weight: 900; text-transform: uppercase; margin-bottom: 8px; }
.no-results-msg p { font-family: var(--font-mono); font-size: 11px; }
.results-bar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1px; padding: 0 0 16px; }
.results-count { font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
.results-count strong { color: var(--amber); }
.compare-tray { position: fixed; bottom: 0; left: 0; right: 0; background: var(--bg2); border-top: 1px solid var(--border2); padding: 14px 24px; display: flex; align-items: center; gap: 20px; z-index: 150; transform: translateY(100%); transition: transform 0.3s cubic-bezier(0.4,0,0.2,1); }
.compare-tray.visible { transform: translateY(0); }
.compare-tray-label { font-family: var(--font-mono); font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; flex-shrink: 0; }
.compare-slots { display: flex; gap: 10px; flex: 1; }
.compare-slot { height: 44px; border: 1px dashed var(--border2); display: flex; align-items: center; justify-content: center; font-family: var(--font-mono); font-size: 10px; color: var(--muted); padding: 0 16px; min-width: 160px; position: relative; }
.compare-slot.filled { border-style: solid; border-color: var(--amber); background: rgba(255,140,0,0.06); }
.compare-slot-name { font-family: var(--font-display); font-size: 13px; font-weight: 700; text-transform: uppercase; color: var(--text); }
.compare-slot-remove { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); background: none; border: none; color: var(--muted); cursor: pointer; font-size: 16px; line-height: 1; transition: color 0.2s; }
.compare-slot-remove:hover { color: var(--text); }
.compare-btn { background: var(--amber); color: #000; font-family: var(--font-display); font-size: 14px; font-weight: 900; text-transform: uppercase; padding: 10px 24px; border: none; cursor: pointer; flex-shrink: 0; transition: background 0.2s; }
.compare-btn:hover { background: var(--amber2); }
.compare-clear { font-family: var(--font-mono); font-size: 11px; color: var(--muted); cursor: pointer; background: none; border: none; flex-shrink: 0; transition: color 0.2s; }
.compare-clear:hover { color: var(--text); }

/* ── SPECS PAGE ── */
.product-hero { padding: 32px 0 0; display: grid; grid-template-columns: 420px 1fr; gap: 64px; align-items: start; }
.product-visual { position: sticky; top: 82px; display: flex; gap: 16px; align-items: stretch; }
.product-visual-frame { background: var(--bg2); border: 1px solid var(--border); aspect-ratio: 1/1; position: relative; overflow: hidden; flex: 1; min-width: 0; cursor: zoom-in; }
.product-visual-frame svg, .product-visual-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
.product-visual-badge { position: absolute; top: 16px; left: 16px; font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; padding: 4px 10px; z-index: 2; }
/* Vertical fader for the multi-angle gallery, only actually mounted (by
   mountProductFader in soundb-specs.html) when a product has 2+ photos. */
.product-visual-fader-slot { flex: 0 0 40px; display: flex; justify-content: center; padding: 20px 0; }
.product-visual-fader-slot .sb-fader-vertical { height: 100%; }
.product-info { padding-bottom: 60px; }
.product-eyebrow { font-family: var(--font-mono); font-size: 11px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.14em; margin-bottom: 8px; }
.product-name { font-family: var(--font-display); font-size: 64px; font-weight: 900; text-transform: uppercase; line-height: 0.92; letter-spacing: -1.5px; color: var(--text); margin-bottom: 6px; }
.product-brand { font-family: var(--font-mono); font-size: 12px; color: var(--muted); margin-bottom: 24px; }
.product-meta-row { display: flex; align-items: center; gap: 24px; padding: 18px 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); margin-bottom: 28px; flex-wrap: wrap; }
.product-price { font-family: var(--font-display); font-size: 36px; font-weight: 900; color: var(--text); }
.product-score-num { font-family: var(--font-display); font-size: 36px; font-weight: 900; color: var(--amber); }
.product-score-den { font-family: var(--font-mono); font-size: 12px; color: var(--muted); }
.product-score-label { font-family: var(--font-mono); font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; margin-top: 4px; }
.product-divider { width: 1px; height: 40px; background: var(--border2); }
.score-bars { display: flex; flex-direction: column; gap: 12px; margin-bottom: 28px; }
.score-bar-row { display: grid; grid-template-columns: 130px 1fr 34px; align-items: center; gap: 12px; }
.score-bar-label { font-family: var(--font-mono); font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }
.score-bar-track { flex: 1; min-width: 0; height: 3px; background: var(--bg3); border: 1px solid var(--border); }
.score-bar-fill { height: 100%; background: var(--amber); width: 0; transition: width 0.9s cubic-bezier(0.4,0,0.2,1); }
.score-bar-val { font-family: var(--font-display); font-size: 14px; font-weight: 700; color: var(--text); text-align: right; }
.btn-primary { flex: 1; background: var(--amber); color: #000; font-family: var(--font-display); font-size: 15px; font-weight: 900; text-transform: uppercase; padding: 13px; border: none; cursor: pointer; transition: background 0.2s; letter-spacing: 0.04em; }
.btn-primary:hover { background: var(--amber2); }
.btn-primary.disabled { opacity: 0.45; cursor: not-allowed; }
.btn-secondary { background: var(--bg3); border: 1px solid var(--border2); color: var(--muted); font-family: var(--font-display); font-size: 14px; font-weight: 700; text-transform: uppercase; padding: 13px 20px; cursor: pointer; transition: all 0.2s; letter-spacing: 0.04em; }
.btn-secondary:hover { color: var(--text); border-color: var(--amber); }
.btn-ghost { background: none; border: 1px solid var(--border); color: var(--muted); font-family: var(--font-mono); font-size: 11px; padding: 8px 16px; cursor: pointer; transition: all 0.2s; }
.btn-ghost:hover { color: var(--amber); border-color: var(--amber); }
.btn-ghost.added { color: #4ADE80; border-color: #4ADE80; }
.btn-ghost.added:hover { color: var(--red); border-color: var(--red); }
.verdict-pill { display: inline-flex; align-items: flex-start; gap: 10px; border: 1px solid var(--border2); padding: 12px 16px; margin-bottom: 24px; width: 100%; }
.verdict-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--amber); flex-shrink: 0; margin-top: 3px; }
.verdict-text { font-family: var(--font-mono); font-size: 11px; color: var(--muted); line-height: 1.6; }
.verdict-text strong { color: var(--text); }
.product-cta { display: flex; gap: 10px; margin-bottom: 14px; }
.tabs-bar { border-bottom: 1px solid var(--border); display: flex; margin: 48px 0 0; }
.tab-btn { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); padding: 14px 22px; background: none; border: none; border-bottom: 2px solid transparent; cursor: pointer; transition: all 0.2s; margin-bottom: -1px; }
.tab-btn:hover { color: var(--text); }
.tab-btn.active { color: var(--amber); border-bottom-color: var(--amber); }
.tab-panel { display: none; padding: 36px 0; }
.tab-panel.active { display: block; }
.specs-section { margin-bottom: 36px; }
.specs-section-title { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--amber); margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 10px; }
.specs-section-title::before { content: ''; width: 16px; height: 1px; background: var(--amber); }
.specs-table { width: 100%; border-collapse: collapse; }
.specs-table tr { border-bottom: 1px solid var(--border); }
.specs-table tr:last-child { border-bottom: none; }
.specs-table td { padding: 11px 0; vertical-align: top; }
.specs-table td:first-child { font-family: var(--font-mono); font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; width: 46%; padding-right: 20px; padding-top: 13px; }
.specs-table td:last-child { font-size: 13px; color: var(--text); line-height: 1.5; }
.overview-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); margin-bottom: 28px; }
.overview-card { background: var(--bg2); padding: 20px; }
.overview-card.highlight { background: rgba(255,140,0,0.05); }
.overview-card-label { font-family: var(--font-mono); font-size: 9px; text-transform: uppercase; letter-spacing: 0.14em; color: var(--muted); margin-bottom: 8px; }
.overview-card-value { font-family: var(--font-display); font-size: 26px; font-weight: 900; color: var(--text); line-height: 1.1; }
.overview-card.highlight .overview-card-value { color: var(--amber); }
.summary-block { background: var(--bg2); border: 1px solid var(--border); border-left: 3px solid var(--amber); padding: 22px; margin-bottom: 28px; }
.summary-label { font-family: var(--font-mono); font-size: 10px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 10px; }
.summary-text { font-size: 14px; color: var(--muted); line-height: 1.75; }
.pros-cons-block { background: var(--bg2); padding: 22px; }
.pros-cons-title { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 14px; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
.pros-cons-title.pros { color: var(--green); }
.pros-cons-title.cons { color: var(--red); }
.pros-cons-item { display: flex; align-items: flex-start; gap: 10px; padding: 8px 0; font-size: 13px; color: var(--muted); line-height: 1.45; border-bottom: 1px solid var(--border); }
.pros-cons-item:last-child { border-bottom: none; }
.pros-cons-icon { font-size: 11px; flex-shrink: 0; margin-top: 2px; }
.pros-cons-icon.pro { color: var(--green); }
.pros-cons-icon.con { color: var(--red); }
.related-section { padding: 48px 0; border-top: 1px solid var(--border); }
.related-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); margin-top: 20px; }
.related-card { background: var(--bg); padding: 20px; cursor: pointer; transition: background 0.2s; }
.related-card:hover { background: var(--card); }
.related-card-cat { font-family: var(--font-mono); font-size: 10px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 4px; }
.related-card-name { font-family: var(--font-display); font-size: 20px; font-weight: 800; text-transform: uppercase; color: var(--text); line-height: 1.05; margin-bottom: 2px; }
.related-card-brand { font-family: var(--font-mono); font-size: 10px; color: var(--muted); margin-bottom: 12px; }
.related-card-footer { display: flex; align-items: center; justify-content: space-between; padding-top: 10px; border-top: 1px solid var(--border); }
.related-card-price { font-family: var(--font-display); font-size: 18px; font-weight: 900; color: var(--text); }
.related-score { font-family: var(--font-display); font-size: 18px; font-weight: 900; color: var(--amber); }

/* ── HOMEPAGE ── */

/* Hero — full-viewport cinematic cover */
.hero-cover { position: relative; height: calc(100vh - 62px); min-height: 480px; max-height: 900px; overflow: hidden; background: var(--bg); }
.hero-cover-media { position: absolute; inset: 0; cursor: pointer; will-change: transform; }
.hero-cover-media img, .hero-cover-media svg { display: block; width: 100%; height: 100%; object-fit: cover; transform: scale(1.08); transition: transform 2s cubic-bezier(.16,.8,.3,1); }
.hero-cover.hero-ready .hero-cover-media img, .hero-cover.hero-ready .hero-cover-media svg { transform: scale(1); }
.hero-cover-scrim { position: absolute; inset: 0; background: linear-gradient(to top, rgba(10,10,11,0.96) 0%, rgba(10,10,11,0.6) 40%, rgba(10,10,11,0.1) 70%, transparent 100%); pointer-events: none; }
.hero-cover-content { position: absolute; left: 0; right: 0; bottom: 0; padding-bottom: 64px; }
.hero-cover-inner { cursor: pointer; max-width: 780px; }
.hero-eyebrow { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 11px; font-weight: 500; color: var(--amber); text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 16px; }
.hero-eyebrow::before { content: ''; width: 24px; height: 1px; background: var(--amber); }
.hero-title { font-family: var(--font-display); font-size: clamp(40px, 6vw, 68px); font-weight: 900; line-height: 0.95; letter-spacing: -1px; color: var(--text); margin-bottom: 18px; text-transform: uppercase; }
.hero-meta { display: flex; align-items: center; gap: 16px; font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
.hero-meta-dot { width: 3px; height: 3px; background: var(--muted); border-radius: 50%; }
/* Desktop's overlay has little vertical room to spare over the image, so
   the excerpt is mobile-only (see the ≤768px block below, where the
   split layout's content panel has real space for it). */
.hero-excerpt { display: none; }

/* Entrance — gated on the JS-added .hero-ready class rather than a
   fire-on-load animation, since the text is populated async after the
   article fetch resolves. */
.hero-eyebrow, .hero-title, .hero-excerpt, .hero-meta { opacity: 0; transform: translateY(24px); transition: opacity 0.9s cubic-bezier(.16,.8,.3,1), transform 0.9s cubic-bezier(.16,.8,.3,1); }
.hero-cover.hero-ready .hero-eyebrow { transition-delay: 0.15s; }
.hero-cover.hero-ready .hero-title { transition-delay: 0.3s; }
.hero-cover.hero-ready .hero-excerpt { transition-delay: 0.42s; }
.hero-cover.hero-ready .hero-meta { transition-delay: 0.5s; }
.hero-cover.hero-ready .hero-eyebrow,
.hero-cover.hero-ready .hero-title,
.hero-cover.hero-ready .hero-excerpt,
.hero-cover.hero-ready .hero-meta { opacity: 1; transform: translateY(0); }

/* Scroll cue */
.hero-scroll-cue { position: absolute; left: 50%; bottom: 24px; transform: translateX(-50%); width: 22px; height: 36px; border: 1.5px solid rgba(255,255,255,0.4); border-radius: 12px; opacity: 0; transition: opacity 1s ease 0.9s; }
.hero-cover.hero-ready .hero-scroll-cue { opacity: 1; }
.hero-scroll-cue span { position: absolute; top: 6px; left: 50%; width: 3px; height: 7px; background: rgba(255,255,255,0.7); border-radius: 2px; transform: translateX(-50%); animation: scrollCueBob 1.8s ease infinite; }
@keyframes scrollCueBob { 0%, 100% { transform: translate(-50%,0); opacity: 1; } 60% { transform: translate(-50%,10px); opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  .hero-cover-media img, .hero-cover-media svg,
  .hero-eyebrow, .hero-title, .hero-meta,
  .hero-scroll-cue span { transition: none; animation: none; opacity: 1; transform: none; }
}

@media (max-width: 768px) {
  /* Split layout: text-over-image (desktop's approach) forces a choice
     between a tall portrait crop of a landscape photo (ugly) or a short
     image with cramped overlaid text (also ugly) — there's no crop that
     makes a 1.54:1 image look good under overlaid text on a 1:2 screen.
     Splitting the image and text into two stacked blocks sidesteps the
     problem entirely: the image keeps its own natural aspect ratio
     (800/520, same as the artSVG fallback / CMS "large" format) with no
     forced cropping, and the text sits below on a normal solid
     background where it has as much room as it needs. Grid (not the
     image being absolutely positioned) is what makes this work: media
     and scrim share one grid cell sized by the image's aspect ratio,
     content flows in the row below it. */
  .hero-cover { height: auto; display: grid; grid-template-columns: 1fr; grid-template-rows: auto auto; overflow: visible; }
  .hero-cover-media, .hero-cover-scrim { position: static; inset: auto; grid-row: 1; grid-column: 1; aspect-ratio: 800 / 520; width: 100%; }
  /* Text no longer sits on the image, so the heavy legibility gradient
     isn't needed — just enough of a fade at the very bottom to blend the
     image's edge into the content panel's background rather than a hard
     seam. */
  .hero-cover-scrim { background: linear-gradient(to bottom, transparent 82%, var(--bg) 100%); }
  .hero-cover-content { position: static; grid-row: 2; grid-column: 1; padding: 26px 0 40px; }
  .hero-cover-inner { max-width: none; }
  .hero-excerpt { display: -webkit-box; font-family: var(--font-body); font-size: 15px; line-height: 1.5; color: var(--muted); margin: 0 0 18px; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
  /* Scroll cue collided with the meta line on short mobile viewports once a
     long headline wrapped to 3-4 lines — mobile doesn't need a scroll hint
     anyway (swipe-to-scroll is the default gesture), so just drop it. */
  .hero-scroll-cue { display: none; }
}

/* Cross-category mosaic — scroll-scrubbed reveal, desktop.
   The reveal (opacity/scale/rise, see soundb.html's update()) is driven by
   scroll through the HERO above this section, finishing right as the
   section scrolls into view. Earlier versions pinned this section
   (position:sticky) with a tall wrapper to hold the viewport still while
   the reveal played out — but once the reveal moved to happen entirely
   during the hero scroll (per repeated "make it visible earlier" rounds),
   the pin no longer had any reveal left to hold for: the wrapper's extra
   scroll room past the pin's own height was, by definition, scroll input
   with nothing left to animate — dead space between the progress bar
   hitting 100% and the footer arriving, no matter how much that room got
   trimmed. Removing the pin outright removes the dead space at the root:
   the section is fully assembled by the time it scrolls into view, then
   flows straight into whatever comes next like a normal section — no held
   frame, no extra scroll runway required. Cell opacity/transform are
   still set directly via JS inline styles on every scroll frame (no CSS
   transition) so the motion is 1:1 with scroll position while it's
   assembling, during the hero scroll. */
.mosaic-scroll-wrap { position: relative; }
.mosaic-pin { padding: 40px 0; background: var(--bg); box-sizing: border-box; }
.mosaic-container { display: flex; flex-direction: column; min-height: 0; }
.mosaic-heading { flex-shrink: 0; display: flex; align-items: center; justify-content: space-between; gap: 24px; padding-bottom: 24px; }
.mosaic-eyebrow { font-family: var(--font-mono); font-size: 11px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.14em; display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.mosaic-eyebrow::before { content: ''; width: 20px; height: 1px; background: var(--amber); }
/* 6x3 track (rather than 4x3) gives finer control for genuine large /
   medium / small variety instead of "1 large + 4 identical" — see the
   per-cell spans below. Increased gap (14px → 26px) for a more premium,
   less-cramped rhythm between cells. */
/* 8x6 track, FULLY tessellating (every cell assigned, no unassigned
   gutter tracks) — asymmetry comes purely from genuinely different cell
   sizes (large/medium/small/small/bottom/bottom — two half-width cells
   along the bottom instead of one spanning the full width), not from
   irregular empty space, so the gap between any two touching cells is
   always exactly one `gap`, never
   stretched wider by a gutter track sitting between them. */
/* Explicit height (not flex:1) — .mosaic-cell's children are all
   position:absolute (media/scrim/body layered on top of each other), so
   the cells themselves have no intrinsic content height, and without the
   old pinned-to-100vh ancestor chain giving this a computed height to
   fill, flex:1 against a now-unsized parent would collapse the whole grid
   to 0px. min()/vh keeps it substantial on tall screens while staying
   reasonable on short ones, without needing the section to be pinned. */
.mosaic-grid { min-height: 0; height: min(700px, 78vh); display: grid; grid-template-columns: repeat(8, 1fr); grid-template-rows: repeat(6, 1fr); gap: 24px; }
.mosaic-cell { position: relative; overflow: hidden; background: var(--bg2); cursor: pointer; opacity: 1; will-change: transform, opacity; }
.mosaic-cell:nth-child(1) { grid-column: 1 / 5; grid-row: 1 / 6; }   /* large — featured, half width, most of the height */
.mosaic-cell:nth-child(2) { grid-column: 5 / 9; grid-row: 1 / 4; }   /* medium — top right */
/* The remaining 4 cells are wrapped in .mosaic-outer-row (see
   renderMosaic) so mobile can turn them into a horizontal scroller —
   display:contents here keeps desktop's CSS Grid placement working
   exactly as if they were still direct, unwrapped grid children. */
.mosaic-outer-row { display: contents; }
.mosaic-outer-row .mosaic-cell:nth-child(1) { grid-column: 5 / 7; grid-row: 4 / 6; }   /* small */
.mosaic-outer-row .mosaic-cell:nth-child(2) { grid-column: 7 / 9; grid-row: 4 / 6; }   /* small */
.mosaic-outer-row .mosaic-cell:nth-child(3) { grid-column: 1 / 5; grid-row: 6 / 7; }   /* bottom-left, short */
.mosaic-outer-row .mosaic-cell:nth-child(4) { grid-column: 5 / 9; grid-row: 6 / 7; }   /* bottom-right, short */
.mosaic-cell-media { position: absolute; inset: 0; transition: transform 0.5s ease; }
.mosaic-cell:hover .mosaic-cell-media { transform: scale(1.04); }
.mosaic-cell-media img, .mosaic-cell-media svg { width: 100%; height: 100%; object-fit: cover; display: block; }
.mosaic-cell-scrim { position: absolute; inset: 0; background: linear-gradient(to top, rgba(10,10,11,0.92) 0%, rgba(10,10,11,0.35) 55%, transparent 100%); }
.mosaic-cell-body { position: absolute; left: 0; right: 0; bottom: 0; padding: 18px; }
.mosaic-cell-cat { font-family: var(--font-mono); font-size: 9px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 6px; }
.mosaic-cell-title { font-family: var(--font-display); font-size: 15px; font-weight: 800; text-transform: uppercase; line-height: 1.15; color: var(--text); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.mosaic-cell-meta { font-family: var(--font-mono); font-size: 9px; color: var(--muted); margin-top: 8px; }
.mosaic-featured .mosaic-cell-title { font-size: 26px; -webkit-line-clamp: 3; }
.mosaic-featured .mosaic-cell-body { padding: 28px; }
/* Small cells are genuinely small (~1/4 width x 1/3 height of the grid) —
   the default 18px padding + 15px title left barely any room, so this
   tier scales both down to fit comfortably instead of clipping/wrapping
   awkwardly. */
.mosaic-small .mosaic-cell-body { padding: 12px; }
.mosaic-small .mosaic-cell-cat { font-size: 8px; margin-bottom: 4px; }
.mosaic-small .mosaic-cell-title { font-size: 12px; line-height: 1.2; -webkit-line-clamp: 2; }
.mosaic-small .mosaic-cell-meta { font-size: 8px; margin-top: 4px; }
/* Bottom cells are short vertically (1/6 of grid height) but each still
   has half the full width to work with — enough room for most titles on
   one line, with a 2-line fallback for longer ones rather than clipping. */
.mosaic-bottom .mosaic-cell-body { padding: 14px 20px; }
.mosaic-bottom .mosaic-cell-title { font-size: 14px; line-height: 1.2; -webkit-line-clamp: 2; }
.mosaic-bottom .mosaic-cell-meta { margin-top: 4px; }

/* Mobile / reduced-motion fallback — no pinning, no shared-timeline
   scroll-scrub (scroll-jacking reads as janky on touch devices). Each
   cell instead fades up relative to its own scroll position (see
   initMosaicScrub's staticUpdate) — opacity/transform are set inline by
   JS every frame, same mechanism as the desktop scrub, so no CSS
   transition or reveal class is needed here. */
.mosaic-scroll-wrap.mosaic-static { height: auto; }
.mosaic-scroll-wrap.mosaic-static .mosaic-pin { position: static; height: auto; overflow: visible; padding: 48px 0; }
.mosaic-scroll-wrap.mosaic-static .mosaic-grid { display: flex; flex-direction: column; gap: 20px; height: auto; }
.mosaic-scroll-wrap.mosaic-static .mosaic-cell { grid-column: unset !important; grid-row: unset !important; height: 260px; }
.mosaic-scroll-wrap.mosaic-static .mosaic-featured { height: 320px; }
/* The small/bottom cells stop stacking after the featured+list slots and
   become a horizontally-scrollable row instead — .mosaic-outer-row
   switches from desktop's display:contents to a real flex row here, with
   its own scroll container. Cards are narrow again at this width, so the
   compact small/bottom typography (defined further up, unchanged) is
   already the right size — no full-width override needed. */
.mosaic-scroll-wrap.mosaic-static .mosaic-outer-row {
  display: flex;
  flex-direction: row;
  gap: 14px;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  margin: 0 -16px;
  padding: 0 16px 4px;
  /* Without this, a horizontal swipe that starts inside this carousel
     can "leak" into a page-level drag/bounce once the carousel hits its
     own scroll limit — contain keeps the gesture local to the row. */
  overscroll-behavior-x: contain;
}
.mosaic-scroll-wrap.mosaic-static .mosaic-outer-row::-webkit-scrollbar { display: none; }
.mosaic-scroll-wrap.mosaic-static .mosaic-outer-row .mosaic-cell {
  flex: 0 0 220px;
  height: 220px;
  scroll-snap-align: start;
}
/* The medium slot holds 4 stacked text items, not one image — squeezing
   it into the same fixed height as a single-image cell (280px ÷ 4 ≈ 70px
   each) left no room for the restored 15px/2-line titles above, and every
   title clipped mid-word. Let it size to its actual content instead: the
   wrapper grows to fit, and each item takes its natural height rather
   than being forced to share a fixed total equally. */
.mosaic-scroll-wrap.mosaic-static .mosaic-medium.mosaic-list { height: auto; }
.mosaic-scroll-wrap.mosaic-static .mosaic-list-item { flex: none; }

@media (prefers-reduced-motion: reduce) {
  .mosaic-cell-media { transition: none; }
}

/* Tablet — the pinned scroll-scrub grid is still active here (the JS
   switches to the static stacked fallback at ≤768px), so the 8-col track
   just needs a tighter gap and smaller type to stay legible at these
   narrower widths rather than a structural change. */
@media (max-width: 1024px) {
  .mosaic-grid { gap: 18px; }
  .mosaic-featured .mosaic-cell-title { font-size: 21px; }
  .mosaic-cell-title { font-size: 13px; }
  .mosaic-cell-body { padding: 14px; }
  .mosaic-featured .mosaic-cell-body { padding: 20px; }
  .mosaic-small .mosaic-cell-body { padding: 10px; }
  .mosaic-small .mosaic-cell-title { font-size: 11px; }
  .mosaic-bottom .mosaic-cell-title { font-size: 12px; }
}

/* ── Mosaic "medium" slot as a text-only list instead of one
   image-backed article — 4 compact rows (badge/title/byline), no media,
   no scrim, stacked to fill the same grid area the single image cell
   used to occupy. */
/* Excluded from the mosaic's shared scroll-scrub timeline (see
   initMosaicScrub) — always visible, so it never dims the 4 list items
   below, which each independently control their own visibility. */
.mosaic-medium.mosaic-list { background: none; display: flex; flex-direction: column; opacity: 1; }
/* flex-basis:auto (not the flex:1 shorthand's implicit 0%) — a 2-line
   title needs more natural height than a 1-line one, and flex:1 forces
   every item to the exact same equal-fraction height regardless, clipping
   whichever item's content happens to need more than its equal share.
   Sizing from each item's own content first, then letting flex-grow only
   distribute genuinely leftover space, fixes that without giving up the
   "fill the panel" behavior for the common case (all short titles). */
.mosaic-list-item { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; justify-content: center; padding: 10px 22px; border-top: 1px solid var(--border); cursor: pointer; will-change: transform, opacity; }
.mosaic-list-item:first-child { border-top: none; }
.mosaic-list-badge { display: inline-block; align-self: flex-start; font-family: var(--font-mono); font-size: 8px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; padding: 2px 7px; border: 1px solid rgba(255,140,0,0.35); background: rgba(255,140,0,0.08); color: var(--amber); margin-bottom: 6px; }
.mosaic-list-title { font-family: var(--font-display); font-size: 14px; font-weight: 800; text-transform: uppercase; line-height: 1.15; color: var(--text); margin-bottom: 4px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; transition: color 0.15s; }
.mosaic-list-item:hover .mosaic-list-title { color: var(--amber); }
.mosaic-list-meta { font-family: var(--font-mono); font-size: 9px; color: var(--muted); }

@media (max-width: 1024px) {
  .mosaic-list-title { font-size: 12px; }
  .mosaic-list-item { padding: 8px 16px; }
}

/* ── All News CTA — simple bridge from the mosaic into soundb-news.html.
   Same small plain-text treatment as .review-card-cta ("Read review →")
   elsewhere on the site — no hover/magnetic effects. ── */
.all-news-wrap { padding: 48px 0; text-align: center; }
.all-news-cta { font-family: var(--font-display); font-size: 11px; font-weight: 700; text-transform: uppercase; color: var(--amber); letter-spacing: 0.06em; transition: opacity 0.2s; }
.all-news-cta:hover { opacity: 0.7; }

/* ── Gear Launch — full-width cross-pillar section (wider shell than the
   standard 1320px .container, on purpose). Left: featured new-launch
   gear with a generated waveform behind the photo, curated feature
   highlights from real spec data, and a pull-quote. Right: rich review
   teasers + a clearly-labeled ad slot. ── */
.gear-launch-wrap { padding: 64px 0; border-top: 1px solid var(--border); }
.gear-launch-shell { max-width: 1680px; margin: 0 auto; padding: 0 40px; box-sizing: border-box; }
.gear-launch-grid { display: grid; grid-template-columns: 1fr 360px; gap: 48px; align-items: start; }

.gl-eyebrow-row { display: flex; align-items: center; gap: 16px; margin-bottom: 24px; }
.gl-eyebrow { font-family: var(--font-mono); font-size: 12px; font-weight: 700; color: var(--amber); text-transform: uppercase; letter-spacing: 0.16em; white-space: nowrap; }
.gl-eyebrow-row::after { content: ''; flex: 1; height: 1px; background: var(--border); }

/* Text info and photo sit side by side in one row — not stacked full-
   width blocks — matching the reference layout exactly. .gl-info takes
   the narrower left share, .gl-visual fills the rest. */
.gl-top-row { display: flex; gap: 44px; align-items: stretch; margin-bottom: 36px; }
.gl-info { flex: 0 0 40%; min-width: 0; display: flex; flex-direction: column; justify-content: center; }

.gl-badge { display: inline-block; align-self: flex-start; font-family: var(--font-mono); font-size: 11px; font-weight: 700; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; border: 1px solid rgba(255,140,0,0.4); background: rgba(255,140,0,0.06); padding: 7px 16px; margin-bottom: 18px; }

.gl-title { display: flex; flex-direction: column; margin-bottom: 8px; }
.gl-brand-name, .gl-product-name { font-family: var(--font-display); font-size: clamp(28px, 2.6vw, 40px); font-weight: 900; text-transform: uppercase; line-height: 1.05; letter-spacing: -0.5px; }
.gl-brand-name { color: var(--text); }
.gl-product-name { color: var(--amber); }
.gl-subtitle { font-family: var(--font-mono); font-size: 13px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 18px; }
.gl-desc { font-family: var(--font-body); font-size: 14px; line-height: 1.7; color: var(--muted); margin-bottom: 0; }

/* Badge/title/subtitle/desc each slide up individually — staggered via
   window.initScrollReveal(selector, {stagger}) so title arrives, then
   subtitle, then desc, rather than the whole block moving as one. */
.gl-info-reveal.reveal { transform: translateY(24px); }
.gl-info-reveal.reveal.is-visible { transform: translateY(0); }

.gl-visual { position: relative; flex: 1; min-width: 0; aspect-ratio: 4/3; overflow: hidden; display: flex; align-items: center; justify-content: center; }
/* Image rotates in alongside the text — same reveal toggle, its own
   transform (tilt + settle) and a slightly longer transition for the
   rotation to read distinctly from the plain text slide-up. */
.gl-visual.reveal { opacity: 0; transform: translateY(26px) rotate(-7deg) scale(0.92); transition: opacity 0.8s cubic-bezier(.16,.8,.3,1), transform 0.9s cubic-bezier(.16,.8,.3,1); }
.gl-visual.reveal.is-visible { opacity: 1; transform: translateY(0) rotate(0deg) scale(1); }
.gl-photo { position: relative; z-index: 1; width: 82%; height: 78%; display: flex; align-items: center; justify-content: center; }
.gl-photo > svg, .gl-photo-main { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; display: block; filter: drop-shadow(0 20px 40px rgba(0,0,0,0.5)); position: relative; z-index: 1; }
/* Subtle blurred contact-shadow, not a mirrored duplicate — a soft dark
   ellipse near the base suggesting the product resting on a glass
   surface. Sits behind the photo (z-index:0 vs. the photo's 1) and low
   enough in .gl-photo that it reads as "under" rather than overlapping
   the product itself. Position is a best-effort estimate (object-fit:
   contain doesn't expose where the image's own visible pixels end), not
   pixel-tied to any specific photo's silhouette. */
.gl-photo-shadow { position: absolute; z-index: 0; left: 50%; bottom: 4%; transform: translateX(-50%); width: 55%; height: 22px; background: radial-gradient(ellipse at center, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.22) 50%, transparent 75%); filter: blur(6px); pointer-events: none; }

.gl-features { display: flex; flex-wrap: wrap; gap: 28px; padding-bottom: 32px; margin-bottom: 32px; border-bottom: 1px solid var(--border); }
.gl-feature { display: flex; align-items: flex-start; gap: 12px; flex: 1 1 160px; min-width: 140px; }
/* Each feature reveals individually — window.initScrollReveal() staggers
   transitionDelay per element so they appear one after another. */
.gl-feature.reveal { transform: translateY(18px); }
.gl-feature.reveal.is-visible { transform: translateY(0); }
.gl-feature-icon { flex-shrink: 0; width: 38px; height: 38px; border-radius: 50%; border: 1px solid rgba(255,140,0,0.35); background: rgba(255,140,0,0.06); display: flex; align-items: center; justify-content: center; color: var(--amber); }
.gl-feature-icon svg { width: 18px; height: 18px; }
.gl-feature-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.gl-feature-text strong { font-family: var(--font-body); font-size: 13px; font-weight: 700; color: var(--text); line-height: 1.3; }
.gl-feature-text span { font-family: var(--font-mono); font-size: 11px; color: var(--muted); line-height: 1.4; }

.gl-quote { position: relative; display: flex; align-items: center; gap: 24px; background: var(--bg2); border-left: 2px solid var(--amber); padding: 24px 28px; margin-bottom: 32px; }
.gl-quote-mark { font-family: var(--font-display); font-size: 40px; color: var(--amber); line-height: 1; flex-shrink: 0; }
.gl-quote p { font-family: var(--font-body); font-style: italic; font-size: 15px; line-height: 1.6; color: var(--text); flex: 1; min-width: 0; margin: 0; }
.gl-quote-wave { display: flex; align-items: center; gap: 3px; height: 32px; flex-shrink: 0; width: 180px; }
.gl-quote-wave span { flex: 1; min-width: 1px; max-width: 1px; background: var(--amber); border-radius: 1px; box-shadow: 0 0 3px rgba(255,140,0,0.9), 0 0 7px rgba(255,140,0,0.5); }

.gl-cta-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.gl-cta-btn { display: inline-flex; align-items: center; gap: 8px; background: var(--amber); color: #000; font-family: var(--font-display); font-size: 13px; font-weight: 900; text-transform: uppercase; letter-spacing: 0.04em; padding: 15px 28px; transition: background 0.2s, border-color 0.2s, color 0.2s; }
.gl-cta-btn:hover { background: var(--amber2); }
.gl-cta-btn-outline { background: none; border: 1px solid var(--amber); color: var(--amber); }
.gl-cta-btn-outline:hover { background: rgba(255,140,0,0.08); color: var(--amber2); }
.gl-cta-soon { font-family: var(--font-mono); font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; border: 1px dashed var(--border2); padding: 15px 20px; }

/* ── Sidebar: reviews teaser + ad ── */
.gl-side { display: flex; flex-direction: column; gap: 24px; }
.gl-reviews-card { border: 1px solid var(--border); padding: 20px; }
.gl-reviews-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.gl-reviews-title { display: flex; align-items: center; gap: 8px; font-family: var(--font-display); font-size: 13px; font-weight: 900; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text); }
.gl-mini-wave { width: 16px; height: 16px; fill: var(--amber); }
.gl-viewall { font-family: var(--font-mono); font-size: 10px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.06em; transition: opacity 0.2s; }
.gl-viewall:hover { opacity: 0.7; }
.gl-reviews-list { display: flex; flex-direction: column; }
.gl-review-item { display: flex; align-items: flex-start; gap: 12px; padding: 14px 0; border-bottom: 1px solid var(--border); }
.gl-review-item:first-child { padding-top: 0; }
.gl-review-item:last-child { border-bottom: none; padding-bottom: 0; }
.gl-review-thumb { flex-shrink: 0; width: 56px; height: 56px; background: var(--bg3); overflow: hidden; }
.gl-review-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.gl-review-cat { font-family: var(--font-mono); font-size: 9px; font-weight: 700; color: var(--amber); text-transform: uppercase; letter-spacing: 0.1em; }
.gl-review-name { font-family: var(--font-display); font-size: 13px; font-weight: 800; text-transform: uppercase; color: var(--text); line-height: 1.2; transition: color 0.15s; }
.gl-review-item:hover .gl-review-name { color: var(--amber); }
.gl-review-hook { font-family: var(--font-body); font-size: 11px; color: var(--muted); line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.gl-explore-btn { display: block; text-align: center; margin-top: 16px; border: 1px solid var(--border2); font-family: var(--font-display); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text); padding: 12px; transition: border-color 0.2s, color 0.2s; }
.gl-explore-btn:hover { border-color: var(--amber); color: var(--amber); }

/* Ad slot — the "Advertisement" label is intentionally plain text, no
   card styling, so it never reads as part of the content it's labeling
   (AdSense policy requires ads to be clearly distinguishable). */
/* display:flex + flex-basis (not height) on the mount is deliberate:
   Google's AdSense "auto, full-width-responsive" format injects
   style="height:auto !important;max-height:none !important" onto its own
   ancestor elements once it initializes (confirmed by inspecting the live
   DOM on soundb-learn.html's ad slot, where this exact pattern was
   diagnosed) — any height/max-height set here is a no-op against that,
   no matter the specificity. flex-basis is a channel Google's script never
   touches, so sizing through it instead sidesteps the override entirely.
   250px preserves this slot's original intended height exactly. */
.gl-ad-card { display: flex; flex-direction: column; }
.gl-ad-label { font-family: var(--font-mono); font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 10px; text-align: center; }
#gl-ad-mount { flex: 0 0 250px; overflow: hidden; }

@media (max-width: 1200px) {
  .gear-launch-grid { grid-template-columns: 1fr 300px; gap: 32px; }
  .gl-features { gap: 20px; }
}
@media (max-width: 1024px) {
  .gear-launch-grid { grid-template-columns: 1fr; }
  .gl-side { flex-direction: row; align-items: stretch; }
  .gl-reviews-card, .gl-ad-card { flex: 1; min-width: 0; }
  /* .gl-info's 40% flex-basis gets too cramped for the description text
     once the main column itself has already narrowed to full-page width
     — stack photo below text instead of squeezing both sideways. */
  .gl-top-row { flex-direction: column; gap: 28px; }
  .gl-info { flex: none; }
  .gl-desc { max-width: 560px; }
}
@media (max-width: 768px) {
  .gear-launch-shell { padding: 0 16px; }
  .gear-launch-wrap { padding: 44px 0; }
  .gl-visual { aspect-ratio: 4/3; order: -1; }
  .gl-features { flex-wrap: wrap; gap: 20px 14px; border-bottom: none; padding-bottom: 0; }
  .gl-feature { flex: 0 0 calc(50% - 7px); min-width: 0; }
  .gl-quote { flex-direction: column; align-items: flex-start; gap: 16px; }
  .gl-quote-wave { width: 100%; }
  .gl-side { flex-direction: column; }
}

/* ── Go Deeper — Watch + Learn cross-promo, between Gear Launch and
   Newsletter. Watch is the wide image-led panel (video needs a real
   thumbnail to read as inviting); Learn is the narrower text-led list —
   same asymmetry Gear Launch uses between its photo and sidebar teaser.
   Eyebrow+rule header matches the mosaic's "Across Soundb"; hairline-
   divided rows (no boxes) match the de-carded review cards and Gear
   Launch's own feature list — no new visual language introduced. ── */
.go-deeper-wrap { padding: 64px 0; border-top: 1px solid var(--border); }
.gd-head { display: flex; align-items: center; gap: 16px; margin-bottom: 32px; }
.gd-eyebrow { font-family: var(--font-mono); font-size: 12px; font-weight: 700; color: var(--amber); text-transform: uppercase; letter-spacing: 0.16em; white-space: nowrap; }
.gd-head::after { content: ''; flex: 1; height: 1px; background: var(--border); }

.gd-grid { display: grid; grid-template-columns: 1.65fr 1fr; gap: 48px; align-items: stretch; }

/* — Watch — */
.gd-watch { position: relative; display: flex; flex-direction: column; cursor: pointer; }
.gd-watch-media { position: relative; display: block; aspect-ratio: 16/9; overflow: hidden; background: #1c130a; }
.gd-watch-art { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.5s cubic-bezier(.16,.8,.3,1); }
.gd-watch-media:hover .gd-watch-art { transform: scale(1.035); }
.gd-watch-scrim { position: absolute; inset: 0; background: linear-gradient(to top, rgba(10,10,11,0.92) 0%, rgba(10,10,11,0.35) 55%, rgba(10,10,11,0.05) 80%, transparent 100%); }
.gd-play { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); width: 64px; height: 64px; border-radius: 50%; border: 1.5px solid rgba(240,237,230,0.6); background: rgba(10,10,11,0.35); backdrop-filter: blur(3px); display: flex; align-items: center; justify-content: center; transition: border-color 0.2s, background 0.2s, transform 0.2s; }
.gd-watch-media:hover .gd-play { border-color: var(--amber); background: rgba(255,140,0,0.12); transform: translate(-50%,-50%) scale(1.06); }
.gd-play svg { width: 20px; height: 20px; fill: var(--text); margin-left: 3px; transition: fill 0.2s; }
.gd-watch-media:hover .gd-play svg { fill: var(--amber2); }
/* Ring traces itself in on hover — cheap, single-accent, matches the
   restrained micro-interaction language used for .gl-cta-btn etc. */
.gd-play::before { content: ''; position: absolute; inset: -1.5px; border-radius: 50%; border: 1.5px solid var(--amber); opacity: 0; transform: scale(0.85); transition: opacity 0.3s, transform 0.4s cubic-bezier(.16,.8,.3,1); }
.gd-watch-media:hover .gd-play::before { opacity: 1; transform: scale(1); }

.gd-watch-text { position: absolute; left: 0; right: 0; bottom: 0; padding: 22px 26px; }
.gd-watch-eyebrow { font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; color: var(--amber); text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 8px; display: block; }
.gd-watch-title { font-family: var(--font-display); font-weight: 800; text-transform: uppercase; font-size: clamp(22px, 2.4vw, 30px); line-height: 1.05; letter-spacing: -0.3px; color: var(--text); margin: 0 0 10px; max-width: 85%; }
.gd-watch-meta { font-family: var(--font-mono); font-size: 11px; color: var(--muted); letter-spacing: 0.04em; }

.gd-watch-foot { display: flex; align-items: center; justify-content: space-between; padding-top: 16px; }
.gd-watch-cta { font-family: var(--font-display); font-size: 12px; font-weight: 700; text-transform: uppercase; color: var(--amber); letter-spacing: 0.04em; transition: opacity 0.2s; }
.gd-watch-cta:hover { opacity: 0.75; }
.gd-watch-sub { font-family: var(--font-mono); font-size: 10.5px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; transition: color 0.2s; }
.gd-watch-sub:hover { color: var(--amber); }

/* — Learn — */
.gd-learn { display: flex; flex-direction: column; }
.gd-learn-title { font-family: var(--font-display); font-size: 19px; font-weight: 800; text-transform: uppercase; letter-spacing: -0.2px; color: var(--text); margin: 0 0 4px; }
.gd-learn-sub { font-family: var(--font-body); font-size: 12.5px; color: var(--muted); margin: 0 0 18px; line-height: 1.5; }

.gd-lessons { display: flex; flex-direction: column; flex: 1; }
.gd-lesson { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 15px 0; border-top: 1px solid var(--border); cursor: pointer; transition: padding-left 0.2s; }
.gd-lesson:last-of-type { border-bottom: 1px solid var(--border); }
.gd-lesson:hover { padding-left: 6px; }
.gd-lesson-body { min-width: 0; }
.gd-lesson-tags { font-family: var(--font-mono); font-size: 9.5px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 5px; display: block; }
.gd-lesson-tags span:first-child { color: var(--amber); }
.gd-lesson-tags .dot { margin: 0 6px; opacity: 0.5; }
.gd-lesson-name { font-family: var(--font-body); font-size: 14px; font-weight: 600; color: var(--text); line-height: 1.35; transition: color 0.2s; }
.gd-lesson:hover .gd-lesson-name { color: var(--amber2); }
.gd-lesson-arrow { flex-shrink: 0; color: var(--muted); font-family: var(--font-mono); font-size: 15px; transition: color 0.2s, transform 0.2s; }
.gd-lesson:hover .gd-lesson-arrow { color: var(--amber); transform: translateX(3px); }

.gd-learn-cta { display: block; margin-top: 20px; text-align: center; border: 1px solid var(--border2); font-family: var(--font-display); font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text); padding: 13px; transition: border-color 0.2s, color 0.2s; }
.gd-learn-cta:hover { border-color: var(--amber); color: var(--amber); }

/* Ad slot — same convention as Gear Launch's .gl-ad-card, sized for
   this narrower column. flex-basis (not height) on the mount for the same
   reason documented on .gl-ad-card above — sidesteps Google's own
   ancestor-targeting inline style override. 150px preserves this slot's
   original intended height exactly. */
.gd-ad-card { margin-top: 24px; display: flex; flex-direction: column; }
.gd-ad-label { font-family: var(--font-mono); font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 10px; text-align: center; }
#gd-ad-mount { flex: 0 0 150px; overflow: hidden; }

/* Text/media reveal on scroll-in, same one-shot .reveal/.is-visible
   toggle and rotate-settle treatment as Gear Launch's .gl-visual — the
   rotation direction is flipped (+ instead of -) so it rhymes with,
   rather than copies, the section just above it. */
.gd-watch.reveal { transform: translateY(24px); }
.gd-watch.reveal.is-visible { transform: translateY(0); }
.gd-watch-media.reveal { opacity: 0; transform: rotate(5deg) scale(0.93); transition: opacity 0.8s cubic-bezier(.16,.8,.3,1), transform 0.9s cubic-bezier(.16,.8,.3,1); }
.gd-watch-media.reveal.is-visible { opacity: 1; transform: rotate(0deg) scale(1); }
.gd-learn.reveal { transform: translateY(24px); }
.gd-learn.reveal.is-visible { transform: translateY(0); }
.gd-lesson.reveal { opacity: 0; transform: translateY(16px); }
.gd-lesson.reveal.is-visible { opacity: 1; transform: translateY(0); }

@media (max-width: 900px) {
  .gd-grid { grid-template-columns: 1fr; }
}
@media (max-width: 768px) {
  .go-deeper-wrap { padding: 44px 0; }
}

/* ── Homepage Featured Review — built from window.renderReviewTrio()/
   window.renderReviewRelated() in soundb-utils.js (not duplicated here
   in case another page wants the same panels later). ── */
.featured-review-wrap { padding: 64px 0; border-top: 1px solid var(--border); }
.fr-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 32px; }
.fr-eyebrow { font-family: var(--font-mono); font-size: 12px; font-weight: 700; color: var(--amber); text-transform: uppercase; letter-spacing: 0.16em; white-space: nowrap; }

/* Review "trio" (About the Artist / Review Highlights / Behind the
   Song), Related Reviews carousel, and Feature Your Music promo.
   Table-less by design: three open columns separated by whitespace, one
   thin rule under the row instead of a bordered grid. Each sub-element
   hides individually when its field is empty, so a review with none of
   the new fields filled in just shows Highlights (built from data that
   already existed) and nothing else. */
.rv-trio-wrap { max-width: 1080px; margin: 0 auto; padding: 0 0 32px; }
.rv-trio { display: grid; grid-template-columns: 200px 1fr 300px; gap: 40px; padding-bottom: 28px; border-bottom: 1px solid var(--border); }
.rv-trio-title { font-family: var(--font-mono); font-size: 9px; color: var(--amber); text-transform: uppercase; letter-spacing: .16em; margin-bottom: 14px; display: flex; align-items: center; gap: 8px; }
.rv-trio-title::before { content: ''; width: 14px; height: 1px; background: var(--amber); }

/* Featured Song — square art + streaming links, in the slot About the
   Artist used to occupy. */
.rv-feat-art { position: relative; width: 100%; aspect-ratio: 1; overflow: hidden; background: var(--bg3); margin-bottom: 10px; }
.rv-feat-art img, .rv-feat-art svg { width: 100%; height: 100%; object-fit: cover; display: block; }
.rv-feat-track { font-family: var(--font-display); font-size: 14px; font-weight: 800; text-transform: uppercase; color: var(--text); line-height: 1.2; }
.rv-feat-artist { font-size: 11.5px; color: var(--muted); margin-bottom: 10px; }
.rv-feat-links { display: flex; align-items: center; gap: 10px; }
.rv-feat-links svg { width: 16px; height: 16px; color: var(--muted); transition: color .2s; }
.rv-feat-links a:hover svg { color: var(--amber); }
.rv-feat-am { font-size: 16px; color: var(--muted); line-height: 1; transition: color .2s; }
.rv-feat-am:hover { color: var(--amber); }

.rv-interview-body { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); }

.rv-artist-top { display: flex; gap: 14px; align-items: center; margin-bottom: 12px; }
.rv-artist-photo { position: relative; width: 56px; height: 56px; border-radius: 50%; overflow: hidden; background: var(--bg3); flex-shrink: 0; }
.rv-artist-photo img, .rv-artist-photo svg { width: 100%; height: 100%; object-fit: cover; display: block; }
.rv-artist-name { font-family: var(--font-display); font-size: 17px; font-weight: 800; text-transform: uppercase; color: var(--text); margin: 0 0 2px; line-height: 1.1; }
.rv-artist-role { font-size: 11.5px; color: var(--muted); }
.rv-artist-location { font-family: var(--font-mono); font-size: 10.5px; color: var(--muted); margin-bottom: 4px; }
.rv-artist-stats { font-family: var(--font-mono); font-size: 10.5px; color: var(--muted); margin-bottom: 12px; }
.rv-artist-stats b { color: var(--text); font-weight: 600; }
.rv-artist-location span.sep, .rv-artist-stats span.sep { color: var(--border2); margin: 0 2px; }
.rv-artist-socials { display: flex; gap: 10px; margin-bottom: 12px; }
.rv-artist-socials svg { width: 15px; height: 15px; color: var(--muted); transition: color .2s; }
.rv-artist-socials a:hover svg { color: var(--amber); }
.rv-artist-cta { font-family: var(--font-display); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--amber); }

.rv-hl-row { display: flex; flex-direction: column; gap: 10px; }
.rv-hl-item { display: flex; align-items: flex-start; gap: 10px; }
.rv-hl-icon { flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%; border: 1px solid rgba(255,140,0,.35); background: rgba(255,140,0,.06); display: flex; align-items: center; justify-content: center; color: var(--amber); }
.rv-hl-icon svg { width: 14px; height: 14px; }
.rv-hl-item-text strong { display: block; font-size: 12.5px; font-weight: 700; color: var(--text); line-height: 1.3; }
.rv-hl-item-text span { font-size: 11.5px; color: var(--muted); line-height: 1.4; }
.rv-hl-viewfull { display: inline-block; margin-top: 16px; font-family: var(--font-display); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--amber); }

.rv-behind-photo { width: 100%; aspect-ratio: 16/6.5; overflow: hidden; background: var(--bg3); margin-bottom: 10px; }
.rv-behind-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rv-behind-text { font-size: 11.5px; color: var(--muted); line-height: 1.55; margin-bottom: 10px; }
.rv-behind-cta { font-family: var(--font-display); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--amber); cursor: pointer; }

.rv-row2-wrap { max-width: 1080px; margin: 0 auto; padding: 0; }
.rv-row2 { display: grid; grid-template-columns: 1fr 280px; gap: 32px; align-items: start; }
/* Grid items default to min-width:auto, which lets the review carousel's
   intrinsic content width (it's meant to be scrolled WITHIN its own
   overflow-x:auto box) bubble up through this unconstrained item instead —
   forcing the whole grid, and the page, wider than the viewport rather than
   clipping/scrolling internally as intended. min-width:0 lets this column
   actually shrink to the track's allotted width. */
.rv-row2 > div:first-child { min-width: 0; }

.rv-carousel-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 14px; }
.rv-carousel-viewall { font-family: var(--font-display); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text); }
.rv-carousel-outer { position: relative; }
.rv-carousel-arrow { position: absolute; top: 56px; width: 30px; height: 30px; border-radius: 50%; border: 1px solid var(--border2); background: var(--card); display: flex; align-items: center; justify-content: center; color: var(--text); z-index: 2; cursor: pointer; }
.rv-carousel-arrow.left { left: -15px; }
.rv-carousel-arrow.right { right: -15px; }
.rv-carousel-track { display: flex; gap: 16px; overflow-x: auto; scrollbar-width: none; padding-bottom: 4px; scroll-behavior: smooth; }
.rv-carousel-track::-webkit-scrollbar { display: none; }

.rv-rel-tile { flex-shrink: 0; width: 130px; cursor: pointer; }
.rv-rel-art { position: relative; width: 130px; height: 130px; overflow: hidden; background: var(--bg3); }
.rv-rel-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rv-rel-art svg.ph, .rv-rel-art svg.m-ph-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.rv-rel-play { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); width: 32px; height: 32px; border-radius: 50%; background: rgba(10,10,11,.55); border: 1px solid rgba(240,237,230,.5); display: flex; align-items: center; justify-content: center; }
.rv-rel-play svg { width: 12px; height: 12px; fill: var(--text); margin-left: 2px; }
.rv-rel-track { font-family: var(--font-display); font-size: 12.5px; font-weight: 800; text-transform: uppercase; color: var(--amber); margin: 8px 0 1px; line-height: 1.15; }
.rv-rel-artist { font-size: 10.5px; color: var(--text); margin-bottom: 5px; }
.rv-rel-verdict { display: inline-block; font-family: var(--font-mono); font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); border: 1px solid var(--border2); padding: 2px 7px; }

.rv-promo-card { background: linear-gradient(160deg, rgba(255,140,0,.09), rgba(255,140,0,.015) 65%); padding: 22px; }
.rv-promo-title { font-family: var(--font-display); font-weight: 900; text-transform: uppercase; font-size: 20px; line-height: 1.02; color: var(--text); margin: 0 0 4px; }
.rv-promo-title em { color: var(--amber); font-style: normal; }
.rv-promo-sub { font-size: 11.5px; color: var(--muted); line-height: 1.5; margin: 0 0 20px; }
.rv-promo-cta { display: block; text-align: center; background: var(--amber); color: #000; font-family: var(--font-display); font-size: 12px; font-weight: 900; text-transform: uppercase; letter-spacing: .03em; padding: 12px; }
.rv-promo-cta:hover { background: var(--amber2); }

@media (max-width: 900px) {
  .rv-trio { grid-template-columns: 1fr; gap: 24px; }
  .rv-row2 { grid-template-columns: 1fr; }
}

/* ── Homepage newsletter — the page's one real conversion action.
   Same centered-band language as All News (eyebrow, bold headline,
   generous padding) for visual consistency between the two closing
   sections, rather than introducing a new layout pattern this late in
   the page. Form validation/submit mirrors soundb-reviews.html's
   #nl-btn pattern — a client-side mock, no real backend yet. ── */
.home-newsletter-wrap { padding: 80px 0 140px; border-top: 1px solid var(--border); }
.home-newsletter { max-width: 440px; margin: 0 auto; text-align: center; }
.home-newsletter-eyebrow { display: block; font-family: var(--font-mono); font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 16px; }
.home-newsletter-title { font-family: var(--font-display); font-size: clamp(30px, 4vw, 42px); font-weight: 900; text-transform: uppercase; letter-spacing: -0.5px; line-height: 1.05; color: var(--text); margin-bottom: 12px; }
.home-newsletter-sub { font-family: var(--font-body); font-size: 14px; color: var(--muted); margin-bottom: 28px; }
.home-newsletter-form { display: flex; gap: 10px; }
.home-newsletter-input { flex: 1; min-width: 0; background: var(--bg3); border: 1px solid var(--border2); color: var(--text); font-family: var(--font-body); font-size: 14px; padding: 13px 16px; outline: none; box-sizing: border-box; transition: border-color 0.2s; }
.home-newsletter-input:focus { border-color: var(--amber); }
.home-newsletter-btn { flex-shrink: 0; background: var(--amber); color: #000; font-family: var(--font-display); font-size: 13px; font-weight: 900; text-transform: uppercase; letter-spacing: 0.02em; padding: 13px 24px; border: none; cursor: pointer; transition: background 0.2s; }
.home-newsletter-btn:hover { background: var(--amber2); }
/* Same dialog-box treatment as .sb-toast — top accent bar, close pinned
   top-right, mono eyebrow label instead of an icon. position:relative
   since (unlike .sb-toast) this sits in normal page flow, not fixed. */
.home-newsletter-toast {
  display: none; position: relative; text-align: left;
  max-width: 440px; margin-top: 14px;
  background: var(--bg3); border: 1px solid var(--border2);
  padding: 22px 32px 16px 18px;
}
.home-newsletter-toast::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--amber); }
.home-newsletter-toast-close { position: absolute; top: 12px; right: 12px; background: none; border: none; color: var(--muted); font-size: 16px; line-height: 1; cursor: pointer; padding: 4px; transition: color .15s; }
.home-newsletter-toast-close:hover { color: var(--text); }
.home-newsletter-toast-eyebrow { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--amber); margin-bottom: 6px; }
.home-newsletter-toast-text { font-family: var(--font-body); font-size: 13px; line-height: 1.55; color: var(--text); }

@media (max-width: 768px) {
  .home-newsletter-wrap { padding: 56px 0 90px; }
  .home-newsletter-form { flex-direction: column; }
}

/* ── SHARED: review headline styles ── */
.review-headline { font-family: var(--font-display); font-size: 68px; font-weight: 900; line-height: 0.92; letter-spacing: -1px; text-transform: uppercase; color: var(--text); margin-bottom: 24px; }
.review-headline em { color: var(--amber); font-style: normal; }
.review-deck { font-family: var(--font-serif); font-size: 19px; color: var(--muted); line-height: 1.65; max-width: 680px; margin-bottom: 32px; font-style: italic; }
.review-hero { padding: 48px 0 0; }
.review-layout { display: grid; grid-template-columns: 1fr 320px; gap: 60px; padding-bottom: 80px; }
/* A grid item's default min-width is auto, which refuses to shrink below
   its content's min-content size — .comparison-table's own min-width:640px
   deep inside .review-body was hitting this, forcing the *entire* 1fr
   track (and therefore every paragraph, heading, etc. in the body) to
   640px on mobile regardless of viewport width, well past the .comparison-
   wrap's own overflow-x:auto scroll container, which only isolates
   horizontal overflow within itself and does nothing for the ancestor
   grid track's sizing. min-width:0 lets the track actually shrink to the
   available space; .comparison-wrap's overflow-x:auto still makes that
   one element scroll horizontally instead of clipping/wrapping. */
.review-body, .article-body { min-width: 0; }
.review-sidebar { display: flex; flex-direction: column; gap: 28px; }
.meta-verdict { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.verdict-badge { background: var(--amber); color: #000; font-family: var(--font-display); font-size: 13px; font-weight: 900; letter-spacing: 0.08em; text-transform: uppercase; padding: 6px 14px; }
.score-pill { font-family: var(--font-display); font-size: 13px; font-weight: 700; color: var(--muted); border: 1px solid var(--border); padding: 6px 14px; }
.meta-actions { margin-left: auto; display: flex; gap: 8px; }
.meta-btn { background: var(--bg3); border: 1px solid var(--border); color: var(--muted); font-family: var(--font-mono); font-size: 11px; padding: 7px 14px; cursor: pointer; display: flex; align-items: center; gap: 6px; transition: all 0.2s; letter-spacing: 0.04em; }
.meta-btn:hover { color: var(--text); border-color: var(--border2); }
.article-headline { font-family: var(--font-display); font-size: 72px; font-weight: 900; line-height: 0.92; letter-spacing: -1px; text-transform: uppercase; color: var(--text); margin-bottom: 24px; }
.article-headline em { color: var(--amber); font-style: normal; }
.article-deck { font-family: var(--font-serif); font-size: 20px; color: var(--muted); line-height: 1.65; max-width: 720px; margin-bottom: 32px; font-style: italic; }
.article-hero { padding: 48px 0 0; }
.article-layout { display: grid; grid-template-columns: 1fr 300px; gap: 64px; padding-bottom: 80px; }
.article-sidebar { display: flex; flex-direction: column; gap: 28px; }
.article-body p { font-family: var(--font-serif); font-size: 18px; line-height: 1.85; color: #D8D5CE; margin-bottom: 28px; }
.article-body h2 { font-family: var(--font-display); font-size: 36px; font-weight: 900; text-transform: uppercase; color: var(--text); margin: 52px 0 20px; line-height: 1; }
.pullquote p { font-family: var(--font-display); font-size: 30px; }

/* ── RESPONSIVE — ALL PAGES ── */
/* .primary-nav/.hamburger toggle lives solely in the 1250px rule above now —
   duplicating it here at 1024px was harmless (1024 < 1250, always agreed)
   but risked exactly this kind of drift if only one of the two was ever
   updated again. */
@media (max-width: 1024px) {
  .gear-grid { grid-template-columns: repeat(2, 1fr); }
  .product-hero { grid-template-columns: 1fr; gap: 32px; }
  .product-visual { position: static; }
  .product-name { font-size: 48px; }
  .related-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 900px) {
  .review-headline { font-size: 42px; }
  .article-headline { font-size: 42px; }
  .review-layout { grid-template-columns: 1fr; }
  .review-sidebar { display: none; }
  .article-layout { grid-template-columns: 1fr; }
  .article-sidebar { display: none; }
  .more-grid { grid-template-columns: 1fr 1fr; }
  .data-callout { grid-template-columns: 1fr 1fr; }
  .inline-newsletter { flex-direction: column; gap: 16px; }
  .inline-newsletter-form { width: 100%; }
  .comparison-table { font-size: 12px; }
  .hero-title { font-size: 36px; }
  .cover-img { height: 280px; }
}
@media (max-width: 768px) {
  .page-title { font-size: 52px; }
  .gear-layout { grid-template-columns: 1fr; }
  .filter-sidebar { display: none; }
  /* Category chips wrapped onto multiple stacked lines on mobile — scroll
     horizontally in one line instead, same pattern already used for wide
     tables/grids elsewhere on the site (.comparison-wrap etc). Chips and
     the sort/view controls each get their own full-width row (rather than
     squeezing onto one line together) so the chips actually get the whole
     row to scroll within — otherwise the sort dropdown ate most of the
     width and left almost nothing for the chips to show. */
  .filter-chips { flex: 1 1 100%; flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .filter-right { flex: 1 1 100%; margin-left: 0; justify-content: space-between; }
  .gear-grid { grid-template-columns: repeat(2, 1fr); }
  .container { padding: 0 16px; }
  .compare-slots { display: none; }
  .overview-grid { grid-template-columns: repeat(2, 1fr); }
  .pros-cons { grid-template-columns: 1fr; }
  .related-grid { grid-template-columns: 1fr; }
  .article-headline, .review-headline { font-size: 48px; letter-spacing: -0.5px; }
  .cover-img { height: 240px; }
  .meta-bar { gap: 12px; }
  .meta-div { display: none; }
  /* Only the review page has a .meta-bar-mobile counterpart to swap in —
     article.html's simpler meta-bar (author + date/read only) keeps
     using the regular responsive wrapping behavior above. */
  .review-hero .meta-bar { display: none; }
  .review-hero .meta-bar-mobile { display: block; }
  .meta-actions { margin-left: 0; width: 100%; }
  .meta-btn { flex: 1; justify-content: center; }
  .meta-verdict { width: 100%; margin-left: 0; }
  .data-callout { grid-template-columns: 1fr 1fr; gap: 16px; padding: 20px; }
  .data-num { font-size: 40px; }
  .score-card { padding: 20px; }
  .score-overall-num { font-size: 56px; }
  .comparison-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .comparison-table { min-width: 640px; }
  /* Gear compare modal — the label column (140/160px) plus --cols (2-3) data
     columns has no room to collapse to 1 column (comparison is inherently
     side-by-side), so scroll horizontally instead, same pattern as
     .comparison-table above. min-width keeps each data column at a legible
     ~130px regardless of --cols. */
  .gear-compare-overlay { padding: 20px 12px; }
  #compare-modal-body { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .gc-header-grid { min-width: calc(140px + var(--cols) * 130px); }
  .gc-score-grid { min-width: calc(140px + var(--cols) * 130px); }
  .gc-spec-grid { min-width: calc(160px + var(--cols) * 130px); }
  .spec-table td:first-child { width: 50%; }
  .more-grid { grid-template-columns: 1fr; }
  .author-bio { flex-direction: column; gap: 14px; }
  .hero-title { font-size: 32px; }
}
@media (max-width: 480px) {
  .page-title { font-size: 40px; }
  .gear-grid { grid-template-columns: 1fr; }
  .gear-grid.list-view .gear-card { flex-direction: column; }
  .gear-grid.list-view .gear-card-img { width: 100%; }
  .product-name { font-size: 36px; }
  .overview-grid { grid-template-columns: 1fr 1fr; }
  .product-cta { flex-direction: column; }
  .article-headline, .review-headline { font-size: 36px; }
  .article-deck, .review-deck { font-size: 16px; }
  .data-callout { grid-template-columns: 1fr; }
  .data-num { font-size: 44px; }
  .cover-img { height: 200px; }
  .pullquote p { font-size: 22px; }
  .score-overall-num { font-size: 48px; }
  .btn-subscribe { display: none; }
  .topbar-inner { padding: 0 14px; }
  .hero-title { font-size: 28px; }
}

/* ══ SHARED — cross-page utilities ═ */
/* (soundb-music.html was removed; these rules are still used by
   soundb-news.html's lazy loading and soundb-transfer.html's placeholder art.) */

/* SVG placeholder — used by window.ph() (soundb-utils.js), consumed by soundb-transfer.html */
.m-ph-svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* ── LAZY LOADING — used by soundb-news.html's IntersectionObserver loader ── */
img[data-src] { opacity: 0; transition: opacity .4s; }
img.lazy-loaded { opacity: 1; }


/* Release strip icon buttons */
.release-btn-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  background: rgba(255,255,255,0.07); border: 1px solid rgba(255,255,255,0.12);
  cursor: pointer; transition: background .2s, border-color .2s;
  text-decoration: none; flex-shrink: 0;
}
.release-btn-icon:hover { background: rgba(255,255,255,0.14); border-color: rgba(255,255,255,0.25); }

/* ══ GEAR COMPARE MODAL ════════════════════════════════════ */
.compare-modal-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,0.85);
  z-index: 200; display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.compare-modal-overlay.hidden { display: none; }
.compare-modal-box {
  background: var(--bg2); border: 1px solid var(--border2);
  width: 100%; max-width: 960px; max-height: 90vh;
  overflow-y: auto; position: relative;
}
.compare-modal-close {
  position: absolute; top: 16px; right: 16px;
  background: none; border: none; color: var(--muted);
  font-size: 24px; cursor: pointer; line-height: 1;
  transition: color .2s;
}
.compare-modal-close:hover { color: var(--text); }
#auth-modal-body { padding: 32px; }
.compare-modal-box.auth-modal-box { max-width: 420px; }
.auth-password-group { margin-bottom: 14px; }
#auth-modal-body .modal-submit-btn { font-size: 15px; }
.auth-toggle-row { margin-top: 16px; text-align: center; }
.auth-newsletter-group { margin: 4px 0 14px; display: flex; flex-direction: column; gap: 8px; }
.auth-checkbox-row { display: flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 12px; color: var(--muted); cursor: pointer; }
.auth-checkbox-row input[type="checkbox"] { accent-color: var(--amber); width: 15px; height: 15px; flex-shrink: 0; }
/* The terms-acceptance row's label is long enough to wrap onto 2-3 lines
   (unlike the single-word newsletter rows this class was written for) —
   align-items:center from the base rule above centered the checkbox against
   the whole wrapped block, reading as oddly floating once there's more than
   one line. flex-start pins it to the first line instead, with a small
   top nudge so it lines up with that line's cap-height rather than its
   full box. The label text itself moves into its own <span> (see the
   markup) so it wraps as one normal run rather than mixing bare text nodes
   with <a> elements as separate flex items, which was the actual cause of
   the disjointed "I agree to the / Terms of Use / and Privacy Policy"
   staircase break — flex line-wrapping of mixed inline content doesn't
   reflow the way a single text container does. */
.auth-checkbox-row-wrap { align-items: flex-start; }
.auth-checkbox-row-wrap input[type="checkbox"] { margin-top: 2px; }
.auth-checkbox-row-wrap span { line-height: 1.5; }
.modal-copy-text { font-family: var(--font-mono); font-size: 12.5px; line-height: 1.7; color: var(--muted); text-align: center; margin: 12px 0 20px; }
.auth-password-checklist { margin: 6px 0 14px; padding: 10px 12px; background: var(--bg3); border: 1px solid var(--border2); display: flex; flex-direction: column; gap: 5px; }
.pw-check-item { font-family: var(--font-mono); font-size: 10.5px; color: var(--muted); display: flex; align-items: center; gap: 6px; transition: color .15s; }
.pw-check-item.met { color: var(--green); }
.pw-check-icon { font-size: 11px; width: 12px; text-align: center; flex-shrink: 0; }
.auth-address-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.auth-address-row .modal-field { width: 100%; }

/* ── Plans + checkout modals (shared — any page can call
   window.openPlansOverlay()/window.openCheckout(), not just soundb-learn.html) ── */
.hero-btn { border:1px solid var(--border2); background:var(--bg3); color:var(--text); font-family:var(--font-display); font-size:14px; font-weight:800; text-transform:uppercase; letter-spacing:.06em; padding:12px 18px; cursor:pointer; transition:all .2s; }
.hero-btn.primary { background:var(--amber); color:#000; border-color:var(--amber); }
.hero-btn:hover { border-color:var(--amber); transform:translateY(-1px); }
.plan-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--border); border:1px solid var(--border); }
.plan-card { background:var(--bg); padding:24px; display:flex; flex-direction:column; min-height:310px; }
.plan-card.featured { background:var(--bg2); position:relative; }
.plan-badge { position:absolute; top:-11px; left:24px; font-family:var(--font-mono); font-size:9px; color:#000; background:var(--amber); text-transform:uppercase; letter-spacing:.12em; padding:4px 8px; }
.plan-name { font-family:var(--font-display); font-size:30px; font-weight:900; text-transform:uppercase; line-height:1; margin-bottom:6px; }
.plan-price { font-family:var(--font-display); font-size:42px; font-weight:900; color:var(--amber); line-height:1; margin-bottom:12px; }
.plan-price span { font-family:var(--font-mono); font-size:11px; color:var(--muted); }
.plan-copy { font-size:13px; color:var(--muted); line-height:1.6; margin-bottom:18px; }
.plan-list { list-style:none; margin:0 0 20px; flex:1; }
.plan-list li { font-family:var(--font-mono); font-size:11px; color:var(--muted); padding:8px 0; border-bottom:1px solid var(--border); }
.plan-list li strong { color:var(--text); font-weight:500; }
.plan-btn { width:100%; background:var(--bg3); border:1px solid var(--border2); color:var(--text); font-family:var(--font-display); font-size:14px; font-weight:900; text-transform:uppercase; letter-spacing:.06em; padding:12px; cursor:pointer; transition:all .2s; }
.plan-btn.primary { background:var(--amber); color:#000; border-color:var(--amber); }
.plan-btn:hover { border-color:var(--amber); transform:translateY(-1px); }
.plan-status-note { font-family:var(--font-mono); font-size:10px; text-transform:uppercase; letter-spacing:.1em; text-align:center; padding:12px 0; }
.plan-status-note.current { color:var(--green); }
/* Highlight ring, not dimming — a current plan gets a live "Manage
   Subscription" action and should read as "yours," not as unavailable.
   Box-shadow (not border) so it doesn't disturb the 1px grid-line illusion
   .plan-grid gets from its gap+background technique. Lower tiers are no
   longer dimmed either — Schedule Downgrade is a real, always-available
   action under this model, not a locked one. */
.plan-card.current { box-shadow:inset 0 0 0 1px var(--green); }
.plans-modal-title { font-family:var(--font-display); font-size:28px; font-weight:900; text-transform:uppercase; line-height:1; margin-bottom:20px; }
.membership-summary { display:flex; flex-wrap:wrap; gap:24px; background:var(--bg2); border:1px solid var(--border); padding:18px 24px; margin-bottom:24px; }
.membership-stat-label { font-family:var(--font-mono); font-size:9px; color:var(--muted); text-transform:uppercase; letter-spacing:.12em; margin-bottom:5px; }
.membership-stat-value { font-family:var(--font-display); font-size:16px; font-weight:900; text-transform:uppercase; color:var(--text); }
.membership-stat-value.active { color:var(--green); }
.membership-stat-value.past-due { color:var(--amber); }
/* When a notice follows the summary directly above it, pull the two
   together (no top border/margin on the notice) instead of a gap between
   them; margin-bottom carries the space before the plan grid below. */
.membership-summary:has(+ .membership-notice) { margin-bottom:0; }
.membership-notice { font-family:var(--font-mono); font-size:11px; line-height:1.6; color:var(--muted); background:var(--bg2); border:1px solid var(--border); border-top:none; padding:14px 24px; margin-bottom:24px; }
.membership-notice.past-due { color:var(--amber); border-color:var(--amber); }
/* Amber toggle switch — same proven component already used on
   soundb-cookies.html's cookie-preference toggles (.cookie-toggle),
   generalized here under the site's shared stylesheet so the Auto Renew
   control (and any future on/off switch) doesn't need its own bespoke CSS
   duplicated per page. */
.toggle-switch-group { display:flex; align-items:center; gap:10px; }
.toggle-switch-label { font-family:var(--font-mono); font-size:10px; text-transform:uppercase; letter-spacing:.1em; color:var(--muted); }
.toggle-switch { position:relative; width:44px; height:24px; flex-shrink:0; }
.toggle-switch input { opacity:0; width:0; height:0; }
.toggle-slider { position:absolute; inset:0; background:var(--bg3); border:1px solid var(--border2); cursor:pointer; transition:background .2s, border-color .2s; border-radius:24px; }
.toggle-slider::before { content:''; position:absolute; width:18px; height:18px; left:2px; top:2px; background:var(--muted); border-radius:50%; transition:transform .2s, background .2s; }
.toggle-switch input:checked + .toggle-slider { background:var(--amber); border-color:var(--amber); }
.toggle-switch input:checked + .toggle-slider::before { transform:translateX(20px); background:#000; }
.toggle-switch input:disabled + .toggle-slider { opacity:.5; cursor:not-allowed; }
.toggle-switch-state { font-family:var(--font-mono); font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.1em; color:var(--muted); min-width:28px; }
.toggle-switch-state.on { color:var(--amber); }
.checkout-modal-box { max-width:480px; }
.plans-modal-box { max-width:920px; }
#checkout-modal-body, #plans-modal-body { padding:32px; }
.checkout-note { font-family:var(--font-mono); font-size:11px; color:var(--muted); }
.checkout-price { font-family:var(--font-display); font-size:22px; font-weight:900; color:var(--amber); margin-bottom:18px; }
.checkout-price-tight { font-family:var(--font-display); font-size:22px; font-weight:900; color:var(--amber); margin-bottom:6px; }
.checkout-plan-title { font-family:var(--font-display); font-size:30px; font-weight:900; text-transform:uppercase; line-height:1; margin-bottom:6px; }
.checkout-order-id { font-family:var(--font-mono); font-size:10px; color:var(--muted); margin-bottom:20px; }
.checkout-mock-note { font-family:var(--font-mono); font-size:11px; color:var(--muted); margin-bottom:18px; line-height:1.6; }
.checkout-error-inline { font-family:var(--font-mono); font-size:11px; color:var(--red); margin-top:14px; }
.checkout-result-title { font-family:var(--font-display); font-size:26px; font-weight:900; text-transform:uppercase; margin-bottom:10px; }
.checkout-result-title.fail { color:var(--red); }
.checkout-result-title.success { color:var(--green); }
.checkout-result-msg { font-family:var(--font-mono); font-size:12px; color:var(--muted); margin-bottom:20px; }
.checkout-cta { width:100%; margin-bottom:8px; }
.full-width { width:100%; }
/* ── Wallet top-up amount picker (soundb-account.html + soundb-wallet.html)
   — the same checkout-modal-body markup on both pages, so shared rather than
   duplicated inline like the page-specific card layouts around them. ── */
.topup-amount-grid { display:grid; grid-template-columns:repeat(3, 1fr); gap:8px; margin:14px 0; }
.topup-amount-btn { font-family:var(--font-mono); font-size:13px; font-weight:700; color:var(--text); background:var(--bg3); border:1px solid var(--border); padding:12px 8px; cursor:pointer; transition:border-color .15s; }
.topup-amount-btn:hover { border-color:var(--amber); }
.topup-amount-btn.selected { border-color:var(--amber); color:var(--amber); }
.topup-amount-btn:disabled { color:var(--muted); cursor:not-allowed; opacity:.4; }
.topup-amount-btn:disabled:hover { border-color:var(--border); }
.topup-custom-row { display:flex; align-items:center; gap:8px; margin-bottom:14px; }
.topup-custom-row input { flex:1; }
@media (max-width:860px) { .plan-grid { grid-template-columns:1fr; } }
/* ── Gear compare modal (soundb-gear.html) — actual live styling used by
   openCompareModal(). (A parallel, never-wired-up .compare-header-row/
   .compare-spec-* class set used to live here — confirmed zero references
   anywhere in the codebase and removed during the 2026-07-03 CSS cleanup.) ── */
.gear-compare-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.85); z-index: 200; overflow-y: auto; padding: 40px 24px; }
.gear-compare-box { max-width: 960px; margin: 0 auto; background: var(--bg2); border: 1px solid var(--border2); position: relative; }
.gear-compare-hd { display: flex; align-items: flex-start; justify-content: space-between; padding: 24px 28px; border-bottom: 1px solid var(--border); }
.gear-compare-title { font-family: var(--font-display); font-size: 24px; font-weight: 900; text-transform: uppercase; }
.gc-title-accent { font-style: italic; color: var(--amber); }
.gear-compare-close { background: none; border: none; color: var(--muted); font-size: 22px; cursor: pointer; line-height: 1; padding: 4px; transition: color 0.2s; }
.gear-compare-close:hover { color: var(--text); }
#compare-modal-body { padding: 28px; }
.gc-section-label-lg { font-family: var(--font-mono); font-size: 9px; color: var(--amber); text-transform: uppercase; letter-spacing: .16em; margin-bottom: 6px; }
.gear-toast { display: none; position: fixed; bottom: 90px; left: 50%; transform: translateX(-50%); background: var(--bg2); border: 1px solid var(--amber); color: var(--text); font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: .08em; padding: 12px 24px; z-index: 300; white-space: nowrap; box-shadow: 0 4px 24px rgba(0,0,0,.5); }

/* ── GLOBAL TOAST (window.showToast, soundb-utils.js) — themed
   replacement for alert(), used sitewide for every transient success/
   error message instead of the browser's native popup. Visually matches
   .gear-toast; error gets a red border/text so the two read as distinct
   at a glance. z-index 700 sits above every existing overlay
   (.compare-modal-overlay 200, .search-overlay 500, subscribe/auth
   modals ~600) but below .cms-offline-overlay's 99999. */
/* Dialog-box treatment: top accent bar + a close button pinned to the
   top-right corner, same convention as the site's other modal dialogs
   (.compare-modal-close etc.) — no icon, a small mono eyebrow label does
   that job instead. */
.sb-toast {
  position: fixed; bottom: 32px; left: 50%; transform: translateX(-50%) translateY(8px);
  width: max-content; max-width: min(420px, calc(100vw - 48px));
  background: var(--bg2); border: 1px solid var(--border2);
  padding: 26px 34px 22px 22px; z-index: 700;
  box-shadow: 0 16px 40px rgba(0,0,0,.5);
  opacity: 0; pointer-events: none;
  transition: opacity .25s ease, transform .25s ease;
}
.sb-toast::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--amber); }
.sb-toast.sb-toast-error::before { background: var(--red); }
.sb-toast.sb-toast-visible { opacity: 1; transform: translateX(-50%) translateY(0); pointer-events: auto; }
.sb-toast-close { position: absolute; top: 14px; right: 14px; background: none; border: none; color: var(--muted); font-size: 18px; line-height: 1; cursor: pointer; padding: 4px; transition: color .15s; }
.sb-toast-close:hover { color: var(--text); }
.sb-toast-eyebrow { font-family: var(--font-mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--amber); margin-bottom: 8px; }
.sb-toast.sb-toast-error .sb-toast-eyebrow { color: var(--red); }
.sb-toast-text { font-family: var(--font-body); font-size: 13.5px; line-height: 1.6; color: var(--text); }

/* Same footnote treatment as the confirmation emails' own "Landed in spam
   or junk?" line — small, muted, visually separate from the real message
   above it. Shared by the newsletter toast, Subscribe modal, and Contact
   modal wherever a "check your inbox" message appears. */
.inbox-spam-hint { font-family: var(--font-body); font-size: 11.5px; line-height: 1.5; color: var(--muted); margin-top: 8px; }

/* ── GLOBAL CONFIRM DIALOG (window.showConfirmDialog) — themed
   replacement for confirm(). Reuses .compare-modal-overlay's visual
   language (dark overlay + centered card) without the "type the word to
   confirm" strictness of the delete/clear modals, which stay as-is for
   genuinely destructive actions. ── */
.sb-confirm-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.85); z-index: 700; display: flex; align-items: center; justify-content: center; padding: 24px; opacity: 0; pointer-events: none; transition: opacity .15s ease; }
.sb-confirm-overlay.sb-confirm-open { opacity: 1; pointer-events: auto; }
.sb-confirm-box { background: var(--bg2); border: 1px solid var(--border2); width: 100%; max-width: 400px; padding: 28px; text-align: center; }
.sb-confirm-message { font-family: var(--font-body); font-size: 15px; color: var(--text); margin-bottom: 22px; line-height: 1.5; }
.sb-confirm-actions { display: flex; gap: 12px; }
.sb-confirm-btn { flex: 1; font-family: var(--font-display); font-weight: 900; text-transform: uppercase; letter-spacing: .04em; padding: 12px; border: none; cursor: pointer; font-size: 13px; }
.sb-confirm-cancel { background: transparent; border: 1px solid var(--border2); color: var(--text); }
.sb-confirm-cancel:hover { border-color: var(--muted); }
.sb-confirm-ok { background: var(--amber); color: #000; }
.sb-confirm-ok:hover { background: var(--amber2); }
.sb-confirm-ok.sb-confirm-danger { background: var(--red); color: #000; }
.sb-confirm-ok.sb-confirm-danger:hover { background: #ff8b8b; }

/* ── IMAGE ZOOM LIGHTBOX (soundb-gear.html) — click a card's photo to open
   a full-size viewer with pagination dots, arrows, swipe and arrow-key nav. */
.image-zoom-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.92); z-index: 400; align-items: center; justify-content: center; }
.image-zoom-overlay.open { display: flex; }
.image-zoom-stage { width: min(86vw, 900px); height: 82vh; position: relative; overflow: hidden; }
.image-zoom-track { display: flex; width: 300%; height: 100%; transform: translateX(-100%); touch-action: pan-y; }
.image-zoom-slide { width: 33.3333%; flex-shrink: 0; height: 100%; display: flex; align-items: center; justify-content: center; }
.image-zoom-slide img { display: block; max-width: 100%; max-height: 100%; object-fit: contain; user-select: none; -webkit-user-select: none; pointer-events: none; }
.image-zoom-close { position: absolute; top: 20px; right: 24px; background: none; border: none; color: var(--muted); font-size: 26px; cursor: pointer; line-height: 1; padding: 6px; transition: color .2s; }
.image-zoom-close:hover { color: var(--text); }
.image-zoom-arrow { position: absolute; top: 50%; transform: translateY(-50%); background: rgba(255,255,255,.06); border: 1px solid var(--border2); color: var(--text); font-size: 30px; line-height: 1; width: 48px; height: 48px; border-radius: 50%; cursor: pointer; transition: background .2s; display: flex; align-items: center; justify-content: center; }
.image-zoom-arrow:hover { background: rgba(255,255,255,.14); }
.image-zoom-prev { left: 20px; }
.image-zoom-next { right: 20px; }
.image-zoom-dots { position: absolute; bottom: 28px; left: 50%; transform: translateX(-50%); display: flex; gap: 8px; }
.image-zoom-dot { width: 8px; height: 8px; border-radius: 50%; background: rgba(255,255,255,.25); border: none; cursor: pointer; padding: 0; transition: background .15s, transform .15s; }
.image-zoom-dot.active { background: #770918; transform: scale(1.25); }
@media (max-width: 640px) {
  .image-zoom-arrow { display: none; }
  .image-zoom-stage { max-width: 94vw; }
}

/* ── SHARE MENU (window.openShareMenu, soundb-utils.js) — small popover
   anchored just below the triggering button, pops in with a soft overshoot
   scale + fade. Not a full-screen overlay — dismissed via outside click or
   Escape (wired in JS), so the rest of the page stays fully visible/usable. */
@keyframes shareMenuPopIn { from { opacity: 0; transform: scale(.82) translateY(-6px); } to { opacity: 1; transform: scale(1) translateY(0); } }
.share-menu-box { display: none; position: fixed; z-index: 400; background: var(--bg2); border: 1px solid var(--border2); border-radius: 14px; padding: 16px; box-shadow: 0 12px 40px rgba(0,0,0,.5); transform-origin: top left; max-width: calc(100vw - 24px); box-sizing: border-box; }
.share-menu-box.open { display: block; animation: shareMenuPopIn .28s cubic-bezier(.34,1.56,.64,1); }
.share-menu-list { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; justify-content: center; }
.share-menu-item { display: flex; flex-direction: column; align-items: center; gap: 7px; background: none; border: none; cursor: pointer; padding: 0; }
.share-menu-icon { width: 42px; height: 42px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: var(--bg3); border: 1px solid var(--border2); color: var(--text); transition: transform .18s cubic-bezier(.34,1.56,.64,1), background .18s, border-color .18s, color .18s; }
.share-menu-icon svg { width: 19px; height: 19px; }
.share-menu-item:hover .share-menu-icon { transform: translateY(-3px) scale(1.06); }
.share-menu-label { font-family: var(--font-mono); font-size: 9px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; transition: color .15s; white-space: nowrap; width: 58px; text-align: center; }
.share-menu-item:hover .share-menu-label { color: var(--text); }
.share-menu-item-copy:hover .share-menu-icon { background: #770918; border-color: #770918; color: #fff; }
.share-menu-item-wa:hover .share-menu-icon { background: #25D366; border-color: #25D366; color: #06130c; }
.share-menu-item-x:hover .share-menu-icon { background: #fff; border-color: #fff; color: #000; }
.share-menu-item-fb:hover .share-menu-icon { background: #1877F2; border-color: #1877F2; color: #fff; }
.share-menu-item-im:hover .share-menu-icon { background: #2ecc57; border-color: #2ecc57; color: #06130c; }
/* Below MOBILE_WIDTH (openShareMenu, soundb-utils.js) the popover centers
   itself in the viewport instead of anchoring to the button, so the pop
   animation should scale from its own center too, not the top-left corner
   used when anchored on wider viewports. These come after the base rules
   above on purpose — same-specificity selectors inside a later media query
   still lose to identical selectors that appear later in plain source
   order, so this block has to be last to actually win at narrow widths. */
@media (max-width: 640px) {
  .share-menu-box { transform-origin: top center; }
}
@media (max-width: 480px) {
  .share-menu-box { padding: 10px; }
  .share-menu-list { gap: 6px; }
  .share-menu-icon { width: 38px; height: 38px; }
  .share-menu-icon svg { width: 17px; height: 17px; }
  .share-menu-label { width: 48px; font-size: 8px; }
}

.gc-header-grid { display: grid; grid-template-columns: repeat(var(--cols), 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); margin-bottom: 24px; }
.gc-header-card { background: var(--bg2); padding: 20px; }
.gc-header-top { display: grid; grid-template-columns: 1fr 160px; align-items: stretch; gap: 12px; margin-bottom: 4px; }
.gc-header-info { min-width: 0; }
.gc-header-img { width: 160px; height: 100%; background: var(--bg3); overflow: hidden; }
.gc-header-img svg, .gc-header-img img { display: block; width: 100%; height: 100%; object-fit: cover; }
.gc-header-badge { font-family: var(--font-mono); font-size: 9px; color: var(--amber); text-transform: uppercase; letter-spacing: .14em; margin-bottom: 8px; }
.gc-header-cat { font-family: var(--font-mono); font-size: 9px; color: var(--muted); text-transform: uppercase; letter-spacing: .1em; margin-bottom: 4px; }
.gc-header-name { font-family: var(--font-display); font-size: 20px; font-weight: 900; text-transform: uppercase; color: var(--text); margin-bottom: 2px; }
.gc-header-brand { font-family: var(--font-mono); font-size: 11px; color: var(--muted); margin-bottom: 12px; }
.gc-header-price-row { display: flex; align-items: baseline; gap: 12px; margin-bottom: 14px; }
.gc-header-price { font-family: var(--font-display); font-size: 15px; font-weight: 700; color: var(--text); }
.gc-header-score { font-family: var(--font-display); font-size: 28px; font-weight: 900; color: var(--amber); line-height: 1; }
.gc-header-score span { font-size: 13px; color: var(--muted); }
.gc-btn-review { background: var(--amber); color: #000; font-family: var(--font-mono); font-size: 10px; font-weight: 700; text-transform: uppercase; padding: 8px 16px; border: none; cursor: pointer; }

.gc-section { margin-bottom: 24px; }
.gc-section-sm { margin-bottom: 20px; }
.gc-section-label { font-family: var(--font-mono); font-size: 9px; color: var(--amber); text-transform: uppercase; letter-spacing: .16em; margin-bottom: 12px; }
.gc-section-label-sm { font-family: var(--font-mono); font-size: 9px; color: var(--amber); text-transform: uppercase; letter-spacing: .14em; margin-bottom: 8px; }
.gc-score-grid { display: grid; grid-template-columns: 140px repeat(var(--cols), 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); }
.gc-spec-grid { display: grid; grid-template-columns: 160px repeat(var(--cols), 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); }
.gc-cell-label { background: var(--bg2); padding: 10px 14px; font-family: var(--font-mono); font-size: 9px; color: var(--muted); }
.gc-cell-name { background: var(--bg2); padding: 10px 14px; font-family: var(--font-mono); font-size: 9px; font-weight: 700; color: var(--text); text-transform: uppercase; }
.gc-cell-row-label { background: var(--bg3); padding: 10px 14px; font-family: var(--font-mono); font-size: 10px; color: var(--muted); }
.gc-cell-bar { background: var(--bg3); padding: 10px 14px; display: flex; align-items: center; gap: 10px; }
.gc-bar-track { flex: 1; height: 3px; background: rgba(255,255,255,.1); }
.score-bar-fill.gc-bar-fill { transition: width .7s cubic-bezier(.4,0,.2,1); }
.gc-bar-value { font-family: var(--font-mono); font-size: 11px; font-weight: 700; color: var(--text); min-width: 28px; text-align: right; }
.gc-spec-label-cell { background: var(--bg2); padding: 8px 12px; font-family: var(--font-mono); font-size: 9px; color: var(--muted); text-transform: uppercase; }
.gc-spec-name-cell { background: var(--bg2); padding: 8px 12px; font-family: var(--font-mono); font-size: 9px; font-weight: 700; color: var(--text); }
.gc-spec-key-cell { background: var(--bg3); padding: 8px 12px; font-family: var(--font-mono); font-size: 10px; color: var(--muted); }
.gc-spec-val-cell { background: var(--bg3); padding: 8px 12px; font-size: 12px; color: var(--muted); }
/* Header cards pair a fixed 160px product photo with text side-by-side
   (.gc-header-top), which doesn't shrink — at the ~130px/column budget the
   compare modal uses on mobile (see max-width:768px block above, tuned for
   the plain-text score/spec grids), that 160px image alone overflowed its
   own card and visually bled into the next product's column. Stacking the
   photo above the text below this breakpoint (full width, square) removes
   the fixed-width element entirely, so the same budget that already works
   for score/spec works here too. This has to come after the base
   .gc-header-top/.gc-header-img rules above — same specificity, later
   source order wins regardless of the media query, so placing it earlier
   (as originally written) got silently overridden by those base rules. */
@media (max-width: 768px) {
  .gc-header-top { grid-template-columns: 1fr; }
  .gc-header-img { width: 100%; height: auto; aspect-ratio: 1/1; }
}

/* ── PODCAST / VIDEO HUB ──────────────────────────────────────────────────
   Deliberately not the grid+filter-sidebar formula used on Gear/Reviews/
   Learn — this page browses via horizontal "shelf" rows instead, closer
   to how a streaming platform browses video/podcast content. */

.podcast-hero { position: relative; height: 560px; overflow: hidden; background: var(--bg3); background-size: cover; background-position: center; }
.podcast-hero::before { content: ''; position: absolute; inset: 0; background: linear-gradient(to top, rgba(10,10,11,0.97) 0%, rgba(10,10,11,0.75) 45%, rgba(10,10,11,0.35) 75%, rgba(10,10,11,0.55) 100%); }
.podcast-hero-body { position: absolute; bottom: 0; left: 0; right: 0; padding: 48px 0 44px; }
.podcast-hero-inner { max-width: 720px; }
.podcast-hero-title { font-family: var(--font-display); font-size: 56px; font-weight: 900; text-transform: uppercase; line-height: 0.95; letter-spacing: -1px; color: var(--text); margin: 14px 0 14px; }
.podcast-hero-deck { font-size: 15px; color: var(--muted); line-height: 1.7; max-width: 520px; margin-bottom: 22px; }
.podcast-hero-actions { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }

.podcast-format-badge { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 10px; font-weight: 700; color: var(--amber); text-transform: uppercase; letter-spacing: 0.12em; border: 1px solid rgba(255,140,0,0.35); padding: 5px 11px; }

.podcast-meta-row { display: flex; align-items: center; gap: 10px; font-family: var(--font-mono); font-size: 11px; color: var(--muted); flex-wrap: wrap; }
.podcast-meta-row span:not(:last-child)::after { content: '·'; margin-left: 10px; opacity: 0.5; }

.podcast-watch-btn { display: inline-flex; align-items: center; gap: 10px; background: var(--amber); color: #000; font-family: var(--font-display); font-size: 15px; font-weight: 900; text-transform: uppercase; letter-spacing: 0.03em; padding: 13px 24px; border: none; cursor: pointer; }
.podcast-watch-btn:hover { background: var(--amber2); }

.podcast-jumpnav { display: flex; gap: 4px; overflow-x: auto; border-bottom: 1px solid var(--border); scrollbar-width: none; }
.podcast-jumpnav::-webkit-scrollbar { display: none; }
.podcast-jumpnav-link { font-family: var(--font-mono); font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; padding: 16px 18px; white-space: nowrap; cursor: pointer; border-bottom: 2px solid transparent; transition: color 0.2s, border-color 0.2s; background: none; border-left: none; border-right: none; border-top: none; }
.podcast-jumpnav-link:hover { color: var(--text); }
.podcast-jumpnav-link.active { color: var(--amber); border-bottom-color: var(--amber); }

.podcast-shelf { padding: 40px 0; border-bottom: 1px solid var(--border); scroll-margin-top: 78px; }
.podcast-shelf-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 18px; }
.podcast-shelf-head.align-right { justify-content: flex-end; }
.podcast-shelf-head.align-right > div { text-align: right; }
.podcast-shelf-eyebrow { font-family: var(--font-mono); font-size: 10px; color: var(--amber); text-transform: uppercase; letter-spacing: 0.14em; }
.podcast-shelf-title { font-family: var(--font-display); font-size: 28px; font-weight: 800; text-transform: uppercase; letter-spacing: -0.5px; margin-top: 4px; }
.podcast-shelf-track { display: flex; gap: 18px; overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: 6px; scrollbar-width: none; }
.podcast-shelf-track::-webkit-scrollbar { display: none; }
.podcast-shelf-track.align-right { justify-content: flex-end; }

.podcast-card { flex-shrink: 0; width: 300px; scroll-snap-align: start; background: var(--card); border: 1px solid var(--border); cursor: pointer; transition: border-color 0.2s; }
.podcast-card:hover { border-color: var(--border2); }
.podcast-card-thumb { position: relative; width: 100%; aspect-ratio: 16/9; background: var(--bg3); overflow: hidden; }
.podcast-card-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.5s; }
.podcast-card:hover .podcast-card-thumb img { transform: scale(1.05); }
.podcast-card-format { position: absolute; top: 10px; left: 10px; font-family: var(--font-mono); font-size: 9px; font-weight: 700; color: #000; background: var(--amber); text-transform: uppercase; letter-spacing: 0.08em; padding: 4px 8px; }
.podcast-card-play { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.2s; background: rgba(0,0,0,0.25); }
.podcast-card:hover .podcast-card-play { opacity: 1; }
.podcast-card-play svg { filter: drop-shadow(0 2px 8px rgba(0,0,0,0.5)); }
.podcast-card-body { padding: 14px 16px 18px; }
.podcast-card-title { font-family: var(--font-display); font-size: 19px; font-weight: 800; text-transform: uppercase; line-height: 1.1; letter-spacing: -0.2px; margin-bottom: 8px; }
.podcast-card-meta { font-family: var(--font-mono); font-size: 10px; color: var(--muted); }
.podcast-card-meta span:not(:last-child)::after { content: '·'; margin-left: 6px; opacity: 0.5; }

.podcast-empty { padding: 80px 0; text-align: center; color: var(--muted); font-family: var(--font-mono); font-size: 12px; }

/* Episode detail page */
.video-embed-wrap { position: relative; width: 100%; padding-top: 56.25%; background: var(--bg3); border: 1px solid var(--border); }
.video-embed-wrap iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: none; }

@media (max-width: 900px) {
  .podcast-hero { height: 460px; }
  .podcast-hero-title { font-size: 38px; }
  .podcast-card { width: 250px; }
}
.gc-spec-val-cell.gc-diff { color: var(--text); font-weight: 600; }

/* ── FADER — mixing-console-style position control for the gear photo
   gallery (soundb-gear.html/soundb-specs.html), built via
   window.createFader() in soundb-utils.js. Physically modeled on a real
   channel-strip fader: thin track, tick marks, a wider rectangular cap. ── */
.sb-fader { position: relative; outline: none; }
.sb-fader:focus-visible .sb-fader-cap { box-shadow: 0 2px 4px rgba(0,0,0,.5), 0 0 0 1px rgba(0,0,0,.4), inset 0 1px 0 rgba(255,255,255,.35), 0 0 0 3px rgba(119,9,24,.4); }
/* Recessed channel groove, like the slot a real fader cap rides in. */
.sb-fader-track { position: relative; background: var(--bg3); border: 1px solid var(--border); cursor: pointer; border-radius: 2px; box-shadow: inset 0 1px 2px rgba(0,0,0,.7), inset 0 -1px 0 rgba(255,255,255,.02); }
.sb-fader-horizontal .sb-fader-track { height: 5px; width: 100%; }
.sb-fader-vertical .sb-fader-track { width: 5px; height: 100%; }
.sb-fader-tick { position: absolute; background: var(--border2); transition: background .15s; }
.sb-fader-horizontal .sb-fader-tick { top: 50%; width: 2px; height: 9px; transform: translate(-50%,-50%); }
.sb-fader-vertical .sb-fader-tick { left: 50%; width: 9px; height: 2px; transform: translate(-50%,50%); }
.sb-fader-tick.active { background: #770918; }
.sb-fader-tick-label { position: absolute; font-family: var(--font-mono); font-size: 8px; color: var(--muted); white-space: nowrap; text-transform: uppercase; letter-spacing: .05em; transition: color .15s; }
.sb-fader-tick.active .sb-fader-tick-label { color: #770918; }
.sb-fader-horizontal .sb-fader-tick-label { top: 12px; left: 50%; transform: translateX(-50%); }
.sb-fader-vertical .sb-fader-tick-label { left: 14px; top: 50%; transform: translateY(-50%); }
/* Cap: brushed-plastic gradient + a raised grip ridge across the middle,
   like the thumb grip molded into a real channel-strip fader cap. */
.sb-fader-cap {
  position: absolute; z-index: 2; border-radius: 3px; cursor: grab;
  background: linear-gradient(180deg, #b8324a 0%, #950c22 42%, #770918 60%, #52050f 100%);
  box-shadow: 0 2px 4px rgba(0,0,0,.5), 0 0 0 1px rgba(0,0,0,.4), inset 0 1px 0 rgba(255,255,255,.35);
  transition: left .15s ease, bottom .15s ease, transform .1s ease, filter .1s ease;
}
.sb-fader-cap::after { content: ''; position: absolute; background: rgba(0,0,0,.4); border-radius: 1px; box-shadow: 0 1px 0 rgba(255,255,255,.15); }
.sb-fader-cap:hover { filter: brightness(1.08); }
.sb-fader-cap.dragging { cursor: grabbing; transition: filter .1s ease; filter: brightness(1.15); box-shadow: 0 3px 8px rgba(0,0,0,.6), 0 0 0 1px rgba(0,0,0,.4), inset 0 1px 0 rgba(255,255,255,.4); }
.sb-fader-horizontal .sb-fader-cap { width: 26px; height: 14px; top: 50%; transform: translate(-50%,-50%); }
.sb-fader-horizontal .sb-fader-cap.dragging { transform: translate(-50%,-50%) scale(1.06); }
.sb-fader-horizontal .sb-fader-cap::after { left: 50%; top: 50%; width: 2px; height: 8px; transform: translate(-50%,-50%); }
.sb-fader-vertical .sb-fader-cap { height: 26px; width: 14px; left: 50%; transform: translate(-50%,50%); }
.sb-fader-vertical .sb-fader-cap.dragging { transform: translate(-50%,50%) scale(1.06); }
.sb-fader-vertical .sb-fader-cap::after { top: 50%; left: 50%; height: 2px; width: 8px; transform: translate(-50%,-50%); }

/* Placeholder shown in the fader's spot for a card/product with fewer than
   2 photos — keeps every card's layout identical whether or not it has a
   gallery, instead of collapsing the space away. */
.sb-fader-disabled { pointer-events: none; cursor: default; }
.sb-fader-disabled .sb-fader-cap { background: linear-gradient(180deg, #4a4a4e 0%, #3a3a3d 50%, #2c2c2e 100%); box-shadow: 0 1px 2px rgba(0,0,0,.4), 0 0 0 1px rgba(0,0,0,.3); cursor: default; }
.sb-fader-disabled .sb-fader-cap::after { background: rgba(0,0,0,.3); box-shadow: none; }

/* ─────────────────────────────────────────────
   IMAGE FADE-IN — paired with the image enhancer in soundb-utils.js.
   Only images that script has actively marked are ever transparent, so if
   the script does not run (or an image was already cached and needs no
   fade at all) images render fully opaque exactly as before. The transition
   is short and opacity-only: it should read as the image settling in, not
   as an animation the reader notices.
───────────────────────────────────────────── */
img.sb-img-loading { opacity: 0; }
img.sb-img-ready { opacity: 1; animation: sb-img-fade 220ms ease-out; }
@keyframes sb-img-fade { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  img.sb-img-loading { opacity: 1; }
  img.sb-img-ready { animation: none; }
}

/* ─────────────────────────────────────────────
   PRORATED UPGRADE BREAKDOWN — shown in the checkout modal when an upgrade
   costs less than the plan's list price because the unused remainder of the
   current plan is credited against it. The arithmetic is spelled out so the
   charge can be reconciled against the advertised price.
───────────────────────────────────────────── */
.checkout-proration { border: 1px solid var(--border); background: var(--bg2); padding: 12px 14px; margin: 12px 0; text-align: left; }
.checkout-proration-row { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; color: var(--text2); line-height: 1.5; }
.checkout-proration-row + .checkout-proration-row { margin-top: 6px; }
.checkout-proration-note { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); font-size: 12px; color: var(--text3); line-height: 1.5; }

/* Undo action inside the "Switching to X on DATE" notice — the way out of a
   scheduled plan change, sitting next to the notice that announces it. */
.membership-notice-undo { background:none; border:1px solid currentColor; color:inherit; font-family:var(--font-mono); font-size:10px; text-transform:uppercase; letter-spacing:.08em; padding:4px 9px; margin-left:8px; cursor:pointer; transition:opacity .2s; }
.membership-notice-undo:hover { opacity:.7; }
