/* ============================================================
   Clap If You Don't Care — "Eric's Notes" design system
   Approved round 02 (concept 2b). See data/site.json and the
   clap-podcast-brand notes for the rules this file implements.

   Non-negotiables encoded here:
   - Four faces, four jobs, no overlap.
   - ONE highlighter swipe per view, never two.
   - Red-pen asides are VERBATIM transcript lines only.
   - No ruled/notepad paper texture. No emoji. No gradients.
   - Never two of the same colourway adjacent.
   ============================================================ */

:root {
  /* Palette — exact values from the approved system */
  --paper:        #F5EFE3;
  --ink:          #1F2A44;
  --highlighter:  #F5C518;
  --pen:          #D64545;
  /* The pen red at body size fails AA on paper (3.82:1), but --pen itself is
     not the thing to change: it matches the cover art, and the hero wordmark
     it was chosen for is large enough to pass on its own. So the display red
     stays exactly as approved and a slightly deeper one carries the small
     text - episode show-note links, the error line, the "just published" flag,
     and the pen button, where it is the GROUND under paper-coloured text and
     so needs the ratio in both directions.
     On the gold ground no red near the brand hue clears AA (--pen is 2.69:1
     there), so the one gold-ground hover gets a genuinely deep red rather than
     giving up the red entirely. */
  --pen-text:     #C43A3A;   /* 4.57:1 on paper, both as text and as ground */
  --pen-on-gold:  #8A2020;   /* 5.58:1 on gold */

  /* Contrast pass. Every value here is measured against the ground it is
     actually used on; the ratio is in the comment so a future tweak can see
     what it is spending. WCAG AA wants 4.5:1 for normal text.

     --muted-on-paper was #6D7688 (3.99:1) and is used sixteen times, including
     the main nav and every form label. Darkened just far enough to clear AA;
     the shift is barely visible and it fixes all sixteen at once. */
  --muted-on-paper: #5F6879;   /* 4.90:1 on paper */
  --muted-on-ink:   #8B95AB;   /* 4.74:1 on ink */

  /* One value, not two. This was --fine-on-gold (#8A6D0C, 3.01:1) for the
     LARGER handwriting labels and --fine-on-gold-deep (5.30:1) for the small
     print, which is backwards - the paler colour was carrying the text that
     needed help least. Consolidated on the one that passes. */
  --fine-on-gold: #5A4A1A;     /* 5.30:1 on gold */

  /* Derived, used sparingly */
  --paper-edge: #E3DACA;
  --ink-edge:   #33405E;

  --measure: 68ch;
  --shell: 1120px;
  --gap: clamp(1.25rem, 3vw, 2.5rem);
  --section-y: clamp(2.75rem, 6vw, 5rem);

  --font-head: "Gabarito", system-ui, sans-serif;
  --font-body: "Hanken Grotesk", system-ui, -apple-system, sans-serif;
  --font-hand: "Caveat", ui-rounded, cursive;
  --font-serif: "Instrument Serif", Georgia, serif;
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: clamp(1rem, .96rem + .2vw, 1.125rem);
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; height: auto; }
a { color: inherit; }

/* ---------- TYPE — four faces, four jobs ---------- */

/* Gabarito 900 — headlines ONLY */
h1, h2, h3, .head {
  font-family: var(--font-head);
  font-weight: 900;
  line-height: .9;
  letter-spacing: -.03em;
  text-wrap: balance;
}

h1 { font-size: clamp(2.75rem, 1.4rem + 6.4vw, 6.5rem); }
h2 { font-size: clamp(2rem, 1.2rem + 3.4vw, 3.75rem); }
h3 { font-size: clamp(1.35rem, 1.1rem + 1.1vw, 1.85rem); }

/* Hanken Grotesk — body + all fine print */
.fine {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  line-height: 1.3;
}

/* Caveat — handwriting: eyebrow + red-pen aside. Lowercase. Nothing else. */
.eyebrow, .aside {
  font-family: var(--font-hand);
  text-transform: lowercase;
}

/* Instrument Serif italic — ONLY the (n.) mark and the & in "Bops & the flops" */
.pos, .amp {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
}

/* ---------- SIGNATURE DEVICES ---------- */

/* 1. Highlighter swipe — one per view, never two */
.swipe {
  background: linear-gradient(transparent 12%, var(--highlighter) 12% 88%, transparent 88%);
  padding: 0 .18em;
  /* On ink grounds the swiped text flips to ink so it stays readable */
}
.ink .swipe, .ink-panel .swipe { color: var(--ink); }

/* A swipe that wraps renders as two separate bands, which reads as two
   highlights on the page even though it is one phrase. Keep short swipes
   intact. Only used where the phrase is short enough to never overflow. */
.nowrap { white-space: nowrap; }

