The chips are objects on a table

Featurekamo-internal
Shipped
September 8, 2026 at 6:27 PM UTC
Author
Kamo
Commit
a0ef40b

A member asked for the poker chips to stop being decoration. They are a subsystem now: real denominations, real stacking, racks, a betting line, pots that add up, and chips that travel between them. WHAT A CHIP IS. `chipDenominations.ts` is the whole economy — the standard casino ladder **************** the set a TABLE deals in derived from its stakes, and one exact breakdown function everything else asks. At 100/200 with a 20,000 buy-in that set is 1K/500/100, so a full stack is one rack of yellows, which is what that game looks like in life. Greedy down the ladder is also MINIMAL here, which is a fact about this ladder rather than about greed — greedy makes six out of 4+1+1 on a 1/3/4 system — so it is proved by exhaustive comparison against a dynamic program rather than assumed. WHAT A CHIP LOOKS LIKE. An SVG seen from a player's own eye level: a top face with a rim, edge spots and an inlay, and a side WALL. A stack is one wall per chip and exactly one face, which is both how a real stack reads and why a hundred chips in a rack is one DOM element. The organisation's Simple Logo is the inlay — in its own colours on the white chip, and as an alpha-preserving white silhouette on every other, because a coloured mark on a coloured chip is unreadable on half the ladder. This organisation's logo is a 3.5 MB, 1,494-path photo trace, so it is rasterised ONCE per tab into two ~10 KB data URLs that every chip shares. WHERE A CHIP GOES. `chipGeometry.ts` puts a betting line on the cloth: chips outside it are yours, chips inside it are the pot's, which is the affordance a real cardroom uses and needs no legend. Placement is by CONSTRUCTION, not by tuned constants — a seat cluster is a fixed 110x91 pixels while its position is a percentage, so as a fraction of the felt it GROWS as the table shrinks, and every set of constants that looked right at 1180 was wrong at 880. Each pile is walked out until it clears its own plate, the board, the edge, its neighbours, and the halfway bearing to the next player. WHAT MOVES. `useChipChoreography` diffs consecutive authoritative frames and `ChipFlightLayer` flies the difference: the chips a player pushed forward, the street swept in, each pot carried to the winners the server named, an uncalled bet going home. Animation is presentation and the frame is the truth — every visual hold carries a deadline enforced by a scheduled STATE CHANGE, never by a `Date.now()` comparison during render, which is a moment that never arrives. A fresh mount holds nothing, so a reconnect snaps. Mid-hand the middle draws `hand.pot` and the bets draw `streetCommitted`; drawing `pots[]` there would put the same chips on the felt twice, because the server recomputes those from every committed chip. Also here: the seat ring moved in, because a 91px cluster at 5% of a 508px box hangs six pixels off the top of the window; the board shrinks with the table for the same reason; and `holdemMotion.test.ts` now reads the COMPONENTS rather than the stylesheet — the old assertion scanned the half of the sheet before the media query, which holds only @keyframes bodies, so it collected an empty set and its loop never ran once. Rewritten, it found four animations running for people who had asked for none. Measured in a browser at 1400x820, 1180x760, 1000x660, 960x600 and 880x540: no pile over a plate or a card, no pile pointing at the wrong player, no clipped cards, no page overflow in either axis.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing