/* ==========================================================================
   Steven Cali — "That's How It Starts" era site · REDESIGN v2 (cinematic)
   + v2.1 GRIT PASS (2026-07-07, client note: "grittier"): heavier film
   grain, punched photo grades + vignetted veils, 7px card edges, short hard
   shadows, tighter/heavier serif set, dirtier glass nav, hotter rim-glow,
   dashed ticket-stub calendar hairlines. All contrast floors recomputed and
   held (see inline notes).
   Dark cinematic outlaw country, editorial serif headlines (Fraunces),
   glass pill nav, full-bleed photo slots. Palette + rules per
   brand/copy-style-guide.md and research/ui-accessibility-brief.md (binding).
   AMBER (#e8a33d) ISOLATION RULE: amber appears ONLY on Spotify CTAs,
   active/focus states, and the hero rim-glow art. Nowhere else. Ever.
   Amber FILLS are rarer still: the hero primary is the only amber fill in
   the first viewport — the nav Play pill is an off-white pill on purpose,
   and the sticky listen bar's amber fill appears only after the hero
   (and its amber CTA) scrolls out of view.
   NO inline styles anywhere — everything lives here (CSP: style-src 'self').
   ========================================================================== */

/* ---------- Fonts (self-hosted WOFF2, latin subsets, font-display: swap) -- */
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/fraunces-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/fraunces-latin-600-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/inter-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/inter-latin-600-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/inter-latin-700-normal.woff2") format("woff2");
}
/* Rye — ornate western circus-poster display face (hero H1 + proof numerals
   ONLY; client-picked from the specimen sheet 2026-07-07, replacing Vast
   Shadow as the "Country Roads"-reference face). Single weight (400). Rye
   has NO built-in drop shadow, so the H1/proof rules add a hard-offset
   text-shadow to echo the reference. */
@font-face {
  font-family: "Rye";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/rye-latin-400-normal.woff2") format("woff2");
}
/* Metric-matched local fallbacks — keep CLS near zero during font swap. */
@font-face {
  font-family: "Fraunces Fallback";
  src: local("Georgia"), local("Times New Roman"), local("Times");
  size-adjust: 103%;
  ascent-override: 95%;
  descent-override: 25%;
  line-gap-override: 0%;
  font-display: swap;
}
@font-face {
  font-family: "Inter Fallback";
  src: local("Arial"), local("Helvetica Neue"), local("Helvetica");
  size-adjust: 107%;
  ascent-override: 90.5%;
  descent-override: 22.5%;
  line-gap-override: 0%;
  font-display: swap;
}
/* Rye runs a touch wide of Times-metric serifs: the uppercase hero strings
   measure 113.1–114.1% of the same strings in a Times-metric serif
   (computed from the woff2 hmtx tables → size-adjust 113.5%); overrides =
   Rye's real vertical metrics (asc 2020 / desc 540 @ 2048 UPM) ÷ size-adjust. */
@font-face {
  font-family: "Rye Fallback";
  src: local("Georgia"), local("Times New Roman"), local("Times");
  size-adjust: 113.5%;
  ascent-override: 86.9%;
  descent-override: 23.2%;
  line-gap-override: 0%;
  font-display: swap;
}

/* ---------- Tokens --------------------------------------------------------- */
:root {
  --bg: #0d0b09;            /* near-black warm canvas */
  --bg-raised: #171310;     /* cards, raised surfaces */
  --text: #f2ede4;          /* warm off-white, ~15:1 on bg */
  --text-muted: #b3a99a;    /* ~7:1 floor — never darker */
  --text-glass: #d5cdbf;    /* link tone on glass pills — ≥4.5:1 worst case */
  --accent: #e8a33d;        /* AMBER — Spotify CTAs + active states ONLY */
  --accent-deep: #b4741f;   /* amber hover/borders, non-text UI only */
  --btn-ink: #141008;       /* text on amber fills */
  --hairline: #322d26;      /* decorative dividers only (<3:1 by design) — darkened in the grit pass */
  --border-strong: #8a7f6a; /* meaningful UI borders — ≥3:1 vs bg + veils (WCAG 1.4.11) */
  --card-line: #262019;     /* decorative card edges */
  --glass: rgb(13 11 9 / .94);        /* pill fallback (no backdrop-filter) */
  --glass-blur: rgb(13 11 9 / .88);   /* pill when backdrop-filter works — dirtier/more opaque (grit pass) */
  --display: "Fraunces", "Fraunces Fallback", Georgia, "Times New Roman", serif;
  --display-western: "Rye", "Rye Fallback", Georgia, "Times New Roman", serif; /* hero + proof numerals ONLY */
  --body: "Inter", "Inter Fallback", -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --radius-card: 7px;                 /* grit pass: was 16px — harder edges */
  --shadow-card: 0 14px 24px -14px rgb(0 0 0 / .8), 0 2px 4px rgb(0 0 0 / .45); /* short + punchy, no soft glow */
  --bar-h: 64px;
  --maxw: 1200px;
}

