b2262f8604599d19789d59dba143d3aba3f3a41d
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e01d8e7c49 |
Tapping a seat gives you that seat
Went to audit the seat editor and couldn't open it: Playwright refused to click the middle of seat 1 because seat 9's dealer chip was sitting there. On a nine-seat table, tapping the centre of one player handed the button to another. I shipped that. The enlarged chip hit area grew outward from a chip already hung over its seat's corner at -10px/-10px -- and on an oval, a seat's corner is the seat next to it. Measured on the nine-seat table: seat 1 10 of 49 sampled points taken by seat 9's chip, including its centre seat 4 9 of 49 taken by seat 5's chip seat 5 3 of 49 taken by seat 6's chip I claimed at the time that no seat tap was stolen, and I had checked -- with an audit that exempted anything inside a `.seat` as harmless crowding. The thief was inside a seat. The check walked straight past it. Two fixes, and the second matters more The chip sits inside its seat now rather than on the rim, and its hit area grows inward over its own seat, which is a big target that can spare a corner. Padding inward alone wasn't enough -- I tried it and the numbers didn't move, because the chip's own box was the problem, not just the pad. Isolating that took disabling the pad and then the overhang separately: pad off gave 2 seats affected, overhang off gave zero. And the audit now asks whether a seat's centre belongs to that seat, as its own check. The occlusion check couldn't answer it: it was built for overlays on top of the table, and this was two pieces of the table fighting over a tap. It exempts a neighbour's body -- seats do overlap by design -- but not a neighbour's controls, which was the exact hole. Seven of eight sizes now have no seat whose centre goes elsewhere, and all four seats I tap open their own editor. What's left, stated rather than buried At 360x640 and 375x667 one seat still loses a single sample point of its rim to a neighbour's chip. Centres are correct; this is the rim of a crowded oval. At 844x390 two seats have centres belonging to the seat next door -- and those are seat bodies, not chips. Nine seats on a 163px-tall landscape table overlap almost completely. That's the landscape felt sizing, it predates all of this, and it wants fixing on its own terms rather than being folded in here. Both are now reported by the audit instead of hidden by it, which is the part I actually trust. 152 tests still passing; contrast clean at every size. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb |
||
|
|
d66abda05a |
Make the dealer puck hittable without making it bigger
Ran the touch-target check that had been sitting in the audit unused. The dealer puck is 22x22 — half what a fingertip needs — in ten places on the table, and tapping it hands the button to that seat and re-posts the blinds. Not a cosmetic control. It stays 22x22. A puck should look like a puck sitting on the rim of its seat, and growing it would take area from the seat itself, which a dealer taps far more often. Instead an invisible pad around it catches the tap: 43x44 hittable on every phone size, close to four times the area, with the pad pushed down and left away from the seat the chip juts towards. Verified that no seat tap is stolen — the occlusion audit is clean at every size. Three things the check itself got wrong, all found before acting on them It read element boxes, and boxes lie in both directions. A control padded out with a transparent ::after responds well past its painted size, and a checkbox wrapped in a label is hit by tapping anywhere on the label — so it reported the dedicated dealer toggle as a 24px fault when it sits inside a 320x44 label that already forwards the tap. It probes outward with elementFromPoint now, which is what a finger actually experiences. The probe walked a fixed 40px each way, so everything wider than 80px reported exactly 80. Every header button came back a suspiciously round "80x42". And it enforced 44px on desktop, where there is no fingertip. Those same header buttons are 64px tall on a phone and 42px with a mouse, which is not a defect. Keyed off hover:none now, the same signal used for the tablet field sizing. Also removed a ::after pad on the dedicated-dealer checkbox that was both inert -- pseudo-elements don't render on replaced elements -- and unnecessary, since the label already does the job. The puck is the one documented exemption: it is deliberately small and "Give the button" is in the seat menu at full size, so it's a shortcut rather than the only way through. The reason sits in the code next to the exemption. Phone sizes: dealer chip 22x22 drawn / 43x44 hittable, zero undersized controls even with the exemption and the pointer rule forced off. Layout and contrast audits clean at all seven sizes. 137 tests passing. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb |
||
|
|
6fa4532781 |
Fix the contrast the audit could finally measure
Contrast is the one check I've got wrong twice, both times by being clever about backgrounds. The first version read only background-color, so text on any of the gradient-painted sheets was measured against transparency and the dealer puck's dark "D" was reported at 1.2:1 against nothing. The second over-corrected and treated low-alpha gradient stops as opaque, scoring white-on-dark at 1.0:1. So this one is built to be incapable of false positives rather than exact. Backgrounds composite through alpha; where a gradient is involved every colour stop is tried and the most flattering one used. A finding means the text fails even under the reading most generous to it. It's checked against known answers before being believed: black on white at 21:1, white on white at 1:1, #767676 on white at the 4.54:1 AA boundary, white over a dark gradient, dark text on that same gradient, white over a 6% white wash on a near-black page. Nine cases, all correct — and building them found a real bug in the check, which walked past an opaque gradient and offered the page background as a candidate. That made it too lenient, which is as bad as the old false positives. What it found: Both blind badges failed against their own gradients, in 9px bold text a dealer reads at a glance across a table. At the worst stop: small blind 3.52:1, big blind 2.15:1. The small blind keeps its blue and darkens to 4.77:1. The big blind flips to dark text on brighter gold, 5.84:1 — how a gold chip is marked anyway, and it makes the two badges far easier to tell apart at speed. Quick Split's footnote names a control the dealer is told to reach for, and that name inherited the muted grey of the surrounding aside: 3.39:1. Emphasised text carrying an instruction gets its own colour now. The felt watermark came back at 1.19:1 and is meant to. It's decoration; holding it to a reading threshold would mean making it not a watermark. It's aria-hidden now, which says the same thing where it also does some good, and the audit skips aria-hidden subtrees. 32 contrast passes over the table, all five overlays and Quick Split at five viewports: zero findings, zero unmeasured. Layout audit still clean. 137 tests pass. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb |
||
|
|
2f6d63400a |
Stop re-typing the layout audit into a console every round
Last round I found a regression I'd shipped two rounds earlier: the standings table's player-name column was zero pixels wide, at every viewport, and nobody noticed because the audit that would have caught it only ever existed in a previous session's scrollback. These checks have been re-written by hand at least six times, and each time they covered only whatever had just changed. So they're a file now. uiAudit.js runs in the page — no build step, no package.json, no dependency — and checks touch-action and tap highlights, that fields stay selectable and are big enough not to trigger iOS zoom, that nothing important is covered or stranded off-screen, that no grid column has collapsed to nothing, and that no text is painted outside its box. runUiAudit.js drives it over the table, all five overlays and Quick Split at thirteen viewports. Deliberately outside CI: the unit suite is dependency-free and runs in a second, this one needs a browser and a running site. Three real faults it found on its first run Fields were 13.3px on every iPad. The 16px minimum that stops iOS zooming the page on focus went in inside a max-width:700px block, and every iPad is wider than that — so a dealer on a tablet, which is the device this is most likely to be propped up on, got the table zoomed every time they touched the blind amount. The reason for that rule was never "narrow screen", it was "iOS". Font size applies at all widths now, and the 44px touch targets key off hover:none, which is what actually distinguishes a finger from a mouse. The seat menu couldn't be scrolled. It had no height limit and no overflow, so on a phone held sideways its first two actions — Fold and All-in — sat below the bottom of the screen with no way to reach them. A dealer in landscape could long-press a seat and then not fold it. The pot wizard sat under the action bar. Every other overlay is z-index 90-98; the wizard alone was at 50, below both the action bar at 55 and the toast at 80. In landscape one of its inputs was completely covered by the Fold button, and a toast could sit over "Confirm Winner(s)". It was the odd one out rather than a decision. Three faults in the audit itself, found by checking before acting Worth recording, because each would have had me "fix" something that wasn't broken: - an ellipsised name was reported as painting outside its seat. A Range measures laid-out text, which runs past the element while overflow:hidden quietly clips it. Only overflow that is actually visible can paint over a neighbour. - every link below the fold was reported as off-screen. Something under the fold on a page that scrolls is reachable; the check now asks whether scrolling can bring it into view, which is the thing that actually matters. - a button in the newly-scrollable seat menu came back "covered by null". elementFromPoint returns null for a point outside a scrollable ancestor's clip — scrolled out of view, not covered by anything. A toast partly over a control is a warning rather than a failure now: it dismisses itself and carries a close button, and on a desktop it necessarily lands over a table that fills the content column. Fully covered by a toast is still a failure, because that was a real bug once — a seat sat exactly under the Undo button. Final sweep: 13 viewports, 65 overlay checks, 13 full-page audits, 4 Quick Split audits, zero failures, one warning. 137 unit tests still passing. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb |