Say ALL IN on the felt, and keep the table above the action bar #63

Closed
jheaps wants to merge 2 commits from fix/casino-holdem-allin-and-bar into fix/casino-holdem-one-dealer-button
Owner

Both found by playing a hand with a short all-in and a side pot — the hand a dealer most needs help with. Stacked on #62.

A player with nothing behind had a blank where their stack goes

So did a seat whose stack nobody had entered. On a table with side pots that is the one distinction the dealer is working from — who can still be bet at, and who is already in for everything they have — and the felt drew the two states identically.

Ann  $40  $160     has chips
Ben  $40           all-in for 40
Cal  $40  $160     has chips
Dee  $12           all-in for 12

The action bar knew: it had already built Main pot $48 — Ann, Ben, Cal, Dee and Side pot 1 $84 — Ann, Ben, Cal. The table it sits under didn't say a word.

Betting.isAllIn is the same stack test nextToAct uses to pass over a player, which is the point: the seat the felt marks is exactly the seat the dealer will never be asked to act on again. There's a test asserting that equivalence rather than restating the condition.

The second half of the condition matters: a seat with an empty stack that has put nothing in is a busted player who shouldn't have been dealt in, not a player who moved all-in, so it isn't marked.

"ALL IN" in gold where the stack was, plus a warmer border on the seat — deliberately quieter than the acting-seat ring, because all-in is a standing fact about a player rather than a request for attention.

The wide layout never read the bar's height

The bar publishes how tall it is so the layout can stay clear of it. Only the phone and landscape rules ever read it. The wide layout sized the felt from its own width — a box 72% as tall as it is wide — so it had no idea what was underneath.

Survivable while the bar was a constant. It isn't: 117px → 172px the moment a hand needs a side pot, which is exactly the hand where the dealer most needs to see who is still in. Measured with two side pots, six seats — how far the bottom seat sat behind the bar:

1280x900 22px 1600x1000 54px
768x1024 23px 1024x768 clear
360x640 39px 390x844 clear

The first attempt didn't work, and the failure is worth recording. The wrap was a padding-bottom: 72% box, and percentage padding resolves against the containing block's width, not the element's own. Capping the width narrowed the felt 822px → 746px and left it exactly 617px tall, so the seat stayed precisely where it was. It's an aspect-ratio box now, with the shape stated once as --feltAspect so the height and the cap both derive from it.

Viewport Felt Bottom seat
1280x900 857x617 → 746x537 22px behind → 51px clear
1600x1000 961x760 → 885x637 54px behind → 59px clear
768x1024 689x689 → 603x603 23px behind → 56px clear

Six-seat tables at 1280x900, 1600x1000, 1024x768 and 768x1024 all go from one covered seat to a clean audit.

Not applied below 700px. The narrow layout already had an answer — it reserves the bar's height as scroll room under the table, and a phone is a thing you scroll — and capping there was measured and rejected: at 360x640 it took the felt 321px → 226px, which fixed the six-seat ring and broke the nine-seat one, two covered seats traded for two seats whose centre landed on a neighbour.

Landscape phones opt out too. They already set their own height from the bar and are sitting on their 7rem floor. 844x390 and 667x375 still have the bottom seat in the bar, and nothing about a 112px-tall table with 73px seats can fix that.

The seat overhang is a constant (~73px seat at every width) rather than something measured off the layout it is about to change, so this settles in one pass instead of asking a different question every time it shrinks the felt.

Validation

172 tests passing (9 new; they fail on a naive all-in condition — dropping the committed-chips and folded checks fails 4 of them).

Playwright across 10 viewports × 2, 6 and 9 seats, each driven through a real short-all-in hand: no console errors, contrast clean, and the wide sizes clean at 6 and 9 seats. Heads-up re-checked separately after a scripted-input artifact made it look broken — clean with the cap on and off.