/* ---------- Reset / base --------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html {
  color-scheme: dark;
  /* Sticky bars must never obscure anchor/focus targets (WCAG 2.4.11) */
  scroll-padding-top: calc(var(--bar-h) + 12px);
  scroll-padding-bottom: calc(var(--bar-h) + 24px);
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-tap-highlight-color: rgb(232 163 61 / .18);
  overflow-x: hidden;
}
img, svg, iframe { display: block; max-width: 100%; }
a { color: var(--text); }

/* ---------- Focus + skip link (WCAG 2.4.7 / 2.4.13) ------------------------ */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
/* Facade buttons fill overflow:hidden containers — an offset outline gets
   clipped. Draw the ring INSIDE, on a dark backing band so the amber stays
   ≥3:1 even over a white video thumbnail (6.13:1 computed worst case). */
.embed-facade .embed-btn:focus-visible,
.video-facade .video-play:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: -6px;
  box-shadow: inset 0 0 0 9px rgb(13 11 9 / .85);
}
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--text);
  color: var(--bg);
  font-weight: 700;
  padding: 14px 22px;
  text-decoration: none;
}
.skip-link:focus-visible { left: 12px; top: 12px; }

/* ---------- Film grain (static, ≤1KB inline SVG noise) ---------------------
   Grit pass: opacity .055 → .10, coarser anisotropic noise (baseFrequency
   0.55×0.74 instead of 0.82). Still a static tile — no animation, so it is
   inherently reduced-motion-safe. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  opacity: .10;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.55 0.74' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 200px 200px;
}

/* ---------- Layout helpers ------------------------------------------------- */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 20px; }
/* Editorial rhythm: LOW density, generous vertical air */
section { padding: clamp(72px, 10vw, 128px) 0; }
.section-head {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: -.025em;  /* grit pass: tighter serif headlines */
  font-size: clamp(2rem, 4.5vw, 3.2rem);
  line-height: 1.06;
  margin-bottom: 10px;
  text-wrap: balance;
}
.section-sub { color: var(--text-muted); font-size: .98rem; margin-bottom: 36px; }
.eyebrow {
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.helper { font-size: .82rem; color: var(--text-muted); margin-top: 8px; text-align: center; }

/* Thin hairline dividers between quiet editorial sections */
#about, #videos, #merch { border-top: 1px solid var(--hairline); }

/* ---------- Scroll reveal (armed by JS only; IO + reduced-motion gated).
   No-JS / no-IO / reduced-motion → content simply visible. ≤400ms. -------- */
@media (prefers-reduced-motion: no-preference) {
  body.reveal-armed .reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity .38s ease, transform .38s ease;
  }
  body.reveal-armed .reveal.is-in { opacity: 1; transform: none; }
}

/* ---------- Legacy .ph gray-plate placeholders: RETIRED 2026-07-08. The
   merch cards (their last user) now carry real product shots in standard
   .img-slot slots — no gray plates remain anywhere. ----------------------- */

/* ---------- PHOTO SLOTS — real client photos (assets/img/PHOTOS-README.md).
   .img-pending shows a warm gradient + faint SC monogram until the file
   loads; js/main.js removes the class on img load. On error the fallback
   simply stays (img is opacity:0 while pending, so no broken-image icon). -- */
.img-slot {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(130% 100% at 50% 0%, #221a12 0%, var(--bg-raised) 52%, #120e0b 100%);
}
.img-slot picture { display: block; width: 100%; height: 100%; }
.img-slot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.img-slot.img-pending img { opacity: 0; }
.img-slot.img-pending::before {
  content: "";
  position: absolute;
  inset: 0;
  opacity: .3;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23p)' opacity='0.16'/%3E%3C/svg%3E");
  background-size: 140px 140px;
}
/* The faint "SC" monogram is decorative and must never be announced by
   screen readers, so it renders only inside aria-hidden nodes: media slots
   with meaningful <img>s carry a dedicated aria-hidden .img-fallback
   overlay div (a sibling of the img — the img itself stays exposed with
   its alt text); .section-bg slots are aria-hidden wholesale, so the
   pseudo-element sits on them directly. */
.img-fallback { position: absolute; inset: 0; pointer-events: none; }
.img-slot.img-pending .img-fallback::after,
.section-bg.img-slot.img-pending::after {
  content: "SC";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(2.2rem, 6vw, 4rem);
  letter-spacing: .1em;
  color: rgb(242 237 228 / .12);   /* decorative monogram, intentionally faint */
}
/* Photo grades (grit pass): every photo gets a unifying warm-sepia wash,
   punched contrast and pulled-back saturation. B&W shots go harder —
   deeper blacks, stronger contrast. Grades only ever DARKEN the photos,
   so the scrim/veil contrast math below still holds worst-case. */
