percentages don’t scale
The old felt was built in percentages. Seat 4 lived at “75% across, 133% down.” Beautiful on a laptop. But drag it toward phone size and the whole thing pulls apart — the distance from the right rail to seat 7 stops matching the distance from the bottom rail to seat 4. The ratios drift. Every element was pinned by hand, so nothing scaled together.
We wanted one rule: shrink the table as far as you like — wide phone, tall phone, anywhere in between — and every distance keeps its ratio.
a seat isn’t a coordinate. it’s a spoke.
the table is polar
Cartesian says “how far right, how far down.” Polar says “which direction, and how far out” — measured from a center point. For a round table that’s the honest frame: a seat is a direction from the middle, and everything it owns — chips, cards, its bet — lives on that spoke.
Two numbers do it: the angle (which o’clock) and the radius (how far to the rail). Pick the radius as a fraction — 0 at center, 1 on the rail — and scaling becomes a single multiply. Ratios hold by construction, at every size.
π = 180° · full turn = 2π ≈ 6.283an oval is two radii
A poker table isn’t a circle — it’s wider than it’s tall. So give the ellipse two radii, one for width and one for height. Our first version let each radius chase a screen dimension — any container, any oval. Watching real players taught us better: appearance consistency beats per-pixel fill. The shipped felt holds one preferred wide oval at uniform scale across almost every screen — letterboxed, centered — and deviates only at the extremes. A really short window flattens it smoothly toward a capped wider shape; a really narrow one morphs it smoothly into a centered circle. No breakpoints, no steps — one continuous mapping.
|x / rx|ⁿ + |y / ry|ⁿ = 1And the frame doesn’t get the whole window. The felt reserves invisible bands along its edges — a column each side for chat, history, and the watching list; a head band for the table’s title; a foot band where your actions float as a card when it’s your turn (the old full-width action bar is gone). The ring solves inside what’s left, so no seat can ever end up underneath a panel — the chrome floats over zones the geometry already promised away. Flip on band guides in the tool below to see them.
how to space nine seats
“Evenly” has two meanings on an oval, and they disagree. Equal angle (40° apart) keeps the degrees round but bunches the seats where the oval curves hardest. Equal arc — equal distance walked along the rim — looks even, but the angles come out un-round. That’s fine: on a table, the angle is an output. You place a seat, then read its angle for the chip line — you never hand-pick degrees.
seats aren’t points
Space the seat centers by equal arc and the gaps still look wrong. Because a seat isn’t a dot — it’s a box: a nameplate with hole cards riding above it. Across the top and bottom the boxes sit shoulder-to-shoulder, so their width eats the gap. Down the sides they stack, so only their height does. Same center spacing, different air: on the old felt, seat 5→6 measured 130px, seat 7→8 measured 155px.
The fix is to space each box by its own footprint along the rail, plus one shared clear gap. Now the air between the cards is equal — everywhere, at every shape.
One refinement the math didn’t predict but eyes demanded: the footprint that spaces a seat is the card body you actually read, not the taller box its hole cards ride in — and vertically stacked side pairs get a tightness factor so they read right, because arithmetically even isn’t optically even. (Collisions still respect the full box.)
gap = ( perimeter − Σ box-widths ) / Nthe geometry was never about the dots. it was about the space between them.
the dealer’s parity
The house dealer sits at top-center. With an odd number of players it takes its own slot and everyone stays mirror-symmetric. With an even number, handing it a slot breaks the mirror — so it doesn’t get one. It rides a normal gap between the top two seats, and every gap (including seat-1 to seat-N straight across the top) stays identical. Odd: own space. Even: no space. Symmetric either way.
the center isn’t the pot
Every seat casts two rays. One to the table center — that sets its distance and scale. One to the pot — and the pot isn’t the center; it rides high above the board. Chips travel the pot ray, not the center ray. The two only coincide for the seat directly beneath the pot; everywhere else they diverge, and the bet slides down the pot line. And a bet sits a constant distance from its player — measured from the card’s edge, not a fraction of the pot distance — so no far seat flings its chips out further than a near one.
One more honesty rule — the crowding policy, in three steps that always happen in order. When the table gets too small to hold everyone at full size, the cards shrink together to protect the gap. The shrink stops at a legibility floor — below a certain size a card is noise, so it refuses to get smaller. Only then are cards allowed to overlap, tilted, z-ordered so you and the acting player always sit on top of the pile.
the whole thing, live
Everything above, in one sandbox — and it isn’t a copy. The tool below imports the actual engine the live table renders from, and every knob starts at the live defaults: the numbers you’re dragging are the shipped table’s tuned config, not stand-ins that drift when we retune. Drag the screen shape and watch it reshape. Change the players to feel the dealer parity flip at odd/even. Flip placement between even gaps and equal arc to see the footprint fix. Open the engine knobs to move the invisible bands, the crowding floor, even the camera. Click any seat to read its geometry — its angle, its reach, and how far its two rays diverge.
interactive · drag anything