/*
  The phone-page layout contract (#498) -- promoted out of study.css's
  `.phone`, the page whose bottom bar never jumped, into one file every page
  carrying the fixed bottom bar loads. `shared/build_stamp.css` and
  `shared/nav.css` beside it are the precedent for the shape: the row/stamp
  have to look and behave identically everywhere, and a fix here has to fix
  it everywhere, so it is its own file rather than four (now six) copies.

  ## The bug, in one sentence

  iOS Safari's URL bar collapses only when the DOCUMENT scrolls. `/study` and
  `/settings` never made the document taller than the viewport, so the
  Safari toolbar sat still on those two; `/read` and `/queue` did, so the
  toolbar collapsed there and dragged the fixed `.milim-nav` bar down the
  screen with it -- "two of the pages are one height and the other two are
  another," reported from the real device, #498.

  ## The fix: the document is capped, one element inside it scrolls instead

  `html, body` are locked to the viewport and forbidden to grow
  (`overflow:hidden`); the page's own top-level column --
  `[data-milim-main]`, the same hook `shared/nav.js` already reads to decide
  where the flow spacer goes -- is the thing that actually scrolls, sized to
  the *dynamic* viewport (`100dvh`, with a plain `100vh` first for a browser
  that predates the unit) so it tracks Safari's toolbar instead of fighting
  it.

  Because the scrolling element and the flow-spacer's parent are the same
  node, `shared/nav.js`'s `main.appendChild(spacer)` keeps doing exactly
  what its own comment says -- reserving the bar's height at the END OF THE
  SCROLLING CONTENT -- without this file having to know the spacer exists.

  ## Where this reads as looser than the bug report, and why

  study.css's `.phone` (the page the ticket calls "the reference
  implementation") is `min-height:100dvh`, not `height:100dvh`, and grep it:
  there is no `overflow-y` anywhere in that file. It never scrolls the
  document today only because a study cue's content has never been taller
  than one viewport on demo.db (the ticket's own measured table: 875/875,
  exactly the viewport). `min-height` does not cap anything -- if a future
  cue's content ever did overflow (a long `.end` summary with several
  `.movedgroup`s is the plausible candidate), `.phone` would grow past the
  viewport and reopen this exact bug on the one page it was supposedly fixed
  on already.

  So this file does not literally copy `.phone`'s declarations -- it
  hardens the CONTRACT the ticket describes ("the document itself never
  scrolls") rather than the specific properties that happen to produce that
  result today on a page whose content has never tested it: `height`
  instead of `min-height`, plus a real `overflow-y:auto` and
  `-webkit-overflow-scrolling:touch` so a page whose content DOES overflow
  (`/queue` is 4894px on demo.db, per #498's own table) scrolls inside
  `[data-milim-main]` instead of growing the document. Flagged here rather
  than changed silently -- see this ticket's PR body for the measurement
  both before and after.

  `overflow-x:hidden` rides along for the reason study.css's own `.phone`
  already carries it (#125, kept there rather than duplicated here -- see
  that file's comment and `tests/test_api_study_page.py`'s
  `test_the_rail_cannot_pan_the_study_page_sideways`, which pins the literal
  text of that specific rule): a fixed-height flex column is exactly the
  shape that lets one wide child pan the whole screen sideways if nothing
  stops it, and every page sharing this file is now that shape.

  ## #116/#841: the iOS status-bar-style measurement every page's `<head>` cites

  #116: makes "Add to Home Screen" launch full-screen instead of a Safari
  bookmark.
  #841: the style was `black-translucent`, which draws content under the
  status bar. Measured on an iPhone 15 standalone install, that anchors the
  document at y=0 while iOS still SHORTENS the viewport by the status bar's
  59px -- so the page occupied screen 0..793 of 852 and the deficit landed at
  the BOTTOM as a dead strip under the nav bar. `viewport-fit=cover` still
  reported env(safe-area-inset-bottom)=34px for a region the page did not
  occupy, so nav.css grew the bar to 58+34=92px and that height landed INSIDE
  the short page: the bar got taller without getting closer to the glass.
  `default` moves the viewport to 59..852 instead. Note what this means for
  anyone re-testing: `innerHeight` is 793 EITHER WAY -- the height never
  changes, only the viewport's POSITION on the screen, which no JS API
  exposes. Eighteen probe readings were identical across the fix; it was
  confirmed by eye. Do not "verify" this with a height measurement.
  The trade is a status bar on an opaque background rather than over the
  page. iOS bakes this at ADD-TO-HOME-SCREEN time, so testing any change
  here requires deleting the icon and re-adding it.

  ## #2683: the top band, standalone only

  Measured on his phone (2026-09-27, ticket #2683's own comments): with
  `status-bar-style: default` above, the home-screen web app starts BELOW
  the status bar, so `env(safe-area-inset-top)` is 0 there and a strip sized
  by that inset renders at 0px -- proven on the live demo, an ETag-confirmed
  reload of a red test strip showed nothing. A strip pinned at a plain,
  fixed 28px DID show, and its upper part faded into the dark: iOS 27 lays a
  fixed fade/blur (the scroll-edge effect) over roughly the top 20-28pt of
  the web view, and scrolling content passing under it smears. The app
  cannot turn that effect off, so the fix is a flat, OPAQUE band in the
  page's own ground colour under it -- fading a flat colour into itself is
  invisible -- with the scrolling content moved down to sit below the band
  instead of passing under it.

  `@media (display-mode: standalone)` only: browser-tab mode (Safari, or
  Chrome) must stay pixel-identical to today, and this is the one media
  query that tells the two apart without any JS or class the app does not
  already set (grep found none, so none is invented here).

  `var(--ground, var(--chalk))`, not a literal: the seven pages that load
  this file split into two token families and neither name is universal --
  `study.css`/`skills.css` declare `--ground`, the other five declare
  `--chalk` (see beat_tokens.css's own header for that split) -- and the two
  are NOT the same literal in either theme (study's light `--ground` is
  `#F3F1EC`, the `--chalk` family's is `#F2F1EC`), so a shared literal here
  would leave a visible seam on whichever family it did not match. The
  `var(x, y)` fallback reads as "whichever the host omits" only when a host
  could omit BOTH -- nav.css's own header explains why that shape is a
  defect there -- but here every one of the seven hosts is confirmed (by
  grep) to declare exactly one of the two names, in both themes, so the
  fallback always resolves to a real, page-matched colour and never to the
  initial/transparent value nav.css's guard exists to catch.

  `[data-milim-main]` -- not `body` -- absorbs the offset: it is the element
  this file already caps to the viewport and scrolls (see the header above),
  so shrinking its height by the band and pushing it down by the same amount
  keeps the total (band + main) at exactly 100dvh, with nothing clipped by
  `html, body`'s `overflow:hidden`. Every page's own top rail
  (`[data-milim-top]`, nav.js's hook) lives inside `[data-milim-main]`, so it
  moves down with the rest of the content for free -- which is what fixes
  the half-covered report-a-problem flag the ticket measured.
*/