/* 2. Red-pen aside — VERBATIM transcript lines only */
.aside {
  display: block;
  color: var(--pen-text);
  font-size: clamp(1.15rem, 1rem + .55vw, 1.5rem);
  line-height: 1.25;
  transform: rotate(-1deg);
  transform-origin: left center;
  max-width: 46ch;
}
.aside::before { content: "↳ "; font-family: var(--font-body); font-weight: 400; }
.aside cite {
  display: block;
  margin-top: .35rem;
  font-family: var(--font-body);
  font-style: normal;
  font-weight: 700;
  font-size: .68rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-on-paper);
  transform: rotate(1deg); /* counter-rotate so the credit sits straight */
}
.ink .aside cite { color: var(--muted-on-ink); }
.gold .aside cite { color: var(--fine-on-gold); }

/* 3. Eyebrow — lowercase Caveat top-left, optional note on the right.
   Sized up and taken to full ink at round 03: at 1.05-1.3rem in muted grey
   these read as decoration and disappeared against the ground. They are the
   section labels — the reader should be able to skim the page on them alone.
   Still Caveat, still lowercase; just no longer whispering. */
.eyebrow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  font-weight: 600;
  font-size: clamp(1.45rem, 1.2rem + 1.05vw, 2rem);
  line-height: 1.1;
  color: var(--ink);
  margin-bottom: clamp(1.25rem, 3vw, 2rem);
  border-bottom: 2px solid var(--paper-edge);
  padding-bottom: .4rem;
}
.eyebrow > span:last-child { white-space: nowrap; }
.ink .eyebrow { color: var(--paper); border-bottom-color: var(--ink-edge); }
.gold .eyebrow { color: var(--ink); border-bottom-color: rgba(90,74,26,.38); }

/* ---------- LAYOUT ---------- */
.shell { width: min(100% - 2.5rem, var(--shell)); margin-inline: auto; }
@media (min-width: 640px) { .shell { width: min(100% - 4rem, var(--shell)); } }

section { padding-block: var(--section-y); }

/* The first section already has the masthead above it. A full section's worth
   of top padding on top of that reads as a hole, not as breathing room. */
main > section:first-child { padding-top: clamp(1.5rem, 3vw, 2.5rem); }

/* A section that flows straight into the next one (same ground, no break)
   shouldn't pay full bottom padding as well. */
.section--continues { padding-bottom: clamp(1.75rem, 3.5vw, 2.75rem); }

/* Colourways — never two of the same adjacent */
.paper { background: var(--paper); color: var(--ink); }
.ink   { background: var(--ink);   color: var(--paper); }
.gold  { background: var(--highlighter); color: var(--ink); }

.ink .fine  { color: var(--muted-on-ink); }
.gold .fine { color: var(--fine-on-gold); }
.paper .fine { color: var(--muted-on-paper); }

/* A card carries its own paper ground wherever it is placed, so the colourway
   rules above must not follow it inside. They were: the six episode cards on
   the home page sit in an .ink section, and `.ink .fine` was painting each
   card's foot line ("Full episode · 15 min") in --muted-on-ink on paper —
   2.63:1, the worst contrast on the site, six times over on the busiest page.
   Anything else that keeps a paper ground inside a coloured section belongs
   in this selector too. */
.ink .card .fine,
.gold .card .fine { color: var(--muted-on-paper); }

.lede { max-width: var(--measure); font-size: clamp(1.05rem, 1rem + .45vw, 1.3rem); }

/* 3px rule above footers — the card skeleton signature */
.rule { border: 0; border-top: 3px solid currentColor; opacity: .18; margin-block: 1.25rem; }

/* ---------- HEADER ---------- */
.site-head {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--paper-edge);
}
.site-head__in { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding-block: .85rem; }
.wordmark {
  font-family: var(--font-head); font-weight: 900;
  font-size: clamp(1.05rem, .9rem + .6vw, 1.4rem);
  line-height: 1; letter-spacing: -.02em;
  text-transform: lowercase;
  text-decoration: none;
  white-space: nowrap;
}
/* The slashes are the joint, not the name — held back so "clap care" reads
   first. Never red: the hero wordmark on the home page owns that. */
.wordmark__slash { color: var(--muted-on-paper); margin-inline: .12em; }
.nav { display: flex; align-items: center; gap: clamp(.85rem, 2.5vw, 1.75rem); }
.nav a {
  font-weight: 700; font-size: .78rem; letter-spacing: .08em; text-transform: uppercase;
  text-decoration: none; color: var(--muted-on-paper);
  padding-block: .35rem; border-bottom: 2px solid transparent;
}

/* Five nav items plus a two-line wordmark cannot share one row on a phone -
   they overflow and CONTACT falls off the edge. Below this width the header
   becomes two rows: wordmark, then the nav spread across the full width. */
