/* ════════════════════════════════════════════════════════════════════════
   native-perf.css - GPU / scroll discipline pass (Proposal 4b, 2026-06-01)
   ────────────────────────────────────────────────────────────────────────
   A small, conservative, CSS-ONLY pass that removes the most visible "web
   jank" and makes the PWA feel native. It does NOT restructure any layout,
   does NOT touch component geometry, and adds NO naked generic component
   selectors (.hero / .card / .popup etc.) per the repo's CSS Cascade Scoping
   Rule - every rule here is anchored to a structural / attribute selector
   (html, body, [hidden]) or a safe, additive property that cannot break an
   existing compact variant.

   Load this AFTER shared-prototype.css so the additive rules below win on
   equal specificity. It is shared across every prototype page; keep it that
   way - anything page-specific belongs in that page's own <style> block.

   The JS side of Proposal 4 (passive touch/scroll listeners) is already in
   good shape and is NOT changed here (CSS-only deliverable). See the handoff
   note for the one place worth a glance.
   ════════════════════════════════════════════════════════════════════════ */


/* ── 1. Overscroll containment (kill the rubber-band + scroll-through) ──────
   `overscroll-behavior` stops a scroll that reaches the end of the page from
   chaining to a parent / the browser viewport. Without it you get the iOS
   rubber-band bounce and the "body scrolls behind the overlay" effect, both
   of which instantly read as "browser, not app".

   The two full-screen MAP pages (vaarinfo, vaarverkeer) already set
   `overscroll-behavior:none` on body in their own <style>; those win on
   source order if this file loads first, and are intentionally `none`
   (they never want any bounce on a fixed map shell). The LIST pages
   (index / status / meer / info-weetjes / boat-info / quiz) did NOT set it,
   which is exactly the gap Proposal 4(c) flagged.

   We use `contain` (not `none`) at the document level: it keeps the bounce
   from chaining out of the app while still allowing the normal vertical
   scroll on long content pages. A page that wants a harder lock (the map
   shells) can still override with `none` in its own stylesheet. */
html,
body {
  overscroll-behavior-y: contain;
}


/* ── 2. iOS momentum scrolling on inner scroll containers ───────────────────
   `-webkit-overflow-scrolling:touch` gives older iOS WebKit the native
   momentum / inertia fling instead of a stiff, drag-to-move scroll. Modern
   iOS does this by default, but the captain's installed PWA can fall back to
   the stiff behaviour on some surfaces, so we set it defensively on any
   element that opts into its own scroll. This is purely additive - it does
   nothing on elements that are not scroll containers.

   Scoped to elements that explicitly declare an overflow scroll/auto via the
   `style` attribute OR carry the project's scroll utility data-hook. We can
   not enumerate every page-local scroll class from a shared file without
   risking the Cascade Scoping Rule, so we attach momentum only where it is
   unambiguously a scroller. Most page-local scrollers already set this in
   their own CSS; this is a backstop. */
[style*="overflow-y:auto"],
[style*="overflow-y: auto"],
[style*="overflow:auto"],
[style*="overflow: auto"],
[style*="overflow-x:auto"],
[style*="overflow-x: auto"],
[data-scroll-momentum] {
  -webkit-overflow-scrolling: touch;
}


/* ── 3. Hidden elements must not paint or take layout ───────────────────────
   A defensive rule so a `[hidden]` element (empty-states, collapsed panels,
   pre-load placeholders) is fully removed from paint + layout. Some UA
   stylesheets lose `display:none` on `[hidden]` when an author rule sets
   `display` on the same element with higher specificity - which is exactly
   the class of bug that cost the captain a 5-commit thrash on the admin
   trip-map (`.map-empty[hidden]{display:none}` was the real fix). Making the
   guarantee explicit here, app-wide, prevents an offscreen hidden node from
   silently driving a paint / compositing layer. */
[hidden] {
  display: none !important;
}


/* ── 4. Keep animations on the compositor (transform / opacity only) ────────
   This is documentation, not an override: the audit confirmed the prototype
   transitions already animate transform/opacity (GPU) rather than layout
   properties (top/left/width/height/margin), which is what keeps the
   expensive `backdrop-filter` glass surfaces buttery during scroll. We do
   NOT blanket-apply `will-change` here - an always-on `will-change` on a
   `backdrop-filter` element balloons GPU memory on iOS WKWebView (the lever
   for a janky glass surface is to REDUCE blur radius, never add will-change).
   Per-element, scoped `will-change` belongs in the owning page/component, not
   in this shared file.

   Honour reduced-motion globally as a safety net: a user who asks for less
   motion should not be hit by any transition/animation this app forgot to
   gate. This is additive and only ever REMOVES motion, so it cannot break a
   layout. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
