/* ==========================================================================
   Ivy Mode — display typeface. Self-hosted (Regular + Italic only; the site
   never sets bold/semibold on the display font, so those weights aren't
   shipped). Georgia is the fallback for the rare case a browser can't use
   these files; no other webfont is loaded to cover the gap.
   ========================================================================== */
@font-face{
    font-family: 'Ivy Mode';
    src: url('/fonts/IvyMode-Regular.woff2') format('woff2'),
         url('/fonts/IvyMode-Regular.woff') format('woff');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face{
    font-family: 'Ivy Mode';
    src: url('/fonts/IvyMode-Italic.woff2') format('woff2'),
         url('/fonts/IvyMode-Italic.woff') format('woff');
    font-weight: 400;
    font-style: italic;
    font-display: swap;
}
/* ==========================================================================
   Tiffany May Peña — Content and Infrastructure
   Design tokens
   ========================================================================== */
:root{
    --bg: #FAF6EC;
    --bg-alt: #F1EAD9;
    --ink: #1A1A18;
    --ink-soft: #5C584F;
    --line: rgba(26,26,24,0.14);
    --accent: #0534E2;
    --accent-light: #8AA3FF; /* accent tint for dark backgrounds */
    --font-display: 'Ivy Mode', Georgia, 'Times New Roman', serif;
    --font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
    --max: 1160px;
    --gutter: clamp(24px, 5vw, 88px);
}

*, *::before, *::after{ box-sizing: border-box; }
html{ scroll-behavior: smooth; }
body{
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}
img{ max-width: 100%; display: block; }
picture{ display: block; }
a{ color: inherit; }
h1, h2, h3, h4{
    font-family: var(--font-display);
    font-weight: 400;
    margin: 0;
}
p{ margin: 0 0 1em; }
p:last-child{ margin-bottom: 0; }
.wrap{
    max-width: var(--max);
    margin: 0 auto;
    padding-left: var(--gutter);
    padding-right: var(--gutter);
}
.lead{
    font-family: var(--font-display);
    font-style: italic;
    font-size: clamp(19px, 2.1vw, 24px);
    line-height: 1.5;
    color: var(--ink);
}
.eyebrow{
    display: inline-block;
    font-size: 12px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 14px;
}
.visually-hidden{
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* ==========================================================================
   Header / nav
   ========================================================================== */
header.site-header{
    position: sticky;
    top: 0;
    z-index: 40;
    background: var(--bg);
    border-bottom: 1px solid var(--line);
}
.site-header .wrap{
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 76px;
}
.nav-group{
    display: flex;
    align-items: center;
    gap: clamp(20px, 3vw, 40px);
    list-style: none;
    margin: 0;
    padding: 0;
}
.nav-group a{
    text-decoration: none;
    font-size: 15px;
    letter-spacing: 0.01em;
}
.nav-primary a{ font-family: var(--font-display); font-size: 19px; }
.nav-utility a{ color: var(--ink-soft); text-transform: lowercase; }
.nav-group a:hover{ color: var(--accent); }
.nav-group a.active{ color: var(--accent); }
.nav-toggle{
    display: none;
    background: none;
    border: 0;
    font-family: var(--font-body);
    font-size: 14px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    cursor: pointer;
    color: var(--ink);
}

/* Mobile menu. The two lists used to be separate fixed overlays, with the
   utility one pushed down by `top: calc(76px + 40vh)` — an arbitrary offset
   that left a hole in the middle of the menu and let the halves drift apart
   at different screen heights. Opening the nav now turns the header's own row
   into one scrolling column, so both lists sit in a single continuous stack
   and the spacing is set by the content rather than by a guess at viewport
   height. A hairline marks the section/utility split that the gap used to. */
@media (max-width: 720px){
    .nav-toggle{ display: block; margin-left: auto; }

    .nav-group.nav-primary,
    .nav-group.nav-utility{ display: none; }

    body.nav-open .site-header .wrap{
        position: fixed;
        inset: 0;
        z-index: 50;
        flex-direction: column;
        align-items: stretch;
        justify-content: flex-start;
        gap: 26px;
        padding: calc(76px + 28px) var(--gutter) 40px;
        background: var(--bg);
        overflow-y: auto;
        overscroll-behavior: contain;
        /* Fade only. A transform here would make the fixed close button
           position against this box instead of the viewport, so it would
           slide with the panel. The rise lives on the lists below, which
           have no fixed descendants. */
        animation: nav-fade 0.2s ease;
    }
    /* Stays pinned in the bar so the control that opened the menu is the same
       control that closes it, in the same place. */
    body.nav-open .nav-toggle{
        position: fixed;
        top: 0;
        right: var(--gutter);
        height: 76px;
        z-index: 51;
    }
    body.nav-open .nav-group.nav-primary,
    body.nav-open .nav-group.nav-utility{
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 20px;
        animation: nav-rise 0.24s ease both;
    }
    body.nav-open .nav-group.nav-utility{
        padding-top: 26px;
        border-top: 1px solid var(--line);
        animation-delay: 0.05s;
    }
    .nav-primary a{ font-size: 28px; }
    .nav-utility a{ font-size: 17px; }
}
@keyframes nav-fade{
    from{ opacity: 0; }
    to  { opacity: 1; }
}
@keyframes nav-rise{
    from{ opacity: 0; transform: translateY(-8px); }
    to  { opacity: 1; transform: none; }
}

/* ==========================================================================
   Panels — the site is static, not scroll-driven: one panel is visible at a
   time and nav links swap which one, instead of scrolling to an anchor.
   ========================================================================== */
.panel{ animation: panel-in 0.25s ease; }
@keyframes panel-in{
    from{ opacity: 0; transform: translateY(6px); }
    to{ opacity: 1; transform: translateY(0); }
}

/* ==========================================================================
   Scroll reveal and parallax

   Both are wrapped in prefers-reduced-motion: no-preference so that anyone
   who asks for less motion gets plain, fully visible content — the hidden
   starting state never applies to them, so there's no way for content to
   be stranded invisible if a script fails to run.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference){
    /* .js-reveal is set by site.js only once it is actually going to run the
       animation. Without it the hidden state never applies, so a JS failure
       leaves readable content rather than a blank page. */
    .js-reveal [data-reveal]{
        opacity: 0;
        transform: translate3d(0, var(--reveal-y, 28px), 0);
        transition: opacity 0.75s cubic-bezier(0.22, 0.61, 0.36, 1),
                    transform 0.75s cubic-bezier(0.22, 0.61, 0.36, 1);
    }
    .js-reveal [data-reveal].is-revealed{
        opacity: 1;
        --reveal-y: 0px;
    }
    [data-parallax]{
        transform: translate3d(0, var(--parallax-y, 0px), 0);
        will-change: transform;
    }
    /* Cover art is scaled up slightly so it has room to drift inside its
       fixed-aspect frame without exposing an edge. */
    .podcast-card picture img[data-parallax],
    .archive-thumb img[data-parallax]{
        transform: scale(1.14) translate3d(0, var(--parallax-y, 0px), 0);
    }
}
section{ padding: clamp(56px, 9vw, 108px) 0; }
section.alt{ background: var(--bg-alt); }
.section-head{ max-width: 720px; margin-bottom: clamp(36px, 6vw, 64px); }
.section-head h2{ font-size: clamp(32px, 4.5vw, 52px); }
.section-head .lead{ margin-top: 16px; }

/* ==========================================================================
   Strategy — case studies
   ========================================================================== */
.case-list{
    display: flex;
    flex-direction: column;
    gap: 0;
}
.case{
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.4fr);
    gap: clamp(24px, 4vw, 64px);
    padding: clamp(32px, 5vw, 52px) 0;
    border-top: 1px solid var(--line);
}
.case:first-child{ border-top: 1px solid var(--line); }
.case-meta{ }
.case-meta .case-number{
    font-family: var(--font-display);
    font-size: 14px;
    color: var(--ink-soft);
    margin-bottom: 8px;
}
.case-meta h3{ font-size: clamp(24px, 3vw, 32px); margin-bottom: 8px; }
.case-meta .case-tag{
    font-size: 13px;
    color: var(--ink-soft);
}
.case-body dl{ margin: 0; }
.case-body dt{
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 6px;
}
.case-body dd{ margin: 0 0 22px; }
.case-body dd:last-child{ margin-bottom: 0; }
.stat-row{
    display: flex;
    flex-wrap: wrap;
    gap: clamp(20px, 4vw, 40px);
    margin-top: 4px;
}
.stat{ min-width: 120px; }
.stat .stat-number{
    font-family: var(--font-display);
    font-size: clamp(28px, 3.4vw, 38px);
    color: var(--accent);
    line-height: 1.1;
    display: block;
}
.stat .stat-label{
    font-size: 13px;
    color: var(--ink-soft);
}