@media (max-width: 719px) {
  .site-head__in { flex-direction: column; align-items: stretch; gap: .7rem; padding-block: .7rem; }
  /* The wordmark gets its own row here, so it can breathe rather than being
     squeezed against the nav. */
  .wordmark { font-size: 1.25rem; line-height: 1; }
  .nav { width: 100%; justify-content: space-between; gap: .4rem; }
  .nav a { font-size: .7rem; letter-spacing: .05em; padding-block: .2rem; }
}
.nav a:hover { color: var(--ink); }
.nav a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--pen); }

/* ---------- BUTTONS ---------- */
.btn {
  display: inline-flex; align-items: center; gap: .5rem;
  font-weight: 700; font-size: .8rem; letter-spacing: .06em; text-transform: uppercase;
  text-decoration: none; padding: .7rem 1.15rem;
  border: 2px solid var(--ink); background: var(--ink); color: var(--paper);
  transition: transform .12s ease, background .12s ease, color .12s ease;
}
.btn:hover { transform: translateY(-2px); }
.btn--ghost { background: transparent; color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: var(--paper); }
.btn--pen { background: var(--pen-text); border-color: var(--pen-text); color: var(--paper); }
.ink .btn { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.ink .btn--ghost { background: transparent; color: var(--paper); }
.ink .btn--ghost:hover { background: var(--paper); color: var(--ink); }

.btn-row { display: flex; flex-wrap: wrap; gap: .7rem; }

/* ---------- HERO ---------- */
.hero { padding-block: clamp(2.5rem, 6vw, 5rem) var(--section-y); }
.hero__grid { display: grid; gap: var(--gap); align-items: end; }
@media (min-width: 900px) { .hero__grid { grid-template-columns: 1.35fr .9fr; } }

/* Red, and only here. It matches the cover art, and it is the one place on the
   site big enough to carry the pen colour as a field rather than an accent.
   At clamp(2.75rem…6.5rem) this clears WCAG AA for large text on paper. */
.hero h1 { color: var(--pen); margin-bottom: 1.25rem; }
.hero__tag { font-size: clamp(1.15rem, 1rem + .85vw, 1.75rem); font-weight: 600; max-width: 26ch; line-height: 1.25; }
/* The hosts, cut out, running off the bottom edge of the section.

   No border: a 3px frame is for cover art, and a framed cutout reads as a
   sticker rather than as two people standing there.

   The WRAPPER holds the square footprint the cover art used to occupy, so the
   grid row is exactly as tall as it was and the left column does not move by
   a single pixel. The photo itself is taken out of flow inside it and hangs
   past the bottom, where the section's overflow clips it. Doing the bleed with
   a negative margin instead shortens the row, and the whole left column
   silently rides up with it. */
.hero { overflow: hidden; }
.hero__art { align-self: end; justify-self: end; width: 100%; aspect-ratio: 1 / 1; position: relative; }
.hero__art img {
  position: absolute;
  /* Anchored RIGHT, not left. Oversized and anchored left it grows off the
     shell edge and the section's overflow takes a slice out of Ricky's arm;
     anchored right it grows inward across the gap, where the cutout's own
     transparency means the overlap is invisible. */
  right: 0;
  bottom: calc(-1 * var(--section-y));
  width: 112%;
  max-width: none;   /* the global img rule caps this at 100% otherwise */
  height: auto;
  display: block;
}

/* Stacked, there is no section edge underneath to bleed into and no left
   column to keep still, so the photo goes back to being an ordinary image. */
@media (max-width: 899px) {
  .hero__art { aspect-ratio: auto; max-width: none; justify-self: stretch; }
  .hero__art img {
    position: static;
    /* Back to 100%: the desktop rule oversizes to 112% and anchors it right,
       which stacked just meant the photo overflowed its column and got
       clipped on one side. */
    width: 100%;
    /* Capped, because the stacked layout runs all the way to 899px and an
       uncapped photo is 835px wide by then — the pair end up larger than the
       headline above them. On a phone the shell is narrower than this anyway,
       so it still fills the width. */
    max-width: 460px;
    /* And sit on the section's bottom edge rather than floating above it. The
       section's bottom padding was leaving a strip of bare paper under their
       feet before the ink started. */
    margin-bottom: calc(-1 * var(--section-y));
  }
}
.hero__meta { margin-top: 1.5rem; display: flex; flex-wrap: wrap; gap: .4rem 1.25rem; }

/* ---------- CARDS ---------- */
.card {
  display: grid; grid-template-rows: auto 1fr auto;
  background: var(--paper); color: var(--ink);
  border: 2px solid var(--ink);
  padding: clamp(1.25rem, 3vw, 1.9rem);
  text-decoration: none;
  transition: transform .14s ease, box-shadow .14s ease;
}
/* The offset block behind a hovered card is the red pen. It used to be ink
   for most cards and pen only for the one-in-six that carried the pen
   colourway, which is why the pop of colour felt arbitrary — it depended on
   the episode number. Now every card does it, so the colour means "you are
   hovering this" rather than "this episode drew the short straw". */
a.card:hover { transform: translateY(-3px); box-shadow: 6px 6px 0 var(--pen); }
.card__eyebrow {
  font-family: var(--font-hand); text-transform: lowercase;
  font-size: 1.05rem; color: var(--muted-on-paper);
  display: flex; justify-content: space-between; gap: .75rem; align-items: baseline;
}
.card h3 { margin-block: .6rem .5rem; }
.card__foot { margin-top: auto; padding-top: 1rem; border-top: 3px solid rgba(31,42,68,.16); }


.grid { display: grid; gap: clamp(1rem, 2.2vw, 1.5rem); }
.grid--3 { grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); }
.grid--2 { grid-template-columns: repeat(auto-fill, minmax(min(100%, 380px), 1fr)); }

