/* =============================================================
   greenranger — landing page
   Scroll-driven color zones.
   Each section sets its own palette via data-* attrs.
   JS picks the most-visible zone and writes the palette to :root.
   CSS transitions interpolate between zones.
   ============================================================= */

/* ---------- tokens (JS-overwritten per zone) ---------- */
:root {
  /* default: green origin */
  --bg: #0a2a1c;
  --bg-2: #06180f;
  --ink: #dff5e6;
  --ink-dim: #7fae90;
  --ink-faint: #4a7a5d;
  --line: #1a4a30;
  --accent: #7af0b9;
  --accent-dim: #1f6f4a;

  /* font + layout (constant across zones) */
  --font-display: 'Fraunces', 'Iowan Old Style', 'Apple Garamond', Georgia, serif;
  --font-body: 'Inter', system-ui, -apple-system, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --max: 1280px;
  --pad: clamp(1rem, 3vw, 2.5rem);
  --radius: 4px;

  /* All palette colors transition together for smooth scroll-blend.
     Tuned ~600ms so the change feels like a slow color wash,
     not a pop. */
  --zone-transition: background-color 600ms cubic-bezier(0.4, 0, 0.2, 1),
                     color 600ms cubic-bezier(0.4, 0, 0.2, 1),
                     border-color 600ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background-color: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  transition: var(--zone-transition);
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; }
::selection { background: var(--accent); color: var(--bg); }

/* ---------- film grain (fixed) ---------- */
.grain {
  position: fixed; inset: 0; z-index: 9999; pointer-events: none;
  opacity: 0.06;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(%23n)' opacity='0.7'/></svg>");
  mix-blend-mode: overlay;
}

/* ---------- zone base ---------- */
/* Each zone is a full-viewport-ish section.
   Each section sets its OWN colors via [data-zone="..."] rules
   below. The global --bg/--ink/--accent variables (set by JS on
   :root) only drive the topbar and the body fallback color
   visible during the brief cross-fade between sections. */
.zone {
  position: relative;
  z-index: 2;
  padding: clamp(5rem, 12vh, 9rem) var(--pad);
  min-height: 100vh;
  /* Dynamic viewport unit fallback for iOS Safari. Without dvh, the
     URL bar makes 100vh larger than the visible area on iOS, leaving
     content below the fold. dvh = dynamic viewport = the actual
     visible area. 100dvh is the iOS 15.4+ syntax. */
  min-height: 100dvh;
  display: flex;
  align-items: center;
  color: var(--ink);
  transition: var(--zone-transition);
}

/* Each zone re-declares its own palette as a local --bg/--ink/--accent
   etc. on the section element, so every descendant (album__title,
   album__blurb, album__tracks, cta) automatically reads the right
   colors without per-element overrides. The :root values still
   drive the topbar via the global CSS variables. */
.zone--hero {
  --bg: #0a2a1c;
  --bg-2: #06180f;
  --ink: #dff5e6;
  --ink-dim: #7fae90;
  --ink-faint: #4a7a5d;
  --line: #1a4a30;
  --accent: #7af0b9;
  --accent-dim: #1f6f4a;
  background-color: #0a2a1c;
  color: #dff5e6;
}
.zone--hero::before {
  background:
    radial-gradient(ellipse at top, rgba(122, 240, 185, 0.12) 0%, transparent 55%),
    radial-gradient(ellipse at bottom, rgba(31, 111, 74, 0.08) 0%, transparent 55%);
}

#zone-ranger {
  --bg: #0e2f1f;
  --bg-2: #08170f;
  --ink: #dff5e6;
  --ink-dim: #82b394;
  --ink-faint: #4a7a5d;
  --line: #1d4a30;
  --accent: #7af0b9;
  --accent-dim: #1f6f4a;
  background-color: #0e2f1f;
  color: #dff5e6;
}
#zone-ranger::before {
  background:
    radial-gradient(ellipse at top, rgba(122, 240, 185, 0.12) 0%, transparent 55%),
    radial-gradient(ellipse at bottom, rgba(31, 111, 74, 0.08) 0%, transparent 55%);
}