@media (max-width: 860px){
    .case{ grid-template-columns: 1fr; }
}

/* ==========================================================================
   Media
   ========================================================================== */
.media-group{ margin-bottom: clamp(48px, 7vw, 80px); }
.media-group:last-child{ margin-bottom: 0; }

/* Media leads with its statement and holds it: the opening section fills
   most of the first screen so the work below genuinely arrives on scroll
   rather than all firing at once on arrival. Groups are then spaced about
   a screen apart so each one enters on its own. */
#media .section-head{
    /* No forced viewport-height hold here: that produced an empty band
       under the title and description. The podcast cards animate in on
       their own as the row enters. */
    margin-bottom: clamp(40px, 7vh, 84px);
}
#media .media-group{ margin-bottom: clamp(80px, 20vh, 240px); }
/* The Photography heading now sits just above the full-bleed roll. */
#media .media-group:last-of-type{ margin-bottom: clamp(18px, 3vh, 34px); }
#media .media-group:last-child{ margin-bottom: clamp(24px, 6vh, 64px); }
.media-group h3{ font-size: 22px; margin-bottom: 20px; }
.podcast-list{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: clamp(24px, 3vw, 40px);
}
.podcast-card{ display: flex; flex-direction: column; }
.podcast-card picture{
    aspect-ratio: 16/10;
    overflow: hidden;
    border-radius: 2px;
    margin-bottom: 16px;
}
.podcast-card img{ width: 100%; height: 100%; object-fit: cover; }
.podcast-card h4{ font-size: 19px; margin-bottom: 6px; }
.podcast-card .case-tag{ font-size: 13px; color: var(--ink-soft); display: block; margin-bottom: 10px; }
.podcast-card p{ font-size: 14.5px; color: var(--ink-soft); margin-bottom: 14px; }
.podcast-card audio{ width: 100%; margin-top: auto; }
.podcast-card .btn{ margin-top: auto; align-self: flex-start; }