.img-slot:not(.bw) img { filter: sepia(.14) saturate(.82) contrast(1.08) brightness(.94); }
.img-slot.bw img { filter: sepia(.32) saturate(.85) contrast(1.14) brightness(.86); }
/* Cover art is EXEMPT from the photo grade — album/single covers must show
   their true colors (they're artwork, not photography). Same specificity as
   the grade rules, declared after, so it wins the cascade. */
.img-slot.cover-art img { filter: none; }
/* Merch product shots are ALSO exempt (like .cover-art): dark 1:1 studio
   renders that already match the site palette — the sepia grade would
   muddy the garment colors buyers need to see true. */
.img-slot.merch-art img { filter: none; }

/* Full-bleed section backgrounds (proof + shows) with a guaranteed veil */
.has-bg { position: relative; isolation: isolate; }
.section-bg {
  position: absolute;
  inset: 0;
  z-index: -2;
}
.section-bg img { position: absolute; inset: 0; }
/* Veil (grit pass): middle stays ≥.88 dark so text ≥4.5:1 and UI borders
   ≥3:1 even over pure-white highlights (computed: muted text 6.3:1, body
   text 12.6:1, strong borders 3.7:1 worst-case); a radial vignette layer
   crushes the edges for grit. Edges melt into --bg so sections blend. */
.section-veil {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% 50%, transparent 42%, rgb(13 11 9 / .6) 100%),
    linear-gradient(180deg,
      var(--bg) 0%,
      rgb(13 11 9 / .88) 22%,
      rgb(13 11 9 / .88) 78%,
      var(--bg) 100%);
}

/* ---------- Buttons (all tap targets ≥44px) ---------------------------------
   Grit pass: main CTAs went squarer (10px) — only the NAV pills stay pills. */
.btn {
  display: block;
  width: 100%;
  max-width: 520px;
  margin: 16px auto 0;
  min-height: 56px;
  padding: 16px 30px;
  border-radius: 10px;
  font-family: var(--body);
  font-size: 1.08rem;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  border: 0;
  transition: background-color .18s ease, border-color .18s ease, transform .18s ease;
}
/* Primary Spotify CTA — the ONLY amber fill in the first viewport (the
   sticky bar reuses the amber fill, but only after the hero scrolls out) */
.btn-spotify {
  background: var(--accent);
  color: var(--btn-ink);
}
.btn-spotify:hover { background: var(--accent-deep); }
/* Secondary Spotify CTA — translucent pill, amber border (still Spotify) */
.btn-spotify-ghost {
  background: rgb(23 19 16 / .55);
  color: var(--text);
  border: 1.5px solid var(--accent);
  min-height: 50px;
  padding: 12px 24px;
  font-size: 1rem;
}
.btn-spotify-ghost:hover { border-color: var(--accent-deep); background: rgb(232 163 61 / .1); }
/* Neutral ghost — non-Spotify actions (subscribe, booking, details). NO amber. */
.btn-ghost {
  background: rgb(23 19 16 / .55);
  color: var(--text);
  border: 1.5px solid var(--border-strong);
  min-height: 50px;
  padding: 12px 24px;
  font-size: 1rem;
}
.btn-ghost:hover { border-color: var(--text-muted); background: rgb(242 237 228 / .05); }

.text-link {
  display: inline-block;
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  font-size: .92rem;
  padding: 12px 8px;      /* ≥44px tap height */
  min-height: 44px;
}
.text-link:hover { color: var(--text); }

/* ==========================================================================
   0. FLOATING PILL NAV — wordmark + glass pill over the hero.
   Scrolls away with the hero; the sticky listen bar then takes over.
   Glass: translucent + backdrop-filter, solid-color fallback (CSP-safe).
   ========================================================================== */
.topnav {
  position: absolute;
  top: calc(14px + env(safe-area-inset-top, 0px));
  left: 0;
  right: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 0 calc(16px + env(safe-area-inset-right, 0px)) 0 calc(16px + env(safe-area-inset-left, 0px));
}
/* Wordmark chip now carries the circular badge LOGO (wired 2026-07-07) —
   white distressed "STEVEN CALI" badge on the same glass chip. The chip
   stays a home link; 5px pad + 48px logo = 58px hit area (≥44px). */
.wordmark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
  padding: 5px;
  border-radius: 999px;
  background: var(--glass);
  border: 1px solid rgb(242 237 228 / .14);
  text-decoration: none;
}
.wordmark img { display: block; width: 48px; height: 48px; }
.wordmark:hover { border-color: rgb(242 237 228 / .3); }
.nav-pill {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 5px;
  border-radius: 999px;
  background: var(--glass);
  border: 1px solid rgb(242 237 228 / .14);
}
/* Grit pass: dirtier glass — lower blur, more opaque dark, and a thin
   amber-tinted top hairline (inset, decorative — an extension of the hero
   rim-glow art, sanctioned by the client's grit brief; conveys nothing). */
