6a59b0d5ba65e37badfaab03dc4d07572625c9a3
The felt is sized from --feltRoomPx, which actionBar.js publishes from the bar's real height, because the bar is fixed to the bottom and grows with the hand so nothing else can know how much window is left. That measurement is right. What it was measuring was not. ActionBar.mount() called watchHeight() before render(), and the bar ships `<div id="actionBar" hidden>`. So the first publish measured a bar that was not there yet and published 0px — not "I don't know" but "the bar takes none of the window", which is the one answer that makes the felt draw itself too big. Traced on a cold load, nine-handed: t=181ms --actionBarHeight 0px bar hidden, 0 tall t=186ms --feltRoomPx 721px t=1056ms --actionBarHeight 151px bar visible, 151 tall — ResizeObserver t=1059ms --feltRoomPx 570px The observer does come round on its own once `hidden` comes off, but a frame later at best, and with nine seats to lay out it was 875ms behind. What a dealer saw at 360x640 was a table drawn 336x504 and collapsing to 336x374 after it was on screen and readable: 130px of felt with every seat on it. 1280x900 lost 13px the same way. Two rules, separate on purpose. publish() now declines rather than guessing while the bar is hidden and not a rail — a rail still publishes its honest zero, because it is a real bar that has moved out of the way. And mount() publishes once render() has given it something to measure. That leaves the frame before any of it, which is real: the scripts are at the end of the body and the table is laid out inside DOMContentLoaded, so the browser has painted by the time --feltRoomPx exists. The fallback there was `100vh` — the worst guess available, since it says the whole window is free. It is now the same guess two other rules in this file already make, 9rem for the bar plus 7rem for what sits above and below, which lands 10px over the truth at 360x640; and it is a ceiling, so over is a small shrink rather than a seat behind the bar. Measured after, on both phones: one draw, no jump, and a layout-shift score of 0 where the felt used to move 130px. 1362 tests pass, 8 of them new — 5 fail against the old code. One existing test pinned the literal fallback string; its claim is about the cap being the measured room, and it now says that. The sweep is clean across 428 audits; contrast unchanged. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb
Description
No description provided
142 MiB
Languages
JavaScript
68.4%
CSS
14.1%
C#
8%
HTML
4.5%
C++
4.4%
Other
0.5%