/*
  The Reckoners — rebuilt static site
  Phase 6B converted this from a 21-page site to one page
  (site/index.html); see notes/design-brief.md for the full spec and
  retired/README.md for what a 21-page build looked like. Base element
  styles below are minimal, generic fallbacks — every page-visible surface
  is scoped under body.redesign, the only body class this build now emits.
*/

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: 'Open Sans', Arial, sans-serif;
  font-size: 14px;
  color: #3d5054;
  background-color: #fff;
  line-height: 1;
}

a { color: #ffa300; text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4, h5, h6 {
  color: #3d5054;
  line-height: 1.2em;
  font-weight: normal;
  padding-bottom: 5px;
}
h1, h2, h3 { letter-spacing: -1px; }

p { padding-bottom: 10px; line-height: 24px; }
strong { font-weight: bold; color: #1c1c1c; }
em, i { font-style: italic; }

.container {
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  padding: 0 20px;
  position: relative;
}

/* ---------------- Embed / placeholder boxes ---------------- */
/* Generator safety net (scripts/build_site.py's replace_images()) — kept
   even though biography currently has zero <img> tags, so nothing emits
   this markup right now. Not dead code: it's still wired to fire if a
   future mirror/clean/biography edit ever reintroduces an image. */

.embed-placeholder, .missing-image {
  display: block;
  border: 2px dashed #d7dbdc;
  background: #f9f9f9;
  color: #8c8c8c;
  padding: 24px;
  margin-bottom: 20px;
  font-size: 14px;
  text-align: center;
}
.embed-placeholder strong, .missing-image strong { display: block; color: #3d5054; margin-bottom: 6px; }

html { scroll-behavior: smooth; }

/* ==================== Redesign (Phase 6A onward; single page since 6B) ====================
   Scoped entirely under body.redesign, the only body class this build
   emits. No third-party font/script/request of any kind: the font stack
   below is system-only, nothing is fetched for it.

   Palette (amendment 6 — inverted from the original near-black-ground
   design partway through Phase 6A, before any page shipped it): the
   primary ground is a pale warm blush sampled from the hero photo's own
   pale window region, so the page flows continuously from the photo with
   no seam at the fold. "Ink" is the text/rule color on that ground —
   amendment 8 delta replaced the original invented near-black with a deep
   warm brown sampled from the hero photo's own dark regions (guitar
   soundhole, window frame, hair — see notes/design-brief.md's "Ink
   sampling record"). The rose accent is one sampled hue at two lightnesses:
   links/rules directly on the blush ground (a darkened on-light variant),
   and — as of Phase 6B, human decision — a much paler tint of the same hue
   for the footer and full-screen nav overlay ground, with ink as the text
   on top of it (one hex can't clear 4.5:1 in both a light-bg-under-dark-text
   role and a dark-fg-on-light role, hence two lightnesses of one hue rather
   than one value doing both jobs). All values below are the
   sampled/computed record from notes/design-brief.md (source of truth for
   these numbers — keep in sync if either changes), not eyeballed:
     --ink (#44322A) on --blush (#F8E3CE):               9.72:1
     --rose-on-light (#7D5A45) on --blush:                4.93:1
     --ink (#44322A) on --rose-pale (#D0B8A9)
       — footer, nav overlay:                             6.40:1
     --ink on the hero photo's pale-window region,
       measured at the quote's actual rendered footprint
       at each required width — 1280/768/375:      9.75/10.03/9.86:1
*/

body.redesign {
  --blush: #F8E3CE;
  /* Amendment 8 delta: ink sampled from the hero photo's own dark regions
     (guitar soundhole, window frame, hair — averaged, not a single pixel).
     See notes/design-brief.md's "Ink sampling record". */
  --ink: #44322A;
  --rose-on-light: #7D5A45;
  /* Phase 6B (human decision): footer/nav-overlay ground is a pale rose
     tint of the SAME sampled hue/saturation as --rose-on-light (hue 22.8°,
     sat 29%), lightness-searched up to 0.74 — not a new sample, a paler cut
     of the existing one. Ink is the text color on this ground (inverse
     arrangement, The National's own footer pattern). See
     notes/design-brief.md's palette section. */
  --rose-pale: #D0B8A9;
  background: var(--blush);
  color: var(--ink);
  font-family: ui-monospace, "SF Mono", "Cascadia Code", "Source Code Pro",
    Menlo, Consolas, "Liberation Mono", monospace;
  line-height: 1.6;
}
body.redesign * { box-sizing: border-box; }
body.redesign a { color: var(--rose-on-light); text-decoration: none; }
body.redesign a:hover { text-decoration: underline; }
body.redesign h1, body.redesign h2, body.redesign h3 {
  color: var(--ink); font-weight: normal; letter-spacing: 0;
}
body.redesign hr {
  border: none; border-top: 1px solid var(--rose-on-light); margin: 28px 0;
}

/* Amendment 7: one shared type "voice" for all header/nav text and section
   headings — monospace (inherited), all-caps, wide tracking, one weight.
   0.1em tracking is mid-range of the brief's 0.08-0.15em band. */
body.redesign .voice,
body.redesign #overlay-nav a,
body.redesign .footer-nav a,
body.redesign .teaser-section h2 {
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
}

/* -------- header + nav-toggle (checkbox hack, no JS) -------- */

body.redesign #site-header .container {
  display: flex; align-items: center; justify-content: space-between;
  padding: 24px 20px;
}
body.redesign #site-header img#logo { max-width: 220px; height: auto; display: block; }
/* Light/cream logo variant (Phase 7 mid-run fix): the original hand-lettered
   logo is wood-toned ink — legible on the pale desktop/tablet garden photo,
   but unreadably dark against the mobile hero crop's darker regions. Rather
   than a CSS filter, a real recolored derivative (site/images/logo-light.png,
   master at assets/logo-light-master.png) swaps in at <=480px: same
   letterform/alpha mask, flat --blush fill instead of the photographed wood
   texture. #logo-light is hidden everywhere above that breakpoint. See
   notes/design-brief.md's "On-dark logo treatment" record for the sampling
   that led here and the contrast figures. */
body.redesign #site-header img#logo-light { max-width: 220px; height: auto; display: none; }

body.redesign .nav-toggle-input {
  position: absolute; opacity: 0; pointer-events: none;
  width: 1px; height: 1px;
}
/* Bare thin-stroke "+" glyph, not a bold icon-font plus — a plain monospace
   "+" character at a light weight reads as thin line-work already. Rotated
   45deg when checked (CSS-only, via the sibling selector below) so it
   visually becomes "×" — no separate open/closed glyph swap needed.

   Punch item d (Phase 6B): pinned to a fixed on-screen position (top-right
   corner, via the header's own layout — flex justify-content:space-between
   keeps it pinned there at every width) and colored per-breakpoint against
   the ACTUAL sampled hero-photo pixels behind it, not a single assumed
   color — see the per-breakpoint color overrides further down and
   notes/design-brief.md's "Nav glyph placement" record for the sampled
   values. No outline, halo, or plate: a soft text-shadow is added only as a
   legibility aid where the sampled region has some variance (thin
   decorative details crossing it), not as a substitute for picking the
   right flat color first. */
body.redesign .nav-toggle-label {
  position: relative; z-index: 101; /* above #overlay-nav's z-index:100, so
    this same glyph stays visible/clickable once the menu is open — the
    trigger toggles both directions, no separate "Close" element needed. */
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  width: 44px; height: 44px; /* generous hit area around a small glyph */
  /* Sampled directly against the rendered hero at 1280px: the glyph's
     fixed top-right position lands on the photo's dark window-frame edge
     there (avg RGB ~89,83,73) — --ink measures only 1.59:1 against it
     (illegible), --blush measures 6.12:1. Below 768px the same fixed
     position lands on the pale sky instead (avg RGB ~253,232,215, sampled
     at both 768 and 375) — --ink is correct there and is set in the
     @media override further down. Cream-on-dark by default, ink-on-pale
     below 768px — not one assumed color for both. See
     notes/design-brief.md's "Nav glyph placement" record. */
  color: var(--blush);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  font-family: inherit; font-weight: 300; font-size: 28px; line-height: 1;
  transition: transform 0.2s ease, color 0.2s ease;
}
body.redesign .nav-toggle-input:checked ~ #site-header .nav-toggle-label {
  transform: rotate(45deg);
  color: var(--ink);
  text-shadow: none;
}

