/* ═══════════════════════════════════════════════════════════════════════════
   m-scroll.css — mobile section scroll-snap.  Loaded last.
   ═══════════════════════════════════════════════════════════════════════════

   Goal: on a phone, a scroll that comes to rest near the top of a section
   settles ON that section instead of half a heading short of it. Nothing more.
   This file adds no JS, no scroll listener and no motion of its own — snapping
   is the browser adjusting the resting point of a fling the user already threw.

   ── THE ONE RULE THAT DECIDES WHAT MAY SNAP ──────────────────────────────
   Everything below follows from one measured fact about how Chrome resolves a
   snap position. A section's snap AREA is its border box grown by its
   scroll-margin, and the area is compared against the snapport:

     area TALLER than the snapport -> the section is a continuous RANGE. Every
       offset that keeps the snapport inside the area is legal, so scrolling
       inside it is completely free and nothing is ever pulled back. The only
       margin here is on top, so the range ends with the section's last pixel
       flush to the bottom of the screen: an oversized section always reads end
       to end.
     area FITS the snapport -> the section is a single POINT, and `proximity`
       pulls to it from 30% of the snapport away (253px at 844, 280px at 932).
       Inside that radius that point is the only offset you can rest at, so a
       deliberate drag with no release velocity shorter than the radius returns
       to it and the page does not move.

   That radius is a Chrome constant; no CSS property changes it. So a point
   target is only acceptable where there is nothing left to read at it — and
   that is the whole selection rule. Measured at its own snap offset, every
   target below shows its ENTIRE section on screen (390x844: problem 701/701,
   how 615/615, demo 764/764 visible; 430x932: 738, 621, 747, 824 all whole),
   or, being oversized, reads to its last pixel inside its own range. Nothing a
   reader could want is behind the radius; the way out is the flick you would
   throw anyway (a 200px flick at ~700px/s clears it from every point, measured).

   ── WHAT IS DELIBERATELY NOT A SNAP TARGET ───────────────────────────────
   .m-hero (1435px at 844) is 1.7 screens, so it is not "its own screen". As a
   target its range ended at ~550, and at ~550 the sticky nav cut its primary
   CTA in half with a dead gap under it — the first thing a visitor saw the
   feature do. Dropped: the hero now scrolls natively, and 200px drags walk
   0 -> 202 -> 403 -> 604 -> 805 -> 1002 straight through it.

   .m-cta and .m-footer were dead declarations. Their snap offsets (5526 and
   5932 at 390x844) sit past max scroll (5440), so Chrome clamped both onto the
   document end and neither could ever be chosen as itself. At 320x568 .m-cta
   was worse than dead — it landed at 5706, inside the document, and a 120px
   drag near the bottom jumped 219px onto it. Removed. The bottom of the page
   is unchanged and correct without them: at max scroll .m-cta is fully visible
   (406px) and .m-footer fully visible (272px), reached by ordinary scrolling.

   ── WHY `proximity` AND NOT `mandatory` ──────────────────────────────────
   Not, as an earlier revision of this comment claimed, because .m-cta and
   .m-footer would become unreachable. That is false and was checked directly:
   under `y mandatory` the page still reaches 5440 (= max) and rests there with
   both fully visible. Chrome clamps an out-of-range snap point onto the
   document end under either strictness.

   The real difference is how much of the page you are allowed to stop on.
   Sweeping every offset at 20px resolution and recording where each one
   settles, at 390x844:

     proximity   135 distinct resting offsets, largest unreachable band 298px
     mandatory    17 distinct resting offsets, largest unreachable band 844px

   `mandatory` has no distance limit, so it owns the whole document and forces
   every scroll onto a section boundary — a full viewport of the page (3946 ->
   4790) stops being a place you can stand. `proximity` acts only within its
   253px radius and leaves the other ~80% of the page free. It also leaves
   `scroll-snap-stop` at its default (`normal`), so a long fling travels
   instead of being caught by each section in turn.

   Cost, honestly, and it is the one real cost: at the three or four point
   targets a no-momentum drag under ~253px (~280px at 932) returns to the
   heading. It is stable and never oscillates, flings are unaffected, and the
   whole section is on screen while it happens — but a reader nudging in tiny
   increments there will feel held. It cannot be removed without removing the
   feature: giving those sections a scroll-margin-bottom to turn them into
   ranges does free the drag, and costs exactly the thing this file exists for
   — measured, flings then rest anywhere inside the range instead of on the
   heading (that is why the fling chain lands at 3890, mid-.m-proof, rather
   than on its heading: .m-proof is oversized and 3890 is a legal offset).

   Every pixel of the page is reachable at all three widths. Largest gap
   between two legal resting positions, swept at 20px: 320x568 -> 208px,
   390x844 -> 298px, 430x932 -> 621px (band 2235..2856, the height of .m-how,
   which is entirely on screen from 2235). All are smaller than their viewport.

   ── WHY THE OFFSET IS `scroll-margin-top` AND NOT `scroll-padding-top` ────
   The two ADD. A snap position is `sectionTop - scroll-margin-top -
   scroll-padding-top`, and the same sum governs anchor jumps. m-nav.css already
   gives #how/#demo/#compare/#cta `scroll-margin-top: calc(var(--nav-h) + 14px)`
   and .m-problem carries an authored 80px, so a scroll-padding-top on the
   scroller would double the offset on five of the eight targets — snapped
   sections (and every nav anchor) would land ~160px low with a band of dead
   beige above the heading. Expressing the whole offset as scroll-margin-top,
   using m-nav's own formula, applies it exactly once and makes the snap
   position and the anchor landing the SAME position by construction.

   --nav-h is owned by m-nav.css; always written with a fallback so this file
   still works if that variable is ever renamed or moved.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── the gate ────────────────────────────────────────────────────────────────
   (pointer: coarse)                 touch only — a mouse wheel is precise and
                                     its owner did not ask for this. Desktop
                                     computes scroll-snap-type: none.
   (max-width: 640px)                the phone breakpoint used page-wide.
   (orientation: portrait)
   + (min-height: 480px)             below this a section is 3+ screens tall,
                                     so a snap point is a rare, jarring event
                                     rather than a rhythm. Keeps snapping off a
                                     568x320 handset in landscape and off a
                                     390x479 window; 844x390 is excluded by the
                                     width gate too — see the note at the end.
   (prefers-reduced-motion: no-preference)
                                     snapping is movement the reader did not
                                     ask for. Under `reduce` this whole block
                                     never applies and scrolling is native.
   ──────────────────────────────────────────────────────────────────────────── */
