Repository navigation
feat: M7 mobile-responsive UI — bottom-docked panel, 44px tap targets, landscape height cap - #18
Merged
Merged
Conversation
On a phone-width viewport the desktop chrome broke down: the fixed top-left #controls panel (~236px) collided with the centered #app-title on a 390px screen, and the buttons were far below finger size — the user's "unusable on iPhone" report. Pure-CSS fix, all inside a new @media (max-width: 640px) block in src/style.css (desktop layout above the breakpoint is untouched, and no JS changed at all): - #controls docks to the bottom edge, full width, with safe-area padding; sliders stretch; buttons and the file input meet the 44px minimum tap target. - #build-credit moves up under the top-center title block, since the docked panel now owns the bottom edge. Test harness: a new `mobile-chromium` Playwright project (390x844, DPR 3, hasTouch, isMobile, same SwiftShader args) runs the new tests/mobile.spec.js: boot-loader dismissal, pairwise no-intersection among the fixed chrome, every control fully in-viewport, tap targets >= 44px, and a real touch drag (CDP Input.dispatchTouchEvent — trusted pointerType:'touch' events; synthetic dispatchEvent would hit OrbitControls' unguarded setPointerCapture and throw NotFoundError) orbits the camera. RED pre-fix on the overlap assert with exactly the reported geometry. Autopilot: STATUS.md M7 (Mobile-responsive UI) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…er finding)
At 640x360 / 568x320 the bottom-docked #controls panel (~336px tall) sat
inside the same <=640px breakpoint, overlapped #app-title/#build-credit,
and with a grown status line extended above the viewport top where
body{overflow:hidden} made rows unreachable. Cap it at
calc(100dvh - 88px) (vh fallback) with internal overflow-y scrolling.
New landscape test pins no-overlap + in-viewport + scroll-reachability;
RED pre-fix on the verifier geometry.
Autopilot: STATUS.md M7 (Mobile-responsive UI)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Folds the 2026-07-08 queue rebuild (M7-M10 from user direction) and the M7 completion record into one atomic update. Rollback HEAD for M7: 58d3b9a. Autopilot: STATUS.md M7 (Mobile-responsive UI) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Milestone 7 — Mobile-responsive UI
Task (STATUS.md NEXT): the app was unusable on an iPhone — the fixed top-left
#controlspanel (~236px) collided with the centered#app-titleon a ~390px screen, and the controls were far below finger size.Fix: pure CSS — one
@media (max-width: 640px)block insrc/style.css. No JS or markup changes anywhere;src/main.js, the render loop, and the M4 decoupling machinery are byte-identical, and desktop above the breakpoint is untouched (every new rule lives inside the query).#controlsdocks to the bottom edge full-width (safe-area padding), sliders stretch, buttons + file input meet the 44px tap minimum.#build-creditmoves up under the top-center title, since the panel now owns the bottom edge.calc(100dvh − 88px)(vh fallback) and scrolls internally, so it never reaches the top chrome or exceeds the viewport.Test harness: new
mobile-chromiumPlaywright project (Chromium, 390×844, DPR 3,hasTouch,isMobile— no WebKit; CI provisions Chromium only) runningtests/mobile.spec.js: boot-loader dismissal, pairwise non-intersection of the fixed chrome, every control fully in-viewport, ≥44px tap targets, the landscape cap/scroll contract at 640×360 with a grown status line, and touch orbit driven via CDPInput.dispatchTouchEvent(trustedpointerType:'touch'events — a syntheticdispatchEventwould hit OrbitControls 0.185's unguardedsetPointerCaptureand throwNotFoundError; verified from the installed source).RED tests: portrait overlap RED on pre-M7 CSS with exactly the reported geometry (
#controlsx 12–248 vs#app-titlex 101–289); landscape RED pre-cap on the verifier's geometry (panel y −16 at 568×320). Both proven non-tautological by reverting only the production CSS (tests kept) → RED → restore → green.Verifier: one adversarial pass REFUTED the initial portrait-only design (landscape phones inside the same breakpoint: overlap + off-viewport panel); after the height-cap fix a re-verification PASSED the full layout matrix (390×844, 640×360, 568×320, grown-panel and webcam-running states), confirmed the fix is load-bearing, clipped rows reachable with 44px targets intact, and panel scrolling doesn't leak into orbit.
Review: inline pass — no unresolved findings. One pre-existing, out-of-scope note carried forward: desktop widths 641–684px still show the controls×title overlap that exists on
main(the "desktop visually unchanged" clause keeps it out of M7; worth a future queue entry if it bothers anyone).Local suite: 20/20 green (
npm test -- --workers=1), verified visually on real builds (mobile portrait + desktop screenshots — desktop byte-identical).Rollback HEAD:
58d3b9a.Autopilot: STATUS.md M7 (Mobile-responsive UI)
🤖 Generated with Claude Code