/* ==========================================================================
   About
   ========================================================================== */
.about-grid{
    display: grid;
    grid-template-columns: minmax(200px, 280px) minmax(0, 1fr);
    gap: clamp(32px, 5vw, 64px);
    align-items: start;
}
/* Portrait crop on desktop, where the tall frame sits alongside the text.
   The phone gets the photograph's own 4:3 instead — see the 640px block. */
.about-photo picture{ aspect-ratio: 4/5; overflow: hidden; border-radius: 2px; }
.about-photo img{ width: 100%; height: 100%; object-fit: cover; }
.about-text p{ font-size: 16.5px; }
/* Body face, like the paragraphs it opens — Ivy Mode is for headings only.
   Size alone marks it as the lede; no weight change, so it reads as the same
   voice rather than an emphasised line. Scoped through .about-text because
   `.about-text p` sets a font-size and would otherwise outrank a bare
   .about-lede on specificity. */
.about-text .about-lede{
    font-family: var(--font-body);
    font-size: 18px;
    line-height: 1.45;
    margin-bottom: 20px;
}
.countries{
    /* Equal-width columns keep the three countries the same height and on one
       horizontal row, instead of wrapping to ragged widths as flex did. */
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: clamp(20px, 3vw, 40px);
    margin-top: 32px;
    padding-top: 28px;
    border-top: 1px solid var(--line);
    list-style: none;
    padding-left: 0;
}
.countries .country-name{
    font-family: var(--font-display);
    font-size: 20px;
    display: block;
    margin-bottom: 4px;
}
.countries .country-role{ font-size: 13.5px; color: var(--ink-soft); }
.contact-card{
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    margin-top: clamp(48px, 8vw, 88px);
    padding: clamp(28px, 4vw, 44px);
    background: var(--bg-alt);
    border: 1px solid var(--line);
    border-radius: 4px;
}
.contact-card h3{
    font-size: clamp(26px, 3vw, 34px);
    margin-bottom: 8px;
}
.contact-card p{
    max-width: 620px;
    margin-bottom: 0;
    color: var(--ink-soft);
}

