/* ================================================================
   MOBILE SINGLE-PAGE SCROLL — mobile-scroll.css

   Below 768px the home page stops being one fixed screen and becomes
   three full-height snap panels: HOME (the landing, seen through a
   transparent spacer), PROJECTS, CONTACT.

   DESKTOP IS UNTOUCHED, and that is enforced twice over:

     1. every rule lives inside `@media (max-width: 768px)`, and
     2. every selector is gated on `.has-ms`, a class mobile-scroll.js
        only ever adds when that same media query matches and the page
        is `body.page-index`.

   Either gate alone would do it; both together mean a stray class on a
   wide viewport still cannot reach a single declaration. Same shape as
   the `has-hs` gate in home-scroll.css.

   The class goes on BOTH <html> and <body>: the scroll container for a
   normally-scrolling document is the viewport, and `scroll-snap-type`
   only propagates to it from the root element — body cannot carry it.
   ================================================================ */

@media (max-width: 768px) {

/* ── SCROLL MODEL ───────────────────────────────────────────────
   The landing ships as `html{height:100%}` + `body{height:100%;
   overflow:hidden}` — one locked screen, no document scroll at all.
   Lift exactly that, and nothing else.

   body's `overflow:hidden` is what actually freezes the page: with
   html at `overflow:visible` the body's value propagates to the
   viewport. Handing body `overflow:visible` gives the scroll back.

   `scroll-snap-type` then has to sit on <html>, because per spec it is
   the ROOT element's snap type that propagates to the viewport — the
   same declaration on body is ignored outright. */
  html.has-ms {
    height: auto;
    scroll-snap-type: y mandatory;
    scroll-behavior: smooth;
  }
  html.has-ms body.page-index {
    height: auto;
    min-height: 100%;
    overflow: visible;
    overflow-x: hidden;
    /* iOS rubber-banding past the last panel drags the whole document
       and leaves the snap mid-flight on release */
    overscroll-behavior-y: none;
  }

  /* Guard, not a fix for anything live: nav.js builds the shared footer
     for every page EXCEPT index, precisely because a normal-flow footer
     on a fixed hero paints over the portrait. Should that exception ever
     be lifted, restoring the scroll here would hang the footer under
     Contact as an unwanted fourth panel. Keep it out. */
  html.has-ms body.page-index .sv-footer { display: none !important; }

  /* A window dragged from desktop width down to phone width has already
     built home-scroll's cinematic stage. home-scroll.js refuses to arm
     it below 768px, so it can never play — but its "scroll" cue is
     position:fixed at full opacity and would sit on the mobile layout
     next to this feature's own cue. Both go. On an actual phone neither
     element was ever created and this rule matches nothing. */
  html.has-ms .hs-stage,
  html.has-ms .hs-cue { display: none !important; }

/* ── STAGE ──────────────────────────────────────────────────────
   One node so teardown is a single removeChild.

   z-index 60 puts the panels over every piece of landing furniture —
   .slide-group (10), .name-section (20), .side (50) — so an opaque
   panel scrolling up genuinely covers the portrait instead of letting
   it print through. It stays under the nav (9000) and the CRT frame
   and overlay (9950+), which are meant to sit on top of everything.

   No transform / filter / will-change here: any of them would make
   this a containing block for the fixed children inside it. */
  html.has-ms .ms-root {
    position: relative;
    z-index: 60;
  }

/* ── PANEL ──────────────────────────────────────────────────────
   --ms-vh is written by mobile-scroll.js from window.innerHeight and
   only rewritten on a real viewport change. 100dvh alone re-measures
   continuously while the URL bar collapses, which moves every snap
   point mid-gesture; the JS value holds still. dvh is the fallback for
   the first paint before the script runs, vh the fallback below that. */
  html.has-ms .ms-panel {
    position: relative;
    height: 100vh;
    height: 100dvh;
    height: var(--ms-vh, 100dvh);
    scroll-snap-align: start;
    /* a hard fling must not skip a panel — this is a 3-beat story */
    scroll-snap-stop: always;
  }

/* ── 01 · HOME ──────────────────────────────────────────────────
   Beyond the scroll hint, no markup of its own. The portrait and the
   fluid canvas are both `position:fixed`, so this only has to supply
   one viewport of height to scroll past. Transparent and inert. */
  html.has-ms .ms-home {
    background: transparent;
    pointer-events: none;
  }

  /* Deliberately still. It lives inside panel 01 rather than being
     fixed, so it simply travels away with the panel — no fade to
     trigger, nothing to animate. The pulsing stroke it used to carry is
     gone: on this screen the photograph is the only thing that moves. */
  html.has-ms .ms-cue {
    position: absolute;
    left: 50%;
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    font-family: var(--font-ui);
    font-size: 0.5rem;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: rgba(28, 25, 23, 0.40);
    pointer-events: none;
  }
  html.has-ms .ms-cue::after {
    content: '';
    width: 1px;
    height: 20px;
    background: linear-gradient(rgba(28, 25, 23, 0.40), transparent);
  }

/* ── THE LANDING'S OWN FURNITURE, WITHDRAWN ─────────────────────
   Two pieces of the desktop landing have no place in the scroll:

   .side — the PROJECTS and ARTWORKS edge labels. Panel 02 now carries
   Projects, and the burger still reaches Artworks, so on a phone they
   were a third route to the same rooms, sitting on top of the name.

   .name-section — main.js's animated lockup, which is structurally
   one word at a time (it builds .name-slot reels for NAMES.left and
   swaps to NAMES.right as the cursor crosses the midline). A phone has
   no cursor, so it can only ever show half the name. .ms-name below
   renders both halves instead.

   `visibility` rather than `display` on purpose: main.js measures glyph
   widths by appending probe elements into #nameDisplay and reading
   getBoundingClientRect(). A display:none ancestor makes every one of
   those measurements zero; visibility:hidden keeps layout intact, so
   its maths still works on an element nobody can see. */
  html.has-ms .side          { display: none !important; }
  html.has-ms .name-section  { visibility: hidden !important; }

/* ── NAME — SIVIN with KOUSHIP set directly under it ────────────
   One two-line lockup above the portrait, not two words bracketing it.
   Static text: no animation, no transition, no parallax — the brief is
   that the photograph is the only thing on this panel that moves.

   Both lines share one size, set so the longer of the two clears the
   width — sizing them independently to match widths would mean one of
   them changing size whenever the name is edited in content.json.

   line-height 0.82 is the landing's own --name-lh, and it is what packs
   the two lines together: Rockwell's caps are ~0.72em, so the lines
   close to roughly a tenth of an em apart without touching. */
  html.has-ms .ms-name {
    position: fixed;
    top: clamp(78px, 11.5vh, 120px);
    left: 0;
    right: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    font-family: var(--font-name);
    font-weight: 400;
    /* 22vw lands KOUSHIP's ink comfortably inside the ~351px the CRT
       bezel leaves on a 375px screen; measured, not guessed. Two
       stacked lines also have to clear the portrait, whose own top 18%
       is mask-faded, so a little overlap there costs nothing. */
    font-size: clamp(50px, 22vw, 112px);
    line-height: 0.82;
    /* the lockup's -127/1000 em tracking, as .name-slot's negative
       margins do it on desktop */
    letter-spacing: -0.127em;
    /* letter-spacing also shortens the LAST glyph's advance, so a
       centred line sits half a step right of true. Nudge it back. */
    text-indent: -0.0635em;
    color: var(--fg);
    white-space: nowrap;
    pointer-events: none;
    user-select: none;
  }
  html.has-ms .ms-name-line { display: block; }

/* ── SHARED PANEL SHELL ─────────────────────────────────────────
   A column that fills the panel: header pinned high, body centred,
   footer at the base. `overflow-y:auto` is a safety valve for very
   short screens (a 500px-tall landscape phone) — normal portrait
   content is sized to fit and never scrolls internally. */
  html.has-ms .ms-inner {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    /* 34px at the base, not 26: the CRT clip-path pulls the bezel 4–12px
       in along the bottom edge and the vignette dims a little further,
       which was enough to make the last row of buttons read as clipped
       even though it measured fully inside the panel. */
    padding:
      calc(90px + env(safe-area-inset-top, 0px))
      clamp(22px, 6.5vw, 34px)
      calc(34px + env(safe-area-inset-bottom, 0px));
    /* overflow-y stays as the safety valve for cramped viewports, but
       NOT `overscroll-behavior: contain`. That is the modal-dialog
       reflex — "scroll me, never the page behind me" — and it is exactly
       backwards here. This element is absolutely positioned across the
       whole panel, so every swipe on Projects or Contact lands on it;
       `contain` then refused to chain the gesture to the document even
       though the box had nothing to scroll (scrollHeight === clientHeight).
       The result: panel 02 was a dead end, and Contact was unreachable by
       swipe. Panel 01 escaped only because it has no .ms-inner at all,
       which is why Home → Projects worked and Projects → Contact did not.
       Chaining is the behaviour we want in both states: scroll the inner
       if it actually overflows, otherwise pass straight to the page. */
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  html.has-ms .ms-eyebrow {
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-ui);
    font-size: 0.56rem;
    font-weight: 600;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    opacity: 0.6;
    flex-shrink: 0;
  }
  html.has-ms .ms-eyebrow::after {
    content: '';
    flex: 1;
    height: 1px;
    background: currentColor;
    opacity: 0.3;
  }

  html.has-ms .ms-title {
    font-family: var(--font-slab);
    font-weight: 400;
    font-size: clamp(2.6rem, 13vw, 4.2rem);
    line-height: 0.92;
    letter-spacing: -0.02em;
    margin-top: 10px;
    flex-shrink: 0;
  }

/* ── 02 · PROJECTS ──────────────────────────────────────────────
   Same warm paper and near-black ink as the real /projects page
   (--bg #f8f1dc / --fg #1c1917), so the panel reads as that page
   rather than as a separate mobile invention. */
  html.has-ms .ms-projects {
    background: #f8f1dc;
    color: #1c1917;
  }

  /* `flex: 1` to fill the panel and centre the rows in it. NO `min-height:
     0` — that is the reflex for a scrollable flex child, and here it was
     exactly wrong: it let the list shrink below its own rows, which then
     painted straight over the title above and the button below on a
     360px-tall landscape phone. Left at the default `min-height: auto`
     the list never shrinks past its content, and .ms-inner's overflow-y
     takes the strain instead. */
  html.has-ms .ms-list {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    margin: 18px 0;
  }

  html.has-ms .ms-item {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 14px;
    padding: 15px 2px;
    border-top: 1px solid rgba(28, 25, 23, 0.16);
    color: inherit;
    -webkit-tap-highlight-color: transparent;
    transition: opacity 200ms ease;
  }
  html.has-ms .ms-item:last-child { border-bottom: 1px solid rgba(28, 25, 23, 0.16); }
  html.has-ms .ms-item:active { opacity: 0.5; }

  html.has-ms .ms-item-nr {
    font-family: var(--font-ui);
    font-size: 0.54rem;
    letter-spacing: 0.14em;
    opacity: 0.4;
  }
  html.has-ms .ms-item-title {
    font-family: var(--font-slab);
    font-size: clamp(1.15rem, 5.6vw, 1.6rem);
    line-height: 1.05;
  }
  html.has-ms .ms-item-meta {
    display: block;
    margin-top: 4px;
    font-family: var(--font-ui);
    font-size: 0.56rem;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    opacity: 0.5;
  }
  html.has-ms .ms-item-arrow {
    font-family: var(--font-ui);
    font-size: 0.9rem;
    opacity: 0.35;
  }

/* ── PANEL 02 FOOTER ────────────────────────────────────────────
   Two tiers, deliberately. `All projects` is the panel's own subject
   and keeps the filled-weight treatment; About and Experiments are the
   two rooms this scroll has no panel for, so they sit under it as a
   quieter pair rather than competing with it in one three-pill row —
   which, measured, overflows 375px anyway (≈330px of pills into a
   327px box) and wrapped unpredictably. */
  html.has-ms .ms-actions {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }

  /* 14px vertical on both tiers puts them at 45px / 44px — measured 37px
     and 34px before, under the 44px comfortable-tap floor. */
  html.has-ms .ms-all {
    padding: 14px 18px;
    border: 1px solid rgba(28, 25, 23, 0.3);
    border-radius: 999px;
    font-family: var(--font-ui);
    font-size: 0.58rem;
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: inherit;
    -webkit-tap-highlight-color: transparent;
  }
  html.has-ms .ms-all:active { background: rgba(28, 25, 23, 0.08); }

  html.has-ms .ms-links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }
  html.has-ms .ms-link {
    padding: 14px 15px;
    border: 1px solid rgba(28, 25, 23, 0.18);
    border-radius: 999px;
    font-family: var(--font-ui);
    font-size: 0.55rem;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(28, 25, 23, 0.68);
    -webkit-tap-highlight-color: transparent;
  }
  html.has-ms .ms-link:active {
    background: rgba(28, 25, 23, 0.08);
    color: #1c1917;
  }
  /* A bit more weight than its neighbours — same pill, red border/ink
     instead of the muted default, matching the accent used for the door
     icon and other call-to-action touches sitewide. */
  html.has-ms .ms-link--accent {
    border-color: rgba(229, 38, 28, 0.55);
    color: #e5261c;
  }
  html.has-ms .ms-link--accent:active {
    background: rgba(229, 38, 28, 0.1);
    color: #e5261c;
  }

