phase: 85_mobile_menu_gate_overlap

All verification complete. Final report:

**Phase 85 final verification pass — all green** (tasks 01–03 already complete; independently re-verified from scratch)
- Verified fix in tree: `styles.css` `.auth-gate` z-index 500→15 + rewritten stacking comment (no `z-index: 500` left); `index.html`/`document.html` comment-only; `token-gate.js` docstring-only (logic byte-identical); `test_mobile_hamburger_nav.py` real-click conversion + new `test_anonymous_toggle_tappable_with_gate_up`; new `tests/unit/test_gate_header_stacking.py` (3 pins); `test_api_tokens.py` untouched
- `uv run pytest` → 1717 passed, 1 warning (exit 0)
- `uv run pytest --cov=app --cov-report=term-missing` → TOTAL **99%** (>90%)
- E2E in isolation: `test_mobile_hamburger_nav.py` **8 passed**; `test_api_tokens.py` **9 passed** (unchanged); `test_smoke.py` **3 passed**; `test_document_viewer.py` **7 passed**
- `uv run ruff check . && uv run pyright` → clean / 0 errors
- Live probe (375×812, anonymous, fresh server): on `/` and `/history.html` `elementFromPoint` at toggle → SVG `path`, never `#auth-gate`; real click opens menu (`aria-expanded=true`); exactly one visible nav link (Chat) + sign-in copy; Chat link topmost over gate; `#main` inert — criteria 1, 2, 3 confirmed directly
- Criteria: (1) real-click menu on / + /history ✅ (2) dropdown above gate ✅ (3) anonymous contents + #main inert ✅ (4) admin byte-identical (phase-46 tests green) ✅ (5) doc-viewer gate under bar (CSS pin + doc-viewer suite) ✅ (6) full gate green ✅ (7) diff scoped to the 5 code files + new unit test + phase files, nothing in `app/` ✅ (8) commit + todo→complete move left to harness per executor rules (task files already in `complete/`)
- Note: `.agents/remediation_plan.md` (untracked) is a pre-existing artifact of the earlier security audit — left untouched; a missing "N passed" line seen mid-pass was my own `-q`+addopts `-q` = `-qq` quirk, not a defect
- Next pending phase: `86_history_page_width`
This commit is contained in:
2026-09-08 01:56:37 -04:00
parent f4150421bb
commit 412a560348
24 changed files with 692 additions and 57 deletions
+16 -11
View File
@@ -1631,23 +1631,28 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
/* Phase 79 (task 05): the in-app token gate — the gate surface of the
two token-only pages (the shell + the document viewer, one shared
.auth-gate markup each). A body-level FIXED overlay (the
body-level doc-modal precedent): while visible it is the ONLY
interactive surface — assets/token-gate.js locks the root (#main,
inert) so focus and keyboard traversal stay inside the gate
(WCAG, the inert-pair contract).
Stacking: z-index 500 — above the app content (the sticky header is
20, the skip-link 100) but BELOW the doc-modal (1000), which can
only be opened from the unlocked app anyway. Solid --bg: the canvas
+ grid texture live on <html> (the body stays transparent), so the
overlay reads as the app's own surface — no blur (the phase-08
perf anchor).
body-level doc-modal precedent): while visible it is the only
CONTENT-level interactive surface — assets/token-gate.js locks the
root (#main, inert) so focus and keyboard traversal stay inside
the gate (WCAG, the inert-pair contract).
Stacking (phase 85, TODO.md L3): z-index 15 — ABOVE all app
content (static) but BELOW the sticky header (20) and its mobile
dropdown (21, inside the header's stacking context): the
unauthenticated visitor keeps a reachable hamburger + menu while
the gate still covers and locks the app content (#main stays
inert — the lock is JS, not z-order — phase 79). The skip-link
(100) and the 1000-family overlays (doc-modal, sync backdrop) are
unaffected — all above 15; the doc-modal can only be opened from
the unlocked app anyway. Solid --bg: the canvas + grid texture
live on <html> (the body stays transparent), so the overlay reads
as the app's own surface — no blur (the phase-08 perf anchor).
The centered card reuses the #sources-gate visual language
(surface card + hairline + glyph + heading + sub + action) in a
tighter column. */
.auth-gate {
position: fixed;
inset: 0;
z-index: 500;
z-index: 15;
display: flex; /* the card is the only in-flow child — margin: auto centers it */
overflow-y: auto; /* short viewports: the card scrolls fully into view */
background: var(--bg);