#zone-red-knight {
  --bg: #2a0c0a;
  --bg-2: #170504;
  --ink: #ffe1dc;
  --ink-dim: #c0857e;
  --ink-faint: #7a4a45;
  --line: #4a1812;
  --accent: #ff6e5a;
  --accent-dim: #a82b22;
  background-color: #2a0c0a;
  color: #ffe1dc;
}
#zone-red-knight::before {
  background:
    radial-gradient(ellipse at top, rgba(255, 110, 90, 0.12) 0%, transparent 55%),
    radial-gradient(ellipse at bottom, rgba(168, 43, 34, 0.08) 0%, transparent 55%);
}

#zone-awordmakesanother {
  --bg: #f5efe4;
  --bg-2: #e8dfd0;
  --ink: #1a0a0a;
  --ink-dim: #5a3a36;
  --ink-faint: #8a6a64;
  --line: #d9cdba;
  --accent: #c43a2e;
  --accent-dim: #7a1a14;
  background-color: #f5efe4;
  color: #1a0a0a;
}
#zone-awordmakesanother::before {
  background:
    radial-gradient(ellipse at top, rgba(196, 58, 46, 0.08) 0%, transparent 55%),
    radial-gradient(ellipse at bottom, rgba(196, 58, 46, 0.05) 0%, transparent 55%);
}

#zone-blue-mage {
  --bg: #0a1640;
  --bg-2: #040818;
  --ink: #dee5ff;
  --ink-dim: #8090c4;
  --ink-faint: #4a558a;
  --line: #15205a;
  --accent: #5d8aff;
  --accent-dim: #1d4dff;
  background-color: #0a1640;
  color: #dee5ff;
}
#zone-blue-mage::before {
  background:
    radial-gradient(ellipse at top, rgba(93, 138, 255, 0.12) 0%, transparent 55%),
    radial-gradient(ellipse at bottom, rgba(29, 77, 255, 0.08) 0%, transparent 55%);
}

#zone-yellow-monk {
  --bg: #2a1e08;
  --bg-2: #160f04;
  --ink: #fff4d6;
  --ink-dim: #c8b074;
  --ink-faint: #7a6840;
  --line: #4a3a18;
  --accent: #ffd66b;
  --accent-dim: #c08a1a;
  background-color: #2a1e08;
  color: #fff4d6;
}
#zone-yellow-monk::before {
  background:
    radial-gradient(ellipse at top, rgba(255, 214, 107, 0.12) 0%, transparent 55%),
    radial-gradient(ellipse at bottom, rgba(192, 138, 26, 0.08) 0%, transparent 55%);
}

#zone-about {
  --bg: #0a1424;
  --bg-2: #060d18;
  --ink: #e8efff;
  --ink-dim: #8a9bb8;
  --ink-faint: #4b5870;
  --line: #1a2640;
  --accent: #7af0b9;
  --accent-dim: #1f6f4a;
  background-color: #0a1424;
  color: #e8efff;
}
#zone-about::before {
  background:
    radial-gradient(ellipse at top, rgba(122, 240, 185, 0.08) 0%, transparent 55%),
    radial-gradient(ellipse at bottom, rgba(31, 111, 74, 0.06) 0%, transparent 55%);
}
/* Edge tint: soft horizontal wash so the zone bleeds into the body bg */
.zone::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse at top, color-mix(in srgb, var(--accent) 12%, transparent) 0%, transparent 55%),
    radial-gradient(ellipse at bottom, color-mix(in srgb, var(--accent) 8%, transparent) 0%, transparent 55%);
  z-index: 0;
}
.zone > * { position: relative; z-index: 1; }