@media (max-width: 640px){
    .about-grid{ grid-template-columns: 1fr; }
    /* Stacked above the text rather than beside it, so the photograph's own
       4:3 works here: it spans the column and reads centred, where the desktop
       portrait crop would sit as a narrow tile off to one side. Wider than the
       old 220px because a landscape frame at that width is a letterbox strip. */
    .about-photo{ max-width: 100%; }
    .about-photo picture{ aspect-ratio: 4/3; }
    .countries{ grid-template-columns: 1fr; gap: 22px; }
}

/* ==========================================================================
   Archive
   ========================================================================== */
.archive-list{ border-top: 1px solid var(--line); }
.archive-row{
    display: flex;
    align-items: flex-start;
    gap: 24px;
    padding: 28px 0;
    border-bottom: 1px solid var(--line);
}
.archive-content{ flex: 1; min-width: 0; order: 1; }
.archive-content h4{ font-family: var(--font-body); font-size: 16px; font-weight: 600; margin-bottom: 4px; }
.archive-content p{ font-size: 14px; color: var(--ink-soft); }
.archive-content audio{ width: 100%; max-width: 360px; margin-top: 12px; }
.archive-thumb{
    order: 2;
    flex: 0 0 120px;
    width: 120px;
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: 2px;
}
.archive-thumb picture, .archive-thumb img{ width: 100%; height: 100%; object-fit: cover; }
.archive-meta{
    order: 3;
    flex: 0 0 220px;
    font-size: 13.5px;
    color: var(--ink-soft);
    text-align: right;
}

@media (max-width: 640px){
    .archive-row{ flex-wrap: wrap; gap: 12px; padding: 20px 0; }
    .archive-content{ order: 1; flex-basis: 100%; }
    .archive-thumb{ order: 2; }
    .archive-meta{ order: 3; flex-basis: auto; text-align: left; }
}

