## Context The game page (`+page.svelte`) hardcodes the `trainingMix` preset at initialization. The setup page saves user-selected config to `sessionStorage`, but nothing reads it. The bot timer uses a `$effect` that re-runs on every reactive update, resetting the countdown. Card visibility only checks `isHuman`, ignoring poker rules for showdown and all-in reveals. ## Goals / Non-Goals **Goals:** - Settings from `/setup` page apply to the game session - Bot countdown timer decrements correctly (13→12→11...→0) - Opponent cards reveal at showdown and when all-in with no further betting **Non-Goals:** - Persistent config across browser sessions (localStorage/database) - Animated card reveals or showmanship - Multi-player online gameplay ## Decisions ### Settings via sessionStorage Using `sessionStorage` (already in use by setup page) rather than URL params or a state store. It's simple, survives the navigation redirect, and clears on tab close — appropriate for a single-session training game. ### Timer fix: $derived.timeRemaining with setInterval outside effect The `$effect` will only anchor on `active` and `duration`, not `remaining`. The interval will update `remaining` directly. This breaks the reactivity cycle since the effect won't re-run when `remaining` changes. ### Card reveal: computed function in PokerTable, passed to PlayerSeat Rather than passing the entire GameState to each PlayerSeat (which it already has via player prop), we add a `revealCards` boolean prop. PokerTable computes this based on betting round, player status, and all-in conditions. ## Risks / Trade-offs [sessionStorage read fails] → Parse with fallback to default preset [Timer still flickers in dev mode] → Svelte 5 fine-grained reactivity may need `$state.raw` for the counter [All-in reveal timing edge cases] → The "last betting round complete" check requires knowing if any active player can still bet — we approximate by checking if all non-folded players are all-in or matched