.wordmark, .nav-pill { box-shadow: inset 0 1px 0 rgb(232 163 61 / .22); }
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .wordmark, .nav-pill {
    background: var(--glass-blur);
    -webkit-backdrop-filter: blur(7px);
    backdrop-filter: blur(7px);
  }
}
.pill-links { display: flex; align-items: center; }
.pill-links a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
  padding: 10px 14px;
  border-radius: 999px;
  color: var(--text-glass);    /* ≥4.5:1 over the glass, worst case (computed) */
  font-size: .85rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  text-decoration: none;
}
.pill-links a:hover { color: var(--text); background: rgb(242 237 228 / .08); }
.pill-play {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 10px 20px;
  margin-left: 4px;
  border-radius: 999px;
  background: var(--text);             /* off-white pill (16.3:1 ink contrast) —
                                          NOT amber: the hero primary keeps the
                                          only amber fill in the first viewport */
  color: var(--btn-ink);
  font-size: .88rem;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .18s ease;
}
.pill-play:hover { background: #fffdf8; }

/* Quiet in-flow site nav — MOBILE ONLY row under the hero copy.
   (Desktop gets the pill links above instead.) */
.site-nav {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 2px;
}
.site-nav a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
  padding: 10px 14px;
  color: var(--text-muted);
  font-size: .85rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
}
.site-nav a:hover { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
@media (min-width: 742px) {
  .site-nav { display: none; }   /* links live in the pill nav on desktop */
}
@media (max-width: 741px) {
  .pill-links { display: none; } /* pill collapses to wordmark + Play */
}
@media (max-width: 380px) {
  .wordmark img { width: 44px; height: 44px; }   /* chip = 54px, tap ≥44px */
  .pill-play { font-size: .82rem; padding: 10px 16px; }
}
@media (max-width: 340px) {
  /* 320px devices: keep logo chip + Play pill on one row, no overflow —
     54px chip + ~104px Play pill + gaps + 20px padding ≈ 188px ≪ 320 */
  .topnav { padding-left: 10px; padding-right: 10px; }
  .pill-play { padding: 10px 12px; font-size: .8rem; }
}

/* ==========================================================================
   1. HERO — single takeover, cinematic photo + rim glow
   ========================================================================== */
.hero {
  position: relative;
  isolation: isolate;
  min-height: 100vh;   /* fallback */
  min-height: 100svh;  /* stable small-viewport height, no URL-bar jump */
  display: flex;
  flex-direction: column;
  padding: calc(96px + env(safe-area-inset-top, 0px)) 0 28px; /* clears pill nav everywhere */
}
.hero-media {
  position: absolute;
  inset: 0;
  z-index: -3;
}
.hero-media img {
  position: absolute;
  inset: 0;
  object-position: 50% 20%;   /* real hero shot: subject's head sits ~upper third */
}
/* Scrim (grit pass, heavier): guarantees text contrast over any photo, incl.
   bright stage haze. Text zones (badge → helpers, ~30–75% down) sit over
   ≥.86 alpha → muted text 5.9:1 / body text 11.7:1 worst case (computed
   over pure white, before the darkening photo grade). */
.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: -2;
  background: linear-gradient(180deg,
    rgb(13 11 9 / .6) 0%,
    rgb(13 11 9 / .86) 30%,
    rgb(13 11 9 / .92) 72%,
    var(--bg) 100%);
  pointer-events: none;
}
/* Amber rim-glow arc rising from the lower-right (echoes the planet-rim
   light in the inspiration). Grit pass: hotter + textured via a third
   layered gradient. Still static, still above the scrim but behind all
   content. GEOMETRY-SAFE: every layer's falloff (72% / 60% / 65% stops)
   ends before the centered text column (≤63% right, ≤75% down), so the
   effective amber under text is ~0 and the scrim floor above holds. */