/* ---------- topbar ---------- */
/* Static (not sticky) — sits at the top of the hero and scrolls
   away with the page. The user wanted the topbar (gem + 'green
   ranger' wordmark + nav) to be part of the hero, not a floating
   UI element. */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.9rem var(--pad);
  background: color-mix(in srgb, var(--bg) 78%, transparent);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--line);
  transition: var(--zone-transition);
}
.brand {
  display: inline-flex; align-items: center; gap: 0.6rem;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink);
}
.brand__gem {
  width: 18px; height: 18px;
  background: linear-gradient(135deg, var(--accent), var(--accent-dim));
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  transition: background 600ms ease;
}
.nav,
.catalog-nav {
  display: flex; gap: clamp(0.7rem, 1.6vw, 1.4rem);
  font-family: var(--font-mono);
  font-size: 0.74rem;
  text-transform: lowercase;
  letter-spacing: 0.05em;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.nav a,
.catalog-nav a {
  color: var(--ink-dim);
  transition: color 200ms ease;
  position: relative;
  text-decoration: none;
}
.nav a:hover, .nav a:focus-visible,
.catalog-nav a:hover, .catalog-nav a:focus-visible { color: var(--accent); }

/* ============================================================
   HERO — green origin
   ============================================================ */
.zone--hero {
  /* min-height: 100vh minus the topbar height (~52px).
     The topbar is now static (not sticky), so the hero sits below
     it in the document flow. Without this calc, the user would
     see a 50px gap at the bottom of the hero before the next
     section started. */
  min-height: calc(100vh - 52px);
  min-height: calc(100dvh - 52px);
  justify-content: center;
  padding-top: 0;
  padding-bottom: 0;
}
.hero {
  width: 100%;
  max-width: var(--max);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(280px, 1fr) minmax(280px, 1.2fr);
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
}
.hero__stage {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  display: grid; place-items: center;
  perspective: 1200px;
  max-width: 460px;
  justify-self: center;
}

/* The gem is now a real photograph (assets/hero-gem.jpg), not an SVG.
   The wrap is a positioning context. The shadow that was here before
   is removed because the photo has its own baked-in shadow on the
   surface beneath the gem. */
.gem-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
}

.gem {
  position: relative;
  width: 70%;
  aspect-ratio: 1;
  /* Subtle green halo around the gem. Less aggressive than the SVG
     version because the photo already has its own lighting — a heavy
     drop-shadow would compete with the baked-in shadow on the surface. */
  filter: drop-shadow(0 0 24px color-mix(in srgb, var(--accent) 35%, transparent))
          drop-shadow(0 0 60px color-mix(in srgb, var(--accent-dim) 22%, transparent));
  transition: transform 250ms ease, filter 600ms ease;
  z-index: 2;
  will-change: transform;
}
.gem__img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
  /* The photo's bg is pure black; on the hero (also dark green) the
     black blends with the bg. No background-color override needed. */
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}
.hero__copy {
  text-align: left;
  max-width: 640px;
}
.hero__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.6rem, 9vw, 7.5rem);
  line-height: 1.15;
  letter-spacing: -0.035em;
  margin: 0 0 1.25rem;
  color: var(--ink);
}
.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--ink-faint);
  margin: 0 0 1rem;
}
.display {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.6rem, 9vw, 7.5rem);
  /* 1.15 — was 0.95, which clipped descenders on 'g', 'y', 'r'.
     Fraunces at 9..144 opsz has deep descenders (the loop on 'g'
     and the tail on 'r' extend ~0.18em below the baseline).
     At 0.95 line-height those descenders drew below the layout
     box, which made them look cut off by sibling elements and
     made the background-clip gradient mask look wrong at the
     bottom. 1.15 keeps them inside the box without making the
     title feel airy. */
  line-height: 1.15;
  letter-spacing: -0.035em;
  margin: 0 0 1.25rem;
  /* Solid color instead of a gradient — on dark sections the
     gradient's dim end made the descenders visually disappear
     into the background. Solid ink is brighter and more readable
     especially for letters with descenders (g, y, p, q, j). */
  color: var(--ink);
}
.tagline {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.1rem, 2.2vw, 1.5rem);
  color: var(--ink-dim);
  margin: 0 0 2rem;
  letter-spacing: -0.01em;
  line-height: 1.4;
}
.hero__cta {
  display: inline-flex; gap: 0.75rem; flex-wrap: wrap;
}
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.8rem 1.4rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: color-mix(in srgb, var(--ink) 3%, transparent);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  text-transform: lowercase;
  letter-spacing: 0.04em;
  color: var(--ink);
  transition: all 220ms ease;
}
.btn:hover {
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  border-color: var(--ink-dim);
  transform: translateY(-1px);
}
.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
}
.btn--primary:hover {
  background: color-mix(in srgb, var(--accent) 90%, var(--ink) 10%);
  box-shadow: 0 0 28px color-mix(in srgb, var(--accent) 45%, transparent);
}
.hero__scroll-hint {
  margin-top: 3rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  text-transform: lowercase;
  letter-spacing: 0.2em;
  color: var(--ink-faint);
  animation: hint 2.2s ease-in-out infinite;
}
@keyframes hint {
  0%, 100% { transform: translateY(0); opacity: 0.5; }
  50% { transform: translateY(6px); opacity: 1; }
}