.btn{
    display: inline-block;
    background: var(--accent);
    color: #fff;
    text-decoration: none;
    font-size: 15px;
    padding: 14px 28px;
    border-radius: 2px;
    white-space: nowrap;
}
.btn:hover{ background: #0428b8; }

/* ==========================================================================
   Footer
   ========================================================================== */
footer.site-footer{ padding: 40px 0; border-top: 1px solid var(--line); }
.footer-row{
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 16px;
    font-size: 13.5px;
    color: var(--ink-soft);
}
.footer-row a{ color: var(--ink-soft); text-decoration: none; }
.footer-row a:hover{ color: var(--accent); }
.footer-links{ display: flex; gap: 20px; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }

/* ==========================================================================
   Media — full-bleed screens

   Adapted from the reference site's structure and choreography, not its
   palette: the brand's cream, accent and Ivy Mode stay. The photography
   stage is the exception and goes dark, because scattered photographs only
   read against a dark field.
   ========================================================================== */
/* --- Podcast production: one full-height screen --- */
/* Podcast sits on the accent tint so the two halves of Media read as
   separate chapters: periwinkle for the podcasts, the warm dark field for
   photography directly below it. The cards keep the site's cream, so the
   contrast against the tint does the separating. */
.pod-screen{
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: clamp(40px, 8vh, 96px) 0;
    background: var(--accent-light);
}
.pod-screen h3{
    font-size: clamp(26px, 3.4vw, 40px);
    margin-bottom: clamp(24px, 4vh, 48px);
    color: var(--ink);
}
.pod-screen .podcast-list{ perspective: 1400px; }
.pod-screen .podcast-list .podcast-card{
    background: none;
    box-shadow: none;
    padding: 0;
}
/* The tilt lives here rather than on the card, so it never shares the
   transform property with the scroll reveal above it. */
.pod-screen .podcast-surface{
    display: flex;
    flex-direction: column;
    height: 100%;
    background: var(--bg);
    border-radius: 5px;
    padding: clamp(14px, 1.4vw, 20px);
    /* Tinted rather than neutral black: a grey shadow over the periwinkle
       reads as dirt, a blue-violet one as depth. */
    box-shadow: 0 22px 50px rgba(12, 24, 92, 0.32);
    transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
    will-change: transform;
}
.pod-screen .podcast-surface{ transition: none; }
.pod-screen .podcast-list .podcast-card picture{
    aspect-ratio: 1/1;
    max-height: none;
    border-radius: 3px;
}
.pod-screen .podcast-list .podcast-card h4{ margin-top: 2px; }
.pod-screen .podcast-list .podcast-card .btn{ box-shadow: 0 6px 18px rgba(5, 52, 226, 0.28); }

/* --- Photography: dark stage, scattered constellation, zoom, pan --- */
.zoom-stage{ background: #17140F; }
.zoom-chip, .zoom-hero, .zoom-track, .zoom-label, .zoom-panel{ margin: 0; }
.zoom-media{ aspect-ratio: 4/3; overflow: hidden; background: #201B14; }
.zoom-media img, .zoom-hero img, .zoom-chip img{
    width: 100%; height: 100%; object-fit: cover; display: block;
}
.zoom-caption{
    font-family: var(--font-display);
    font-style: italic;
    font-size: clamp(14px, 1.6vw, 17px);
    color: rgba(250, 246, 236, 0.72);
    margin-top: 12px;
}

/* Fallback (no JS / reduced motion): a plain readable stack, no dark field. */
.zoom-scatter{ display: none; }
.zoom-label, .zoom-legend, .zoom-title{ display: none; }
.zoom-track{ display: grid; gap: clamp(16px, 3vw, 28px); }
.zoom-stage{ background: none; }
.zoom-caption{ color: var(--ink-soft); }

/* --- Enhanced --- */
.js-zoom .zoom{ position: relative; height: 900vh; }
.js-zoom .zoom-stage{
    position: sticky;
    top: 0;
    height: 100vh;
    width: 100%;
    overflow: clip;
    background: #17140F;
    display: block;
    /* Horizontal trackpad swipes are translated into scroll by site.js;
       this stops any leftover gesture triggering back-navigation. */
    overscroll-behavior-x: contain;
}

.js-zoom .zoom-scatter{
    display: block;
    position: absolute;
    inset: 0;
    z-index: 2;
}
.js-zoom .zoom-chip{
    position: absolute;
    outline: 1px solid rgba(250, 246, 236, 0.10);
    outline-offset: -1px;
    width: clamp(120px, 11vw, 190px);
    aspect-ratio: 4/3;
    overflow: hidden;
    box-shadow: 0 14px 40px rgba(0, 0, 0, 0.45);
    left: 50%;
    top: 50%;
    /* --sx/--sy are in vw/vh, which lets the offset live inside transform.
       Percentages could not: inside translate() they resolve against the
       chip's own box, and via left/top they animate layout on every frame
       across nine elements — the main source of scroll jank here. */
    transform:
        translate(-50%, -50%)
        translate(calc(var(--sx) * var(--drift, 1)), calc(var(--sy) * var(--drift, 1)))
        rotate(var(--sr))
        scale(var(--chip-scale, 1));
    opacity: var(--chip-opacity, 0);
    will-change: transform, opacity;
}
.js-zoom .zoom-hero{
    position: absolute;
    top: 50%;
    left: 50%;
    height: 74vh;
    aspect-ratio: 4/3;
    overflow: hidden;
    z-index: 3;
    transform: translate(-50%, -50%) scale(var(--hero-scale, 0.42));
    opacity: var(--hero-opacity, 1);
    box-shadow: 0 30px 90px rgba(0, 0, 0, 0.5);
    will-change: transform, opacity;
}
.js-zoom .zoom-title{
    display: block; /* the fallback rule above hides it; restore for the stage */
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 4;
    width: max-content;
    max-width: 92vw;
    text-align: center;
    opacity: var(--label-opacity, 1);
    transform: translate(-50%, -50%)
               translateY(calc((1 - var(--label-opacity, 1)) * -14px));
    pointer-events: none;
    will-change: opacity, transform;
}
.js-zoom .zoom-legend{
    display: block;
    font-family: var(--font-body);
    font-size: clamp(11px, 1.1vw, 14px);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--accent-light);
    margin-bottom: clamp(10px, 1.6vh, 20px);
    text-shadow: 0 1px 12px rgba(0, 0, 0, 0.8);
}
.js-zoom .zoom-label{
    display: block;
    font-family: var(--font-display);
    font-size: clamp(44px, 8.5vw, 118px);
    line-height: 1;
    color: #FAF6EC;
    text-shadow: 0 3px 34px rgba(0, 0, 0, 0.72), 0 1px 4px rgba(0, 0, 0, 0.5);
}

.js-zoom .zoom-track{
    display: flex;
    gap: 0; /* panels butt together as one continuous strip, no dividers */
    align-items: center;
    /* --edge is written by site.js from the stage's real pixel width. A
       percentage here resolved against the content-sized grid area and
       doubled the track; a px value measured once per frame cannot. */
    padding: 0 var(--edge, 0px);
    position: absolute;
    top: 50%;
    left: 0;
    z-index: 3;
    transform: translate3d(var(--pan-x, 0px), -50%, 0);
    opacity: var(--track-opacity, 0);
    will-change: transform, opacity;
}
/* Varied rhythm: a lead frame, a smaller counterpoint, and an occasional
   stacked pair. The change of scale is what stops the strip reading as a
   conveyor belt of identical rectangles. */
.js-zoom .zoom-panel{
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1.6vh;
}
/* Width is derived from height explicitly rather than left as auto: inside a
   shrink-to-fit panel, `width: auto` means "fill the parent" while the parent
   sizes to its content, so the two wait on each other and both collapse to 0. */
.js-zoom .zoom-media{ height: 58vh; width: calc(58vh * 4 / 3); flex: 0 0 auto; }
.js-zoom .zoom-panel--lead .zoom-media{ height: 84vh; width: calc(84vh * 4 / 3); }
.js-zoom .zoom-panel--pair .zoom-media{ height: 40vh; width: calc(40vh * 4 / 3); }

/* The client name sits on the lead frame. Legibility comes from a scrim
   gradient plus a text shadow, so it holds over a bright photo as well as a
   dark one — text alone over an image is a coin toss. */
.js-zoom .zoom-media{ position: relative; }
.js-zoom .zoom-plate{
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: clamp(40px, 7vh, 90px) clamp(18px, 2.4vw, 36px) clamp(16px, 2.4vh, 30px);
    background: linear-gradient(to top,
        rgba(10, 8, 5, 0.82) 0%,
        rgba(10, 8, 5, 0.55) 42%,
        rgba(10, 8, 5, 0) 100%);
    pointer-events: none;
}
.js-zoom .zoom-plate-name{
    display: block;
    font-family: var(--font-display);
    font-size: clamp(24px, 3vw, 42px);
    line-height: 1.1;
    color: #FAF6EC;
    text-shadow: 0 2px 18px rgba(0, 0, 0, 0.75), 0 1px 3px rgba(0, 0, 0, 0.6);
}
.js-zoom .zoom-plate-meta{
    display: block;
    margin-top: 8px;
    font-family: var(--font-body);
    font-size: clamp(10px, 1vw, 12.5px);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--accent-light);
    text-shadow: 0 1px 10px rgba(0, 0, 0, 0.8);
}

@media (max-width: 720px){
    .js-zoom .zoom{ height: 620vh; }

    /* Phone framing. Every override here has to clear `height` as well as set
       a width: `aspect-ratio` is ignored the moment both axes are given, so a
       width-only override left the desktop `height: 84vh` in place and a 3:2
       photograph got cover-cropped inside a tall portrait box — the frames
       that arrived zoomed past the subject.

       The frames are 3:2 to match how nearly all of these were shot, so on a
       phone the photograph is shown whole instead of trimmed to fit. The two
       that were not shot 3:2 carry their own ratio below. */
    .js-zoom .zoom-hero{ height: auto; width: 86vw; aspect-ratio: 3/2; }
    .js-zoom .zoom-media{ height: auto; width: 86vw; aspect-ratio: 3/2; }
    .js-zoom .zoom-panel--lead .zoom-media{ height: auto; width: 92vw; aspect-ratio: 3/2; }
    /* A stacked pair is the one thing that reaches top and bottom on a phone,
       so its frames run nearly as wide as a lead rather than being shrunk to
       mark them as secondary — two 3:2 frames at 90vw is the tallest a stack
       can get before the width runs out. */
    .js-zoom .zoom-panel--pair .zoom-media{ height: auto; width: 90vw; aspect-ratio: 3/2; }
    /* Scoped through .zoom-panel so these outrank the per-panel rules above
       whichever kind of panel the frame happens to sit in — the portrait one
       lives in a --pair, whose selector is otherwise the more specific. */
    .js-zoom .zoom-panel .zoom-media--square{ width: 76vw; aspect-ratio: 1/1; }
    .js-zoom .zoom-panel .zoom-media--portrait{ width: 58vw; aspect-ratio: 2/3; }

    .js-zoom .zoom-chip{ width: clamp(84px, 22vw, 130px); }
    .pod-screen .podcast-card picture{ max-height: none; }
    .pod-screen{ min-height: 0; }
}
