/* ============================================================
   PROTOTYPE — the page as a sequence of full screens
   Soft snap, not a hijacked pager: native scrolling throughout,
   the rest positions simply land on section tops.
   Everything here is scoped to html.snap, so the layer is inert
   until it is switched on and can be deleted in one piece.
   ============================================================ */

/* The guards. Paging only where a screen is big enough to hold a
   section, and never against a reduced-motion preference. Below
   these the page is an ordinary scroll — which is what the
   reference does at 767px. */
@media (min-width:900px) and (min-height:700px){
  /* soft — CSS scroll-snap. Native scrolling; the rest position lands on a
     section top. It cannot resist and spring back: snap only acts once the
     scroll has already stopped. For that feel, use the pager. */
  html.snap{scroll-snap-type:y proximity}

  /* pager — JS drives the scroll. CSS snap must be out of the way entirely,
     or it fights every tween the pager starts. */
  html.snap.snap--pager{scroll-snap-type:none}
  html.snap.snap--pager section{scroll-snap-align:none}

  /* The rhythm becomes height-aware here. On the free-scrolling page the
     spacing is driven by width, which is right — there is always more page
     below. Inside a fixed panel it is the height that is scarce, so every
     vertical step takes whichever of the two is smaller. Without this a
     wide-but-short screen (1512x820, 1366x768) keeps full-width padding it
     has no room for, and the panel overflows. */
  html.snap{
    --sp-sec:clamp(var(--f3), min(6.2vw, 6.4svh), var(--f6));
    --sp-blk:clamp(var(--f3), min(3.8vw, 3.1svh), var(--f5));
    --sp-grp:clamp(var(--f2), min(2.4vw, 2.8svh), var(--f4));
    /* These two were left fixed at 21 and 13, and they are the ones that add
       up: Focus spends 168px of its budget on row padding alone. Inside a
       panel they have to give like everything else. */
    --sp-itm:clamp(var(--f2), min(1.7vw, 2.1svh), var(--f3));
    --sp-tgt:clamp(var(--f1), min(1.1vw, 1.4svh), var(--f2));
  }

  /* A 68px nav is a fixed toll on every panel. On a short screen that is a
     tenth of the budget, so it comes down with everything else. */
  @media (max-height:820px){ html.snap{--nav:82px} }

  /* Body copy in the list-heavy sections tracks the height too. 1rem is the
     floor — below that this stops being a design decision and becomes a
     legibility problem. */
  html.snap .ob li,html.snap .hn__i p,html.snap .dg__c li{
    font-size:clamp(1rem, min(1.4vw, 1.75svh), 1.13rem)}
  /* display type is the other thing that does not know how tall the screen is */
  html.snap .d1{font-size:clamp(2.2rem, min(6.6vw, 9.4svh), 6rem)}
  html.snap .d2{font-size:clamp(1.7rem, min(3.7vw, 5.2svh), 3.15rem)}
  html.snap .big,html.snap .bl__s{font-size:clamp(1.3rem, min(2.5vw, 3.4svh), 2.05rem)}
  html.snap .sig{font-size:clamp(2rem, min(5.4vw, 7.2svh), 4.2rem)}
  /* the model section is the densest on the page — three pillars with folded
     phases, the Assure band and two tiles — so its display sizes track the
     height as well */
  html.snap .ms__s h3{font-size:clamp(1.2rem, min(2.2vw, 2.9svh), 1.75rem)}
  html.snap .bn__f b{font-size:clamp(1.5rem, min(3vw, 3.6svh), 2.6rem)}

  html.snap section{
    min-height:100svh;                 /* svh, not vh — vh is wrong by the mobile URL bar */
    scroll-snap-align:start;
    scroll-snap-stop:normal;           /* never trap a fast flick */
    display:flex;flex-direction:column;justify-content:center;
    /* Two rules govern this padding.
       1. padding-top minus padding-bottom must equal the nav. The nav is fixed
          and covers the top of the panel, so that difference is what puts the
          content's centre at (nav + height) / 2 — the middle of what is
          actually visible rather than the middle of the screen.
       2. Beyond that difference, keep it as small as possible. A roomy panel
          is centred by justify-content and does not care; a tight one is
          pushed over 100svh by every pixel. At 126 + 58 this padding alone
          was overflowing Focus (content 782 into a 832 budget) and Studio
          (740 into 832) — panels whose content fits perfectly well.
       So: a flat 21px gutter, with the nav added on top. */
    padding-top:calc(var(--nav) + var(--f3));
    padding-bottom:var(--f3);
  }
  html.snap section > .wrap{width:100%}


  /* The model panel is the one section whose height genuinely changes while
     you are looking at it. Centred, an opening phase pushes the heading up
     and the tiles down at the same time — everything moves. Pinning the
     header to the top and the tiles to the foot leaves the growth somewhere
     it costs nothing: the slack between them. Nothing outside the cards
     moves at all. */
  html.snap #model > .wrap{flex:1;display:flex;flex-direction:column;
    justify-content:space-between;gap:var(--sp-itm)}
  html.snap #model .bn{margin-top:0}
  /* Two children, not three: with the heading and the cards as one group the
     slack sits only below them, so an opening phase grows downward. Left as
     three, the gap above the cards flexed too and the whole block rose. */
  html.snap #model .md__top{display:flex;flex-direction:column}
  /* Drop the cards off the heading rather than letting them sit tight under
     it. The slack below still has to swallow an opening phase, so this is
     bounded: the tallest phase adds about 103px, and there was 211px between
     the cards and the tiles. Taking 55 leaves 156 — comfortably more than the
     growth, so nothing below moves. */
  html.snap #model .hd{margin-bottom:calc(var(--sp-sec) + var(--sp-grp))}
  /* On a short screen there is not enough slack to give away: at 768 the
     drop left 79px to absorb a 102px phase, and the tiles started moving
     again. The heading gap goes back to the standard one there — the cards
     sit higher, but nothing shifts, which matters more. */
  @media (max-height:840px){
    html.snap #model .hd{margin-bottom:var(--sp-blk)}
  }

  /* The team card is aspect-ratio:2/3, so at three columns it is 598px tall and
     the panel cannot hold it alongside the header. Inside a fixed panel the
     height is the constraint, not the ratio, so cap it against the screen: the
     card gives up some of its portrait rather than the section giving up a
     screen. Nothing is removed — the card simply stops being taller than the
     room it has. 372px is the nav, the gutters, the header and its gap. */
  /* Four columns rather than three. A narrower card is naturally shorter at
     the same 2:3, which buys the height back without squashing the ratio the
     design system fixes for these cards, and without dropping a member. The
     max-height stays as a safety for genuinely short screens. */
  html.snap .tm{--tm-cols:4}
  /* Measured on the live page: 400 was about 25px short of what the panel
     actually costs, so team ran over the screen by 16-25px for every window
     between 700 and 820 tall. Above ~825 the 2:3 ratio governs and the cap
     never applies, so this only tightens the short band.
     The width has to be stated: left to the 2:3 ratio, the browser carries the
     height cap across to the width, and the cards shrank inside their columns
     (192px cards in 267px columns at 1520x753) instead of only getting shorter. */
  html.snap .tm__c{width:100%;max-height:calc(100svh - 465px)}

  /* A panel taller than the screen must not be centre-cropped — it anchors to
     the top and keeps its own internal travel, which the pager reads to the
     end before it advances. */
  /* Belief is the other panel that will not fit a short window: at 700 it needs
     742. The section gap under the statement is the biggest single item there
     (45px), and the instrument's own gutter the next, so both step down rather
     than shrinking the type. */
  @media (max-height:760px){
    html.snap #belief .bl__t{margin-bottom:var(--sp-grp)}
    html.snap #belief .al__ls{padding:var(--f2)}
  }
  /* at the guard itself (700) that still leaves it 3px over */
  @media (max-height:720px){
    html.snap #belief .bl__t{margin-bottom:var(--sp-itm)}
    html.snap #belief .al__l + .al__l{margin-top:var(--f1)}
    html.snap #belief .al__hd{padding-block:var(--f1)}
  }

  html.snap section.snap--tall{justify-content:flex-start}

  html.snap .ft{scroll-snap-align:end}
}