/* ============================================================
   responsive — mobile (≤820px)
   ============================================================ */
@media (max-width: 820px) {
  /* Hero stacks vertically, centers, shrinks the gem. */
  .hero {
    grid-template-columns: 1fr;
    text-align: center;
  }
  .hero__copy { text-align: center; margin: 0 auto; }
  .hero__cta { justify-content: center; }
  .hero__scroll-hint { text-align: center; }
  .hero__stage { max-width: 320px; }

  /* Album rows collapse to 1 column. */
  .album,
  .zone--reverse .album {
    grid-template-columns: 1fr;
  }
  .zone--reverse .album__art { order: 0; }
  .zone--reverse .album__body { order: 1; }
  .album__art { max-width: 360px; margin: 0 auto; }
  .album__tracks { grid-template-columns: 1fr; }

  /* Album sections: shorter min-height on mobile. 100dvh is a lot
     of empty space when the content (cover + blurb + 7 tracks +
     CTA) only takes ~700px. Reduce to 100svh (small viewport) or
     auto so the section sizes to its content. */
  .zone--album {
    min-height: auto;
    padding-block: clamp(3.5rem, 8vh, 5rem);
  }

  /* Touch targets: Apple HIG says 44px minimum, Material says 48dp.
     The buttons (0.8rem padding + 0.78rem text ≈ 25px tall) fall
     short. Bump padding so the tap target is ≥44px. */
  .btn {
    padding: 1rem 1.5rem;
    min-height: 44px;
  }
  .album__cta {
    padding: 0.95rem 1.4rem;
    min-height: 44px;
  }

  /* Topbar: lighter backdrop-filter on mobile. The blur(14px) +
     saturate(140%) on a 78% opacity background is expensive on
     lower-end Android. Use a simple solid background instead —
     the topbar is only at the top of the page anyway (not sticky),
     so there's nothing behind it to blur. */
  .topbar {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: var(--bg);
  }
}

/* Same responsive fixes for nav — but on mobile we hide the nav
   and show a hamburger button instead (added in HTML/JS). */
@media (max-width: 820px) {
  .catalog-nav { display: none; }
  .nav-toggle { display: inline-flex; }
}
@media (min-width: 821px) {
  .nav-toggle { display: none; }
  .nav-mobile { display: none !important; }
}

/* ============================================================
   ALBUM ZONE — full-bleed feature row per release
   ============================================================ */
.album {
  width: 100%;
  max-width: var(--max);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(280px, 0.85fr) minmax(320px, 1fr);
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
}
.zone--reverse .album {
  grid-template-columns: minmax(320px, 1fr) minmax(280px, 0.85fr);
}
.zone--reverse .album__art { order: 2; }
.zone--reverse .album__body { order: 1; }

.album__art {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--bg-2);
  box-shadow:
    0 30px 80px -20px rgba(0,0,0,0.55),
    0 0 0 1px color-mix(in srgb, var(--accent) 20%, transparent);
}
.album__art img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(0.92);
  transition: transform 800ms cubic-bezier(0.16, 1, 0.3, 1), filter 600ms ease;
}
.album__art:hover img {
  transform: scale(1.03);
  filter: saturate(1.05);
}
/* subtle inner border tinted to accent */
.album__art::after {
  content: '';
  position: absolute; inset: 0;
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: inherit;
  pointer-events: none;
}