/* ---------- FEATURED EPISODE ---------- */

/* Applied when JS swaps in an episode newer than the build. It reuses the
   featured layout rather than stacking a second "latest episode" card above
   it - two competing latest-episode blocks read as a mistake. */
.featured__flag {
  display: inline-block;
  font-weight: 700; font-size: .62rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--pen-text); border: 1.5px solid var(--pen-text);
  padding: .2rem .45rem; margin-bottom: .6rem;
}
.featured__pending { font-size: .85rem; opacity: .75; align-self: center; }
.featured { display: grid; gap: var(--gap); align-items: start; }
@media (min-width: 820px) { .featured { grid-template-columns: 300px 1fr; } }
.featured__art { border: 3px solid currentColor; }
.featured h2 { margin-block: .75rem 1rem; }

/* ---------- EPISODE LIST ---------- */
.ep-list { display: grid; gap: 0; border-top: 2px solid var(--ink); }
.ep {
  display: grid; gap: .35rem 1.5rem; align-items: baseline;
  padding-block: clamp(1.1rem, 2.5vw, 1.6rem);
  border-bottom: 1px solid var(--paper-edge);
  text-decoration: none;
  transition: background .12s ease, padding-inline .12s ease;
}
@media (min-width: 760px) {
  .ep { grid-template-columns: 8.5rem 1fr auto; }
}
.ep:hover { background: rgba(31,42,68,.045); padding-inline: .75rem; }
.ep__date { font-family: var(--font-body); font-weight: 700; font-size: .72rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted-on-paper); }
.ep__title { font-family: var(--font-head); font-weight: 900; line-height: .95; letter-spacing: -.02em; font-size: clamp(1.15rem, 1rem + .7vw, 1.5rem); }
.ep__meta { font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted-on-paper); white-space: nowrap; }
.ep__desc { grid-column: 1 / -1; color: var(--muted-on-paper); max-width: var(--measure); font-size: .95rem; }
@media (min-width: 760px) { .ep__desc { grid-column: 2 / 3; } }

/* ---------- FILTERS ---------- */
.filters { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 2rem; }
.filter {
  font-family: var(--font-body); font-weight: 700; font-size: .74rem; letter-spacing: .08em;
  text-transform: uppercase; padding: .5rem .9rem; cursor: pointer;
  border: 2px solid var(--ink); background: transparent; color: var(--ink);
}
.filter[aria-pressed="true"] { background: var(--ink); color: var(--paper); }

/* ---------- PRESS ---------- */

/* Byline block: the credential paragraph beside the one photo of Ricky that
   works as a portrait. Photo second in the source so it reads after the claim
   on a phone, where the claim is what matters. */
.byline { display: grid; gap: clamp(1.5rem, 4vw, 3rem); align-items: start; }
@media (min-width: 820px) { .byline { grid-template-columns: 1.35fr 1fr; } }

/* Every photo on these pages is Ricky's own. The frame and the credit line
   are not decoration - they are the provenance, and the caption always says
   whose camera it was. */
.shot { margin: 0; }
.shot img { border: 3px solid currentColor; width: 100%; }
.shot figcaption { margin-top: .6rem; text-transform: none; letter-spacing: .02em; font-weight: 600; font-size: .74rem; line-height: 1.4; }

/* ---------- RED CARPET WALL ----------
   Masonry, because the source frames run from 675x1200 to 1200x675 and no
   single cap suits both: capping WIDTH made a portrait render three times
   taller than the landscape beside it, and capping HEIGHT shrank everything to
   fit the worst case. Columns let each photo keep its true shape and simply
   stack, so nothing is cropped and nothing is capped.

   CSS multi-column rather than flex columns: the browser balances the heights
   itself and reflows at every width, so adding a photo never means re-packing
   anything by hand. wallOrder() in build.mjs feeds it alternating tall and wide
   frames, which is what keeps the balance good rather than merely automatic. */