body.redesign #overlay-nav {
  position: fixed; inset: 0; z-index: 100;
  background: var(--rose-pale);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity 0.2s ease;
}
body.redesign .nav-toggle-input:checked ~ #overlay-nav {
  opacity: 1; visibility: visible; pointer-events: auto;
}
body.redesign #overlay-nav ul {
  list-style: none; text-align: center; margin: 0; padding: 0;
  width: 100%; max-width: 480px;
}
body.redesign #overlay-nav li { border-bottom: 1px solid var(--ink); }
body.redesign #overlay-nav li:first-child { border-top: 1px solid var(--ink); }
body.redesign #overlay-nav a {
  display: block; padding: 18px 32px; color: var(--ink);
  font-size: 22px;
}

/* -------- hero + quote rotator -------- */
/* Amendment 4: text sits directly on the photo — no box, no background
   fill, no border. Measured directly against the actual photo pixels the
   text sits over (notes/design-brief.md), at each required viewport width
   (1280/768/375), against the amendment-8 ink: 9.75/10.03/9.86:1 (quote,
   ink) and 5.02/4.93/4.75:1 (attribution, --rose-on-light) — both
   comfortably clear AA at every width, so none of the fallback treatments
   (reposition / gradient scrim / text-shadow) were needed. */

body.redesign.home #site-header {
  position: absolute; top: 0; left: 0; right: 0; z-index: 102;
  /* Must exceed #overlay-nav's z-index:100 — setting a z-index here makes
     #site-header its own stacking context, which would otherwise trap
     .nav-toggle-label's z-index:101 *inside* it and cap the header's whole
     stack at whatever value sits here. Found via browser hit-test
     verification, not visual inspection alone — see
     notes/design-brief.md's nav bug-fix record. */
  background: transparent;
}
body.redesign.home #hero {
  position: relative;
  /* Fallback chain, deliberately two declarations: 100vh first (always
     supported, never collapses — the Phase 4 lesson this project already
     learned once about hero height) and 100svh second, which wins in
     browsers that support it and gives a more reliable full-bleed height
     on mobile Safari than 100vh alone (100vh there can include space the
     dynamic toolbar will cover). Unsupported browsers simply ignore the
     second declaration and keep the first — never a collapsed hero. */
  min-height: 100vh;
  min-height: 100svh;
  background-image: url(images/header-bg.jpg);
  background-size: cover; background-position: center top;
  background-repeat: no-repeat;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
