/* ==========================================================================
   PHONE LAYER — the small screen designed on its own terms, not squeezed.
   Loaded last. Three jobs: kill horizontal overflow at the root, replace
   desktop compositions with phone compositions, and cut the effects that
   make a phone scroll badly (backdrop-filter, perspective, big shadows).
   ========================================================================== */

/* ---- 1. nothing may ever scroll sideways ---- */
html{overflow-x:clip}
body{overflow-x:clip;max-width:100%}
.wrap{min-width:0}
.hero-in>*,.hstage,.jsec-stage>*,.an-panel,.stk-card,.film-in>*{min-width:0}

@media (max-width:899px){

/* ---- 2. scroll performance: blur and depth are desktop luxuries ---- */
.nav,.mbar{backdrop-filter:none;-webkit-backdrop-filter:none;background:var(--bg-canvas)}
:root[data-theme="dark"] .nav,:root[data-theme="dark"] .mbar{background:var(--bg-canvas)}
.hdeck{perspective:none}
.hcard,.stk-card,.an-panel{box-shadow:var(--sh-md)}

/* ---- 3. nav: logo, theme, burger. The CTA lives in the sticky bar. ---- */
.nav .wrap{height:58px;gap:.25rem}
.nav-brand img{height:22px}
.nav-act .btn{padding:.5rem .85rem;font-size:var(--fs-sm)}
.drawer{inset:58px 0 0}
body.nav-locked .nav{position:fixed;top:0;left:0;right:0}

/* ---- 4. hero: one card, one chip, a snapping tab strip ---- */
.hero{padding-block:1.5rem 2rem}
.hero-in{gap:1.5rem}
.hero-copy{gap:1rem;max-width:none}
/* the hero headline was 32px against 35px section h2s: the page's most
   important line was the smallest heading on it */
.hero h1{font-size:clamp(2.5rem,1.4rem + 5.2vw,3.25rem)}
.section h2,.sec-head h2{font-size:clamp(1.75rem,1.1rem + 2.6vw,2.125rem)}
.hero .sub{font-size:1.0625rem;max-width:none}
.hero .note{font-size:var(--fs-xs);gap:.25rem .55rem}
.cta-row .btn{width:100%;flex:1 1 100%}

.hstage{gap:.85rem}
.hdeck{height:clamp(376px,104vw,440px);max-width:none}
/* no floating chips on a phone. There is no room for an overlay that never
   covers the card, and the card header already names the channel. */
.hchips{display:none}

.htabs{margin-inline:calc(var(--gutter) * -1);padding-inline:var(--gutter);
  scroll-snap-type:x mandatory;gap:.25rem;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 var(--gutter),#000 calc(100% - var(--gutter)),transparent);
  mask-image:linear-gradient(90deg,transparent,#000 var(--gutter),#000 calc(100% - var(--gutter)),transparent)}
/* an inactive tab was --fg-4 on canvas: 2.29:1, the worst contrast on the
   page, on the deck's own navigation. --fg-3 only reaches 4.21:1, so the
   label needs --fg-2 (8.96:1) to clear AA at 14px. */
.htab{scroll-snap-align:center;min-height:40px;padding:.5rem .8rem;color:var(--fg-2)}
.htab[aria-selected="true"]{color:var(--fg-1)}

/* ---- 5. channel chips: touch-sized rows, not tall lozenges ---- */
/* single-column stages: never let a wide child force the track */
.jsec-stage,.film-stage,.film-in,.dev-grid{grid-template-columns:minmax(0,1fr)}
/* a code sample must be reachable, never clipped */
.code,.ep-list{overflow-x:auto;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch}
.code pre,.code .ln{width:max-content;min-width:100%}
/* Two truncated scrollers stacked is bad UX, so neither one scrolls now.
   The spine becomes a real segmented control: drop the dash connectors and
   all four chapters fit the width, with the active segment underlined. */
.js-spine{display:grid;grid-template-columns:repeat(4,1fr);gap:0;width:100%;
  overflow:visible;margin-inline:0;padding-inline:0;
  border-bottom:1.5px solid var(--border-1)}
.js-spine>i{display:none}
/* 9px was below any readable floor and --fg-3 is 4.21:1, under AA. At 378px
   each segment is 85px wide, so 11px fits "Measure" with room to spare. */
.js-spine button{width:100%;min-width:0;padding:.5rem .15rem;font-size:.6875rem;
  letter-spacing:.05em;border:0;border-radius:0;background:none;color:var(--fg-2);
  box-shadow:inset 0 -2px 0 transparent;transition:color var(--t-fast),box-shadow var(--t-fast)}
.js-spine button.on{color:var(--fg-1);font-weight:var(--fw-bold);
  box-shadow:inset 0 -2px 0 var(--coral);background:none}
/* the dot carries done/upcoming state; the halo made the active one read as a
   blob next to its label, so it lifts by weight rather than by a ring */
.js-spine button::before{width:6px;height:6px}
.js-spine button.on::before{transform:none;box-shadow:none;background:var(--coral)}
.js-spine button:not(.on):not(.done)::before{background:var(--border-3)}

/* Six labelled chips cannot fit a phone, so they are icons on one row and
   only the ACTIVE channel opens to its name. Nothing is cut, the row still
   says 'six channels', and the beat you are on is unmistakable. */
.js-chans{display:flex;grid-template-columns:none;flex-wrap:nowrap;gap:.3rem;
  overflow:visible;margin-inline:0;padding-inline:0;align-items:center}
.js-chan{flex:1 1 0;flex-direction:row;justify-content:center;gap:0;
  min-width:0;height:46px;min-height:46px;padding:0;
  border-radius:var(--r-md);overflow:hidden;
  transition:opacity var(--t-base) var(--ease-out),filter var(--t-base) var(--ease-out),
    background var(--t-fast),border-color var(--t-fast)}
.js-chan svg,.js-chan i{width:20px;height:20px;flex:none}
.js-chan b{display:none;font-size:.75rem;white-space:nowrap}
/* Several channels are lit per beat, so expanding them all just truncates
   every label. They stay equal tiles: lit means involved, dim means not,
   and the caption underneath names the beat. */
.js-chan{opacity:.4;filter:grayscale(1)}
.js-chan.on{opacity:1;filter:none}
.js-bars{display:none}
/* the overlays are absolutely positioned in here: it must keep real height */
.js-view{min-height:clamp(270px,44svh,400px)}

/* ---- film scene 03, built for the phone, not shrunk ----
   A 6-deep absolute fan cannot work in 480px. On a phone the signals become
   a single scrolling strip of channel chips and the contact record, which is
   the actual point of the scene, gets all the remaining height. */
.sc-rec{display:flex;flex-direction:column;gap:.55rem;align-content:normal}
.sc-sigs{--t-ic:19px;position:static;height:auto;flex:none;display:flex;flex-wrap:nowrap;
  gap:.35rem;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;
  margin-inline:-.7rem;padding:0 .7rem .15rem}
.sc-sigs::-webkit-scrollbar{display:none}
.sig{position:static;flex:none;width:auto;gap:.35rem;white-space:nowrap;
  padding:.3rem .6rem .3rem .3rem;border-radius:var(--r-pill);border:1px solid var(--border-2);
  box-shadow:none;font-size:.6875rem;font-weight:var(--fw-semibold);opacity:0;transform:none}
.fscene.on .sig{animation:spIn .45s var(--ease-out) both;
  animation-delay:calc(var(--i) * 90ms) !important}

.rec{flex:1;min-height:0;display:flex;flex-direction:column;gap:.5rem;padding:.7rem .75rem;overflow:hidden}
.rec-h{align-items:center;gap:.55rem}
.rec-h .av{width:38px;height:38px;font-size:.8125rem;flex:none}
.rec-h b{font-size:var(--fs-base);line-height:1.2}
.rec-h small{font-size:0.6875rem;line-height:1.4;display:block}
.rec-tags span{font-size:.625rem;padding:.2rem .55rem}
.rec-meta{gap:.5rem;flex-wrap:wrap;font-size:0.6875rem}
.rec-tl{gap:.1rem}
.rec-tl .tl{padding:.3rem 0;font-size:var(--fs-xs)}

/* THE broadcast fix. .js-bcast is a fill-height absolute panel and .bc-foot is
   margin-top:auto, so a fixed-height .bc-vid either overflowed (16/7 at 154px)
   or, when hidden, left its space as a hole above the pinned footer. Make the
   film still the FLEXIBLE child: it absorbs exactly the slack, at any width. */
.bc-vid{display:block;flex:1 1 auto;min-height:88px}
.bc-vid img{height:100%;aspect-ratio:auto;object-fit:cover}
.bc-head>span{flex:1 1 auto;min-width:0}
.bc-head small{font-size:.625rem}
/* A scroller always cuts a pill at the edge (clutter, 'narrow pills'), but
   three full-width rows do not fit the panel's fixed budget either: its only
   flexible child is already at its min-height floor, so the extra height
   pushed the cost line out of the box. So: ONE pill, full width and properly
   sized, carrying the claim that is unique to this panel. Consent and
   suppression are covered in full by the governance chapter. */
.bc-pace{display:flex;flex-direction:column;align-items:stretch;gap:.35rem;
  overflow:visible;margin-inline:0;padding-inline:0}
.bc-pace span{width:100%;justify-content:flex-start;white-space:nowrap;
  font-size:.6875rem;padding:.45rem .7rem;border-radius:var(--r-md)}
.bc-pace span:nth-child(n+2){display:none}
/* the panel bleeds -8px past .js-view by design; tighten the rhythm so the
   cost line clears the container edge too, not just the panel's own box */
.js-bcast{gap:.375rem}
/* the cost is a figure, so it gets the panel's own tile treatment: label
   left, value right, full width, matching .bc-tiles above it */
.bc-foot{margin-top:0}
.bc-foot>span:not(.bc-cost){display:none}
.bc-cost{flex:1 1 auto;justify-content:space-between;align-items:center;
  padding:.5rem .7rem;border-radius:var(--r-md)}
.bc-cost small{font-size:0.6875rem}
.bc-cost b{font-size:var(--fs-base)}

/* ---- 6. film and journey ---- */
/* the compact tiers are height-keyed, so an 852-tall phone never gets them
   and ends up with the SHORTEST stage. Compress by width instead.
   NB: no padding on .film-stage — its scenes are inset:0, which sizes to the
   padding box, so any padding makes every scene overhang the content box. */
.film-in{gap:.5rem;padding-bottom:.4rem}
.film-in .sec-head{gap:.3rem}
.film-in .sec-head .eyebrow{font-size:0.6875rem}
.film-in .sec-head h2{font-size:1.5rem;line-height:1.12}
.film-in .sec-head>p{font-size:var(--fs-sm);line-height:1.45;max-width:38ch}
.fs-cap{font-size:var(--fs-sm);line-height:1.4;padding-top:.5rem}
/* the broadcast panel is 16px taller than its own container at ~345px:
   let the footer sentence take full width instead of a leftover track */
.bc-foot{flex-wrap:wrap;row-gap:.15rem}
.bc-foot>span{flex:1 1 100%}
.bc-prog{padding:.55rem .65rem}
.bc-tiles{gap:.35rem}
.bc-tiles>div{padding:.4rem .5rem}
.js-bcast{min-height:0}
/* ---- shorter thumb travel per chapter ---- */
.film-track{height:340vh}
.jsec-track{height:360vh}

/* ---- 7. footer: the credential pill must wrap, not force the grid ---- */
.foot-in{grid-template-columns:minmax(0,1fr);gap:2rem}
.foot-brand{max-width:none}
.cred{flex-wrap:wrap;row-gap:.4rem;border-radius:var(--r-lg)}
.cred .sep{display:none}
.foot-cols{grid-template-columns:repeat(2,minmax(0,1fr))}

/* ---- 9. tap targets and type floors ---- */
.an-chip,.htab,.btn-txt{min-height:44px}
.nav-brand{min-height:44px}
/* the nav CTA only renders at 397px and up, so the narrow-width audit
   never measured it: 8+14+8+3 = 33px with no floor */
.nav-act .btn{min-height:44px}
.js-spine button{min-height:44px}
.stk-foot a{min-height:44px;display:inline-flex;align-items:center}
/* .land is new: inline-flex so the hit area matches the label rather than
   spanning the whole column and misleading the pointer */
.land a{min-height:44px;display:inline-flex;align-items:center;justify-self:start}
.foot li a,.cap-col a{min-height:42px}
.an-tr .it b,.an-tr .ch,.an-tr .mt b{font-size:var(--fs-sm)}
.foot a,.cap-col a{min-height:40px;display:inline-flex;align-items:center}

}

/* ---- 8. very small phones: give the words the room ---- */
@media (max-width:400px){
  .nav-act .btn-primary{display:none}
  .hero h1{font-size:2.25rem}
  /* stop the branch arms wrapping to a second line and stealing 23px */
  .sc-n{padding:.3rem .45rem;gap:.4rem}
  .sc-n b{font-size:var(--fs-xs)}
  .sc-n small{font-size:0.625rem}
  .sc-arms .fchip,.sc-arms b{font-size:.6875rem}
  .sc-arms small{font-size:0.6875rem}
  .film-in .sec-head>p{font-size:var(--fs-xs)}
  .fs-cap{font-size:var(--fs-xs);line-height:1.38}
}

/* short viewports: no slack for the film still, and the rest tightens */
@media (max-width:899px) and (max-height:820px){
  .bc-vid{display:none}
  .bc-tiles{gap:.3rem}
  .bc-tiles>*{padding:.4rem .5rem}
  .bc-tiles b{font-size:.8125rem}
  .bc-prog{padding:.5rem .7rem}
  .bc-foot{font-size:.625rem;line-height:1.35;margin-top:0}
  /* no flexible child here, so spread the slack across every gap
     instead of pooling it all above a bottom-pinned footer */
  .js-bcast{justify-content:space-between}
}

/* ============================================================
   FLEX-SHORTFALL GUARDS
   Two children are 'flex:1; overflow:hidden' inside fixed-height
   parents, so when space runs short they hide their last rows
   instead of resizing. Give the content back its space.
   ============================================================ */

/* 1. Audit chain: at 667px tall the chain gets 158px for 210px of
   content, dropping the last entry AND the 'chain verified' pill,
   which is the whole point of the governance chapter. The
   max-height:640 tier never fires at 667, so add the missing tier. */
@media (max-height:760px){
  .chain{gap:.15rem;padding-top:.4rem;overflow-y:auto;
    scrollbar-width:thin;scrollbar-color:var(--border-3) transparent}
  .chain::-webkit-scrollbar{width:4px}
  .chain::-webkit-scrollbar-thumb{background:var(--border-3);border-radius:99px}
  .lk{padding:.18rem .45rem}
  .lk:nth-of-type(1){display:none}
  .sc-gov>.vfy{margin-top:.25rem;padding:.2rem .55rem}
  .mx .c{min-height:20px}
  .fscene{padding:.7rem}
}

/* 2. Hero post cards: .pst-img claims up to 38% of a fixed-height
   card, so .pst-b hides the flowing comments the user asked for.
   Narrow the still, hand the rows back their space. */
@media (max-width:400px){
  .pst-b{gap:.3rem;padding:.45rem .7rem}
  .hcard .pst-b .cmt:nth-of-type(3){display:none}
}
/* Cards are fixed height, so SOMETHING must absorb the slack. Let the photo
   do it, the way a real feed post looks, instead of leaving white below a
   short body (the Facebook card was ~250px of empty). */
@media (max-width:899px){
  /* the body keeps its content height; the photo takes only what is left */
  .pst-b{flex:0 0 auto}
  .pst-img{flex:1 1 auto;min-height:72px;max-height:none;aspect-ratio:auto}
  /* the deck is swipeable: follow the thumb, and never fight page scroll */
  [data-hdeck]{touch-action:pan-y}
  .hcard.is-active{transform:translateX(var(--drag,0)) !important}
  [data-hdeck].is-dragging .hcard.is-active{transition:none}
}

/* ============================================================
   MOBILE RHYTHM AND SIZING   (kept inside the phone tier)
   ============================================================ */
@media (max-width:899px){
  /* Sections were compressed to padding-top:0, so anything following a pinned
     section (the film, the journey) began flush against it with no air.
     Specificity must beat the existing .section:not(...) rule. */
  /* .pt0 suppresses top padding on desktop because the neighbour above is
     full-bleed. On phones the pinned sections have no bottom padding, so
     those sections need their air back. */
  main>section.section,main>section.section.pt0{padding-top:2.5rem}

  /* THE JOURNEY STUDIO SCENE.
     It is absolutely positioned for a wide canvas (trigger 3%, condition 38%,
     branches at right:3%), so in portrait the nodes collide horizontally while
     the tall canvas sits empty. On phones it becomes a real vertical flow:
     trigger, condition, then the two branches side by side. */
  .sc-canvas{display:grid;grid-template-columns:1fr 1fr;align-content:center;
    justify-items:stretch;gap:.85rem .6rem;padding:1rem .9rem}
  .sc-canvas .wires,.sc-token{display:none}
  /* the nodes carry inline left/right/top for the desktop canvas, which no
     stylesheet can beat, and the reveal keyframe ends at translateY(-50%)
     because the desktop nodes are centred on their row */
  .jn{position:relative !important;left:auto !important;right:auto !important;
    top:auto !important;bottom:auto !important;width:auto !important;min-width:0 !important;
    transform:none;grid-column:1/-1;padding:.6rem .7rem;gap:.5rem;border-radius:var(--r-lg)}
  .fscene.on .jn{animation-name:jnPopFlow}
  .fscene.settled .jn{transform:none !important}
  .jn.pick{grid-column:1}
  .jn.pick~.jn{grid-column:2}
  .jn b{font-size:.8125rem;line-height:1.2;letter-spacing:-.01em}
  .jn .lbl,.jn small{font-size:0.625rem;letter-spacing:.1em}
  .jn .ic{width:22px;height:22px;border-radius:7px}
  .jn .ic svg{width:12px;height:12px}
  /* connectors: trigger to condition, condition to the branch row */
  .jn:not(.pick):not(.pick~.jn)::after{content:"";position:absolute;left:50%;top:100%;
    width:2px;height:.85rem;transform:translateX(-50%);background:var(--border-3);border-radius:2px}
  .jn.pick::before,.jn.pick~.jn::before{content:"";position:absolute;left:50%;bottom:100%;
    width:2px;height:.85rem;transform:translateX(-50%);background:var(--border-3);border-radius:2px}
}
@keyframes jnPopFlow{from{opacity:0;transform:translateY(8px) scale(.96)}to{opacity:1;transform:none}}
@media (max-width:899px){

  /* Halve every scene delay so a chapter resolves well inside its hold. */
  .fscene.on .sp,.fscene.on .sp-pop,.fscene.on .jn,.fscene.on .sig,.fscene.on .tl,
  .fscene.on .lk,.fscene.on .mx .c,.fscene.on .rec-tags span,.fscene.on .chain .vfy,
  .fscene.on .sc-canvas .wires path{animation-delay:calc(var(--d,0) * .5ms)}

  /* .pst is flex:0 1 auto inside a flex card, so it never grew to fill it and
     left white below the post. It must be the growing child. */
  .pst{flex:1 1 auto;min-height:0}
}

/* ============================================================
   PASS-2 MOBILE REFINEMENTS
   ============================================================ */
@media (max-width:899px){
  /* The sticky CTA bar is 73px and floats over the page end, so the last
     rows of the footer sat underneath it. */
  .foot{padding-bottom:calc(3rem + 73px)}

  /* Horizontal strips hide their scrollbars, so nothing said they scroll.
     A soft edge fade is the conventional affordance. */
  .htabs,.film-rail,.an-chips,.sc-sigs{
    -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 26px),transparent);
    mask-image:linear-gradient(90deg,#000 calc(100% - 26px),transparent)}

  /* 9px captions inside the live panels were below reading size */
  .js-sig .tx small,.sig .tx small{font-size:.6875rem}
  .js-sig .tx b,.sig .tx b{font-size:.8125rem}
}

/* The chapter rail's active state reads as an elevated pill on desktop. On
   phones it was resolving to no fill at all, so only the dot marked it. */
@media (max-width:899px){
  /* No background or shadow on the active chapter here. This tier's base rule
     makes the spine a segmented control with border-radius:0 and border:0, so
     a pill fill renders as a square slab, and box-shadow:var(--sh-sm) would
     overwrite the inset underline that marks the active segment. */
  .js-spine button{padding:.5rem .35rem;gap:.4rem}
  .js-spine i{width:14px}
}

@media (max-width:899px){
  .js-bcast{overflow-y:auto;scrollbar-width:none}
  .js-bcast::-webkit-scrollbar{display:none}
}

/* the header mark steps down on phones, so the footer mark matches it */
@media (max-width:899px){
  .foot-brand img{height:22px}
}

/* ============================================================
   NESTED REVEALS
   A .rv inside a revealing parent compounds its own offset, so a child can
   start two or three steps out and swing further than the box it lives in.
   On a phone that excursion also reaches past the viewport. One step only.
   ============================================================ */
@media (max-width:899px){
  /* A horizontal entrance is a desktop gesture. On a phone the element is
     already full-bleed, so a 32px sideways offset starts it past the viewport
     edge, and a nested one starts it 64px out. Both reveal upward instead. */
  .rv-l,.rv-r{animation-name:uxRise !important}
}

/* ============================================================
   GRAPHIC BEFORE COPY (mobile)
   On a phone the animation is the fastest way to understand the
   page, and it is also the smallest thing to scroll past. So the
   stage comes first and the copy follows it, with the breadcrumb
   staying at the top where a reader expects it.
   ============================================================ */
@media (max-width:899px){
  /* capability, use-case and scenario heroes */
  .phero-in.uch{display:flex;flex-direction:column;align-items:stretch}
  .phero-in.uch>*{min-width:0;max-width:100%}
  .phero-in.uch .bcrumb{order:0}
  .phero-in.uch .uch-stage{order:1;margin-bottom:1.25rem}
  .phero-in.uch .uch-copy{order:2}
  /* channel heroes */
  .phero-in.phero-split,.phero-split{display:flex;flex-direction:column;align-items:stretch}
  .phero-split>*{min-width:0;max-width:100%}
  .phero-split .bcrumb{order:0}
  .phero-split .chero-stage{order:1;margin-bottom:1.25rem}
  .phero-split .phero-copy{order:2}
  /* the home hero: the deck leads, the headline follows */
  .hero-in{display:flex;flex-direction:column;align-items:stretch}
  .hero-in>*{min-width:0;max-width:100%}
  .hero-in .hstage{order:1;margin-bottom:1.25rem;width:100%}
  .hero-in .hero-copy{order:2}
  /* the deck and its cards must scale to the frame, not to their own width */
  .hero-in .hdeck{max-width:100%;width:100%}
  .hero-in .hcard{max-width:100%}
}
