/* ============================================
   PIVOT POINTS — series stylesheet (v3)
   Identity keyed to Valero Doval's cover sketch:
   bone paper ground, navy-slate ink, vermilion +
   dusty blue accents, the cover's geometric-sans
   caps as the label voice over Garamond text.
   Palette sampled from the July cover sketch and
   verified identical against Valero's final files
   (Sept 7 2026, pivotpoints/_art/cover-final/).
   ============================================ */

:root {
    /* Sampled from the cover. Contrast on paper: ink 10.5:1 ·
       ink-soft 5.9:1 · faint 4.6:1 · accent 5.2:1 · indigo 4.8:1 —
       all AA. Bright vermilion (3.7:1) is reserved for large or
       non-text moments; ochre lives only in the artwork itself. */
    --pp-paper: #e1d7c3;         /* the art's bone ground, exactly */
    --pp-paper-deep: #d6c9b2;    /* edges / gradients */
    --pp-cream: #f5ead6;         /* the crescent — panels lift off the paper */
    --pp-ink: #182933;           /* deep navy-slate, the circle's ink */
    --pp-ink-soft: #3e505a;
    --pp-accent: #9e2b18;        /* vermilion, deepened for small type */
    --pp-accent-bright: #c63724; /* the canvas vermilion — display & non-text */
    --pp-accent-soft: rgba(198, 55, 36, 0.45);
    --pp-indigo: #3d5c86;        /* the art's dusty blue, deepened for links */
    --pp-rule: rgba(24, 41, 51, 0.16);

    --pp-display: 'Cormorant Garamond', Georgia, serif;
    --pp-serif: 'EB Garamond', Georgia, serif;
    --pp-sans: 'Jost', 'Futura', 'Century Gothic', sans-serif;
}

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

html {
    font-size: 106.25%; /* 17px at the browser default, but scales with the reader's font-size setting */
    -webkit-font-smoothing: antialiased;
    scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}

body {
    font-family: var(--pp-serif);
    background-color: var(--pp-paper);
    color: var(--pp-ink);
    line-height: 1.65;
    min-height: 100vh;
}

/* Soft paper grain + faint vignette toward the edges, pinned to the screen.
   A fixed layer of its own, not `background-attachment: fixed` on the body:
   iPhone Safari ignores that and stretches the vignette over the whole
   document, darkening the page (Oct 2026). 100lvh covers the tallest
   viewport, so no bare strip shows when Safari's toolbar collapses. */
body::before {
    content: "";
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100vh;
    height: 100lvh;
    z-index: -1;
    pointer-events: none;
    background-image:
        url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='grain'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23grain)' opacity='0.5'/%3E%3C/svg%3E"),
        radial-gradient(ellipse at center, var(--pp-paper) 55%, var(--pp-paper-deep) 100%);
    /* the grain is a 200px tile, repeated. Without an explicit size the
       browser stretched the single tile across the whole viewport, which
       blew the specks up into soft blotches (fixed Oct 2026). */
    background-size: 200px 200px, auto;
    background-blend-mode: soft-light, normal;
}

/* solid, not a wash: the transcripts' playing sentence is a faint vermilion
   wash, and selection must read apart from it. The deep vermilion, not the
   canvas one: calmer for readers who select as they read (Sept 30 2026). */
::selection {
    background: var(--pp-accent);
    color: var(--pp-cream);
}

/* Room for the fixed bottom bar */
body {
    padding-bottom: 3.4rem;
    padding-bottom: calc(3.4rem + env(safe-area-inset-bottom, 0px));
}

a {
    color: inherit;
    text-decoration: underline;
    text-decoration-color: var(--pp-accent-soft);
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    transition: text-decoration-color 0.2s ease, color 0.2s ease;
}

a:hover {
    color: var(--pp-indigo);
    text-decoration-color: var(--pp-indigo);
}

main {
    max-width: 640px;
    margin: 0 auto;
    padding: 0 2rem;
}

/* Tracked-caps utility label — the cover's geometric-sans voice.
   Jost runs a touch wider and taller than the old Garamond caps,
   so label sizes sit a hair under their former values. */
.pp-label {
    font-family: var(--pp-sans);
    font-size: 0.7rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.24em;
    color: var(--pp-ink-soft);
}

/* ============================================
   PLACEHOLDER MARKING
   [Bracketed text] = structural placeholder,
   awaiting Oshan's words. Styled so it can't be
   mistaken for finished copy.
   ============================================ */

.pp-placeholder {
    color: var(--pp-ink-soft);
    font-style: italic;
}

/* ============================================
   EMBLEM (the cover's circle-form — homepage
   hero only; episode pages run without a mark)
   ============================================ */

.pp-emblem {
    display: block;
    color: var(--pp-ink-soft);
}

/* Emblems breathe in as their chapter arrives */
.pp-reveal .pp-emblem {
    opacity: 0;
    transform: scale(0.92);
    transition: opacity 1.1s ease, transform 1.1s cubic-bezier(0.22, 1, 0.36, 1);
}

.pp-reveal.in-view .pp-emblem {
    opacity: 1;
    transform: scale(1);
}