/* Hidden above the mobile breakpoint by default — desktop's garden hero
   above is completely untouched by this rule; the @media (max-width:480px)
   block further down is what makes this visible and covers #hero there. */
body.redesign .hero-mobile-bg { display: none; }
/* .quote-stage is a purely structural wrapper — zero background, zero
   border, zero padding of its own — that exists only to give the stacked,
   absolutely-positioned .quote elements a sized, positioned ancestor to
   fill. Without it, position:absolute children opt out of #hero's flex
   centering entirely. */
body.redesign.home .quote-stage {
  position: relative;
  width: 100%; max-width: 720px;
  min-height: 140px;
}
body.redesign.home .quote {
  position: absolute; inset: 0;
  padding: 0 20px;
  opacity: 0;
  text-align: center;
}
/* Graceful degradation: the first quote is the rest-state default (opacity
   1 with no animation applied) — if @keyframes never run (old browser,
   prefers-reduced-motion), this is what stays on screen: one complete,
   legible, attributed quote, never blank. */
body.redesign.home .quote:first-of-type { opacity: 1; }
body.redesign.home .quote p {
  font-size: 30px; font-weight: 700; letter-spacing: 0.02em;
  line-height: 1.4; margin: 0 0 16px; color: var(--ink);
}
body.redesign.home .quote cite {
  color: var(--rose-on-light); font-style: normal;
  font-size: 14px; text-transform: uppercase; letter-spacing: 0.1em;
}