@media (pointer: coarse) and (max-width: 640px) and (orientation: portrait)
   and (min-height: 480px) and (prefers-reduced-motion: no-preference) {

  html {
    scroll-snap-type: y proximity;
  }

  /* Snap targets: the five sections that are a screen, in document order.
     .m-hero, .m-cta and .m-footer are deliberately absent — see the header.
     .m-strip too: it and its wrapper are display:none at this width, so an
     alignment on it would be dead weight.
     `start` only — each section is introduced by its heading. At 320x568 all
     five are taller than the snapport and therefore ranges, which is why a
     320 phone reads the entire page with 200px drags and never stalls. */
  .m-problem,
  .m-how,
  .m-demo,
  .m-proof,
  .m-compare {
    scroll-snap-align: start;
  }

  /* The sticky-nav offset, for the targets that do not already carry one from
     m-nav.css (#how/#demo/#compare) or from the markup (.m-problem, 80px ~= the
     same value). Same formula as m-nav.css so the snap resting point and an
     anchor jump land on the identical pixel — verified: #how, #demo and
     #compare all land with sectionTop = 79 and do not drift on re-read. */
  .m-proof {
    scroll-margin-top: calc(var(--nav-h, 65px) + 14px);
  }
  /* .m-problem's authored 80px predates --nav-h; re-derive it so all five
     targets track the real bar height together. It has no id, so no anchor
     depends on this value. */
  .m-problem {
    scroll-margin-top: calc(var(--nav-h, 65px) + 14px) !important;
  }

  /* The 79px between a target's snap offset and its own top is not slack, it
     IS the offset: it is what puts the heading 14px clear of a 65px nav
     instead of underneath it. Same number for a snap landing and a nav anchor,
     by construction.

     Nothing here touches .m-demo's internal state. Its height swings by
     hundreds of px as the reader moves through add -> cart -> checkout -> pay;
     because the section start is the snap target and Chrome re-snaps to the
     element it was already on, the section stays pinned — measured across the
     flow at 390: scrollY 2734 and demoTop 79 unchanged while the section
     itself resized. m-demo.js also scrolls the page deliberately on view
     changes, and it cooperates rather than collides: its holdSnap() sets
     documentElement.style.scrollSnapType = 'none' for the length of its own
     smooth scroll and then CLEARS the property, handing control back to this
     stylesheet. Do not start setting scroll-snap-type from script here too. */
}

/* ── landscape phones: deliberately NOT snapped ──────────────────────────────
   At 844x390 the usable viewport is ~311px tall while every section is several
   screens tall, so no section is ever a "screen" and there is no rhythm for a
   snap to reinforce. The width gate above already excludes it; this note
   records that it is a decision, not an oversight. Verified none: 844x390
   touch, 568x320 touch, 390x479 touch. */