.wall { margin-top: clamp(1.75rem, 4vw, 2.5rem); columns: 3; column-gap: 18px; }
@media (max-width: 900px) { .wall { columns: 2; column-gap: 14px; } }
@media (max-width: 560px) { .wall { columns: 1; } }

.wshot {
  break-inside: avoid;
  margin: 0 0 18px;
  position: relative;
  border: 3px solid var(--paper);
  overflow: hidden;
  transition: transform .14s ease, box-shadow .14s ease;
}
@media (max-width: 900px) { .wshot { margin-bottom: 14px; } }
.wshot img { display: block; width: 100%; height: auto; }

/* The label rides on the photo. The scrim is mixed from the site's own ink
   (#1F2A44) rather than a generic black, so it reads as the page darkening
   rather than as a stock overlay dropped on top. Three stops, so it fades in
   high enough that a two-line name never sits on a hard edge. */
.wshot figcaption {
  position: absolute; inset: auto 0 0 0;
  padding: clamp(2.5rem, 6vw, 3.5rem) 1rem .85rem;
  background: linear-gradient(to bottom,
    rgba(31, 42, 68, 0) 0%,
    rgba(20, 27, 44, .78) 46%,
    rgba(16, 22, 36, .95) 100%);
}
.wshot b {
  display: block;
  font-family: var(--font-head); font-weight: 900;
  font-size: clamp(1.05rem, 1rem + .35vw, 1.3rem);
  letter-spacing: -.02em; line-height: 1.02;
  color: var(--paper);
}
.wshot i {
  display: block; margin-top: .3rem; font-style: normal;
  font-weight: 700; font-size: .66rem; letter-spacing: .09em;
  text-transform: uppercase; color: #BFC7D6;
}

/* ---------- the claims ----------
   The wall says who and where. Everything that is an ASSERTION — who he
   interviewed, and the story that backs it — sits here once, so "interviewed"
   does not repeat down ten captions and the evidence stays visually separate
   from the claim it supports. */
.facts { margin-top: clamp(2.25rem, 5vw, 3rem); border-top: 2px solid var(--paper); }
.fact {
  display: grid; gap: .35rem 1.5rem;
  padding-block: clamp(.9rem, 2vw, 1.15rem);
  border-bottom: 1px solid var(--ink-edge);
  align-items: baseline;
}
@media (min-width: 860px) {
  .fact { grid-template-columns: 15.5rem 11rem 1fr auto; }
}
.fact--head { display: none; }
@media (min-width: 860px) {
  .fact--head { display: grid; padding-block: .5rem .6rem; }
}
.fact__name { font-family: var(--font-head); font-weight: 900; font-size: 1.3rem; letter-spacing: -.02em; }
.fact__who { font-weight: 600; max-width: 46ch; }
.fact__links { display: flex; flex-wrap: wrap; gap: .35rem 1.1rem; }
.fact__link {
  font-weight: 700; font-size: .72rem; letter-spacing: .06em; text-transform: uppercase;
  text-decoration: none; color: var(--paper);
  border-bottom: 2px solid var(--pen); padding-bottom: 2px; white-space: nowrap;
}
.fact__link:hover { color: var(--highlighter); border-bottom-color: var(--highlighter); }

/* Featured clips. One row per clip: the headline, and a note under it saying
   what the piece was. The kind labels were dropped - repeated on nearly every
   row, they read as chrome rather than as information. */
.clips { list-style: none; padding: 0; margin: clamp(1.5rem, 4vw, 2.5rem) 0 0; border-top: 2px solid var(--ink); }
.clip { padding-block: clamp(1.1rem, 2.5vw, 1.5rem); border-bottom: 1px solid var(--paper-edge); }
.clip__link { display: grid; gap: .35rem 1.5rem; align-items: baseline; text-decoration: none; }
.clip__link:hover .clip__title { background: var(--highlighter); }
.clip__date { font-weight: 700; font-size: .72rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted-on-paper); white-space: nowrap; }
.clip__title { font-family: var(--font-head); font-weight: 900; line-height: .95; letter-spacing: -.02em; font-size: clamp(1.1rem, 1rem + .6vw, 1.4rem); }
.clip__note { margin-top: .5rem; color: var(--muted-on-paper); font-size: .95rem; max-width: var(--measure); }
.clip__cobyline { font-weight: 700; }

/* The full 65-story index. Deliberately plain - no tags, no notes, no art.
   Anything that dresses this list up turns an archive into a content farm. */
.clip-year { font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2.25rem); margin-top: clamp(2.5rem, 5vw, 3.5rem); }
.clip-index { list-style: none; padding: 0; margin-top: 1rem; border-top: 2px solid var(--ink); }
.clip-index a {
  display: grid; gap: .2rem 1.5rem; align-items: baseline;
  padding-block: .8rem; border-bottom: 1px solid var(--paper-edge);
  text-decoration: none; transition: background .12s ease, padding-inline .12s ease;
}
@media (min-width: 700px) { .clip-index a { grid-template-columns: 8.5rem 1fr; } }
.clip-index a:hover { background: rgba(31,42,68,.045); padding-inline: .6rem; }