@media (prefers-reduced-motion: no-preference) {
  body.redesign.home .quote { animation: quote-cycle 32s infinite; }
  body.redesign.home .quote:nth-of-type(1) { animation-delay: 0s; }
  body.redesign.home .quote:nth-of-type(2) { animation-delay: 8s; }
  body.redesign.home .quote:nth-of-type(3) { animation-delay: 16s; }
  body.redesign.home .quote:nth-of-type(4) { animation-delay: 24s; }
}
@keyframes quote-cycle {
  0%   { opacity: 0; }
  3%   { opacity: 1; }
  22%  { opacity: 1; }
  25%  { opacity: 0; }
  100% { opacity: 0; }
}

/* -------- content column width (layout rider) -------- */
body.redesign .container { max-width: 1200px; }

/* -------- section pattern (amendment 3 / layout rider): full-width rules
   above and below each section heading, heading centered between them -------- */

body.redesign .teaser-section { padding: 56px 0; border-bottom: 1px solid var(--rose-on-light); }
body.redesign .teaser-section:last-of-type { border-bottom: none; }
body.redesign .teaser-section hr { margin: 0; }
body.redesign .teaser-section h2 { font-size: 18px; text-align: center; padding: 20px 0; }

/* News-entry pattern: narrow label column left, content right. Single
   column below 768px (layout rider point 2). Used by Biography's grouped
   paragraphs. */
body.redesign .entry-row {
  display: grid; grid-template-columns: 140px 1fr; gap: 24px;
  padding: 24px 0; border-bottom: 1px solid var(--rose-on-light);
}
body.redesign .entry-row:last-of-type { border-bottom: none; }
body.redesign .entry-label {
  font-size: 13px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--rose-on-light); padding-top: 4px;
}
body.redesign .entry-content { min-width: 0; }

/* -------- Music -------- */

body.redesign .release-full { padding: 32px 0; border-bottom: 1px solid var(--rose-on-light); }
body.redesign .release-full:last-child { border-bottom: none; }
/* Cover art restored to the release row in Phase 7 — see the code comment
   in render_music_section() for why this isn't a duplicate of the
   Bandcamp embed's own small artwork chrome further down the row. */
body.redesign .release-full-head {
  margin-bottom: 20px; display: flex; align-items: center; gap: 16px;
}
body.redesign .release-cover {
  width: 72px; height: 72px; flex: 0 0 auto; display: block;
  object-fit: cover;
}
body.redesign .release-full-head h3 { font-size: 16px; }
body.redesign .release-year { font-size: 14px; font-weight: normal; color: var(--rose-on-light); text-transform: none; letter-spacing: 0; }
body.redesign .bandcamp-embed { margin-bottom: 15px; }
body.redesign .tracklist {
  list-style: decimal;
  margin: 0 0 15px 22px;
  padding-bottom: 15px;
  border-bottom: 1px solid var(--rose-on-light);
}
body.redesign .tracklist li { font-size: 15px; padding: 4px 0; }
body.redesign .credits p { font-size: 13px; padding-bottom: 6px; color: var(--rose-on-light); }
body.redesign .credits strong { color: var(--ink); }
/* Content amendment: streaming links are now hairline-outline buttons
   (amendment 5 exception — same idiom as elsewhere), not plain text links. */
body.redesign .streaming-links { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 12px; }
/* Layout rider point 3 ("amendment 5 exception"): hairline-outlined text
   buttons are permitted — a 1px ink border and transparent fill are rules,
   not a filled/shadowed/rounded panel. */
body.redesign .btn-outline {
  display: inline-block; padding: 10px 20px;
  border: 1px solid var(--ink); color: var(--ink); font-size: 13px;
  background: transparent;
}
body.redesign .btn-outline:hover { background: var(--ink); color: var(--blush); text-decoration: none; }

/* -------- Video: CSS-only scroll-snap carousel (no JS, no arrows, no
   autoplay) -------- */

