fix(r3): fold heid's code review — equal stage widths, the axis guard, players, and tests that read the observable

The one drift: the separator was a border on B, making B's stage 1px
narrower than A's; it is now a 1px column gap, so the stages are the same
size to the pixel. Tests now read what the contract promises instead of a
proxy: the strip's ring order, the full bakeoff sequence, 1:1 and Fit by
geometry, the 900px break from both sides, A wrapping, each form naming its
own item, a sibling-prefix symlink, both reveals, the strip's flag, the back
arrow unlinked, a one-axis picture, a focused player, two videos with no
toggle. The contract names .cmp-cap, a press on a stage, INV-4's URL-driven
picker and the redirect branch's isinstance check. r3.toml gains ten rows.
This commit is contained in:
vh
2026-09-24 13:54:29 -07:00
parent 8c7fe77841
commit 23f1bdb41f
5 changed files with 213 additions and 26 deletions
+13 -8
View File
@@ -47,7 +47,8 @@ assumptions:
- **A missing or empty param is a 404, not FastAPI's 422.** The review
declares `f: str` and so answers 422 when `f` is absent. Compare declares
`a: str = ""` and `b: str = ""`, 404s an empty one, and checks each with the
same `isinstance(str)` the view branch gives `f`.
same `isinstance(str)` that `_mark_redirect`'s `back=view` branch gives `f`
(the view route itself declares `f: str` and checks nothing more).
- **Route order:** the compare route is registered BEFORE the catch-all
`/b/{name}/{filepath:path}`, as view is. Accepted, and written down: a booth
FILE literally named `compare` is unreachable at `/b/<name>/compare`. This
@@ -71,8 +72,9 @@ assumptions:
- Each frame is marked `A`, `B`, or nothing (both marks when `a == b`).
- With JS, a click on a frame sets the ACTIVE side to that item and stays on
the compare page. The active side defaults to B.
- The active side wears the SVOS reticle (the one selection device). A click
on either stage, or the key `X`, makes that side (or the other) active.
- The active side wears the SVOS reticle (the one selection device). A press
on either stage (pointerdown, so starting a 1:1 pan there also makes it
active), or the key `X`, makes that side (or the other) active.
- **The active side lives on a NON-region element**, the side's wrapper
around its stage, and in the URL's `side` (C2), rewritten in place when it
changes. An in-place save swaps regions (strip, labels, flags), and
@@ -131,8 +133,9 @@ assumptions:
review's.
- **The two stages are always the same size.** The sides share one set of rows
(subgrid), so a caption under one side takes its height from both stages,
never from that side's alone. Two stages of different sizes would draw the
same picture at two scales in Fit.
never from that side's alone, and the separator between them is a column
gap, never a border that comes out of one side's width. Two stages of
different sizes would draw the same picture at two scales in Fit.
- **At phone width (600px and below) a top bar that cannot hold its controls
WRAPS** instead of scrolling the page sideways or crushing a control. This
applies to the review's bar too, which gains the Compare control (only its
@@ -245,8 +248,9 @@ assumptions:
- compare.html carries `{% block html_attrs %} data-booth="{{ name }}"`,
because without it Reveal all's script and the head script's reveal
restore both bail (S6, r2b's mutation row for the review).
- **Each side's caption** shows under its stage, clamped to 20vh with its own
scroll, the same element style as the review's `.vcap`.
- **Each side's caption** shows under its stage in `.cmp-cap`: the review's
`.vcap` type (size, leading, colour, pre-wrap), clamped to 20vh rather than
the review's 30vh, with its own scroll. Two sides share the height.
## Invariants
@@ -261,7 +265,8 @@ assumptions:
would apply a stored 1:1, which is itself a script): two Fit stages. Both
sides' flag forms are present, so choosing which side to flag needs no
picker; per-side and linked step
links; filmstrip links that set B; flag forms that land back on the same pair.
links; filmstrip links that replace the URL's active side (B by default,
C2); flag forms that land back on the same pair.
Nothing judgment-bearing hides behind a script.
- **INV-5 — one record of the stage mode**, shared with the review:
`stage-one` on `<html>`. Storage never raises.