@media (prefers-reduced-motion: reduce) {
    .pp-reveal .pp-emblem {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* ============================================
   HERO / LANDING FRAME
   ============================================ */

.pp-hero {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    position: relative;
    /* phones: the heavier bottom padding lifts the composition clear of the
       fixed bottom bar; the gap to episode 1 is set by the homepage script */
    padding: 5rem 0 10rem;
}

/* The cover's circle-form on the landing frame — a transparent cut of
   the art, so the page ground shows right up to the shapes. The frame
   holds clear space below the crescent, so only a breath of margin is
   needed before the wordmark. */
.pp-hero .pp-cover-emblem {
    width: clamp(230px, 36vh, 330px);
    height: auto;
    margin-bottom: 0.6rem;
}

/* Wordmark — Jost, the same face as the site's caps labels (decided
   Sept 3 2026 after trying Valero's cover face, Sinhala Sangam MN, which
   is Mac-only and unlicensable for the web, plus Untitled Sans, Authentic
   Sans, Marcellus and Penumbra). Weight, tracking and word gap were fitted
   by measurement to Valero's final cover: stroke weight, letter gaps and
   word gap match his to within a few percent of cap height. These values
   belong to Jost; refit if the face ever changes. (padding-left = tracking
   recenters the tracked line; the size keeps the line single down to
   narrow phones.) */
.pp-wordmark {
    font-family: var(--pp-sans);
    font-weight: 500;
    font-size: clamp(1.7rem, 5.2vw, 2.7rem);
    line-height: 1.15;
    letter-spacing: 0.103em;
    word-spacing: -0.011em;
    padding-left: 0.103em;
    text-transform: uppercase;
    color: var(--pp-ink);
}

.pp-tagline {
    font-family: var(--pp-serif);
    font-size: 1.1rem;
    line-height: 1.6;
    color: var(--pp-ink);
    margin-top: 1.75rem;
    max-width: 31em;
    /* S-Town-style even block: justified lines, centered last line */
    text-align: justify;
    text-align-last: center;
}

.pp-tagline + .pp-tagline {
    margin-top: 0.9rem;
}

/* "Listen to the trailer" — Floodlines-style preview element */
.pp-trailer {
    display: inline-flex;
    align-items: center;
    gap: 0.85rem;
    margin-top: 2.25rem;
    color: var(--pp-ink);
    transition: color 0.2s ease;
    cursor: pointer; /* the whole row is one play/pause toggle, in every state */
}

/* play/pause glyphs share one slot; the pause pair shows only while playing */
.pp-trailer-icon-pause {
    display: none;
}
.pp-trailer.is-playing .pp-trailer-icon-play {
    display: none;
}
.pp-trailer.is-playing .pp-trailer-icon-pause {
    display: inline;
}

.pp-trailer-btn {
    position: relative; /* anchors the progress ring overlay */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 46px;
    height: 46px;
    padding: 0;
    border: 0;
    background: none;
    border-radius: 50%;
    color: var(--pp-ink);
    cursor: pointer;
    transition: color 0.2s ease, transform 0.2s ease;
}

/* both glyphs are pinned to the circle's center. The pause bars are
   mass-symmetric, so exact center is right for them. The triangle's visual
   mass sits left of its bounding box (centroid 1.5px left of box center at
   this size), so it carries a +0.75px optical nudge — half the centroid gap —
   to LOOK centered; the 0.75px box shift on glyph swap is imperceptible. */
.pp-trailer-icon-play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(calc(-50% + 0.75px), -50%);
}
.pp-trailer-icon-pause {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

/* Progress ring: the resting circle (track) is overdrawn clockwise by the
   accent arc (progress) as the trailer plays — set via JS stroke-dashoffset. */
.pp-trailer-ring {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}
.pp-trailer-ring-track {
    stroke: var(--pp-ink-soft);
    stroke-width: 1.5;
    transition: stroke 0.2s ease;
}
.pp-trailer-ring-progress {
    stroke: var(--pp-accent-bright);
    stroke-width: 1.5;
    stroke-linecap: round;
    transform: rotate(-90deg); /* start the sweep at 12 o'clock */
    transform-origin: center;
    transform-box: fill-box;
    transition: stroke-dashoffset 0.25s linear, stroke-width 0.35s ease;
}
/* while playing, the arc bolds — with no numeric readout it carries
   time-remaining alone (r=22.5 leaves room for the wider stroke) */
.pp-trailer.is-active .pp-trailer-ring-progress {
    stroke-width: 2.75;
}

.pp-trailer-label {
    font-family: var(--pp-sans);
    font-size: 0.78rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.2em;
}

.pp-trailer:hover {
    color: var(--pp-accent);
}

/* glyph takes the canvas vermilion (non-text, 3.7:1); the label keeps the
   deep accent. The ring's resting border brightens on hover only before
   playback starts — once the arc is showing, the track stays quiet so the
   progress reads apart from the hover state. */
.pp-trailer:hover .pp-trailer-btn {
    color: var(--pp-accent-bright);
    transform: scale(1.05);
}
.pp-trailer:not(.is-active):hover .pp-trailer-ring-track {
    stroke: var(--pp-accent-bright);
}

.pp-listen-row {
    margin-top: 1.75rem;
    font-family: var(--pp-serif);
    font-size: 0.9rem;
    letter-spacing: 0.04em;
    color: var(--pp-ink);
}

.pp-listen-row a {
    color: var(--pp-ink);
    text-decoration: none;
    border-bottom: 1px solid var(--pp-accent-soft);
    padding-bottom: 1px;
    margin: 0 0.35rem;
}

.pp-listen-row a:hover {
    color: var(--pp-indigo);
    border-bottom-color: var(--pp-indigo);
}

/* ============================================
   HOMEPAGE LANDING — a taper (Sept 30 2026)
   Centered lines read as a silhouette before they read as words, so the
   frame narrows line by line down to the trailer and ends on its narrowest
   element, the platform marks (a cul-de-lampe). Widths were measured on
   laptops: tagline 529/365 > byline 347 > trailer 260 > marks 117.
   Scoped to .pp-home. The trailer page (.pp-prelaunch) shares the
   tagline and the vermilion trailer disc (Sept 30 2026).
   ============================================ */

/* not justified: in a two-line block, justification stretched word gaps
   to 3-4x a space on phones. Centered and balanced instead, one sentence
   per line where the frame is wide enough. */
.pp-home .pp-hero .pp-tagline,
.pp-prelaunch .pp-hero .pp-tagline {
    text-align: center;
    text-align-last: auto;
    text-wrap: balance;
}
@media (min-width: 701px) {
    .pp-home .pp-hero .pp-tagline:not(.pp-byline) > span,
    .pp-prelaunch .pp-hero .pp-tagline > span {
        display: block;
    }
}

/* the byline steps down to fine print, a notch under the tagline's
   second line so the silhouette keeps narrowing; on phones, one sentence
   per line. (0,3,0 so the short-screen tagline sizes below don't reach it) */
.pp-home .pp-hero .pp-tagline.pp-byline {
    font-size: 0.85rem;
}
@media (max-width: 700px) {
    .pp-home .pp-hero .pp-byline > span {
        display: block;
    }
}

/* the trailer is the frame's one action: a filled disc in the deep
   vermilion (the same red as "Coming Soon"), cream glyph; the progress arc
   draws in cream on the disc */
.pp-home .pp-trailer-btn,
.pp-prelaunch .pp-trailer-btn {
    background: var(--pp-accent);
    color: var(--pp-cream);
    transition: background-color 0.2s ease, transform 0.2s ease;
}
.pp-home .pp-trailer-ring-track,
.pp-home .pp-trailer:not(.is-active):hover .pp-trailer-ring-track,
.pp-prelaunch .pp-trailer-ring-track,
.pp-prelaunch .pp-trailer:not(.is-active):hover .pp-trailer-ring-track {
    stroke: transparent;
}
.pp-home .pp-trailer-ring-progress,
.pp-prelaunch .pp-trailer-ring-progress {
    stroke: var(--pp-cream);
}
.pp-home .pp-trailer:hover .pp-trailer-btn,
.pp-prelaunch .pp-trailer:hover .pp-trailer-btn {
    background: color-mix(in srgb, var(--pp-accent) 80%, black);
    color: var(--pp-cream);
}

/* where to listen: three marks, the tip of the taper */
.pp-listen-icons {
    display: flex;
    justify-content: center;
    gap: 1.5rem;
    margin-top: 1.5rem;
}
.pp-listen-icons a {
    display: inline-flex;
    color: var(--pp-ink-soft);
    transition: color 0.2s ease, transform 0.2s ease;
}
.pp-listen-icons a:hover {
    color: var(--pp-accent-bright);
    transform: scale(1.08);
}
.pp-listen-icons svg {
    width: 22px;
    height: 22px;
    fill: currentColor;
}

/* ============================================
   CHAPTER BLOCKS (series homepage)
   ============================================ */

.pp-chapters {
    display: flex;
    flex-direction: column;
}

/* Section-break ornament — a miniature of the series mark between short
   hairlines, replacing full-width rules (books punctuate; they don't rule off).
   The first episode gets none: the landing frame's own ending marks that
   threshold. */
.pp-chapters .pp-chapter:first-of-type::before {
    content: none;
}

.pp-chapter::before,
.pp-substack::before,
.pp-credits::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 128px;
    height: 12px;
    background: url("data:image/svg+xml,%3Csvg viewBox='0 0 128 12' xmlns='http://www.w3.org/2000/svg'%3E%3Cline x1='10' y1='6' x2='48' y2='6' stroke='%23182933' stroke-opacity='0.22' stroke-width='1'/%3E%3Cline x1='80' y1='6' x2='118' y2='6' stroke='%23182933' stroke-opacity='0.22' stroke-width='1'/%3E%3Ccircle cx='64' cy='6' r='4.5' fill='none' stroke='%233e505a' stroke-opacity='0.6' stroke-width='1'/%3E%3Ccircle cx='64' cy='6' r='1.5' fill='%239e2b18'/%3E%3C/svg%3E") center / contain no-repeat;
    pointer-events: none;
}

/* ============================================
   HOMEPAGE DIVIDERS — from many to (n)one
   Pythagoras tree after Laukkonen & Slagter
   (2021), Fig. 1's own register: one constant
   deep solid-ink tree at every threshold; a
   concentric layer of its own squares turns
   vermilion, stepping inward as the series
   deepens — levels 4, 3, 2, 1, 0, one step
   per threshold. Layers outside level 4 never
   take the red: too fine at divider scale to
   read as a ring. The tree never changes;
   only which ring is lit.
   Assets in images/dividers/ are generated by
   script (see launch checklist); regenerate
   rather than hand-edit. Box size = the SVG's
   native size (script prints it).
   ============================================ */

#episode-2::before,
#episode-3::before,
#episode-4::before,
#episode-5::before,
.pp-substack::before {
    width: 65px;
    height: 45px;
    /* Lifted above the section seam so a settled episode shows only the
       mark BELOW it (the threshold ahead) — the one above sits just off
       the top of the frame. One tree at a time keeps the ring's descent
       legible; two at once read as a decorative frame.
       6vh tracks the settle geometry across viewport heights. */
    transform: translate(-50%, calc(-50% - 6vh - 2px));
    background-image: url("images/dividers/ring-hl4.svg");
}

#episode-3::before { background-image: url("images/dividers/ring-hl3.svg"); }
#episode-4::before { background-image: url("images/dividers/ring-hl2.svg"); }
#episode-5::before { background-image: url("images/dividers/ring-hl1.svg"); }
.pp-substack::before { background-image: url("images/dividers/ring-hl0.svg"); }

/* an invisible link laid over the last mark (same box, same lift), so the
   full tree opens the paper it comes from */
.pp-source-link {
    position: absolute;
    top: 0;
    left: 50%;
    width: 65px;
    height: 45px;
    transform: translate(-50%, calc(-50% - 6vh - 2px));
    z-index: 1;
}

/* the scroll arrives at the source before Go Deeper;
   credits takes no mark so the sequence ends once */
.pp-credits::before { content: none; }

.pp-chapter {
    min-height: 88vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    position: relative;
    padding: 5rem 0;
}

/* Reveal-on-scroll targets the INNER wrapper, not the section: the section's
   ::before divider mark rides ~6vh ahead of its section, so hiding the whole
   section kept the mark invisible on a reader's first pass. Punctuation stays
   put; only the episode content breathes in. */
.pp-chapter .pp-chapter-inner {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 0.9s ease, transform 0.9s ease;
}

.pp-chapter.in-view .pp-chapter-inner {
    opacity: 1;
    /* "none" (not translateY(0)) so the settled content drops its stacking
       context — otherwise later chapters paint over the open listen menu */
    transform: none;
}

@media (prefers-reduced-motion: reduce) {
    .pp-chapter .pp-chapter-inner {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* Quote-as-artwork composition: the episode's standout quote is the
   visual element, set beside the episode banner. Sides alternate
   down the scroll, Floodlines-style. */
.pp-chapter-inner {
    position: relative;
    width: min(880px, calc(100vw - 3.5rem));
    display: grid;
    grid-template-columns: 1.15fr 0.85fr;
    gap: clamp(2.5rem, 6vw, 5rem);
    align-items: center;
    text-align: left;
}

.pp-chapter:nth-of-type(even) .pp-quote {
    order: 2;
}

.pp-chapter:nth-of-type(even) .pp-chapter-info {
    order: 1;
}

.pp-quote {
    position: relative;
    margin: 0;
}

.pp-quote p {
    /* hang the opening quotation mark so the text edge stays flush */
    text-indent: -0.45em;
    font-family: var(--pp-display);
    font-style: italic;
    font-weight: 500;
    /* the quote is the episode's art surrogate — it leads the title by a
       steady ~1.10-1.14 step at every viewport (the old 3.4vw/2.15 clamp tied
       it with the title at desktop and INVERTED under it near 900px) */
    font-size: clamp(1.75rem, 4.6vw, 2.4rem);
    line-height: 1.35;
    color: var(--pp-ink);
}

/* Long narrative quotes set smaller — a passage, not a monument */
.pp-quote-long p {
    font-size: clamp(1.2rem, 2.4vw, 1.5rem);
    line-height: 1.5;
}

.pp-quote-attr {
    display: block;
    margin-top: 1.25rem;
    font-style: normal;
    color: var(--pp-accent);
}

.pp-chapter-info {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.pp-chapter-label {
    margin-bottom: 0.85rem;
    color: var(--pp-accent);
}

.pp-chapter-title {
    font-family: var(--pp-display);
    font-weight: 600;
    font-size: clamp(1.6rem, 4.2vw, 2.1rem);
    letter-spacing: 0.01em;
    line-height: 1.15;
}

.pp-chapter-title a {
    text-decoration: none;
    color: var(--pp-ink);
    transition: color 0.2s ease;
}

.pp-chapter-title a:hover {
    color: var(--pp-indigo);
}

/* the episode's one-line description, under its title */
.pp-chapter-tease {
    font-size: 1.1rem;
    line-height: 1.45;
    color: var(--pp-ink);
    margin-top: 0.7rem;
}

/* Inline episode player. A card goes live (.is-live + an <audio> child)
   when its draft file lands in media/; the rest stay dormant placeholders.
   AT LAUNCH the audio srcs swap to the Podbean-hosted MP3s — the
   component itself doesn't change. */
.pp-player {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    margin-top: 1.6rem;
    width: 100%;
    /* 340 (was 300 pre-speed-chip): gives the seek line back most of
       the ~44px the chip claims; the card column runs ~341px wide */
    max-width: 340px;
}

/* Docked player (episode pages): once playback has started and the reader
   has scrolled the player off the top, the same player pins to the bottom
   edge. On phones that is directly above the nav bar — the Spotify/Apple
   Music stack: the transport rides on the tabs; on wider screens the bar
   is at the top and the strip has the bottom edge to itself. Paper + a
   rule above, like the bar itself. The script sets `bottom` to the bar's
   height (0 when the bar is on top) and keeps a placeholder in the
   player's original spot so nothing jumps. */
body .pp-player.is-docked { /* `body` outweighs the header's margin/max-width rule below */
    position: fixed;
    bottom: 0; /* overridden inline to the bar's height */
    left: 0;
    right: 0;
    z-index: 60;
    margin: 0;
    max-width: none;
    /* side padding is set by the script to the reading column's edges, so
       the transport lines up with the text it controls; this is the fallback */
    padding: 0.6rem max(1.25rem, calc((100% - 520px) / 2));
    /* the bar's own veil, so strip and bar read as one dock — and on
       the homepage the focus dimming runs through the strip as it does
       through the bar, instead of stopping at a paper band */
    background: rgba(225, 215, 195, 0.68);
    -webkit-backdrop-filter: blur(12px) saturate(1.05);
    backdrop-filter: blur(12px) saturate(1.05);
    border-top: 1px solid rgba(24, 41, 51, 0.10);
    animation: pp-dock-in 0.35s ease;
}

/* Now-playing strip (homepage): one strip for six sources, in the DOM
   from the start and shown only while docked. Its sides sit on the
   episode grid's edges (.pp-chapter-inner: min(880px, 100vw - 3.5rem)),
   so the transport spans the block the cards sit in. */
.pp-dock:not(.is-docked) {
    display: none;
}

body .pp-player.pp-dock.is-docked {
    padding-left: max(1.75rem, calc((100% - 880px) / 2));
    padding-right: max(1.75rem, calc((100% - 880px) / 2));
}

/* the strip stays up once it has appeared; when the audio ends it runs
   its entrance backwards — down behind the bar's top edge — and goes.
   Its own keyframes, not pp-dock-in reversed: re-declaring a finished
   animation under the same name never restarts it (or fires its end). */
body .pp-player.pp-dock.is-docked.is-leaving {
    animation: pp-dock-out 0.3s ease forwards;
}

@keyframes pp-dock-out {
    from { transform: none;             clip-path: inset(0px 0px 0% 0px); }
    to   { transform: translateY(100%); clip-path: inset(0px 0px 100% 0px); }
}

/* what's playing, in the card's own kicker voice */
.pp-dock-name {
    flex-shrink: 0;
    white-space: nowrap;
    color: var(--pp-accent);
}

/* docked, the play button steps down one size so the strip sits just a
   little taller than the nav bar beneath it — siblings, not parent and child */
body .pp-player.is-docked .pp-player-btn {
    width: 34px;
    height: 34px;
}
body .pp-player.is-docked .pp-player-btn svg {
    width: 16px;
    height: 16px;
}

/* The strip rises out of the bar's top edge, not up through the bar: the
   clip tracks the slide frame for frame, so only the part already above
   the bar is ever painted and the tabs are never covered. */
@keyframes pp-dock-in {
    from { transform: translateY(100%); clip-path: inset(0px 0px 100% 0px); }
    to   { transform: none;             clip-path: inset(0px 0px 0% 0px); }
}

@media (prefers-reduced-motion: reduce) {
    body .pp-player.is-docked { animation: none; }
}

.pp-player-btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    padding: 0;
    background: none;
    border: 1px solid var(--pp-ink-soft);
    border-radius: 50%;
    color: var(--pp-ink);
}

button.pp-player-btn {
    cursor: pointer;
}

.pp-player-btn svg {
    /* optical centering: the triangle's mass sits left of its box; nudge by
       half the centroid gap at this scale (same rule as the hero trailer) */
    transform: translateX(0.6px);
}

/* pause bars are mass-symmetric — exact center, no nudge (the hero rule) */
.pp-player-btn .pp-player-icon-pause {
    transform: none;
    display: none;
}

.pp-player.is-playing .pp-player-icon-play {
    display: none;
}

.pp-player.is-playing .pp-player-icon-pause {
    display: block;
}

.pp-player-time {
    font-family: var(--pp-serif);
    font-size: 0.78rem;
    letter-spacing: 0.06em;
    color: var(--pp-ink-soft);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.pp-player-track {
    --p: 0%;
    position: relative;
    flex: 1;
    height: 1px;
    background: rgba(24, 41, 51, 0.22);
}

/* live tracks are seekable — a 15px hit zone around the same 1px line */
.pp-player.is-live .pp-player-track {
    height: 15px;
    padding: 7px 0;
    background-clip: content-box;
    cursor: pointer;
}

/* the start tick doubles as the playhead once audio drives --p */
.pp-player-track::before {
    content: "";
    position: absolute;
    left: var(--p);
    top: 50%;
    transform: translate(-50%, -50%);
    width: 2px;
    height: 9px;
    background: var(--pp-ink-soft);
}

/* elapsed line, in the hero arc's vermilion */
.pp-player-track::after {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    height: 1px;
    width: var(--p);
    background: var(--pp-accent-bright);
}

/* speed control — a bare numeral in the timestamp's register, the
   row's two ends bookended by quiet figures. The width stays fixed
   (invisibly) so the seek line doesn't jitter as the label swings
   between "1×" and "1.2×"; left-aligned so the line-to-numeral gap
   mirrors the timestamp-to-line gap (slack falls off the row's edge).
   line-height matches the time span so both sit on the same baseline.
   Padding + negative margin widen the tap target without visual size */
.pp-player-rate {
    flex-shrink: 0;
    width: 2rem;
    padding: 0.45rem 0;
    margin: -0.45rem 0;
    background: none;
    border: 0;
    font-family: var(--pp-serif);
    font-size: 0.78rem;
    line-height: inherit;
    letter-spacing: 0.06em;
    text-align: left;
    font-variant-numeric: tabular-nums;
    color: var(--pp-ink-soft);
    cursor: pointer;
    transition: color 0.15s ease;
}

.pp-player-rate:hover,
.pp-player-rate:focus-visible {
    color: var(--pp-ink);
}

/* ============================================
   FEATURING LINE (homepage cards, eps 3 & 4)
   Text-only guest credit set between the player
   and the actions. A liner-note register: the
   whole credit in italic text-serif, "Featuring"
   in accent — editorial, not a tracked-caps label;
   its italic echoes the pull-quote across the gutter.
   The simplest form until Valero's art suggests more.
   ============================================ */

.pp-voices-line {
    margin-top: 1.6rem;
    max-width: 24em;
    font-family: var(--pp-serif);
    font-style: italic;
    font-size: 1.1rem;
    line-height: 1.5;
    color: var(--pp-ink-soft);
}

.pp-voices-lead {
    color: var(--pp-accent);
}

/* ============================================
   EPISODE ACTIONS (homepage cards)
   One quiet line beneath the player: the "Listen
   elsewhere" disclosure and the Details link,
   same register, no glyphs — the words carry it.
   The platforms wait in a paper panel.
   ============================================ */

.pp-actions {
    position: relative;
    display: flex;
    flex-wrap: wrap; /* the episode link is long; let it drop below on narrow screens */
    align-items: baseline;
    row-gap: 0.55rem;
    margin-top: 1.5rem;
}

.pp-actions-link,
.pp-listen-btn {
    font-family: var(--pp-sans);
    font-size: 0.7rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--pp-ink-soft);
    text-decoration: none;
    background: none;
    border: 0;
    /* same link underline as the hero's "Listen on" row */
    border-bottom: 1px solid var(--pp-accent-soft);
    padding: 0 0 2px;
    cursor: pointer;
    white-space: nowrap;
    transition: color 0.2s ease, border-bottom-color 0.2s ease;
}

.pp-actions-link:hover,
.pp-listen-btn:hover,
.pp-listen-btn[aria-expanded="true"] {
    color: var(--pp-indigo);
    border-bottom-color: var(--pp-indigo);
}

.pp-actions-sep {
    margin: 0 0.7rem;
    color: var(--pp-accent-soft);
    font-size: 0.7rem;
}

.pp-listen-menu {
    position: absolute;
    top: calc(100% + 0.6rem);
    left: 0;
    background: var(--pp-cream);
    border: 1px solid var(--pp-rule);
    border-radius: 5px;
    box-shadow: 0 12px 28px rgba(24, 41, 51, 0.13);
    z-index: 6;
}

.pp-listen-menu a {
    display: block;
    padding: 0.65rem 1rem;
    font-family: var(--pp-sans);
    font-weight: 500;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--pp-ink-soft);
    text-decoration: none;
    white-space: nowrap;
    transition: color 0.2s ease;
}

.pp-listen-menu a + a {
    border-top: 1px solid var(--pp-rule);
}

.pp-listen-menu a:hover {
    color: var(--pp-indigo);
}

/* ============================================
   EPISODE META (episode pages only — homepage
   uses .pp-actions above; unify when the episode
   pages are redesigned)
   Two registers beneath the player. The listen
   row belongs to the player unit; a hairline
   closes that unit; Details / Transcript sit
   below it as the card's quiet footer.
   ============================================ */

.pp-episode-meta {
    width: 100%;
    margin-top: 1.25rem;
}

.pp-meta-cluster {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    row-gap: 0.35rem;
}

.pp-meta-label {
    font-family: var(--pp-sans);
    font-weight: 500;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--pp-accent);
    margin-right: 0.8rem;
}

.pp-episode-meta a {
    font-family: var(--pp-sans);
    font-weight: 500;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.18em; /* matches the homepage card's action links */
    color: var(--pp-ink-soft);
    text-decoration: none;
    /* same link underline as the hero's "Listen on" row */
    border-bottom: 1px solid var(--pp-accent-soft);
    padding-bottom: 2px;
    transition: color 0.2s ease, border-bottom-color 0.2s ease;
    white-space: nowrap;
}

.pp-episode-meta a:hover {
    color: var(--pp-indigo);
    border-bottom-color: var(--pp-indigo);
}

.pp-meta-sep {
    margin: 0 0.5rem;
    font-size: 0.78rem;
    color: var(--pp-accent-soft);
}

/* ============================================
   FOCUS (homepage) — the breathing periphery
   The ground already carries a faint fixed
   vignette; under body.pp-focused these layers
   deepen it and soften the screen's edges —
   periphery as the eye knows it: lower
   resolution, quieter color, never dark.
   The homepage's scroll gravity used to conduct
   it; that script was removed (Oct 2026), so
   only the trailer page's playback sets
   body.pp-focused now.
   Three FLAT fixed siblings, deliberately not
   wrapped: the tone layer's mix-blend-mode
   would turn a shared wrapper into an isolated
   group, and the blur layers' backdrop-filters
   would then sample that empty group instead
   of the page — the blur silently vanishes.
   Each mask rides on its own blur element for
   the same family of reasons.
   Every ellipse centers 27px above viewport
   center — the middle of the area above the
   bottom bar.
   ============================================ */

.pp-focus-layer {
    position: fixed;
    inset: 0;
    z-index: 40; /* under the bottom bar (50) */
    pointer-events: none;
    opacity: 0;
    /* release: attention lets go quickly — never fight the reader */
    transition: opacity 240ms ease-out;
}

body.pp-focused .pp-focus-layer {
    opacity: 1;
    /* arrival: in with the glide, same easeInOutSine as the motion */
    transition: opacity 750ms cubic-bezier(0.37, 0, 0.63, 1);
}

/* THE TONE — the ground's vignette taking one more step along its
   own paper axis. Multiply keeps it pigment-like (ink deepens, never
   fogs); the eased stops hide any start-edge; the body grain dithers
   the long ramp against banding. */
.pp-focus-tone {
    background: radial-gradient(ellipse at 50% calc(50% - 27px),
        rgba(203, 186, 160, 0)    50%,
        rgba(203, 186, 160, 0.05) 61%,
        rgba(203, 186, 160, 0.14) 70%,
        rgba(202, 183, 154, 0.27) 79%,
        rgba(199, 177, 146, 0.40) 88%,
        rgba(193, 168, 135, 0.52) 100%);
    mix-blend-mode: multiply;
}

/* THE OPTICS — two masked backdrop rings, radii small on purpose
   (the whisper is the point; the tone carries the legible change).
   The outer ring samples the inner ring's output, so softness
   compounds toward the corners; saturate() quiets peripheral color
   the way the retina does. */
.pp-focus-blur-1 {
    -webkit-backdrop-filter: blur(2px) saturate(0.96);
    backdrop-filter: blur(2px) saturate(0.96);
    -webkit-mask-image: radial-gradient(ellipse at 50% calc(50% - 27px), transparent 56%, #000 74%);
    mask-image: radial-gradient(ellipse at 50% calc(50% - 27px), transparent 56%, #000 74%);
}

.pp-focus-blur-2 {
    -webkit-backdrop-filter: blur(5px) saturate(0.92);
    backdrop-filter: blur(5px) saturate(0.92);
    -webkit-mask-image: radial-gradient(ellipse at 50% calc(50% - 27px), transparent 70%, #000 92%);
    mask-image: radial-gradient(ellipse at 50% calc(50% - 27px), transparent 70%, #000 92%);
}

/* Phones: text runs nearly edge to edge — tone only, gentler,
   living mostly in the corners */
@media (max-width: 700px) {
    .pp-focus-blur-1,
    .pp-focus-blur-2 {
        display: none;
    }

    body.pp-focused .pp-focus-tone {
        opacity: 0.6;
    }
}

/* Guards the focus toggle from animating under reduced motion */
@media (prefers-reduced-motion: reduce) {
    .pp-focus-layer {
        transition: none;
    }
}

/* ============================================
   NAV BAR (site-wide wayfinding, S-Town style)
   Phones: fixed to the bottom edge, in thumb's reach.
   Tablets, laptops, desktops (701px and up): fixed to
   the top edge — see the "bar on top" block after the
   Episodes menu rules. The class keeps its first name.
   ============================================ */

.pp-bottom-bar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 50;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 2.75rem;
    padding: 0.85rem 1.25rem;
    /* clear the home indicator on notched phones and in standalone/PWA mode */
    padding-bottom: calc(0.85rem + env(safe-area-inset-bottom, 0px));
    /* Solid paper on every page (Oct 2026). The homepage's bar used to be
       a translucent veil so the focus dimming could read through it; with
       the focus effect dormant, all the veil did was let quotes and
       divider marks smear under the labels — and a soft patch behind a
       single item reads as a selected state. */
    background: var(--pp-paper);
    border-top: 1px solid var(--pp-rule);
}

.pp-bottom-bar a,
.pp-bar-toggle,
.pp-bar-share {
    font-family: var(--pp-sans);
    font-size: 0.7rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.24em; /* on the optical curve: 0.7rem caps track at 0.24 */
    color: var(--pp-ink-soft);
    text-decoration: none;
    white-space: nowrap;
    transition: color 0.2s ease;
}

.pp-bar-toggle,
.pp-bar-share {
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
}

.pp-bottom-bar a:hover,
.pp-bottom-bar a.active,
.pp-bar-toggle:hover,
.pp-bar-toggle[aria-expanded="true"],
.pp-bar-share:hover {
    color: var(--pp-accent);
}

/* Corner utilities — home mark left, Share right (S-Town's zoning:
   destinations centered, tools at the edges as counterweights) */
.pp-bar-mark {
    position: absolute;
    left: 1.4rem;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
}

/* The mark is the cover's engraving disc (img); the SVG stacked on it
   is the hover state — the vermilion disc and the shell's-eye dot —
   fading in over the imprint. */
.pp-bar-mark img {
    display: block;
    border-radius: 50%;
}

.pp-bar-mark svg {
    display: block;
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity 0.2s ease;
}

.pp-bar-mark:hover svg {
    opacity: 1;
}

.pp-bar-share {
    position: absolute;
    right: 1.4rem;
    top: 50%;
    transform: translateY(-50%);
}

.pp-bar-share.copied {
    color: var(--pp-accent);
}

/* Episodes menu — the series' table of contents, opening above the bar.
   inline-flex collapses the wrapper's body-font line box so the toggle
   sits on the same line as the bar's other labels */
.pp-nav-episodes {
    position: relative;
    display: inline-flex;
}

.pp-episodes-menu {
    position: absolute;
    bottom: calc(100% + 1.1rem);
    left: 50%;
    transform: translateX(-50%);
    min-width: 300px;
    max-width: calc(100vw - 2rem);
    background: var(--pp-cream);
    border: 1px solid var(--pp-rule);
    padding: 0.6rem 0;
    box-shadow: 0 10px 34px rgba(24, 41, 51, 0.11);
}

/* with the player docked above the bar, the menu clears the strip as well
   (the episode page's script publishes the strip's height as --pp-dock-h) */
.pp-player-docked .pp-episodes-menu {
    bottom: calc(100% + 1.1rem + var(--pp-dock-h, 0px));
}

.pp-episodes-menu a {
    display: flex;
    align-items: baseline;
    gap: 0.85rem;
    padding: 0.5rem 1.4rem;
    font-family: var(--pp-serif);
    font-size: 1rem;
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    white-space: nowrap;
    color: var(--pp-ink);
    text-decoration: none;
    transition: color 0.15s ease, background-color 0.15s ease;
}

.pp-episodes-menu a:hover {
    color: var(--pp-indigo);
    background: #ecdfc8; /* a shade under the cream panel */
}

.pp-episodes-menu .pp-menu-n {
    font-family: var(--pp-sans);
    font-size: 0.7rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    color: var(--pp-accent);
    min-width: 1em;
}

/* Bar on top — tablets, laptops and desktops (Oct 2026). Phones keep the
   bar at the bottom. The page makes room above instead of below, the
   Episodes menu opens downward, and in-page jumps stop clear of the bar.
   A docked player then sits alone on the bottom edge (the scripts read
   where the bar is), and the page pads itself by the strip's height so
   the strip never covers the last lines. */
@media (min-width: 701px) {
    html {
        scroll-padding-top: 3.4rem;
    }

    body {
        padding-bottom: 0;
    }

    /* the trailer page has no bar to clear */
    body:not(.pp-prelaunch) {
        padding-top: 3.4rem;
    }

    body.pp-player-docked {
        padding-bottom: var(--pp-dock-h, 0px);
    }

    .pp-bottom-bar {
        top: 0;
        bottom: auto;
        padding-top: calc(0.85rem + env(safe-area-inset-top, 0px));
        padding-bottom: 0.85rem;
        border-top: 0;
        border-bottom: 1px solid var(--pp-rule);
    }

    .pp-episodes-menu,
    .pp-player-docked .pp-episodes-menu {
        top: calc(100% + 1.1rem);
        bottom: auto;
    }

    /* the landing frame fills the screen below the bar; the bottom
       padding no longer has a bar to lift the composition clear of */
    .pp-hero {
        min-height: calc(100vh - 3.4rem);
        padding-bottom: 6.5rem;
    }
}

/* ============================================
   ABOUT + CREDITS (homepage)
   ============================================ */

.pp-about,
.pp-credits {
    position: relative;
    padding: 5rem 0;
    text-align: center;
}

.pp-section-label {
    display: block;
    margin-bottom: 2rem;
    color: var(--pp-accent);
}

.pp-about p {
    font-size: 1.1rem;
    color: var(--pp-ink);
    max-width: 32em;
    margin: 0 auto 1.25rem;
    text-align: left;
}

/* Go Deeper — invitation to the Substack companion material.
   Left-set like the credits: the page's back matter shares one
   left axis (colophon register), while chapters stay centered. */
.pp-substack {
    position: relative;
    padding: 4rem 0;
    text-align: left;
}

/* Section title in the display voice — Go Deeper is the page's sixth
   movement, not a kicker; sized a notch under the episode titles so
   the episodes keep primacy. */
/* Vermilion kicker over the title — the episode kickers' voice,
   carrying the bottom bar's word for this section */
.pp-substack-kicker {
    display: block;
    color: var(--pp-accent);
    margin-bottom: 0.85rem;
}

.pp-substack-title {
    font-family: var(--pp-display);
    font-weight: 600;
    font-size: clamp(1.5rem, 3.6vw, 1.9rem);
    letter-spacing: 0.01em;
    line-height: 1.15;
    color: var(--pp-ink);
    margin-bottom: 1.4rem;
}

.pp-substack p {
    font-size: 1.1rem;
    color: var(--pp-ink);
    max-width: 34em;
    margin: 0 0 1.2rem;
}

.pp-substack p:last-of-type {
    margin-bottom: 0;
}

/* Example teasers use the episode pages' .pp-deeper-list rows;
   here the list aligns with the section's paragraph, not centered */
.pp-substack .pp-deeper-list {
    margin: 2.2rem 0 0;
}

.pp-substack a {
    color: var(--pp-ink);
    text-decoration-color: var(--pp-accent-soft);
}

.pp-substack a:hover {
    color: var(--pp-indigo);
    text-decoration-color: var(--pp-indigo);
}

/* Credits — left-aligned, tight stacked list */
.pp-credits {
    text-align: left;
    padding: 4rem 0 5rem;
}

.pp-credits-title {
    display: block;
    color: var(--pp-accent);
    margin-bottom: 1.25rem;
}

.pp-credits-list {
    list-style: none;
}

.pp-credits-list li {
    font-size: 1rem;
    color: var(--pp-ink-soft);
    line-height: 1.5;
    padding: 0.2rem 0;
}

.pp-credit-name {
    color: var(--pp-ink);
    font-weight: 500;
}

/* ============================================
   EPISODE PAGES
   ============================================ */

/* Left-set reading pages on the homepage's 880 canvas, with a label
   rail: section captions and the episode number hang right-aligned in
   a margin column (book-caption grammar). Prose keeps its ~66-character
   measure in the content field — only the frame widened. Pages opt in
   via body.pp-episode-page (main is shared with the homepage). */
.pp-episode-page main {
    max-width: calc(880px + 4rem);
}

/* One spacing scale for the page, built on the paragraph gap (1.25rem):
   1 step inside a group (title→tease, player→listen-on), 2 steps between
   the title block and the transport, and 3rem+3rem at every section
   boundary — the header's bottom padding matches the sections' so the
   first boundary is the same size as the rest. */
.pp-episode-header {
    padding: 6rem 0 3rem;
    display: grid;
    grid-template-columns: 168px 1fr;
    column-gap: 3rem;
    align-items: start;
}

.pp-episode-header > * {
    grid-column: 2;
}

.pp-episode-header .pp-chapter-label {
    grid-column: 1;
    grid-row: 1;
    align-self: baseline;
    color: var(--pp-accent);
    text-align: right;
    margin-bottom: 0;
}

.pp-episode-title {
    align-self: baseline; /* shares the rail label's baseline group */
    font-family: var(--pp-display);
    font-weight: 600;
    font-size: clamp(2.1rem, 7vw, 3.1rem);
    letter-spacing: 0.01em;
    line-height: 1.12;
    max-width: 14em;
}

.pp-episode-tease {
    font-style: italic;
    font-size: 1.1rem;
    color: var(--pp-ink);
    margin-top: 1.25rem;
    max-width: 28em;
}

/* The header player: same transport as the homepage cards, roomier */
.pp-episode-header .pp-player {
    margin-top: 2.5rem;
    max-width: 380px;
}

/* Episode body sections — each is a rail row: caption left, content right */
.pp-episode-section {
    position: relative;
    padding: 3rem 0;
    display: grid;
    grid-template-columns: 168px 1fr;
    column-gap: 3rem;
}

.pp-episode-section > * {
    grid-column: 2;
}

.pp-episode-section .pp-section-label {
    grid-column: 1;
    grid-row: 1;
    align-self: baseline;
    text-align: right;
    margin-bottom: 0;
}

/* the first content item joins the label's baseline group, so the caps
   sit exactly on the content's first baseline at any size */
.pp-episode-section .pp-section-label + * {
    align-self: baseline;
}

/* A section's last paragraph keeps its bottom margin inside a grid (or
   above padding), which used to add a stray step to that boundary alone.
   Zero it so every section boundary measures the same. */
.pp-episode-section > :last-child,
.pp-transcript > :last-child {
    margin-bottom: 0;
}

/* Featuring: one guest per row, portrait plate left of the bio.
   Two-up was the older arrangement; it forced the bios down to a
   28-character measure, and enlarging the portraits inside it only
   made that worse — the photo and the prose were competing for the
   same 305px. One row per guest gives both room: 120px plates and a
   ~64-character measure. It also absorbs episode 4's fifth guest,
   which left an orphan on the last row of a two-column grid. */
.pp-featuring {
    grid-template-columns: 168px 1fr;
    row-gap: 2.75rem;
}

.pp-featuring .pp-section-label {
    grid-column: 1;
    /* a guest row's grid baseline is its photo edge, not the name — opt
       out of baseline alignment and seat the caps by measure. The name is
       cap-trimmed, so the row now starts ON the name's cap line and this
       is just the difference between the two faces' cap heights. */
    align-self: start;
    padding-top: 1px;
}

.pp-featuring .pp-section-label + .pp-guest {
    align-self: start;
}

/* every guest sits in the content column — grid auto-placement would
   otherwise wrap the next row back into the rail */
.pp-featuring > .pp-guest {
    grid-column: 2;
}

.pp-featuring .pp-guest {
    margin: 0;
    gap: 1.75rem;
    max-width: none; /* the row is the measure now, not a 34em card */
}

/* Square plates, not circles: a round mask throws away a fifth of the
   frame, and the book-plate read suits the cover's engraving language.
   120px is the ceiling the 240px source files support at 2x. */
.pp-featuring .pp-guest-photo {
    width: 120px;
    height: 120px;
    border-radius: 2px;
}

/* The About header carries only a title. Episode headers fill the space
   below theirs with the meta cluster and the player, so the header's 3rem
   and the first section's 3rem read as one unit there; here they stack
   into a hole. Collapse them to a single breath about the size of the
   title's own line. */
.pp-about-page .pp-episode-header {
    padding-bottom: 0;
}

.pp-about-page .pp-episode-header + .pp-episode-section {
    padding-top: 3rem;
}

/* About page: the lede takes the title's seat — the blurb's first
   paragraph in the display voice, sized for a four-line statement rather
   than a three-word title. */
.pp-about-page .pp-episode-title {
    font-size: clamp(1.55rem, 4.2vw, 1.85rem);
    line-height: 1.28;
    letter-spacing: 0.005em;
    max-width: 20em;
}

/* About page: below the lede, the series copy runs in a two-thirds
   column with the apparatus — the two bios, then the credits list — beside
   it in a smaller face. Both columns start on one baseline.
   No rail here (Oct 2026): the "About" label was dropped — the nav's own
   highlighted About already says where you are — so the header and the
   section are plain blocks and the lede + two columns sit centred in the
   window as one 821px block (the width they had beside the 168px rail in
   the old 1040px page, so both measures are unchanged). */
.pp-episode-page.pp-about-page main {
    max-width: calc(821px + 4rem);
}

.pp-about-page .pp-episode-header,
.pp-about-page .pp-episode-section {
    display: block;
}

.pp-about-columns {
    display: grid;
    grid-template-columns: 2fr 1fr;
    column-gap: 2.75rem;
    align-items: baseline;
}

/* `.pp-about-page` prefixes outrank `.pp-episode-section p`, which is
   declared later in this file */
.pp-about-page .pp-about-body p {
    max-width: none;
}

.pp-about-page .pp-about-body p:last-child {
    margin-bottom: 0;
}

.pp-about-page .pp-about-aside p {
    font-size: 0.92rem;
    line-height: 1.55;
    color: var(--pp-ink);
    max-width: none;
    margin: 0 0 0.9rem;
}

.pp-about-page .pp-about-aside p:last-child {
    margin-bottom: 0;
}

.pp-aside-credits {
    margin-top: 2.25rem;
}

.pp-aside-credits:first-child {
    margin-top: 0;
}

.pp-aside-credits-title {
    display: block;
    color: var(--pp-accent);
    margin-bottom: 0.7rem;
}

/* Credits rhythm, after the podcast and magazine credit pages: the two
   bios part like short paragraphs, the one-line credits sit closer, as
   list lines do — equal gaps read as wider between one-liners */
.pp-about-page .pp-aside-credits p {
    margin-bottom: 0.6em;
}

.pp-aside-credits .pp-credits-list li {
    font-size: 0.92rem;
    line-height: 1.55;
    padding: 0;
    margin-bottom: 0.3em;
}

.pp-aside-credits .pp-credits-list li:last-child {
    margin-bottom: 0;
}

/* One column on narrower windows: body, then bios, then credits — held to
   a reading measure and centred, since there is no rail to take up width */
@media (max-width: 900px) {
    .pp-about-page .pp-episode-header,
    .pp-about-page .pp-episode-section {
        max-width: 38rem;
        margin-left: auto;
        margin-right: auto;
    }

    .pp-about-columns {
        display: block;
    }

    .pp-about-aside {
        margin-top: 2.5rem;
    }

    .pp-about-page .pp-about-aside p {
        max-width: 34em;
    }
}

/* About page: credits join the rail grammar */
.pp-episode-page .pp-credits {
    display: grid;
    grid-template-columns: 168px 1fr;
    column-gap: 3rem;
}

.pp-episode-page .pp-credits > * {
    grid-column: 2;
}

.pp-episode-page .pp-credits .pp-credits-title {
    grid-column: 1;
    grid-row: 1;
    align-self: baseline;
    text-align: right;
    margin-bottom: 0;
}

.pp-episode-page .pp-credits .pp-credits-title + * {
    align-self: baseline;
}

/* Between the phone stack and a roomy desktop, a full-width rail and a
   120px plate can't both have their room: at 768px the bios fall back
   under a 40-character measure. Tighten the rail instead of shrinking
   the portraits — the caps still fit 104px, and the prose sections gain
   the same width. */
@media (min-width: 701px) and (max-width: 900px) {
    .pp-episode-header,
    .pp-episode-section,
    .pp-featuring,
    .pp-episode-page .pp-credits {
        grid-template-columns: 104px 1fr;
        column-gap: 2rem;
    }
}

/* The rail returns to a stack on small screens (guests are already
   one-up at every width, so there is no intermediate fold to make) */
@media (max-width: 700px) {
    .pp-episode-header,
    .pp-episode-section,
    .pp-featuring,
    .pp-episode-page .pp-credits {
        display: block;
    }

    .pp-episode-header .pp-chapter-label {
        display: block;
        text-align: left;
        margin-bottom: 1rem;
    }

    .pp-episode-section .pp-section-label {
        text-align: left;
        margin-bottom: 2rem;
        padding-top: 0; /* release the Featuring rail seat */
    }

    .pp-episode-page .pp-credits .pp-credits-title {
        text-align: left;
        margin-bottom: 1.25rem;
    }

    .pp-featuring .pp-guest {
        margin: 0 0 2.25rem;
    }

    .pp-featuring .pp-guest:last-of-type {
        margin-bottom: 0;
    }
}

.pp-episode-section p {
    font-size: 1.1rem;
    color: var(--pp-ink);
    max-width: 32em;
    margin: 0 0 1.25rem;
}

/* Transcript — the script's own formatting grammar: narration runs the
   full measure, tape is indented, speaker names carry real weight
   (EB Garamond 600, loaded on transcript pages only) */
.pp-transcript .pp-tape {
    padding-left: 2.5rem;
}

.pp-speaker {
    font-weight: 600;
    font-style: normal;
}

/* Timed transcript (episode 1 first, Sept 2026): each phrase is a .pp-cue
   carrying its start time. The phrase being spoken takes a faint
   vermilion wash; any phrase can be clicked to play from there. */
.pp-transcript .pp-cue {
    cursor: pointer;
    border-radius: 2px;
    transition: color 0.15s ease, background-color 0.25s ease;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
}
/* a faint underline on hover says "this is clickable" without dressing
   every phrase as a link — the site's own link rule, at rest strength */
.pp-transcript .pp-cue:hover {
    color: var(--pp-ink);
    text-decoration: underline;
    text-decoration-color: var(--pp-accent-soft);
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}
.pp-transcript .pp-cue.is-now {
    color: var(--pp-ink);
    background-color: rgba(198, 55, 36, 0.10);
    box-shadow: 0 0 0 2px rgba(198, 55, 36, 0.10); /* lets the wash breathe past the glyphs */
}

/* Guest bios */
.pp-guest {
    display: flex;
    gap: 1.75rem;
    align-items: flex-start;
    max-width: 34em;
    margin: 0 0 2.5rem;
}

.pp-guest:last-child {
    margin-bottom: 0;
}

.pp-guest-photo {
    flex-shrink: 0;
    width: 92px;
    height: 92px;
    border-radius: 50%;
    border: 1px solid var(--pp-rule);
    overflow: hidden;
}

.pp-guest-photo img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Tone the portraits toward the paper palette so differently-lit
       photos sit together. Drop the filter to run them plain. */
    filter: saturate(0.82) sepia(0.16);
}

/* The name is a display heading and takes display leading — it was the
   only heading on the page inheriting the body's 1.65, which is reading
   leading. The episode title runs 1.12, chapter titles 1.15. */
.pp-guest-name {
    font-family: var(--pp-display);
    font-size: 1.4rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--pp-ink);
    margin-bottom: 0.5rem;

    /* Trim the half-leading and the ascender gap above the capitals, so
       the element's top edge IS the cap line. The portrait beside it is
       flex-start aligned, so it then meets the top of the name's caps
       rather than an invisible box edge ~7px higher. The CSS Inline
       Layout spec makes this case explicitly: the visual boundaries of
       Latin text are the cap height and the baseline, not the ascent
       and descent, so aligning a picture to the box "often doesn't
       yield the intended visual effect". */
    text-box-trim: trim-start;
    text-box-edge: cap alphabetic;
}

/* text-box-trim reached Baseline in Aug 2026 but is not everywhere yet,
   and it fails back to precisely the misalignment it fixes. The fallback
   pulls the same distance off the top by hand: Cormorant Garamond's
   line-box-top-to-cap at 1.4rem/1.2, in em of the name's own size, so it
   still scales with the reader's font-size setting. Recompute it if the
   display face, size or leading change. */
@supports not (text-box-trim: trim-start) {
    .pp-guest-name {
        margin-top: -0.256em;
    }
}

.pp-guest-bio {
    font-size: 1rem;
    color: var(--pp-ink);
    line-height: 1.6;
}

/* Same inline-link language as the hero listen row */
.pp-guest-bio a {
    color: var(--pp-ink);
    text-decoration: none;
    border-bottom: 1px solid var(--pp-accent-soft);
    padding-bottom: 1px;
    transition: color 0.2s ease, border-bottom-color 0.2s ease;
}

.pp-guest-bio a:hover {
    color: var(--pp-indigo);
    border-bottom-color: var(--pp-indigo);
}

/* Go deeper — Substack bonus material */
.pp-deeper-list {
    list-style: none;
    max-width: 34em;
    margin: 0;
}

.pp-deeper-list li {
    border-bottom: 1px solid var(--pp-rule);
}

.pp-deeper-list li:first-child {
    border-top: 1px solid var(--pp-rule);
}

/* Each extra is one ruled row, and the whole row is the outbound link.
   No bullets, no numerals — scale contrast between the display-serif
   title and the small italic note does the work. */
.pp-deeper-link {
    display: block;
    padding: 1.4rem 0.15rem;
    text-decoration: none;
}

.pp-deeper-title {
    display: block;
    font-family: var(--pp-display);
    font-size: 1.4rem;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: 0.01em;
    color: var(--pp-ink);
    transition: color 0.2s ease;
}

.pp-deeper-note {
    display: block;
    font-size: 0.9rem;
    color: var(--pp-ink-soft);
    margin-top: 0.3rem;
    font-style: italic;
}

.pp-deeper-link:hover .pp-deeper-title {
    color: var(--pp-accent);
}

/* Trailing whisper under the list — the rolling-basis cue.
   p.pp-deeper-more so it outweighs the .pp-substack p defaults. */
p.pp-deeper-more {
    /* 34rem, not em: the list's 34em resolves at 1rem, and em here
       would shrink with this note's smaller type — right edges must meet */
    max-width: 34rem;
    margin: 0.7rem 0 0;
    text-align: right;
    font-size: 0.85rem;
    font-style: italic;
    color: var(--pp-ink);
}

/* Prev / next chapter nav */
.pp-episode-nav {
    border-top: 1px solid var(--pp-rule);
    padding: 2.5rem 0;
    display: flex;
    justify-content: space-between;
    gap: 2rem;
}

.pp-episode-nav a {
    font-family: var(--pp-sans);
    font-weight: 500;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.24em; /* on the optical curve: 0.7rem caps track at 0.24 */
    color: var(--pp-ink-soft);
    text-decoration: none;
}

.pp-episode-nav a:hover {
    color: var(--pp-indigo);
}

.pp-episode-nav .pp-nav-spacer {
    flex: 1;
}

/* ============================================
   RESPONSIVE
   ============================================ */

@media (max-width: 700px) {
    /* One flex row on phones — the desktop's absolute corners collide with
       four centered destinations at 375px, so mark, links, and Share share
       a single space-between row where overlap is impossible. */
    .pp-bottom-bar {
        justify-content: space-between;
        gap: 0.5rem;
        padding: 0.8rem 0.9rem;
        padding-bottom: calc(0.8rem + env(safe-area-inset-bottom, 0px));
    }

    .pp-bottom-bar a,
    .pp-bar-toggle,
    .pp-bar-share {
        font-size: 0.62rem;
        letter-spacing: 0.12em;
    }

    /* relative, not static: the mark's hover overlay anchors to it
       (left/top reset so the desktop offsets don't nudge it in-flow) */
    .pp-bar-mark {
        position: relative;
        left: auto;
        top: auto;
        transform: none;
    }

    .pp-bar-share {
        position: static;
        transform: none;
    }

    /* On phones the Episodes label sits near the left edge, so a menu
       centered on it runs off-screen. Anchor it to the bar instead
       (static wrapper → the fixed bar is the containing block), flush
       with the bar's left gutter and never wider than the screen. */
    .pp-nav-episodes {
        position: static;
    }

    .pp-episodes-menu {
        left: 0.9rem;
        transform: none;
        bottom: calc(100% + 1px);
        min-width: min(300px, calc(100vw - 1.8rem));
        max-width: calc(100vw - 1.8rem);
    }

    .pp-player-docked .pp-episodes-menu {
        bottom: calc(100% + 1px + var(--pp-dock-h, 0px));
    }

    /* the bar rule above also matches the menu's anchors (same
       specificity, later in file) — restate the book register so
       episode names don't shrink into tracked caps on phones */
    .pp-episodes-menu a {
        white-space: normal;
        font-size: 1rem;
        letter-spacing: 0;
    }

    .pp-chapter {
        padding: 4rem 0 5rem;
    }

    /* Phone stack: title anchors, quote follows, player acts.
       display:contents dissolves the two desktop columns so their pieces
       can interleave in one ordered column */
    .pp-chapter-inner {
        grid-template-columns: 1fr;
        gap: 0;
        width: 100%;
    }

    .pp-quote,
    .pp-chapter-info {
        display: contents;
    }

    .pp-chapter-label { order: 1; }
    .pp-chapter-title { order: 2; }
    .pp-chapter-tease { order: 2; } /* follows the title: same order, later in the DOM */
    .pp-quote p { order: 3; }
    .pp-quote-attr { order: 4; }
    .pp-player { order: 5; }
    .pp-voices-line { order: 6; }
    .pp-actions { order: 7; }

    /* under the title the quote reads as a passage, not the headline —
       step it below the title's 1.6rem instead of above it */
    .pp-quote p {
        margin-top: 1.6rem;
        font-size: 1.4rem;
        line-height: 1.5;
    }

    .pp-quote-long p {
        font-size: 1.2rem;
    }

    .pp-player {
        margin-top: 1.75rem;
    }

    /* now-playing strip: sides on main's padding; the label yields its
       room to the seek line (the reader tapped that card themselves) */
    body .pp-player.pp-dock.is-docked {
        padding-left: 2rem;
        padding-right: 2rem;
    }

    .pp-dock-name {
        display: none;
    }
}

@media (max-width: 600px) {
    main {
        padding: 0 1.4rem;
    }

    body .pp-player.pp-dock.is-docked {
        padding-left: 1.4rem;
        padding-right: 1.4rem;
    }

    .pp-hero {
        padding: 4rem 0 6rem;
    }

    .pp-chapter {
        min-height: 78vh;
    }

    .pp-guest {
        flex-direction: column;
        align-items: flex-start;
    }

    .pp-episode-nav {
        flex-direction: column;
        align-items: center;
        gap: 1.25rem;
    }
}

/* ============================================
   SHORT VIEWPORTS
   The landing frame is a fixed ~587px of content. On a short screen it
   outgrows the window, justify-content:center runs out of slack, and the
   listen row — the only call to action — slides under the fixed bottom bar.
   These blocks tighten the frame just enough to keep it whole. Height-gated,
   so they are inert on any window tall enough to lay out normally.
   ============================================ */

/* Short desktop windows (a 1366x768 laptop lands near 660px of viewport).
   min-width keeps this walled off from the phone rules above. */
@media (min-width: 701px) and (max-height: 780px) {
    .pp-hero {
        padding-top: 2.5rem;
        padding-bottom: 3.5rem;
    }

    .pp-hero .pp-cover-emblem {
        width: min(30vh, 240px);
        margin-bottom: 0.5rem;
    }

    .pp-hero .pp-wordmark {
        font-size: clamp(1.6rem, 4.6vw, 2.4rem);
    }

    .pp-hero .pp-tagline {
        margin-top: 1.25rem;
    }

    .pp-hero .pp-trailer {
        margin-top: 1.75rem;
    }

    .pp-hero .pp-listen-row {
        margin-top: 1.35rem;
    }
}

/* Short phones — iPhone SE and the 667px generation. Needs a deeper cut than
   the desktop case: the bar leaves only ~611px and the frame wants ~763px. */
@media (max-width: 700px) and (max-height: 750px) {
    .pp-hero {
        padding: 2rem 0 3rem;
    }

    .pp-hero .pp-cover-emblem {
        width: min(28vh, 200px);
        margin-bottom: 0.4rem;
    }

    .pp-hero .pp-wordmark {
        font-size: clamp(1.5rem, 5.2vw, 2.2rem);
    }

    .pp-hero .pp-tagline {
        font-size: 1rem;
        margin-top: 1.1rem;
    }

    .pp-hero .pp-tagline + .pp-tagline {
        margin-top: 0.6rem;
    }

    .pp-hero .pp-trailer {
        margin-top: 1.4rem;
    }

    .pp-hero .pp-listen-row {
        margin-top: 1.1rem;
    }
}

/* ============================================
   LANDING LAYOUT TRIAL — PENDANT (Oct 2 2026)
   A second landing-frame layout, on trial beside the stacked one: the art
   on the left, the text flush left beside it with its middle on the art's
   equator. It applies only when <body> carries .pp-layout-pendant, which
   the homepage's trial switch sets — and that switch only runs on a local
   copy, so a deployed page always shows the stacked frame. Windows under
   900px and phones are stacked either way.
   WHEN DECIDED: delete either this block (keep stacked) or the switch and
   the stacked-only rules (keep Pendant), and the script block marked
   "LAYOUT TRIAL" in index.html. The stacked page as it stood is saved in
   _explore/homepage-stacked-2026-10-02/.
   Art geometry (from the cut-out's opaque bounds): ink spans 7.1%–93.0%
   across and 10.1%–94.3% down; the equator is at 51.5%.
   ============================================ */
@media (min-width: 900px) {
    .pp-home.pp-layout-pendant .pp-hero {
        --art: clamp(360px, min(66vh, 44vw), 640px);
        --gutter: 3.75rem;
        --bar: 1rem;                            /* evens the space above and below under the top bar */
        display: grid;
        grid-template-columns: max-content max-content;
        /* equal flexible rows above and below the text centre it on the art */
        grid-template-rows: 1fr auto auto [credits] auto auto auto 1fr;
        justify-content: center;
        justify-items: start;
        align-items: start;
        column-gap: var(--gutter);
        text-align: left;
        padding: 0 0 var(--bar);
    }

    .pp-home.pp-layout-pendant .pp-hero .pp-cover-emblem {
        grid-column: 1;
        grid-row: 1 / -1;
        align-self: center;
        width: var(--art);
        max-width: none;
        /* trims the cut-out's transparent border; top and bottom are cut
           to equal distances from the equator so the box centres on it */
        margin: calc(var(--art) * -0.101) calc(var(--art) * -0.07 + 2.7rem * 0.065 + 1px) calc(var(--art) * -0.071) calc(var(--art) * -0.071);
    }

    .pp-home.pp-layout-pendant .pp-hero .pp-wordmark,
    .pp-home.pp-layout-pendant .pp-hero .pp-tagline,
    .pp-home.pp-layout-pendant .pp-hero .pp-trailer,
    .pp-home.pp-layout-pendant .pp-hero .pp-listen-icons {
        grid-column: 2;
    }

    .pp-home.pp-layout-pendant .pp-hero .pp-wordmark {
        grid-row: 2;
        font-size: 2.7rem;
        /* discounts the clear space above the caps inside the wordmark's
           line, so the inked block (caps to foot) centres on the equator */
        margin-top: calc(2.7rem * -0.2225);
        padding-left: 0;
        margin-left: -0.065em;                  /* optical: the P's stem meets the text edge */
        margin-right: -0.103em;                 /* drop the trailing tracking */
        white-space: nowrap;
    }
    .pp-home.pp-layout-pendant .pp-hero .pp-tagline {
        grid-row: 3;
        max-width: min(31em, 100vw - var(--art) * 0.859 - var(--gutter) - 7rem);
        margin-top: 1.5rem;
        text-align: left;
    }
    .pp-home.pp-layout-pendant .pp-hero .pp-tagline.pp-byline {
        grid-row: 4;
        margin-top: 0.8rem;
    }
    .pp-home.pp-layout-pendant .pp-hero .pp-trailer {
        grid-row: 5;
        margin-top: 2.1rem;
    }
    .pp-home.pp-layout-pendant .pp-hero .pp-listen-icons {
        grid-row: 6;
        justify-content: flex-start;
        margin-top: 1.4rem;
    }
}

/* windows too narrow for one sentence per line: the measure drops to the
   second sentence's length and the first breaks in two */
@media (min-width: 900px) and (max-width: 1179px) {
    .pp-home.pp-layout-pendant .pp-hero .pp-tagline:not(.pp-byline) {
        max-width: 19.7em;
    }
}
/* ============ END LANDING LAYOUT TRIAL ============ */