.press-entry { display: grid; gap: .5rem 2rem; padding-block: clamp(1.5rem, 3.5vw, 2.5rem); border-bottom: 1px solid var(--paper-edge); }
@media (min-width: 760px) { .press-entry { grid-template-columns: 1fr 1.6fr; } }
.press-entry:first-of-type { border-top: 2px solid var(--ink); }
.press-entry__q { font-size: clamp(1.1rem, 1rem + .6vw, 1.4rem); font-weight: 600; line-height: 1.35; max-width: 40ch; }

/* On repeat — pulled from the show notes, so the length changes weekly. */
.picks { list-style: none; padding: 0; display: grid; gap: .85rem; }
.picks li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .1rem .6rem;
  font-size: clamp(1.05rem, 1rem + .45vw, 1.25rem); font-weight: 600;
  padding-bottom: .85rem; border-bottom: 1px solid rgba(90,74,26,.28);
}
.picks li:last-child { border-bottom: 0; padding-bottom: 0; }
.picks__who {
  font-family: var(--font-hand); font-weight: 600; text-transform: lowercase;
  font-size: 1.15rem; color: var(--fine-on-gold); flex: 0 0 3.4rem;
}
.picks a { text-underline-offset: 3px; }
.picks a:hover { color: var(--pen-on-gold); }

.stats { display: grid; gap: clamp(1rem, 3vw, 2rem); grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
.stat__figure { font-family: var(--font-head); font-weight: 900; line-height: .85; letter-spacing: -.03em; font-size: clamp(2.5rem, 1.5rem + 4vw, 4.5rem); }

/* ---------- HOSTS ---------- */
.host { display: grid; gap: .9rem; }

/* The role label is an eyebrow, not fine print. Rendering it as fine print made
   it identical to the citation above it, so consecutive host blocks ran
   together into one strip of small caps with no visible boundary. Caveat
   handwriting is the system's label voice and separates the two jobs cleanly. */
/* Square, not round. The system has no rounded corners anywhere, and a
   squared crop sits with the cards and panels instead of arguing with them.
   Cropped in the build rather than with CSS, so the file that ships is the
   file you see. In colour: the hero is mono, but these are the two of them
   and the warm brick is the one place on an ink page that wants some heat. */
.host__photo { display: block; width: 100%; max-width: 230px; height: auto; }

.host__role {
  font-family: var(--font-hand);
  text-transform: lowercase;
  font-size: clamp(1.2rem, 1.05rem + .6vw, 1.5rem);
  font-weight: 600;
  line-height: 1.2;
  color: var(--muted-on-paper);
  margin-bottom: .15rem;
}
.ink .host__role { color: var(--muted-on-ink); }
.gold .host__role { color: var(--fine-on-gold); }

.host__quote {
  font-size: clamp(1.05rem, 1rem + .5vw, 1.3rem);
  font-weight: 600;
  line-height: 1.35;
  border-left: 3px solid var(--pen);
  padding-left: 1rem;
}
/* The citation belongs to the quote, so it sits inside the rule rather than
   floating between two blocks where it could be mistaken for the next label. */
.host__quote cite {
  display: block;
  margin-top: .65rem;
  font-style: normal;
  font-weight: 700;
  font-size: .68rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-on-paper);
}
.ink .host__quote cite { color: var(--muted-on-ink); }

/* ---------- EPISODE DETAIL ---------- */
.ep-detail__body { max-width: var(--measure); }
.ep-detail__body p { margin-bottom: 1rem; }
.ep-detail__body a { color: var(--pen-text); text-underline-offset: 3px; }
.ep-detail__body a:hover { background: var(--highlighter); color: var(--ink); text-decoration: none; }
/* Native <audio>. Browsers won't let us restyle the internals, so we frame it
   instead: the surrounding border and ground do the brand work. */
.player {
  width: 100%;
  height: 54px;
  margin-block: 1.5rem;
  border: 2px solid var(--ink);
  background: var(--paper);
  border-radius: 0;
}
.player::-webkit-media-controls-panel { background: var(--paper); }

/* ---------- FOOTER ---------- */
.site-foot { background: var(--ink); color: var(--paper); padding-block: clamp(3rem, 7vw, 5rem) 2rem; }
.foot-grid { display: grid; gap: var(--gap); }
@media (min-width: 760px) { .foot-grid { grid-template-columns: 1.4fr 1fr 1fr; } }
.site-foot a { color: var(--paper); text-decoration: none; }
.site-foot a:hover { color: var(--highlighter); }
.foot-list { list-style: none; padding: 0; display: grid; gap: .5rem; }
/* Studio mark. Typographic until the real artwork exists — see studioMark()
   in build.mjs and _STUDIO_LOGO in data/site.json. */
