Seat the table properly on a phone held sideways #100

Closed
jheaps wants to merge 1 commits from fix/casino-holdem-landscape-ring into feat/casino-holdem-table-file
Owner

Landscape is the one shape this layout has never really fitted, and the audit was calling two separate faults there.

The felt guessed at the header. It sized itself as 100vh - bar - 7rem, assuming everything above it came to 7rem. That is 108px at 640x360, which the guess covers, and 119px at 844x390, which it doesn't — so on an iPhone on its side the bottom row of seats sat up to 26px inside the action bar. The measurement it needed was already published for the wide layout, so it uses that now. The floor under it drops from 220px to 96px: 220 is not a size a 390px-tall window has to give, and holding out for it was itself how seats ended up behind the Fold button — the one thing the floor exists to prevent.

The header took two rows, and the second row is 44px of the 390. The title block and the five buttons came to 829px inside a 765px header, missing one line by 64px. The page title goes — the one thing on this screen a dealer already knows — hidden from the eye rather than removed, so the heading is still there for a screen reader. The buttons tighten across but never down: they stay a 44px thumb target.

The seats were spaced by angle, which is only even spacing on a circle. On a 601x126 felt, ten seats at 36° apart put four of them down each steep end, 20px apart, with pucks 72px tall — a seat's centre belonged to its neighbour, so tapping a player got the wrong one. They now walk the rim by distance, which puts them along the two long rails the way a real table seats people. Closest neighbours go from 33px apart to 59px.

Validated

  • Before/after with the same audit, same tables. Baseline: 5 of 6 combinations failed across 640x360, 667x375 and 844x390 with 9- and 10-seat tables. After: every one clean except a 10-seat table at 640x360, where two seats at the end of a rim that flat still overlap — stated rather than suppressed.
  • 16 audits across 13 viewports plus Quick Split: clean, no console errors.
  • Real touch context (hasTouch, isMobile, coarse pointer, no hover) at 844x390, 390x844 and 640x360: clean.
  • A hand played through in landscape — blinds, raise pad, calls, street close.
  • Portrait, tablet and desktop measured unchanged: the floor never bound there, and on a rounder felt walking the rim gives back the same angles it always did.
  • 18 new tests, suite at 418, 0 failures. Every new assertion was checked by breaking the code on purpose first: equal-angle spacing fails the ring tests, the 220px floor fails the room tests, a bet on the wrong index fails the spoke test.

One correction

Moving a bet chip onto its seat's own angle is in here, and my first note called it a fix. Measured, the two answers are within 0.42° — invisible. It is the honest way to say "on that player's spoke" and it saves a second walk round the rim, nothing more; the test asserts the chip is on the seat's line and short of it, which is a property that can actually fail.

Landscape is the one shape this layout has never really fitted, and the audit was calling two separate faults there. **The felt guessed at the header.** It sized itself as `100vh - bar - 7rem`, assuming everything above it came to 7rem. That is 108px at 640x360, which the guess covers, and 119px at 844x390, which it doesn't — so on an iPhone on its side the bottom row of seats sat up to **26px inside the action bar**. The measurement it needed was already published for the wide layout, so it uses that now. The floor under it drops from 220px to 96px: 220 is not a size a 390px-tall window has to give, and holding out for it was itself how seats ended up behind the Fold button — the one thing the floor exists to prevent. **The header took two rows**, and the second row is 44px of the 390. The title block and the five buttons came to 829px inside a 765px header, missing one line by 64px. The page title goes — the one thing on this screen a dealer already knows — hidden from the eye rather than removed, so the heading is still there for a screen reader. The buttons tighten across but never down: they stay a 44px thumb target. **The seats were spaced by angle**, which is only even spacing on a circle. On a 601x126 felt, ten seats at 36° apart put four of them down each steep end, 20px apart, with pucks 72px tall — a seat's centre belonged to its neighbour, so tapping a player got the wrong one. They now walk the rim by distance, which puts them along the two long rails the way a real table seats people. Closest neighbours go from 33px apart to 59px. ### Validated - **Before/after with the same audit, same tables.** Baseline: 5 of 6 combinations failed across 640x360, 667x375 and 844x390 with 9- and 10-seat tables. After: every one clean except a 10-seat table at 640x360, where two seats at the end of a rim that flat still overlap — stated rather than suppressed. - 16 audits across 13 viewports plus Quick Split: clean, no console errors. - Real touch context (`hasTouch`, `isMobile`, coarse pointer, no hover) at 844x390, 390x844 and 640x360: clean. - A hand played through in landscape — blinds, raise pad, calls, street close. - Portrait, tablet and desktop measured unchanged: the floor never bound there, and on a rounder felt walking the rim gives back the same angles it always did. - 18 new tests, suite at **418, 0 failures**. Every new assertion was checked by breaking the code on purpose first: equal-angle spacing fails the ring tests, the 220px floor fails the room tests, a bet on the wrong index fails the spoke test. ### One correction Moving a bet chip onto its seat's own angle is in here, and my first note called it a fix. Measured, the two answers are within **0.42°** — invisible. It is the honest way to say "on that player's spoke" and it saves a second walk round the rim, nothing more; the test asserts the chip is on the seat's line and short of it, which is a property that can actually fail.
jheaps added 1 commit 2026-09-02 03:13:56 -06:00
Landscape is the one shape this layout has never really fitted, and the audit
was calling two separate faults there.

The felt worked its own height out as `100vh - bar - 7rem`, guessing that
everything above it came to 7rem. That is 108px at 640x360, which the guess
covers, and 119px at 844x390, which it doesn't — so on an iPhone on its side the
bottom row of seats sat up to 26px inside the action bar. The measurement it
needed was already being published for the wide layout: the bar's real height,
the wrap's real offset and the bottom seat's overhang, all taken off the window.
It uses that now. The floor under it drops from 220px to 96px, because 220 was
not a size a 390px-tall window has to give — holding out for it was itself how
seats ended up behind the Fold button, which is the one thing the floor exists
to prevent.

That still left the header taking two rows, and the second row is 44px of the
390. The title block and the five buttons came to 829px inside a 765px header,
missing one line by 64px. The page title goes — the one thing on this screen a
dealer already knows — hidden from the eye rather than removed, so the heading
is still there for a screen reader. The buttons tighten across but never down:
they stay a 44px thumb target.

The seats themselves were spaced by angle, which is only even spacing on a
circle. On a 601x126 felt, ten seats at 36° apart put four of them down each
steep end, 20px apart, with pucks 72px tall — a seat's centre belonged to its
neighbour, so tapping a player got the wrong one. They now walk the rim by
distance instead, which puts them along the two long rails the way a real table
seats people. Closest neighbours go from 33px apart to 59px.

Measured at 640x360, 667x375 and 844x390 with 9-, 10- and 12-seat tables: every
combination the audit used to fail is clean, bar a 10-seat table at 640x360,
where two seats at the end of a rim that flat still overlap. Portrait, tablet
and desktop are unchanged — the floor never bound there, and on a rounder felt
walking the rim gives back the same angles it always did.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb
jheaps closed this pull request 2026-09-02 09:58:04 -06:00

Pull request closed

Please reopen this pull request to perform a merge.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jheaps/JoshHeaps.Net#100