        /* ══════════════════════════════════════════════════════════════
           THE PAGE STACK — the container every pushed page lives in. Driven by
           public/17-pagestack.js; eleven rooms scope their own rules onto it.

           Was 06-pagestack.css, at position #48. It is not legacy — it is the base
           of a live mechanism — but it WAS in the wrong place, and that is the reason for
           the number as much as the name.

           ⚠️ A BASE THAT LOADS LAST IS NOT A BASE. At #48 it came after every room that
           overrides it (17k #25, 17m #27, 17y #39, 17za #41, 17zb #42, 17ze #45), so on any
           tie the shared default beat the room that had bothered to be specific — the same
           fault .place-suggestions had. It loads at #6 now, before all of them.

           WHAT THAT CHANGED, exactly once: `.pgstack-page.pgstack-docked .pgstack-header`
           here and `.pgstack-page.log-page .pgstack-header` in 17m-journal.css:492 are both
           (0,3,0) and both set the horizontal padding. The weather page and the checklist are
           docked AND log-page (02-state.js:3563, :4247), so they were taking this file’s hard
           20px instead of 17m’s --sp-lg — and 17m’s note is the owner’s own 2026-09-11
           complaint about exactly that inset being wrong. They read 24 now. Found with
           dev/css-flip.mjs, which reported two flips for the move and nothing else; the other
           was body.pgstack-open vs body.sheet-open, both declaring `overflow-y: hidden`, where
           the order cannot matter because the value is the same.

           Its nine outgoing-world tokens were converted on the way. --log-* resolves in here:
           .pgstack-root is on the scope list at css/02-auth.css:88.
           ══════════════════════════════════════════════════════════════ */
        /* ============================================
           PAGE STACK
           ============================================
           Full-screen pages that push and pop, as distinct from the modal system. See
           17-pagestack.js for why this is separate rather than another portaled modal.

           The root is a child of <body>, positioned over .app-frame by measurement, so
           the frame's `transform: translateZ(0)` never gets a chance to capture it. */
        /* Scroll lock. Mirrors `body.sheet-open` exactly, and for the same reason it
           documents: on mobile the document scrolls, on desktop .app-frame does, so both
           have to be pinned. Separate class from the sheet's so the two locks are
           independent — one can be released while the other still holds. */
        body.pgstack-open {
            overflow: hidden;
            height: 100vh;
        }

        body.pgstack-open .app-frame {
            overflow-y: hidden;
        }

        .pgstack-root {
            position: fixed;
            top: 0;
            height: 100dvh;
            display: none;
            /* left / width / z-index are set by align() — they depend on where the
               phone frame actually is, which differs between desktop and handset. */
            /* The root is a transparent frame, not a surface. A page docked inside the
               trip drawer (dockPageInDrawer, 02-state.js) leaves the cover above it and
               the backdrop beside it uncovered; those must still take taps — the
               backdrop is how the drawer's "tap outside to close" reaches the page. So
               the root passes events through and each page takes its own. */
            pointer-events: none;
        }

        .pgstack-root.active {
            display: block;
        }

        .pgstack-page {
            position: absolute;
            inset: 0;
            display: flex;
            flex-direction: column;
            /* The chart stock, not --bg-primary (#E8E3D9, the outgoing parchment), which showed wherever a room's
               body did not cover its page and while a page slid in (2026-09-17, capture --legacy). */
            background: var(--log-stock);
            /* Re-enabled per page; the root above passes events through. */
            pointer-events: auto;
            /* Starting state: off to the right. `.entered` slides it in. */
            transform: translateX(100%);
            transition: transform 0.3s ease;
        }

        /* will-change only while a transition is actually running.
           It was set permanently, which keeps every page in its own compositor layer for
           as long as it exists — pages stay mounted when covered, so a three-deep stack
           held three permanent layers plus whatever the map and the sheets already own.
           On a phone that is a real cost, and layer pressure is a plausible cause of the
           flicker the diagnostics have now ruled resize out of. The hint is applied on
           the way in and dropped once the page has landed. */
        .pgstack-page.animating { will-change: transform; }

        .pgstack-page.entered {
            transform: translateX(0);
        }

        /* A covered page keeps its scroll position and its listeners, but must not
           receive taps meant for the page above it. Nudged slightly left so the edge of
           the page beneath is briefly visible during the transition, which is what makes
           the movement read as depth rather than as a replacement. */
        .pgstack-page.covered {
            pointer-events: none;
            transform: translateX(-18%);
        }

        @media (prefers-reduced-motion: reduce) {
            .pgstack-page { transition: none; }
            .pgstack-page.covered { transform: translateX(0); }
        }

        .pgstack-header {
            flex: none;
            display: flex;
            align-items: center;
            gap: var(--sp-xs);
            padding: var(--sp-sm) var(--sp-md);
            /* The notch. The header's own background fills the inset rather than the
               page being padded, so the bar reads as one surface running to the top edge
               of the screen. Nothing else in this app uses env() yet; on a desktop
               browser the inset resolves to 0 and this is identical to plain padding. */
            padding-top: calc(var(--sp-sm) + env(safe-area-inset-top, 0px));
            /* The band and a firm rule — the same two the migrated stack pages already wear
               (17m-journal.css:492 dresses .log-page this way). Was --bg-primary and --border,
               the outgoing parchment and its grey. --log-* resolves here: .pgstack-root is on
               the scope list at the head of css/02-auth.css (:88), put there because the root
               is appended to document.body and inherits from no page. */
            background: var(--log-stock-band);
            border-bottom: 1px solid var(--log-rule-firm);
        }

        /* ⚠️ A WORD, NOT A 32px GLYPH BOX (owner, 2026-09-10). Nine pages are drawn from
           one place, so the chevron came off all nine at once. The box goes with it: a word
           is as wide as it is, and this one keeps the 44px height a thumb needs. */
        .pgstack-back {
            flex: none;
            display: inline-flex;
            align-items: center;
            min-height: 44px;
            padding: 0;
            border: none;
            background: transparent;
            cursor: pointer;
            font-family: var(--log-print);
            font-size: var(--fs-micro);
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            text-decoration: underline;
            text-underline-offset: 0.25em;
            text-decoration-thickness: 1px;
            color: var(--log-ink);
        }

        /* × for pages that present as a layer rather than a page. Same box as the back
           button so the header's geometry does not change between the two; same
           glyph treatment as .modal-close so it reads as the app's one close control.
           Focus ring comes from the global button:focus-visible rule. */
        .pgstack-close {
            flex: none;
            display: flex;
            align-items: center;
            justify-content: center;
            width: 32px;
            height: 32px;
            padding: 0;
            border: none;
            background: transparent;
            font-size: var(--fs-display);
            line-height: 1;
            color: var(--log-ink-soft);
            cursor: pointer;
            transition: color 0.3s;
        }
        /* Ink-Not-Glow: the hover goes to full ink, not to a hue. --primary was the outgoing brown. */
        .pgstack-close:hover { color: var(--log-ink); }

        /* A page docked inside the trip drawer (dockPageInDrawer, 02-state.js) sits
           under the drawer's cover and beside its backdrop, so it reads as a layer over
           the drawer, not as a page. A layer is dismissed with ×, not ‹: the chevron is
           hidden and the title moves to the left edge, where the × on the right can
           answer it. Type is unchanged. */
        .pgstack-page.pgstack-docked .pgstack-back { display: none; }
        .pgstack-page.pgstack-docked .pgstack-title { text-align: left; }
        /* 20px, not the header's var(--sp-md): the title now starts a column, and the
           column it starts is the content's (.wx-stop, and the checklist's rows in 17za, are padded 20px).
           Same number the old sheet header used. */
        .pgstack-page.pgstack-docked .pgstack-header { padding-left: 20px; padding-right: 20px; }

        /* Default title treatment: the house voice — letter-spaced uppercase. */
        .pgstack-title {
            flex: 1;
            min-width: 0;
            text-align: center;
            font-family: var(--log-write);
            font-size: var(--fs-small);
            letter-spacing: 2px;
            text-transform: uppercase;
            color: var(--log-ink-soft);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        /* Opt-in alternative for titles that carry a date or a name and want the
           display face. Oldstyle figures, as everywhere dates and names are set. */
        .pgstack-title.display {
            font-family: var(--log-write);
            font-size: var(--fs-lg);
            font-weight: var(--fw-regular);
            letter-spacing: 0;
            text-transform: none;
            color: var(--log-ink);
            font-variant-numeric: oldstyle-nums;
        }

        .pgstack-actions {
            flex: none;
            display: flex;
            align-items: center;
            gap: var(--sp-xs);
            /* Matches the back button's width so a title with no action still sits
               optically centred rather than shifted one button to the right. */
            min-width: 32px;
            justify-content: flex-end;
        }

        .pgstack-body {
            flex: 1;
            min-height: 0;
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
            /* Home indicator on a gesture-navigation handset. */
            padding-bottom: env(safe-area-inset-bottom, 0px);
        }

        /* Self-test readout. Present only inside the demo pages pushed by
           pageStackSelfTest(), which exists so the stack can be checked on a handset
           where there is no console to read. */
        .pgstack-selftest-info {
            margin: var(--sp-md);
            padding: var(--sp-sm) var(--sp-md);
            border: 1px solid var(--log-rule);
            background: var(--log-stock);
            font-family: var(--log-write);
            font-size: var(--fs-small);
            line-height: 1.7;
            letter-spacing: 0.04em;
            color: var(--log-ink-soft);
        }

        /* The journal entry page's sixty-five rules lived here and moved to
           css/17m-journal.css on 2026-09-10, when it was migrated into the deck log. They
           are not duplicated: this file no longer styles `.jp-` anything.

           ⚠️ THE DAY VIEW BELOW STILL EMITS `.jp-nav` AND `.jp-date`, on purpose — the same
           control, so it should not be a second set of styles that can drift. It is dressed
           by 17m now, which is why the day's date bar changed on the same day the journal's
           did, and why both markups lost their chevrons in the same commit. */

        /* The day page's rules moved to css/17p-day.css on 2026-09-11, when the room was
           migrated into the deck log. They are not duplicated: this file no longer styles
           `.tday-` anything. Its date bar is still `.jp-nav` / `.jp-date`, dressed with the
           journal entry's in css/17m-journal.css — the same control, so not a second set of
           styles that can drift. */


