The gate check ran during SSR where navigator is undefined,
rendering the 'Unsupported browser' div into the initial HTML.
Now gated on browser (client-only) so SSR renders the app
and the gate evaluates in the browser.
1. drawOverlay: checkerboard mask overlay now drawn in axis + measure
states (mask carry-forward — slab is isolated)
2. Removed the separate red axis line + arrowhead — the rect's long
side IS the axis
3. Rect rotates: uses axisState.rect.angle (from UAT-8a)
4. Replace three rotate buttons with slider (-180..180, step 1) +
minus/plus nudge buttons (same pattern as Sensitivity slider)
587 lines, 109/109 tests, build OK.
reduceAxisState 'rotate' now changes state.rect.angle and re-derives
state.axis via axisFromRect(newRect). The rectangle rotates as a whole;
the axis for Measure is derived from the rotated rect's long side.
2 new regression tests: rect.angle changes on rotate, axis is
re-derived from rotated rect. 109/109 tests green.
Spec CAPTURE.md §Browsers: Phone iOS Safari / Android Chrome, PC
Chrome / Edge / Firefox, others hard stop.
- browserGate.js: UA detection + allowlist (pure, DOM-free)
- +layout.svelte: renders hard-stop panel when unsupported
- iPadOS 13+ reports as Macintosh — added Safari rule (Version/ +
Safari/ without Chrome/) so iPad Safari is not blocked
- 27 unit tests incl. iPad Safari regression
- 107/107 full suite green
Root cause: auto selected the key with MORE kept pixels, which always
picked the green key (it keeps 100% of dark non-green backgrounds).
The black key correctly isolates the slab on dark surfaces.
Fix:
- auto now prefers the key with FEWER kept pixels (removed more bg)
when both are non-empty
- green key has a greenness pre-filter: non-greenish pixels pass
through (kept) so the black key can handle them, instead of the
green key keeping 100% of a dark surface
- added 3 regression tests: dark-bg auto selection, green-sheet auto
selection, green-key passthrough on non-green surfaces
106/106 unit tests green.
Spec CAPTURE.md §Mask lists exactly two controls: Sheet and Sensitivity. Edge offset and feather nudge buttons were extra. Removed from the UI; core params (edgeOffset, feather) remain in maskState.js, still unit-tested.