.album__body { display: flex; flex-direction: column; gap: 1.25rem; }
.album__number {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--accent);
  margin: 0;
}
.album__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.2rem, 6vw, 5rem);
  letter-spacing: -0.03em;
  /* 1.15 — was 0.95, same descender clipping problem as .display.
     "ranger", "red knight", "yellow monk" all have descenders
     (g, k, y) that need vertical room. 1.15 keeps them inside
     the layout box. */
  line-height: 1.15;
  margin: 0;
  /* Solid color (was gradient) — same reasoning as .display: the
     gradient's dim end made descenders look clipped on dark bg. */
  color: var(--ink);
}
.album__blurb {
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.6vw, 1.25rem);
  font-style: italic;
  color: var(--ink-dim);
  line-height: 1.5;
  margin: 0;
  max-width: 52ch;
}
.album__tracks {
  list-style: none;
  margin: 0.5rem 0 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.4rem 1.5rem;
  border-top: 1px solid var(--line);
  padding-top: 1.25rem;
}
.album__tracks li {
  display: flex; gap: 0.85rem; align-items: baseline;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--ink);
  padding: 0.3rem 0;
  border-bottom: 1px dashed color-mix(in srgb, var(--line) 60%, transparent);
}
.album__tracks li span {
  color: var(--accent);
  font-size: 0.7rem;
  font-weight: 500;
  opacity: 0.7;
  min-width: 1.6rem;
}
.album__cta {
  align-self: flex-start;
  margin-top: 0.5rem;
  padding: 0.75rem 1.3rem;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: transparent;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  text-transform: lowercase;
  letter-spacing: 0.05em;
  color: var(--accent);
  transition: all 250ms ease;
}
.album__cta:hover {
  background: var(--accent);
  color: var(--bg);
  transform: translateY(-1px);
  box-shadow: 0 0 28px color-mix(in srgb, var(--accent) 35%, transparent);
}
.album__cta--primary {
  background: var(--accent);
  color: var(--bg);
}
.album__cta--primary:hover {
  background: color-mix(in srgb, var(--accent) 90%, var(--ink) 10%);
  color: var(--bg);
}

/* section padding for non-first/last */
.zone--album:not(.zone--final) {
  /* keep min-height for screen presence */
}

/* ============================================================
   LIGHT ISLAND — awordmakesanother
   The cover is white-on-multicolor, so the page itself becomes
   a light zone. The transition is faster than the dark zones
   so the contrast beat reads as deliberate, not a snap.
   ============================================================ */
.zone--light {
  /* Faster, snappier transition for the light beat. */
  --zone-transition: background-color 320ms cubic-bezier(0.4, 0, 0.2, 1),
                     color 320ms cubic-bezier(0.4, 0, 0.2, 1),
                     border-color 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* When the light zone is active, the body fades faster too,
   so the surrounding dark zones don't try to cross-fade into
   it over 600ms (which reads as a slow burn into white). */
body[data-zone="zone-awordmakesanother"] {
  --zone-transition: background-color 320ms cubic-bezier(0.4, 0, 0.2, 1),
                     color 320ms cubic-bezier(0.4, 0, 0.2, 1),
                     border-color 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* Soft halo around the cover art in the light zone so the white
   cover has a visible frame — without it, the art panel melts
   into the page background. */
.zone--light .album__art {
  box-shadow:
    0 30px 80px -20px rgba(0,0,0,0.4),
    0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent),
    0 0 0 6px color-mix(in srgb, var(--accent) 6%, var(--bg));
}
.zone--light .album__art::after {
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
}
/* In the light zone, the eyebrow/number is a bit bolder so it
   reads against the soft cream bg. */
.zone--light .album__number {
  font-weight: 600;
  letter-spacing: 0.22em;
}
/* In the light zone, text colors are inherited from --ink (near-black)
   which is correct. The previous blurb italic was tuned for dark bg;
   override its color in the light zone so it doesn't read as washed-out
   dim gray on cream. */
.zone--light .album__blurb,
.zone--light .tagline {
  color: var(--ink-dim);
}
/* Tracklist numbers in the light zone need full opacity, the
   0.7 default was tuned for dark backgrounds. */
.zone--light .album__tracks li span {
  opacity: 1;
}
/* The CTA in the light zone: filled with accent on cream reads
   strong and matches the cover's red ink. */
.zone--light .album__cta {
  background: var(--accent);
  color: var(--bg-2);
  border-color: var(--accent);
}
.zone--light .album__cta:hover {
  background: color-mix(in srgb, var(--accent) 90%, var(--ink) 10%);
  color: var(--bg-2);
}

@media (max-width: 820px) {
  .album,
  .zone--reverse .album {
    grid-template-columns: 1fr;
  }
  .zone--reverse .album__art { order: 0; }
  .zone--reverse .album__body { order: 1; }
  .album__art { max-width: 360px; margin: 0 auto; }
  .album__tracks { grid-template-columns: 1fr; }
}

/* ============================================================
   ABOUT / CONTACT — settles back to neutral
   ============================================================ */
.zone--about { min-height: auto; padding-block: clamp(5rem, 10vh, 8rem); }
.section__header {
  max-width: var(--max);
  margin: 0 auto clamp(2rem, 5vw, 3.5rem);
  padding: 0;
}
.section__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2rem, 5vw, 3.5rem);
  letter-spacing: -0.02em;
  margin: 0 0 0.5rem;
  color: var(--ink);
}
.about__grid {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: start;
}
@media (max-width: 720px) {
  .about__grid { grid-template-columns: 1fr; }
}
.about__lede {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 2.2rem);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin: 0;
  color: var(--ink);
}
.about__body {
  font-size: 1.05rem;
  color: var(--ink-dim);
  line-height: 1.65;
  margin: 0;
}