/* ── 03 · CONTACT ───────────────────────────────────────────────
   The /contact page's own treatment: its photograph under the same
   dark scrim, white type, yellow accent. */
  html.has-ms .ms-contact {
    background: #0d0d0d;
    color: #ffffff;
  }
  /* The photograph is the panel, not wallpaper behind it. A flat 62–76%
     scrim (what the /contact page uses, where the type spans the full
     height) buried it. A graded one instead: enough at the top to hold
     the headline, almost nothing across the middle so the frame reads,
     and heavy at the base where the mail button and socials sit. */
  html.has-ms .ms-contact::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background:
      linear-gradient(180deg,
        rgba(8, 8, 10, 0.72) 0%,
        rgba(8, 8, 10, 0.46) 22%,
        rgba(8, 8, 10, 0.20) 40%,
        rgba(8, 8, 10, 0.62) 66%,
        rgba(8, 8, 10, 0.92) 100%),
      url('/assets/images/contact-bg.jpg') center center / cover no-repeat;
  }
  html.has-ms .ms-contact .ms-inner { z-index: 1; }
  html.has-ms .ms-contact .ms-title em {
    color: #ffd633;
    font-style: italic;
  }
  /* smaller than the Projects hero so the frame keeps its middle */
  html.has-ms .ms-title--sm {
    font-size: clamp(1.9rem, 9vw, 2.9rem);
    text-shadow: 0 2px 18px rgba(0, 0, 0, 0.55);
  }

  /* flex-end, not center: the action block rides the bottom of the
     panel, inside the thumb's arc, and the freed middle is where the
     photograph gets to be a photograph.
     No min-height:0 — see the note on .ms-list. */
  html.has-ms .ms-contact-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: 14px;
    margin: 20px 0 16px;
  }

  html.has-ms .ms-sub {
    font-family: var(--font-ui);
    font-size: 0.72rem;
    letter-spacing: 0.05em;
    color: rgba(255, 255, 255, 0.72);
    text-shadow: 0 1px 10px rgba(0, 0, 0, 0.6);
  }

  /* The one thing on this panel worth making unmissable: full-width,
     filled in the page's own yellow, 50px tall, and labelled with the
     address itself — a visible address converts better than a coy
     "Get in touch", and still opens the mail app on tap. */
  html.has-ms .ms-mail {
    display: block;
    padding: 15px 16px;
    border-radius: 999px;
    background: #ffd633;
    color: #14120d;
    font-family: var(--font-ui);
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-align: center;
    box-shadow: 0 6px 26px rgba(0, 0, 0, 0.42);
    -webkit-tap-highlight-color: transparent;
    transition: transform 160ms ease, background 160ms ease;
  }
  html.has-ms .ms-mail:active { background: #ffe066; transform: scale(0.985); }

  html.has-ms .ms-contact-routes {
    display: grid;
    gap: 9px;
  }
  html.has-ms .ms-contact-route {
    min-height: 58px;
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-rows: auto auto;
    align-content: center;
    gap: 3px 12px;
    padding: 11px 15px;
    border: 1px solid rgba(255,255,255,.30);
    border-radius: 15px;
    background: rgba(6,8,7,.30);
    color: #fff;
    font-family: var(--font-ui);
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
  }
  html.has-ms .ms-contact-route--whatsapp {
    border-color: rgba(155,240,172,.58);
    background: rgba(83,181,112,.16);
  }
  html.has-ms .ms-contact-route span {
    font-size: .67rem;
    font-weight: 650;
    letter-spacing: .12em;
    text-transform: uppercase;
  }
  html.has-ms .ms-contact-route small {
    color: rgba(255,255,255,.62);
    font-size: .62rem;
  }
  html.has-ms .ms-contact-route b {
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: center;
    font-size: 1rem;
    font-weight: 400;
  }
  html.has-ms .ms-contact-route:active { transform: scale(.985); }
  html.has-ms .ms-contact-email {
    color: rgba(255,255,255,.70);
    font-family: var(--font-ui);
    font-size: .66rem;
    letter-spacing: .04em;
    text-decoration: underline;
    text-underline-offset: 4px;
  }

  /* Two equal columns rather than a wrapping row, so the pair reads as
     one secondary tier squared off under the mail button instead of a
     ragged afterthought. */
  html.has-ms .ms-socials {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
  }
  html.has-ms .ms-social {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    /* 14px of padding puts these at 45px tall — measured 39px at 11px,
       which is under the 44px comfortable-tap floor */
    padding: 14px 12px;
    border: 1px solid rgba(255, 255, 255, 0.32);
    border-radius: 999px;
    font-family: var(--font-ui);
    font-size: 0.58rem;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: #ffffff;
    -webkit-tap-highlight-color: transparent;
  }
  html.has-ms .ms-social:active { background: rgba(255, 255, 255, 0.12); }
  html.has-ms .ms-social svg { width: 14px; height: 14px; display: block; }

  html.has-ms .ms-copy {
    flex-shrink: 0;
    font-family: var(--font-ui);
    font-size: 0.52rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.38);
  }