.hero-glow {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(52% 42% at 84% 106%, rgb(232 163 61 / .38) 0%, rgb(232 163 61 / .16) 45%, transparent 72%),
    radial-gradient(30% 22% at 88% 102%, rgb(255 196 92 / .18) 0%, transparent 60%),
    radial-gradient(95% 55% at 70% 114%, rgb(180 116 31 / .22) 0%, transparent 65%);
}
.hero-inner {
  width: 100%;
  max-width: 760px;
  margin: auto;           /* centers between pill nav and featured row */
  padding: 0 20px;
  text-align: center;
}
/* Centered pill badge above the headline (à la "First Commercial Flight") */
.hero-badge {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  max-width: 100%;
  margin-bottom: 22px;
  padding: 7px 16px 7px 8px;
  border-radius: 999px;
  background: rgb(13 11 9 / .7);
  border: 1px solid rgb(242 237 228 / .2);
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--text);
}
.badge-chip {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  padding: 3px 10px;
  background: var(--text);
  color: var(--btn-ink);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
}
.hero h1 {
  /* Western pass v2 (client-picked 2026-07-07): Rye, ALL-CAPS via
     text-transform (HTML text content untouched). Rye has no built-in
     shadow, so a subtle HARD-OFFSET drop shadow (no blur, near-black warm
     #1e1812) echoes the Country Roads reference. Paint-only — shadows
     don't affect layout, and every breakpoint holds ≥17px of slack. */
  font-family: var(--display-western);
  font-weight: 400;          /* Rye ships a single 400 weight */
  text-transform: uppercase;
  letter-spacing: 0;         /* no negative tracking — the ornate glyphs need air */
  text-shadow: 3px 3px 0 #1e1812;
  /* Rye is narrower than Vast Shadow, so the clamp is retuned from the
     woff2 hmtx metrics: "THAT'S HOW" (longest line) = 6.8325em. Computed
     line widths: 320px vp → 38.4px × 6.8325 = 262px (280 avail) · 360px vp
     → 43.2px × 6.8325 = 295px (320 avail) · 740px vp → 88.8px × 6.8325 =
     607px (700 avail) · cap 5.6rem → 612px (720 avail in .hero-inner). */
  font-size: clamp(2.4rem, 12vw, 5.6rem);
  line-height: 1.1;
  max-width: 7.5em;          /* "THAT'S HOW" = 6.83em ≤ 7.5em < "THAT'S HOW IT"
                                = 8.25em → deterministic two-line break:
                                "THAT'S HOW / IT STARTS" */
  margin: 0 auto 14px;
  text-wrap: balance;
}
.hero .sub {
  color: var(--text-muted);
  font-size: 1.05rem;
  max-width: 480px;
  margin: 0 auto;
}
.hero .sub, .hero .eyebrow { text-wrap: pretty; }

/* Two centered pill CTAs, side by side (stack ≤560px) */
.hero-ctas {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 30px;
}
.hero-ctas .btn { display: inline-flex; align-items: center; justify-content: center; width: auto; margin: 0; }
@media (max-width: 560px) {
  .hero-ctas { flex-direction: column; }
  .hero-ctas .btn { width: 100%; max-width: 520px; }
}

/* Spotify embed facade — slim glass card, click-to-load, space reserved */
.embed-facade {
  max-width: 520px;
  height: 152px;              /* Spotify track-embed height, reserved */
  margin: 26px auto 0;
  border-radius: var(--radius-card);
  overflow: hidden;
}
.embed-facade .embed-btn {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: rgb(23 19 16 / .6);
  border: 1px solid rgb(242 237 228 / .14);
  border-radius: var(--radius-card);
  color: var(--text-glass);
  font-family: var(--body);
  font-size: .92rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color .18s ease, color .18s ease;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .embed-facade .embed-btn { -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); }
}
.embed-facade .embed-btn:hover { color: var(--text); border-color: var(--border-strong); }
/* Cover thumb inside the facade button — decorative, aria-hidden. Fixed
   square well inside the reserved 152px, so zero layout shift; if the file
   ever 404s the alt="" img renders empty and the button reads as before. */
.embed-btn .facade-art {
  flex: 0 0 auto;
  width: 104px;
  height: 104px;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 10px rgb(0 0 0 / .45);
}
.embed-btn .facade-art img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 480px) {
  .embed-btn .facade-art { width: 84px; height: 84px; }
}
.embed-facade iframe { width: 100%; height: 152px; border: 0; }

/* Bottom-of-hero press row ("As featured by" — Omi partner-logos pattern) */
.hero-featured {
  width: 100%;
  max-width: var(--maxw);
  margin: 40px auto 0;
  padding: 0 20px;
  text-align: center;
}
.featured-label {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 14px;
}
.press-logos {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 34px;
  justify-content: center;
  align-items: center;
  list-style: none;
}
.press-logos li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  text-align: center;
}
/* Real outlet logos (pre-tinted ivory #f2ede4 PNGs, alpha). Static — not
   links, so no hover state. Height-locked, width auto from the intrinsic
   ratio (attrs match the display scale → zero CLS). At .75 opacity over
   the scrim's darkest press-row band the marks compute ≥8:1 vs the
   worst-case (scrim .92 over pure-white photo) — well past the 3:1
   graphical-object floor. */
.press-logos img {
  display: block;
  height: 30px;
  width: auto;
  max-width: 130px;   /* cap — The Daily Orange wordmark (501:120) must not dominate */
  object-fit: contain;
  opacity: .75;
}
.press-logos .logo-wide { height: 26px; }  /* Daily Orange: very wide, render a step smaller */
.press-logos .mark-sub { font-size: .7rem; letter-spacing: .06em; color: var(--text-muted); }

/* ==========================================================================
   2. STICKY LISTEN BAR — top desktop (after hero scroll-out), bottom mobile
   ========================================================================== */
.listenbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  min-height: var(--bar-h);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 8px 16px;
  padding-left: calc(16px + env(safe-area-inset-left, 0px));
  padding-right: calc(16px + env(safe-area-inset-right, 0px));
  background: rgb(13 11 9 / .92);
  border-bottom: 1px solid var(--hairline);
  transform: translateY(-100%);
  visibility: hidden;
  transition: transform .28s ease, visibility .28s;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .listenbar { background: rgb(13 11 9 / .84); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
}
.listenbar.is-visible { transform: translateY(0); visibility: visible; }
.listenbar .bar-title {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.02rem;
  letter-spacing: .01em;
  color: var(--text);
  white-space: nowrap;
}
.listenbar .bar-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 10px 22px;
  border-radius: 10px;  /* grit pass: squarer CTA (nav pills stay pills) */
  background: var(--accent);           /* Spotify CTA — amber allowed */
  color: var(--btn-ink);
  font-weight: 700;
  font-size: .95rem;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .18s ease;
}
.listenbar .bar-cta:hover { background: var(--accent-deep); }

/* ==========================================================================
   3. MORE MUSIC — flank photo + cover grid (newest 2×), every tile Spotify
   ========================================================================== */
.music-cols { display: grid; grid-template-columns: 1fr; gap: 20px; }
.music-flank {
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  aspect-ratio: 16 / 10;      /* mobile: wide banner crop */
}
.music-flank img { object-position: 50% 22%; }
@media (min-width: 960px) {
  .music-cols { grid-template-columns: minmax(250px, 1fr) 2.3fr; gap: 28px; align-items: stretch; }
  .music-flank { aspect-ratio: auto; height: 100%; min-height: 420px; }
}
.music-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 18px;
}
.tile {
  position: relative;
  display: block;
  text-decoration: none;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--bg-raised);
  border: 1px solid var(--card-line);
  box-shadow: var(--shadow-card);
  transition: border-color .18s ease, transform .18s ease;
}
.tile:hover { border-color: var(--border-strong); transform: translateY(-3px); }
.tile .cover { aspect-ratio: 1 / 1; border: 0; border-bottom: 1px solid var(--card-line); }
.tile-meta { padding: 16px 18px 18px; }
.tile-title {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.08rem;
  letter-spacing: 0;
  line-height: 1.18;
  color: var(--text);
}
.tile-sub { font-size: .82rem; color: var(--text-muted); margin-top: 4px; }
.tile-newest { grid-column: span 2; grid-row: span 2; }
.tile-newest .tile-title { font-size: clamp(1.5rem, 3vw, 2.1rem); }
.tile-newest .tile-sub { font-size: .9rem; }
.tile-flag {
  display: inline-block;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--text-muted);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  padding: 3px 10px;
  margin-bottom: 8px;
}
.grid-follow { max-width: 420px; margin-top: 36px; }

/* ==========================================================================
   4. PROOF + PRESS QUOTES — over the crowd photo (veiled)
   ========================================================================== */
.proof { border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
/* Western pass v2: the NUMBERS get Rye (echoes the hero; short strings, the
   28px floor holds — Rye's ornate inline detail needs it). Widths from the
   woff2 hmtx: "800+" = 2.6421em (widest) → 74px at the 28px floor, 110px at
   the 41.6px cap; widest span "800+ SHOWS" ≈ 167px — three spans + 2×56px
   gaps ≈ 590px on desktop, and the row stacks ≤480px, so no overflow at
   320/360. Labels stay tracked-out Inter caps. */
.proof-row {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 56px;
  justify-content: center;
  align-items: baseline;
  line-height: 1.1;
}
.proof-row span { white-space: nowrap; }
.proof-num {
  font-family: var(--display-western);
  font-weight: 400;
  font-size: clamp(1.75rem, 3.6vw, 2.6rem);   /* min 28px — legibility floor for Rye's inline detail */
  text-shadow: 2px 2px 0 #1e1812;             /* hard offset, no blur — echoes the hero H1 */
}
.proof-label {
  font-family: var(--body);
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--text);
  margin-left: 2px;
}
.shared-stages {
  text-align: center;
  color: var(--text-muted);
  font-size: .95rem;
  margin-top: 18px;
}
.press-quotes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  margin-top: 48px;
  list-style: none;
}
.press-quotes li {
  background: var(--bg-raised);
  border: 1px solid var(--card-line);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 28px 24px;
  text-align: center;
}
.press-quotes blockquote, .press-quotes .award-line {
  font-family: var(--display);
  font-weight: 600;          /* grit pass: heavier serif (was 400) */
  letter-spacing: -.01em;
  font-size: 1.22rem;
  line-height: 1.4;
  color: var(--text);
  text-wrap: balance;
}
.press-quotes .attrib {
  display: block;
  margin-top: 14px;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-muted);
  font-style: normal;
}

/* ==========================================================================
   5. ABOUT — forest + mic duo (side-by-side, offset), editorial columns.
   Re-cut 2026-07-07: the old stacked/overlapped pair towered ~870px over a
   ~250px bio, leaving a blank band. Now both portraits crop to 4:5 in a
   2-up grid with a 12px offset — media block ≈ 270px vs bio ≈ 248px at
   1280 (8.6% mismatch) and ≈ 266px at 1180 (7.0%), computed with real
   Inter metrics. Items stay top-aligned; grades + .img-pending unchanged.
   ========================================================================== */