.contact { margin-top: clamp(4rem, 8vw, 6rem); }
.contact__links {
  list-style: none;
  max-width: var(--max);
  margin: 0 auto;
  padding: 0;
  display: flex; flex-direction: column;
  gap: 0.6rem;
}
.contact__links a {
  display: inline-block;
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 2.5vw, 1.6rem);
  letter-spacing: -0.01em;
  color: var(--ink);
  border-bottom: 1px solid transparent;
  transition: all 250ms ease;
  padding-bottom: 0.1rem;
  width: max-content;
}
.contact__links a:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
  transform: translateX(4px);
}
.footer {
  max-width: var(--max);
  margin: 4rem auto 0;
  padding: 2rem 0 0;
  border-top: 1px solid var(--line);
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 1rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--ink-faint);
  text-transform: lowercase;
  letter-spacing: 0.05em;
}
.footer p { margin: 0; }
.footer__build { opacity: 0.6; }

/* ============================================================
   hamburger + mobile menu
   ============================================================ */
.nav-toggle {
  display: none;
  width: 44px; height: 44px;
  align-items: center; justify-content: center;
  flex-direction: column; gap: 4px;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  color: var(--ink);
  padding: 0;
  -webkit-tap-highlight-color: transparent;
}
.nav-toggle__bar {
  display: block;
  width: 18px; height: 2px;
  background: currentColor;
  border-radius: 1px;
  transition: transform 220ms ease, opacity 180ms ease;
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) {
  opacity: 0;
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

.nav-mobile {
  /* hidden by default, opens via JS by removing [hidden] */
  display: flex;
  flex-direction: column;
  padding: 1rem var(--pad) 1.5rem;
  background: color-mix(in srgb, var(--bg) 96%, transparent);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--line);
  position: relative;
  z-index: 99;
  /* Respect iOS safe area at the bottom. */
  padding-bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px));
}
.nav-mobile[hidden] { display: none; }
.nav-mobile a {
  display: block;
  padding: 0.85rem 0;
  font-family: var(--font-mono);
  font-size: 0.9rem;
  text-transform: lowercase;
  letter-spacing: 0.05em;
  color: var(--ink-dim);
  border-bottom: 1px solid var(--line);
  min-height: 44px;
  -webkit-tap-highlight-color: transparent;
}
.nav-mobile a:last-child { border-bottom: none; }
.nav-mobile a:hover, .nav-mobile a:focus-visible, .nav-mobile a:active {
  color: var(--accent);
}

/* ============================================================
   AUDIO PLAYER — yellow monk
   Click a track in the album list to play. Sticky transport
   bar docks at the bottom of the viewport once playback starts,
   styled to harmonize with whichever zone is currently active
   (reads --bg, --ink, --accent off :root).
   ============================================================ */

