Build image / build-and-push (push) Successful in 10s
Gadfly on #104: - The handles keyed off `pointer: coarse` but the NudgePad off `md:hidden` (viewport), so a large touchscreen or a narrow mouse window got them disagreeing. Extracted one `isCoarsePointer` in shared.ts that both use — the pad now shows on a coarse pointer, same as the bigger handles. - Wrapped commitLater/nudgeSelected in useCallback([]) — stable identity, so NudgePad doesn't re-render each parent render, and the mount-once keydown effect capturing nudgeSelected is now explicitly safe (a comment spells out the refs-only invariant that makes the empty-deps capture correct). - isCoarsePointer's optional-chained matchMedia keeps it false (mouse defaults) under test/SSR, addressing the constants-file testability note. tsc + build green. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