body.redesign .carousel {
  display: flex; overflow-x: auto; gap: 24px;
  scroll-snap-type: x mandatory;
  padding: 8px 20px 24px;
  margin: 0 auto; max-width: 1200px;
  -webkit-overflow-scrolling: touch;
  /* Polish item 2 (Phase 7): a branded, always-visible scrollbar rather
     than the browser default or a hidden one — the carousel has no
     arrows, so the scrollbar is the only persistent affordance that this
     row scrolls. Firefox/standards via scrollbar-color (thumb, then
     track); WebKit/Blink via the ::-webkit-scrollbar rules below. Palette
     only: --rose-on-light thumb, --blush track (transparent falls back to
     the section's own blush ground). */
  scrollbar-color: var(--rose-on-light) var(--blush);
  scrollbar-width: thin;
}
body.redesign .carousel::-webkit-scrollbar { height: 10px; }
body.redesign .carousel::-webkit-scrollbar-track { background: var(--blush); }
body.redesign .carousel::-webkit-scrollbar-thumb {
  background-color: var(--rose-on-light);
  border-radius: 0; /* rule-heavy, not pill-shaped — matches the hairline/no-rounded-corner idiom used everywhere else */
  border: 2px solid var(--blush); /* creates comfortable visual padding around the thumb without a taller track */
}
body.redesign .carousel-item {
  flex: 0 0 80%; max-width: 480px; scroll-snap-align: start;
}
body.redesign .carousel-item p.video-title {
  font-size: 14px; font-weight: normal; padding-top: 10px; padding-bottom: 0;
  color: var(--ink);
}

/* -------- Press: native <details>/<summary> accordions, ruled list -------- */

body.redesign .press-list { max-width: 800px; margin: 0 auto; }
body.redesign .press-item {
  border-bottom: 1px solid var(--rose-on-light); padding: 20px 0;
}
body.redesign .press-item:first-of-type { border-top: 1px solid var(--rose-on-light); }
body.redesign .press-item summary {
  cursor: pointer; font-size: 15px; list-style: none;
}
body.redesign .press-item summary::-webkit-details-marker { display: none; }
body.redesign .press-item summary::before { content: "+ "; }
body.redesign .press-item[open] summary::before { content: "− "; }
body.redesign .press-quote { color: var(--ink); }
body.redesign .press-source {
  display: block; margin-top: 6px; color: var(--rose-on-light);
  font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em;
  font-weight: normal;
}
body.redesign .press-body { padding-top: 16px; max-width: 68ch; }
body.redesign .press-body p {
  font-family: 'Iowan Old Style', Georgia, serif;
  font-size: 16px; line-height: 1.6; color: var(--ink);
}

/* -------- Biography: serif body copy, two-column gutter, pull-quotes,
   reserved lead-image slot (punch list item b) -------- */

body.redesign .bio-accordion { border: none; }
body.redesign .bio-accordion summary {
  cursor: pointer; list-style: none; text-align: center;
  font-size: 14px; padding: 8px 0 32px;
}
body.redesign .bio-accordion summary::-webkit-details-marker { display: none; }
body.redesign .bio-accordion summary::after { content: " +"; }
body.redesign .bio-accordion[open] summary::after { content: " −"; }

/* Reserved lead-image slot: zero visible footprint while empty (no
   border/background/min-height), so its absence is genuinely graceful, not
   a visible gap. When the media phase supplies a photo, an <img> goes
   inside this div and this rule's :empty guard stops applying. */
body.redesign .bio-lead-image:empty { display: none; }
body.redesign .bio-lead-image img {
  display: block; width: 100%; max-width: 800px; height: auto;
  margin: 0 auto 32px;
}

/* Punch item b: readable serif body copy, ~17-18px, line-height ~1.65,
   measure capped ~70ch — monospace voice is retained for headings, nav,
   labels, dates, attributions, and pull-quotes only, never for prose. */
body.redesign .bio-body .entry-content p {
  font-family: 'Iowan Old Style', Georgia, serif;
  font-size: 17px; line-height: 1.65; max-width: 70ch;
  color: var(--ink);
}
body.redesign .bio-pull-quote {
  text-align: center; padding: 40px 0; margin: 0;
  border-top: 1px solid var(--rose-on-light);
  border-bottom: 1px solid var(--rose-on-light);
}
body.redesign .bio-pull-quote p {
  font-size: 26px; font-weight: 700; letter-spacing: 0.01em;
  line-height: 1.4; max-width: 20ch; margin: 0 auto; color: var(--ink);
}

/* -------- footer -------- */