@media (prefers-reduced-motion:reduce){
  html.snap{scroll-snap-type:none}
}

/* ---- the rail: progress indicator and jump menu in one ---------------- */
.sr{position:fixed;right:var(--f3);top:50%;transform:translateY(-50%);z-index:115;
  display:none;flex-direction:column;gap:var(--f2);align-items:center}
@media (min-width:900px) and (min-height:700px){
  html.snap .sr{display:flex}
}
.sr a{position:relative;display:block;width:var(--f2);height:var(--f2);
  display:flex;align-items:center;justify-content:center;text-decoration:none}
.sr a::before{content:"";width:7px;height:7px;border-radius:50%;
  background:currentColor;opacity:.28;
  transition:opacity .28s var(--e),transform .28s var(--e)}
.sr a:hover::before{opacity:.65;transform:scale(1.25)}
.sr a[aria-current="true"]::before{opacity:1;transform:scale(1.5);background:var(--blue)}
/* the label rides out on hover, so the rail is a menu and not just dots */
.sr a span{position:absolute;right:calc(100% + var(--f2));white-space:nowrap;
  font-size:.62rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  padding:4px var(--f1);border-radius:var(--r-chip);
  background:var(--ink);color:var(--paper);
  opacity:0;transform:translateX(6px);pointer-events:none;
  transition:opacity .24s var(--e),transform .24s var(--e)}