/* ── PANEL RAIL ─────────────────────────────────────────────────
   Three dots on the right edge — which beat you are on, and a tap
   target to jump. Fixed inside .ms-root, so it is removed with it. */
  html.has-ms .ms-dots {
    position: fixed;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 10px 6px;
  }
  html.has-ms .ms-dot {
    width: 7px;
    height: 7px;
    padding: 0;
    border: 1px solid rgba(28, 25, 23, 0.45);
    border-radius: 50%;
    background: transparent;
    -webkit-tap-highlight-color: transparent;
    cursor: pointer;
    transition: background 260ms ease, border-color 260ms ease, transform 260ms ease;
  }
  html.has-ms .ms-dot.is-active {
    background: rgba(28, 25, 23, 0.75);
    transform: scale(1.25);
  }
  /* the rail sits over a dark photograph once Contact is up */
  html.has-ms.ms-dark .ms-dot { border-color: rgba(255, 255, 255, 0.5); }
  html.has-ms.ms-dark .ms-dot.is-active { background: #ffd633; border-color: #ffd633; }

/* ── NAV BURGER OVER PANEL 03 ───────────────────────────────────
   nav.css tunes the burger per page, and index's is set for the light
   landing: near-black bars (--nav-fg-hover: #1C1814) on a 34%-black
   scrim. That was safe while the home page could only ever be the pale
   portrait screen. It is not any more — panel 03 is a dark photograph,
   and the button disappeared into it. Flip to the light-on-dark
   treatment nav.css already gives the genuinely dark pages, for exactly
   as long as that panel is up. `!important` matches nav.css's own on
   the bars.

   Only the scrim is transitioned, not the bars: `.nav-burger:hover span`
   in nav.css carries its own transform/width transition, and a
   `transition` here would outrank and replace it. */
  html.has-ms .nav-burger { transition: background 260ms ease; }
  html.has-ms.ms-dark .nav-burger { background: rgba(255, 255, 255, 0.14); }
  html.has-ms.ms-dark .nav-burger span {
    background: #ffffff !important;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  }

/* ── SHORT VIEWPORTS ────────────────────────────────────────────
   A phone on its side is ~360px tall, and the panels are sized for a
   portrait screen more than twice that. The fixed nav still occupies
   the top 68px, so there is a floor on how much can be recovered:
   trim the type and the gaps to get close, and let .ms-inner's
   overflow-y carry whatever is left over rather than pretending it
   fits. Rows stay at 44px+ so they remain comfortable tap targets. */
  @media (max-height: 560px) {
    html.has-ms .ms-inner {
      padding-top: calc(76px + env(safe-area-inset-top, 0px));
      padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    }
    html.has-ms .ms-title { font-size: clamp(1.7rem, 6vh, 2.4rem); margin-top: 4px; }
    html.has-ms .ms-title--sm { font-size: clamp(1.4rem, 5.2vh, 2rem); }
    html.has-ms .ms-list,
    html.has-ms .ms-contact-body { margin: 6px 0; }
    html.has-ms .ms-contact-body { gap: 9px; }
    html.has-ms .ms-item { padding: 7px 2px; }
    html.has-ms .ms-item-title { font-size: 1.05rem; }
    html.has-ms .ms-item-meta { margin-top: 2px; }
    /* The name lockup is sized off WIDTH, which is the scarce axis in
       portrait and the abundant one here — at 740x360 the 23vw ran
       straight into the 118px cap, and the two words closed over the
       portrait until only a face peered out between them. Size it off
       height instead, so the picture keeps the middle of the frame. */
    html.has-ms .ms-name { font-size: clamp(26px, 10.5vh, 48px); top: 76px; }
    /* the hint has nowhere to sit under a 360px-tall panel */
    html.has-ms .ms-cue { display: none; }

    /* Tap targets give a little here, and only here: a 360px-tall
       landscape screen has no room for 45px pills, and the alternative
       is pushing the panel into internal scrolling to reach them. */
    html.has-ms .ms-actions { gap: 7px; }
    html.has-ms .ms-all  { padding: 10px 18px; }
    html.has-ms .ms-link { padding: 9px 15px; }
    html.has-ms .ms-contact-route { min-height: 48px; padding: 8px 13px; }
    html.has-ms .ms-social { padding: 9px 12px; }

    /* A phone on its side has no height to spare and width to burn, so
       fold the two tiers of panel 02's footer onto one line — that alone
       reclaims a whole 41px row, which was the difference between the
       About / Experiments pair sitting below the fold and on it. Held at
       min-width 560px so a genuinely small portrait screen (320x480 also
       matches max-height: 560px) never gets three pills forced into
       320px of width. */
    @media (min-width: 560px) {
      html.has-ms .ms-actions {
        flex-direction: row;
        align-items: center;
        gap: 8px;
      }
    }
  }

/* ── REDUCED MOTION ─────────────────────────────────────────────
   Snapping stays (it is layout, not decoration); the smooth scroll
   the dot rail animates itself to goes. Nothing else here moves. */
  @media (prefers-reduced-motion: reduce) {
    html.has-ms { scroll-behavior: auto; }
  }

} /* /@media (max-width: 768px) */