html, body {
  height: 100%;
  margin: 0;
  /* The document is never the thing that scrolls -- see the header. This is
     the backstop: even if `[data-milim-main]`'s own height math were ever
     wrong on some page, the document cannot grow to compensate and hide
     that mistake as a return of #498. */
  overflow: hidden;
}

[data-milim-main] {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow-y: auto;
  overflow-x: hidden;
  /* iOS momentum scrolling. Without this a `overflow-y:auto` box on iOS
     Safari scrolls, but stops dead the instant the finger lifts instead of
     coasting -- #498's own care note about `/queue`'s 4894px list. */
  -webkit-overflow-scrolling: touch;
}

/* #2683: AFTER the base `[data-milim-main]` rule above, and it must stay
   there -- `tests/js/test_top_band.mjs`'s cascade reader merges same-selector
   rules in source order and a later declaration wins, same as a real browser.
   Moved once already: an earlier draft of this block sat up near the header
   comment, ahead of the base rule, so the base rule's un-offset `height`/
   plain absence of `margin-top` won at every viewport, standalone included --
   caught by that same test going red for a reason that had nothing to do
   with the feature it was written to guard. See this file's header, "#2683:
   the top band, standalone only", for the fix itself and why each value is
   what it is. */
@media (display-mode: standalone) {
  body::before {
    content: "";
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 28px;
    background: var(--ground, var(--chalk));
    z-index: 2147483000;
    pointer-events: none;
  }

  [data-milim-main] {
    height: calc(100vh - 28px);
    height: calc(100dvh - 28px);
    margin-top: 28px;
  }
}