.studio-mark {
  font-family: var(--font-head); font-weight: 900;
  font-size: clamp(1.6rem, 1.25rem + 1.6vw, 2.4rem);
  line-height: .92; letter-spacing: -.03em;
  color: var(--paper);
  display: grid;
}
.studio-mark span:last-child { padding-left: .12em; }
.studio-logo { width: clamp(112px, 34%, 152px); height: auto; }
.site-foot .aside { margin-top: 1.35rem; }
.site-foot .foot-grid > div + div { padding-top: .25rem; }
.foot-bottom { margin-top: clamp(2.5rem, 6vw, 4rem); padding-top: 1.5rem; border-top: 1px solid var(--ink-edge); display: flex; flex-wrap: wrap; gap: .75rem 2rem; justify-content: space-between; }

/* ---------- BLOG HAND-OFF PANEL ---------- */
/* Covers the viewport while the browser loads blog.clapifyoudontcare.com and
   plays the headphones-off / glasses-on swap on top of it. 1290ms.

   Reveal is stroke-dashoffset, deliberately. An earlier build clipped the art
   instead, and WebKit computes clip-path on an SVG <g> without ever painting
   it — both states showed stacked and motionless in Safari while reporting
   healthy animations and a correct computed clip-path. If this ever needs
   clipping again, clip an HTML box, never an SVG group.

   The ground must stay --paper — four fills in the art are paper-coloured
   knockouts (the cushion creases, the lens interiors) and read as light
   patches against anything else. */
.j-panel {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  /* place-content, not place-items: the caption and the art are two rows that
     want centring as a group, not one centred box each. */
  place-content: center;
  justify-items: center;
  gap: clamp(1.75rem, 4vw, 2.75rem);
  background: var(--paper);
}

/* The caption sits above the art: it is the sentence the animation then acts
   out, and reading it first makes the swap land as a punchline rather than a
   subtitle. Fine print, so it never competes with the mark. */
.j-say {
  order: -1;
  margin: 0;
  font-weight: 700;
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-on-paper);
  opacity: 0;
}
.j-panel.is-playing .j-say { animation: j-say-in 320ms ease 120ms both; }
@keyframes j-say-in { from { opacity: 0; } to { opacity: 1; } }
.j-panel[hidden] { display: none; }

/* The stage is just a sizing box now — no layers, no clip-path. Strokes draw
   themselves, which is both simpler and the one technique WebKit has never had
   trouble with. */
.j-stage { width: min(600px, 62vw); aspect-ratio: 320 / 200; }
.j-art { display: block; width: 100%; height: 100%; }
.j-art path { stroke-dasharray: var(--len); stroke-linejoin: round; }

/* Rest: headphones painted on, glasses not yet drawn. */
.j-cans path { stroke-dashoffset: 0; }
.j-specs path { stroke-dashoffset: var(--len); }

/* The headphones un-paint in the order they were put on — cushions and cups,
   then the stems, then the band — and the glasses grow outward from the
   bridge. Raising the offset retreats the stroke from its far end back toward
   where it started, which is why this reads as undrawing rather than fading.

   `both` is load-bearing: without it a delayed path paints its un-animated
   state during its delay, and both states show together for a frame. */
/* 0 -> 320ms is a hold. The headphones sit there fully painted and nothing
   moves, because an object that starts coming apart on frame one never gets
   read as an object at all. The caption fading in at 120ms covers the pause,
   so it registers as a beat rather than as lag. */
.j-panel.is-playing .j-cup-l,
.j-panel.is-playing .j-cup-r,
.j-panel.is-playing .j-seam-l,
.j-panel.is-playing .j-seam-r  { animation: j-erase 280ms cubic-bezier(.2,.8,.2,1)  320ms both; }
.j-panel.is-playing .j-stem-l,
.j-panel.is-playing .j-stem-r  { animation: j-erase 280ms cubic-bezier(.2,.8,.2,1)  390ms both; }
.j-panel.is-playing .j-band,
.j-panel.is-playing .j-crown   { animation: j-erase 320ms cubic-bezier(.2,.8,.2,1)  460ms both; }

.j-panel.is-playing .j-bridge  { animation: j-draw  200ms cubic-bezier(.2,.8,.2,1)  900ms both; }
.j-panel.is-playing .j-lens-l,
.j-panel.is-playing .j-lens-r  { animation: j-draw  320ms cubic-bezier(.2,.8,.2,1)  940ms both; }
.j-panel.is-playing .j-arm-l,
.j-panel.is-playing .j-arm-r   { animation: j-draw  280ms cubic-bezier(.2,.8,.2,1) 1010ms both; }