.album__tracks--playable {
  /* The <ol> stays; we just turn each <li> into a button host. */
  margin: 0;
}
.album__tracks--playable li {
  /* Override the default li flex layout so the button fills it. */
  border-bottom: 1px dashed color-mix(in srgb, var(--line) 60%, transparent);
  padding: 0;
}
.track {
  /* The whole row is a link (native file download). */
  display: flex;
  align-items: center;
  gap: 0.85rem;
  width: 100%;
  background: transparent;
  border: 0;
  padding: 0.55rem 0.4rem;
  margin: 0;
  font: inherit;
  color: var(--ink);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  border-radius: 4px;
  transition: background-color 180ms ease, color 180ms ease;
  font-family: var(--font-mono);
  font-size: 0.85rem;
}
.track:hover,
.track:focus-visible {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--accent);
  outline: none;
}
.track.is-playing {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.track.is-playing .track__num {
  /* Hide the static number when playing indicator is shown. */
  font-size: 0;
}
.track.is-playing .track__num::before {
  content: "◆";
  display: inline-block;
  font-size: 0.7rem;
  margin-right: 0.4rem;
  color: var(--accent);
  animation: gr-spin 1.6s linear infinite;
  transform-origin: center;
}
@keyframes gr-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .track.is-playing .track__num::before {
    animation: none;
  }
}
.track__num {
  color: var(--accent);
  font-size: 0.7rem;
  font-weight: 500;
  opacity: 0.7;
  min-width: 1.6rem;
}
.track__title {
  flex: 1;
}
.track__time {
  color: var(--ink-faint);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
}

.album__cta-row {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 0.5rem;
}

/* Play-album button — same pill as .album__cta but a real <button>
   element. Reset browser-default button styling. */
button.album__cta {
  cursor: pointer;
  font: inherit;
  text-decoration: none;
  appearance: none;
  -webkit-appearance: none;
}
button.album__cta:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Sticky transport bar — hidden until first playback. */
.transport {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90;
  background: color-mix(in srgb, var(--bg-2) 92%, black 8%);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid color-mix(in srgb, var(--accent) 25%, var(--line));
  color: var(--ink);
  box-shadow: 0 -10px 40px rgba(0, 0, 0, 0.45);
  transform: translateY(0);
  transition: transform 280ms cubic-bezier(0.4, 0, 0.2, 1),
              opacity 280ms ease;
  opacity: 1;
}
.transport[hidden] {
  display: none;
}
.transport__inner {
  max-width: var(--page-max, 1200px);
  margin: 0 auto;
  padding: 0.75rem 1.25rem;
  display: grid;
  grid-template-columns: auto 1fr auto auto auto;
  align-items: center;
  gap: 1rem;
  padding-bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px));
}
.transport__btn {
  background: transparent;
  border: 1px solid var(--accent);
  color: var(--accent);
  width: 38px;
  height: 38px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 0.95rem;
  padding: 0;
  transition: background-color 180ms ease, color 180ms ease;
}
.transport__btn:hover,
.transport__btn:focus-visible {
  background: var(--accent);
  color: var(--bg);
  outline: none;
}
.transport__btn--close {
  width: 28px;
  height: 28px;
  font-size: 1.1rem;
  border-color: var(--ink-faint);
  color: var(--ink-dim);
}
.transport__meta {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  min-width: 0; /* allow truncation */
  font-family: var(--font-mono);
}
.transport__num {
  font-size: 0.65rem;
  color: var(--accent);
  opacity: 0.85;
  letter-spacing: 0.05em;
}
.transport__title {
  font-size: 0.9rem;
  color: var(--ink);
  text-transform: lowercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.transport__album {
  font-size: 0.7rem;
  color: var(--ink-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.transport__progress {
  min-width: 0; /* allow the input to shrink */
}
.transport__seek {
  width: 100%;
  accent-color: var(--accent);
  cursor: pointer;
}
.transport__time {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.transport__time-sep {
  margin: 0 0.35rem;
  color: var(--ink-faint);
}

/* When the player is visible, push the page bottom up so the
   sticky bar doesn't permanently cover the footer. */
body.has-player .footer {
  padding-bottom: 5rem;
}

/* Mobile: stack the meta and progress on separate rows. */
@media (max-width: 720px) {
  .transport__inner {
    grid-template-columns: auto 1fr auto auto;
    grid-template-areas:
      "play meta time close"
      "seek  seek  seek seek";
    gap: 0.6rem 0.75rem;
    padding: 0.65rem 0.9rem;
  }
  .transport__btn--play { grid-area: play; }
  .transport__meta { grid-area: meta; }
  .transport__time { grid-area: time; }
  .transport__btn--close { grid-area: close; }
  .transport__progress { grid-area: seek; }
  .transport__album { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
