1 · Camera & calibration zones
Accuracy strategy: cards go in the fixed zones below (hole cards bottom, board across the middle), camera top-down with even light. Each zone is read by its top-left corner crop (rank+suit corner) — that is what real recognizers read. Drag-free zones = no search problem, far fewer misreads.
Recognizer status: pluggable hook, manual-confirm implementation shipped.
No ML model is bundled — nothing is auto-read until a recognizer (template matcher / on-device model / AI tier) is plugged into
window.PokerRecognizer.recognize(). Sampling without one leaves slots uncertain (by design — we do not fake reads).
The Simulate button feeds the demo hand through the voting machine so you can see acceptance work end-to-end (clearly a simulation, not ML).
2 · Card slots — crops, corner zoom, threshold preview, confirmation
Tap a slot to select it, then set its card. Statuses: accepted uncertain manual empty. A recognizer reading is only accepted after the same card wins the required votes above the confidence bar.
3 · Money & decision
4 · AI review tier disabled by default · mock mode
On demand only — sends the restored state JSON + per-slot corner crops (never raw video), and only when the state changed
or a slot is low-confidence. Mock mode returns a structured mock review locally; wiring a real vision endpoint (e.g. Gemini via a key-holding proxy)
is a separate approved step. See ai_review.js.
5 · This device — what the browser can actually use
Short version: for this workload the browser is not the bottleneck — WebGPU + multi-threaded WASM reach most of the machine's GPU/CPU. Real limits and the native escape hatch are in the README.