body.redesign #site-footer { background: var(--rose-pale); color: var(--ink); }
body.redesign #site-footer .container { padding: 48px 20px; max-width: 1200px; }
body.redesign .footer-nav {
  list-style: none; margin: 0 0 32px; padding: 0;
  display: flex; flex-wrap: wrap; gap: 4px 24px;
}
body.redesign .footer-nav li { border-bottom: 1px solid var(--ink); flex: 0 0 auto; }
body.redesign .footer-nav a { display: block; padding: 10px 0; color: var(--ink); font-size: 14px; }
body.redesign .footer-social { display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 24px; }
/* Polish item 1 (Phase 7): a link distinguished only by color fails the
   "more than color" rule wherever it sits in prose/credits/accordion
   context. footer-social's own color (--ink) doesn't even contrast against
   the rest of the footer's ink text, so it needed a non-color signal on
   top of the uppercase/letter-spacing treatment it already had —
   underline, not a border, to stay a plain label row rather than turning
   into a second row of buttons next to the streaming .btn-outline set. */
body.redesign .footer-social a {
  color: var(--ink); font-size: 13px; text-transform: uppercase;
  letter-spacing: 0.08em; text-decoration: underline;
}
body.redesign .footer-contact {
  font-family: 'Iowan Old Style', Georgia, serif; font-size: 14px;
  margin: 0 0 16px; color: var(--ink);
}
/* Polish item 1: the "Facebook" link inside this prose sentence was
   color-only (rose-on-light against ink prose) with no other signal in
   its default state — underline fits the serif/print voice of the
   sentence it's inside, per the human decision for this fix. */
body.redesign .footer-contact a { text-decoration: underline; }
body.redesign .footer-credit { font-size: 13px; margin: 0; color: var(--ink); }

/* -------- Responsive -------- */