Both found by playing a hand with a short all-in and a side pot — the hand a dealer most needs help with. Stacked on #62. ## A player with nothing behind had a blank where their stack goes So did a seat whose stack nobody had entered. On a table with side pots that is the one distinction the dealer is working from — who can still be bet at, and who is already in for everything they have — and the felt drew the two states identically. ``` Ann $40 $160 has chips Ben $40 all-in for 40 Cal $40 $160 has chips Dee $12 all-in for 12 ``` The action bar knew: it had already built `Main pot $48 — Ann, Ben, Cal, Dee` and `Side pot 1 $84 — Ann, Ben, Cal`. The table it sits under didn't say a word. `Betting.isAllIn` is **the same stack test `nextToAct` uses to pass over a player**, which is the point: the seat the felt marks is exactly the seat the dealer will never be asked to act on again. There's a test asserting that equivalence rather than restating the condition. The second half of the condition matters: a seat with an empty stack that has put nothing in is a busted player who shouldn't have been dealt in, not a player who moved all-in, so it isn't marked. "ALL IN" in gold where the stack was, plus a warmer border on the seat — deliberately quieter than the acting-seat ring, because all-in is a standing fact about a player rather than a request for attention. ## The wide layout never read the bar's height The bar publishes how tall it is so the layout can stay clear of it. Only the phone and landscape rules ever read it. The wide layout sized the felt from its own width — a box 72% as tall as it is wide — so it had no idea what was underneath. Survivable while the bar was a constant. It isn't: **117px → 172px the moment a hand needs a side pot**, which is exactly the hand where the dealer most needs to see who is still in. Measured with two side pots, six seats — how far the bottom seat sat behind the bar: | | | | | | --- | --- | --- | --- | | 1280x900 | **22px** | 1600x1000 | **54px** | | 768x1024 | **23px** | 1024x768 | clear | | 360x640 | **39px** | 390x844 | clear | **The first attempt didn't work, and the failure is worth recording.** The wrap was a `padding-bottom: 72%` box, and percentage padding resolves against the *containing block's* width, not the element's own. Capping the width narrowed the felt 822px → 746px and left it exactly 617px tall, so the seat stayed precisely where it was. It's an `aspect-ratio` box now, with the shape stated once as `--feltAspect` so the height and the cap both derive from it. | Viewport | Felt | Bottom seat | | --- | --- | --- | | 1280x900 | 857x617 → **746x537** | 22px behind → **51px clear** | | 1600x1000 | 961x760 → **885x637** | 54px behind → **59px clear** | | 768x1024 | 689x689 → **603x603** | 23px behind → **56px clear** | Six-seat tables at 1280x900, 1600x1000, 1024x768 and 768x1024 all go from one covered seat to a **clean audit**. **Not applied below 700px.** The narrow layout already had an answer — it reserves the bar's height as scroll room under the table, and a phone is a thing you scroll — and capping there was measured and rejected: at 360x640 it took the felt 321px → 226px, which fixed the six-seat ring and broke the nine-seat one, two covered seats traded for two seats whose centre landed on a neighbour. **Landscape phones opt out too.** They already set their own height from the bar and are sitting on their 7rem floor. 844x390 and 667x375 still have the bottom seat in the bar, and nothing about a 112px-tall table with 73px seats can fix that. The seat overhang is a constant (~73px seat at every width) rather than something measured off the layout it is about to change, so this settles in one pass instead of asking a different question every time it shrinks the felt. ## Validation **172 tests passing** (9 new; they fail on a naive all-in condition — dropping the committed-chips and folded checks fails 4 of them). Playwright across 10 viewports × 2, 6 and 9 seats, each driven through a real short-all-in hand: no console errors, contrast clean, and the wide sizes clean at 6 and 9 seats. Heads-up re-checked separately after a scripted-input artifact made it look broken — clean with the cap on and off.
jheaps added 2 commits 2026-09-01 12:36:20 -06:00
A player with nothing behind had a blank where their stack goes. So did a seat whose
stack nobody had entered. On a table with side pots that is the one distinction the
dealer is working from -- who can still be bet at, and who is already in for
everything they have -- and the felt drew the two states identically.

  Ann  $40  $160     has chips
  Ben  $40           all-in for 40
  Cal  $40  $160     has chips
  Dee  $12           all-in for 12

The action bar knew: it had already built "Main pot $48, Ann/Ben/Cal/Dee" and
"Side pot 1 $84, Ann/Ben/Cal". The table it sits under didn't say a word.

Betting.isAllIn is the same stack test nextToAct uses to pass over a player, which is
the point: the seat the felt marks is exactly the seat the dealer will never be asked
to act on again. There's a test asserting that equivalence rather than restating the
condition.

The second half of the condition matters. A seat with an empty stack that has put
nothing in is a busted player who shouldn't have been dealt in, not a player who
moved all-in, so it isn't marked.

"ALL IN" in gold where the stack was, and a warmer border on the seat -- deliberately
quieter than the acting-seat ring, because all-in is a standing fact about a player
rather than a request for attention.

9 tests (172 total). They fail on a naive condition: dropping the committed-chips and
folded checks fails 4 of them.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb
The bar publishes its height so the layout can stay clear of it. Only the phone and
landscape rules ever read it. The wide layout sized the felt from its own width -- a
box 72% as tall as it is wide -- and so had no idea what was underneath it.

That was survivable while the bar was a constant. It isn't: it grows from 117px to
172px the moment a hand needs a side pot, which is exactly the hand where the dealer
most needs to see who is still in. Measured with two side pots, six seats, the bottom
seat sat this far behind the bar:

  1280x900    22px      1600x1000   54px
  768x1024    23px      1024x768    clear
  360x640     39px      390x844     clear

The first attempt at this didn't work and the failure is worth recording: the wrap was
a padding-bottom: 72% box, and percentage padding resolves against the containing
block's width rather than the element's own. Capping the width narrowed the felt from
822px to 746px and left it exactly 617px tall, so the seat stayed where it was. It is
an aspect-ratio box now, and the shape is stated once as --feltAspect so the height
and the cap both derive from it.

  1280x900   felt 857x617 -> 746x537   seat 22px behind the bar -> 51px clear
  1600x1000       ...760 -> 885x637              54px behind -> 59px clear
  768x1024   felt 689x689 -> 603x603              23px behind -> 56px clear

Six-seat tables at 1280x900, 1600x1000, 1024x768 and 768x1024 all go from one covered
seat to a clean audit.

Not applied below 700px. The narrow layout already had an answer -- it reserves the
bar's height as scroll room under the table, and a phone is a thing you scroll -- and
capping there was measured and rejected: at 360x640 it took the felt from 321px to
226px, which fixed the six-seat ring and broke the nine-seat one, two covered seats
traded for two seats whose centre landed on a neighbour.

Landscape phones opt out too. They set their own height from the bar already and are
sitting on their 7rem floor; 844x390 and 667x375 still have the bottom seat in the
bar, and nothing about a 112px-tall table with 73px seats can fix that.

The seat overhang is a constant rather than something measured off the layout it is
about to change -- a seat is ~73px tall at every width -- so this settles in one pass
instead of asking a different question each time it shrinks the felt.

172 tests still passing; no console errors; contrast clean.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb
jheaps referenced this issue from a commit 2026-09-01 12:53:03 -06:00
jheaps closed this pull request 2026-09-02 09:58:32 -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#63