.about-cols {
  display: grid;
  grid-template-columns: 1fr 1.6fr;   /* media narrowed (was 1.45fr) so the duo height ≈ bio height */
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
.about-media {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  align-items: start;
}
.about-portrait {
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
.about-portrait img { object-position: 50% 30%; }  /* 2:3 source in a 4:5 slot — keep the face high */
.about-mic {
  aspect-ratio: 4 / 5;
  margin-top: 12px;           /* offset duo, gallery-wall feel */
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
.about-mic img { object-position: 50% 28%; }       /* profile-at-the-mic sits upper-center */
.about-text p { max-width: 62ch; }
.about-text p + p { margin-top: 18px; }

/* ==========================================================================
   6. SHOWS — luxurious calendar rows over the string-lights crowd photo
   ========================================================================== */
/* Grit pass: calendar rows use dashed hairlines — reads like a torn ticket
   stub against the crowd photo. Purely decorative (rows aren't interactive
   boundaries), so the <3:1 hairline exemption still applies. */
.show-list { border-top: 1px dashed var(--hairline); }
.show-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 24px;
  padding: 26px 6px;
  border-bottom: 1px dashed var(--hairline);
  font-size: .98rem;
}
.show-row .date {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: 0;
  font-size: 1.08rem;
  min-width: 150px;
}
.show-row .venue { flex: 1 1 260px; font-weight: 600; }
.show-row .venue .city { display: block; font-weight: 400; color: var(--text-muted); font-size: .85rem; }
.show-row .when { color: var(--text-muted); font-size: .85rem; white-space: nowrap; }
.show-row .btn-details {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 10px 22px;
  border-radius: 8px;   /* grit pass: squarer (was pill) */
  border: 1.5px solid var(--border-strong);
  color: var(--text);
  font-weight: 700;
  font-size: .88rem;
  text-decoration: none;
  transition: border-color .18s ease;
}
.show-row .btn-details:hover { border-color: var(--text-muted); }
.shows-empty { color: var(--text-muted); padding: 24px 0; }
.btn-book { max-width: 420px; margin-top: 36px; }

/* ==========================================================================
   7. VIDEOS — click-to-play facades (youtube-nocookie injected on click)
   ========================================================================== */
.video-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
.video-facade {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--bg-raised);
  border: 1px solid var(--card-line);
  box-shadow: var(--shadow-card);
}
.video-facade img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(.4) contrast(1.12) sepia(.14) brightness(.78);  /* grit pass */
}
.video-facade iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.video-play {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  border: 0;
  background: linear-gradient(180deg, rgb(13 11 9 / .55), rgb(13 11 9 / .85));
  color: var(--text);
  cursor: pointer;
  font-family: var(--body);
}
.video-play .play-ring {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  border: 2px solid var(--text);
  background: rgb(13 11 9 / .75);
  font-size: 1.15rem;
  padding-left: 4px;
  transition: transform .18s ease, border-color .18s ease;
}
.video-play:hover .play-ring { transform: scale(1.06); }
.video-play .video-label {
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .04em;
  margin: 0 16px;
  padding: 6px 12px;
  border-radius: 999px;
  /* Pinned dark plate: label stays ≥4.5:1 even over a white thumbnail */
  background: rgb(13 11 9 / .78);
}

/* ==========================================================================
   8. MERCH — 6 product cards + "the guy behind the shirts" banner photo
   (2026-07-08: the flank moved from a side column to a full-width banner
   ABOVE the grid — a side flank can't stretch beside 3 rows of cards
   without a dead strip. Grid: 3×2 ≥960px, 2×3 below.)
   ========================================================================== */
.merch-cols { display: grid; grid-template-columns: 1fr; gap: 20px; }
.merch-flank {
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  aspect-ratio: 16 / 10;      /* mobile: wide banner crop */
}
.merch-flank img { object-position: 50% 25%; }
@media (min-width: 960px) {
  .merch-cols { gap: 28px; }
  .merch-flank { aspect-ratio: 21 / 9; }   /* desktop: cinematic banner */
}
.merch-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);   /* mobile + tablet: 2×3 */
  gap: 18px;
}
@media (min-width: 960px) {
  .merch-grid { grid-template-columns: repeat(3, 1fr); }  /* desktop: 3×2 */
}
.merch-card {
  background: var(--bg-raised);
  border: 1px solid var(--card-line);
  border-radius: var(--radius-card);
  overflow: hidden;
  text-align: center;
  padding-bottom: 20px;
  box-shadow: var(--shadow-card);
}
/* Product shot fills the card top edge-to-edge: 1:1, object-fit cover (via
   .img-slot img), no plate/frame — the near-black studio bg blends straight
   into the card. Hairline under the photo separates it from the label zone. */