@keyframes j-erase { from { stroke-dashoffset: 0; } to { stroke-dashoffset: var(--len); } }
@keyframes j-draw  { from { stroke-dashoffset: var(--len); } to { stroke-dashoffset: 0; } }

/* Reduced motion: no travel and no wipe, but still a cross-fade. The
   preference is about movement, and a swap nobody can see is not an
   improvement on one they can. The panel covers the load either way. */
@media (prefers-reduced-motion: reduce) {
  .j-art path { stroke-dasharray: none; stroke-dashoffset: 0; }
  .j-specs path { opacity: 0; }
  .j-panel.is-playing .j-cans path  { animation: j-fade-out 320ms linear   0ms both; }
  .j-panel.is-playing .j-specs path { animation: j-fade-in  320ms linear 300ms both; }
}

@keyframes j-fade-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes j-fade-in  { from { opacity: 0; } to { opacity: 1; } }

/* ---------- EMBED ---------- */
/* Spotify's own snippet ships border-radius:12px on the iframe. Squared off
   here to match everything else — the system has no rounded corners, and a
   soft-cornered panel in the middle of the page reads as pasted in from
   somewhere else, which it is. */
.embed { border: 3px solid var(--ink); background: var(--ink); line-height: 0; }
.embed iframe { display: block; width: 100%; height: min(72vh, 600px); border: 0; border-radius: 0; }
@media (max-width: 600px) { .embed iframe { height: min(76vh, 520px); } }

/* ---------- UTILITIES ---------- */
.stack > * + * { margin-top: var(--flow, 1rem); }
.mt-lg { margin-top: clamp(2rem, 5vw, 3.5rem); }
.mb-lg { margin-bottom: clamp(2rem, 5vw, 3.5rem); }
.center-col { max-width: var(--measure); }

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: var(--paper); padding: .75rem 1rem; z-index: 100;
  font-weight: 700; font-size: .8rem; letter-spacing: .06em; text-transform: uppercase;
}
.skip:focus { left: .5rem; top: .5rem; }

:focus-visible { outline: 3px solid var(--pen); outline-offset: 3px; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

[hidden] { display: none !important; }

/* Wide content must scroll inside its own container, never the body */
.scroll-x { overflow-x: auto; }

@media print {
  .site-head, .site-foot, .filters { display: none; }
  body { background: #fff; }
}

/* ---------- FORM ---------- */
.form { display: grid; gap: 1.25rem; }

.field { display: grid; gap: .45rem; }
.field label { color: var(--muted-on-paper); }

.field input,
.field select,
.field textarea {
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--ink);
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: 0;
  padding: .7rem .85rem;
  width: 100%;
  /* iOS zooms the page if an input is under 16px, so never go below 1rem. */
}
.field textarea { resize: vertical; min-height: 8rem; line-height: 1.5; }
.field select { appearance: none; background-image: none; cursor: pointer; }

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible { outline: 3px solid var(--pen); outline-offset: 2px; }

.field input[aria-invalid="true"],
.field textarea[aria-invalid="true"] { border-color: var(--pen); }

.hint { font-size: .85rem; color: var(--muted-on-paper); }

/* Honeypot: off-screen rather than display:none, because some bots skip
   hidden fields but not positioned ones. Never focusable, never announced. */
.hp {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden; opacity: 0; pointer-events: none;
}

.form-status { margin-top: 1rem; font-weight: 600; max-width: 46ch; }
.form-status[data-state="error"] { color: var(--pen-text); }
.form-status[data-state="sending"] { color: var(--muted-on-paper); }

button.btn { font-family: var(--font-body); cursor: pointer; }
button.btn[disabled] { opacity: .55; cursor: progress; }

/* The form is done: replace it with the confirmation rather than leaving a
   filled-in form sitting there looking like it might send again. */
.form--sent { display: none; }
.sent-note {
  border: 2px solid var(--ink);
  padding: clamp(1.25rem, 3vw, 1.9rem);
  font-size: clamp(1.05rem, 1rem + .45vw, 1.25rem);
  font-weight: 600;
}

/* ---------- CATCHUP (Follow bridge) ---------- */
/* Gold, not ink, so this section does not sit against the ink footer —
   two of the same colourway adjacent is a hard rule. No swipe here: the
   hero already spent the one highlighter the page is allowed. */
.catchup-starts {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: clamp(1.25rem, 3vw, 2rem);
  max-width: var(--measure);
}
.catchup-starts a {
  font-family: var(--font-head);
  font-weight: 900;
  font-size: clamp(1.35rem, 1.1rem + 1.1vw, 1.85rem);
  letter-spacing: -.03em;
  line-height: 1.05;
  text-decoration: none;
}
.catchup-starts a:hover { color: var(--pen-on-gold); }
.catchup-starts p { margin-top: .4rem; max-width: 46ch; }