@media (max-width: 768px) {
  body.redesign #site-header .container { padding: 16px; }
  body.redesign #site-header img#logo { max-width: 160px; }
  body.redesign #overlay-nav a { font-size: 19px; padding: 14px 24px; }
  body.redesign.home .quote p { font-size: 23px; }
  body.redesign .entry-row { grid-template-columns: 1fr; gap: 8px; }
  body.redesign .entry-label { padding-top: 0; }
  body.redesign .carousel-item { flex-basis: 88%; }
  /* Punch item d: at 768px and below, the glyph's fixed position lands on
     the photo's pale sky (sampled directly, not assumed — see
     notes/design-brief.md's "Nav glyph placement" record), where --ink is
     the correct color, not --blush (the default set above for the
     dark-region case at wider viewports). */
  body.redesign .nav-toggle-label { color: var(--ink); text-shadow: 0 1px 3px rgba(248, 227, 206, 0.65); }
  body.redesign .nav-toggle-input:checked ~ #site-header .nav-toggle-label { text-shadow: none; }
}
@media (max-width: 480px) {
  body.redesign #site-header img#logo { max-width: 130px; display: none; }
  /* Superseded the earlier drop-shadow-on-the-original-logo approach: a
     phone check found it wasn't actually legible against the mobile crop's
     dark regions. This swaps to the real recolored derivative instead —
     see the base #logo-light rule above and notes/design-brief.md's
     "On-dark logo treatment" record for the contrast figures. */
  body.redesign #site-header img#logo-light { max-width: 130px; display: block; }
  body.redesign .nav-toggle-label { width: 36px; height: 36px; font-size: 24px; }
  body.redesign #overlay-nav a { font-size: 17px; padding: 12px 20px; }
  body.redesign.home .quote p { font-size: 19px; }
  body.redesign .carousel-item { flex-basis: 92%; }
  body.redesign .bio-pull-quote p { font-size: 21px; }
  /* Mid-run fix (Phase 7): SPOTIFY/APPLE MUSIC/BANDCAMP in one row, not a
     vertical stack, at mobile widths — human decision. flex:1 with
     min-width:0 gives each button an equal, shrinkable share of the row so
     the three fit together; the base .streaming-links flex-wrap:wrap
     (unchanged) is what provides the approved 2+1 fallback automatically
     if a given width genuinely can't fit all three — see
     notes/design-brief.md for which widths were actually tested and
     whether the wrap ever engaged. */
  body.redesign .streaming-links { gap: 8px; }
  body.redesign .streaming-links .btn-outline {
    flex: 1 1 0; min-width: 0;
    padding: 14px 6px; font-size: 11px; text-align: center;
  }

  /* -------- Mobile hero art direction (Phase 7) --------
     Portrait crop of hero-mobile-hands.png (accordion keys foreground,
     guitar behind), human-supplied, warm-graded at the image level (see
     the code comment in render_hero(), scripts/build_site.py, and
     notes/design-brief.md for the documented R/G/B gain values — no CSS
     color filter is used for the grade itself). Desktop's #hero
     background-image is completely untouched; this layer only exists,
     and is only shown, at this breakpoint. */
  body.redesign.home #hero { position: relative; }
  body.redesign .hero-mobile-bg {
    display: block; position: absolute; inset: 0; z-index: 0;
    overflow: hidden;
  }
  body.redesign .hero-mobile-bg img {
    width: 100%; height: 100%; object-fit: cover;
    /* Favors the accordion (left-of-center in the source crop) slightly
       over dead-center, since a narrow mobile viewport crops the sides of
       the 900x1079 source more aggressively than it crops the top/bottom —
       verified in-browser against the actual rendered crop at 375px, not
       assumed. See notes/design-brief.md's "Mobile hero art direction"
       record. */
    object-position: 46% center;
    display: block;
  }
  body.redesign.home .quote-stage { position: relative; z-index: 1; }
  /* Ink overrides for the mobile photo specifically — sampled against the
     actual rendered crop at 375px (not reused from the desktop garden
     photo's own sampled values, which describe a different image). See
     notes/design-brief.md's "Mobile hero art direction" record for the
     sampled regions, raw RGB, and computed contrast ratios. */
  /* text-shadow as a legibility aid on top of the measured color choice —
     same idiom already used for the nav glyph, not a substitute for
     picking the right flat color first. Added after per-pixel sampling
     (notes/design-brief.md) showed the attribution's worst-case footprint
     crossing a brighter edge of the accordion body at some scroll/quote
     combinations. */
  body.redesign.home .quote p { color: var(--blush); text-shadow: 0 1px 4px rgba(0, 0, 0, 0.5); }
  body.redesign.home .quote cite { color: var(--rose-pale); text-shadow: 0 1px 4px rgba(0, 0, 0, 0.5); }
  body.redesign .nav-toggle-label {
    color: var(--blush);
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
  }
  body.redesign .nav-toggle-input:checked ~ #site-header .nav-toggle-label {
    color: var(--ink); text-shadow: none;
  }

  /* Safe-area handling (mid-run fix, Phase 7): a phone check found the
     hero photo stopping short of the physical top of the screen, with the
     page background showing in the status-bar/notch region above it. Two
     separate causes, both fixed: (1) the <meta viewport> tag was missing
     viewport-fit=cover — without it, iOS never extends page layout under
     the safe areas at all, and every env(safe-area-inset-*) value below
     evaluates to 0 regardless of what's written here (fixed in
     render_page()/render_404_page(), scripts/build_site.py); (2) insets
     had been applied to #hero itself, which was unnecessary for the photo
     (background-image paints under padding by default — padding only
     insets #hero's flex-centered *content*) but is exactly wrong per the
     human decision here: the PHOTO must bleed full to the physical top,
     and insets apply only to the overlaid elements that actually need to
     clear the notch (the header — logo/glyph — and the quote text), not
     to the hero container as a whole. */
  body.redesign #site-header {
    padding-top: env(safe-area-inset-top);
  }
  body.redesign #site-header .container {
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
  }
  body.redesign.home .quote {
    padding-left: max(20px, env(safe-area-inset-left));
    padding-right: max(20px, env(safe-area-inset-right));
  }
}

/* -------- 404 page (Phase 7 deploy prep) -------- */
/* On-brief, not a bare error page: ink on blush, monospace (inherited),
   the logo, and a way home — nothing else. */
body.redesign .not-found {
  min-height: 100vh; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center;
  gap: 20px; padding: 20px;
}
body.redesign .not-found-logo { max-width: 220px; height: auto; }
body.redesign .not-found h1 { font-size: 48px; letter-spacing: 0.05em; }
body.redesign .not-found p { color: var(--ink); }