.merch-card .merch-art { aspect-ratio: 1 / 1; border: 0; border-bottom: 1px solid var(--card-line); }
.merch-card h3 {
  font-family: var(--body);
  font-size: .95rem;
  font-weight: 600;
  margin: 16px 12px 4px;
}
.merch-card .price {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.12rem;
  letter-spacing: .01em;
  color: var(--text-muted);
}
.merch-card .avail { font-size: .78rem; color: var(--text-muted); margin-top: 2px; }
/* .price-foot RETIRED 2026-07-08 — prices are client-confirmed (v1.5), the
   "Final prices set with the store launch." footnote no longer renders. */
.merch-cta-line { text-align: center; margin-top: 14px; }

/* ==========================================================================
   9. SUBSCRIBE — outbound ghost button only (no on-site form)
   ========================================================================== */
.subscribe { text-align: center; border-top: 1px solid var(--hairline); }
.subscribe .section-head { margin-bottom: 6px; }
.subscribe .section-sub { margin-bottom: 4px; }
.btn-subscribe { max-width: 340px; }

/* ==========================================================================
   10. FOOTER
   ========================================================================== */
.site-footer {
  border-top: 1px solid var(--hairline);
  padding: 72px 0 52px;
  text-align: center;
}
.social-row {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
  list-style: none;
  margin-bottom: 10px;
}
.social-row a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  color: var(--text-muted);
  transition: border-color .18s ease, color .18s ease;
}
.social-row a:hover { border-color: var(--text-muted); color: var(--text); }
.social-row svg { width: 20px; height: 20px; fill: currentColor; }
.footer-cta { max-width: 420px; }
.footer-lines { margin-top: 30px; font-size: .88rem; color: var(--text-muted); }
.footer-lines p + p { margin-top: 8px; }
.footer-lines a {
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  display: inline-block;
  padding: 12px 6px;   /* ≥44px tap height */
}
.footer-lines a:hover { color: var(--text); }

/* ==========================================================================
   404 page
   ========================================================================== */
.page-404 {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 40px 20px;
}
.page-404 .logo-404 { width: 96px; height: 96px; margin-bottom: 20px; opacity: .92; }
.page-404 h1 {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: -.015em;
  font-size: clamp(2.4rem, 8vw, 4.5rem);
  line-height: 1.04;
  margin: 14px 0 10px;
}
.page-404 p { color: var(--text-muted); max-width: 46ch; }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width: 960px) {
  .music-grid { grid-template-columns: repeat(2, 1fr); }
  .video-row { grid-template-columns: 1fr; max-width: 640px; margin: 0 auto; }
  .press-quotes { grid-template-columns: 1fr; max-width: 560px; margin: 40px auto 0; }
  .about-cols { grid-template-columns: 1fr; max-width: 640px; margin: 0 auto; }
  /* Mobile: the duo stays 2-up above the bio (each portrait ≤313px wide,
     4:5 — taller feel returns naturally as the column widens). */
}
@media (max-width: 741px) {
  /* Sticky bar moves to fixed bottom thumb zone (CRO brief #8) */
  html {
    scroll-padding-top: 12px;
    scroll-padding-bottom: calc(var(--bar-h) + env(safe-area-inset-bottom, 0px) + 24px);
  }
  .listenbar {
    top: auto;
    bottom: 0;
    border-bottom: 0;
    border-top: 1px solid var(--hairline);
    padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    transform: translateY(100%);
  }
  .listenbar.is-visible { transform: translateY(0); }
  .listenbar .bar-title { display: none; }
  .listenbar .bar-cta { width: 100%; max-width: 520px; min-height: 48px; }
  body { padding-bottom: calc(var(--bar-h) + env(safe-area-inset-bottom, 0px)); }
  .hero { padding-top: calc(84px + env(safe-area-inset-top, 0px)); padding-bottom: 20px; }
  .hero-featured { margin-top: 32px; }
  .press-logos { gap: 8px 22px; }   /* logos may wrap to 2 rows ≤360px — clean by design */
  .press-logos img { height: 22px; max-width: 96px; }
  .press-logos .logo-wide { height: 19px; }
}
@media (max-width: 480px) {
  .music-grid { gap: 12px; }
  .tile-newest { grid-row: auto; }
  .proof-row { flex-direction: column; align-items: center; gap: 10px; }
  .merch-grid { gap: 12px; }
  .hero-badge { font-size: .78rem; }
}
/* Short landscape viewports: fixed bar would eat the viewport — hide it.
   Hero photo recrops to keep the subject visible in landscape. */
@media (max-height: 430px) {
  .listenbar { display: none; }
  body { padding-bottom: 0; }
  html { scroll-padding-bottom: 24px; }
}
@media (max-height: 500px) and (orientation: landscape) {
  .hero-media img { object-position: 50% 18%; }
}

/* ==========================================================================
   REDUCED MOTION — kill all animation (ui brief §5, binding)
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .tile:hover, .video-play:hover .play-ring { transform: none; }
}