.sr a:hover span,.sr a:focus-visible span{opacity:1;transform:none}
/* the rail inverts against whatever panel it is currently over */
.sr{color:var(--ink)}
.sr.on-dark{color:var(--paper)}
.sr.on-dark a span{background:var(--paper);color:var(--ink)}

/* ---- the toggle, so both modes can be compared side by side ----------- */
.snapt{position:fixed;right:var(--f3);bottom:var(--f3);z-index:130;
  display:inline-flex;align-items:center;gap:var(--f1);
  padding:var(--f1) var(--f2);border-radius:var(--r-chip);
  border:1px solid var(--rule);background:var(--paper);color:var(--ink);
  font-size:.7rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  box-shadow:var(--sh-rest);cursor:pointer;
  transition:border-color .22s var(--e),background .22s var(--e),box-shadow .22s var(--e)}
.snapt:hover{border-color:var(--ink);box-shadow:var(--sh-lift)}
.snapt b{font-weight:700;color:var(--grey)}
html.snap .snapt b{color:var(--blue-d)}
html.snap--pager .snapt b{color:var(--blue)}
.snapt i{width:7px;height:7px;border-radius:50%;background:var(--rule);font-style:normal}
html.snap .snapt i{background:var(--blue-l)}
html.snap--pager .snapt i{background:var(--blue)}
@media (max-width:899px),(max-height:699px){ .snapt{display:none} }

/* ---- input stands aside while a commit is running --------------------
   Hover states firing mid-flight are the second source of stutter: each one
   repaints (and, where a hover moved the box, relaid out) on frames the
   transition needs. Suppressing the pointer for the length of the commit
   means the hover simply lands when the page arrives. */
html.is-moving body *{pointer-events:none !important}

/* ---- panel entrance -------------------------------------------------
   On the free-scrolling page the whole .wrap fades as one block in .7s.
   That is right when the reveal is incidental to scrolling past. On a panel
   you have deliberately arrived at, it flashes — the eye never catches it.

   So in panel mode the wrapper stops animating and hands the job to its
   parts, which arrive in sequence and take long enough to be read as an
   entrance rather than a state change. */
@media (min-width:900px) and (min-height:700px){
  html.snap .rv{opacity:1;transform:none;transition:none}
  html.snap .rv > *{
    opacity:0;transform:translateY(var(--f3));
    transition:opacity 1.15s var(--e),transform 1.15s var(--e)}
  html.snap .rv.in > *{opacity:1;transform:none}
  html.snap .rv.in > *:nth-child(1){transition-delay:.06s}
  html.snap .rv.in > *:nth-child(2){transition-delay:.24s}
  html.snap .rv.in > *:nth-child(3){transition-delay:.42s}
  html.snap .rv.in > *:nth-child(4){transition-delay:.60s}
  html.snap .rv.in > *:nth-child(5){transition-delay:.78s}
  html.snap .rv.in > *:nth-child(6){transition-delay:.96s}

  /* The card grid hands its entrance to its children — see .rv .fy__i. Left
     in the parent sequence it would fade as a slab first, and the stagger
     underneath would be invisible. */
  html.snap .rv > .fy__q{opacity:1;transform:none;transition:none}

  /* the eyebrow leads the headline rather than arriving welded to it */
  html.snap .rv > .hd > .tag{
    opacity:0;transform:translateY(var(--f2));
    transition:opacity .9s var(--e) .10s,transform .9s var(--e) .10s}
  html.snap .rv.in > .hd > .tag{opacity:1;transform:none}
}
@media (prefers-reduced-motion:reduce){
  html.snap .rv > *,html.snap .rv > .hd > .tag{opacity:1;transform:none;transition:none}
}
