- Remove unused card_revealed broadcast + 1s asyncio.sleep in swap handler
(client never handled this message, causing pure dead wait before game_state)
- Defer swap-out (opacity:0) on hand cards to onStart callback so overlay
covers the card before hiding it — eliminates visual gap for all players
- Defer heldCardFloating visibility hide to onStart — held card stays visible
until animation overlay replaces it
- Thread onStart callback through animateUnifiedSwap → _runUnifiedSwap
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full-codebase commenting pass focused on the tricky, fragile, and
non-obvious spots: animation coordination flags in app.js, AI decision
safety checks in ai.py, scoring evaluation order in game.py, animation
engine magic numbers in card-animations.js, and server infrastructure
coupling in main.py/handlers.py/room.py. No logic changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Increase post_draw_settle timing (1.1s→1.3s) and swap retry delay
(100ms→350ms) to prevent draw animation from being cut short by the
arriving swap animation. Also make CPU go-out decisions consider
opponent scores and avoid swapping high cards (8+) into hidden slots.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Style the flip overlay's front face to match player hand cards (gradient
background, proper border/shadow) instead of using generic card-front
styles. Hide the underlying card during the animation so the green table
shows through the flip rather than a white card peeking behind it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The turn pulse shake was targeting .discard-stack, which is an ancestor of
#held-card-floating. A CSS transform on any ancestor breaks position:fixed,
causing the held card to render far from the deck area. Now target #discard
directly instead.
Also fix duplicate getCardPointValue methods — the 3-arg scoring version
shadowed the 1-arg tooltip version, leaving cardValues undefined on hover.
Add staging deploy script (rsync working tree, no git pull needed).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix dumb AI knocks (e.g. Maya knocking on 13 points) by adding opponent
threat checks and a hard cap of 10 to should_knock_early(). Remove dead
should_go_out_early() call whose return value was never used. Retune knock
chance tiers to be more conservative at higher projected scores.
On the client side, fix round-end reveal sequencing so the last player's
swap/discard animation plays before the reveal sequence starts, and prevent
re-renders from clobbering swap animations during reveals. Also make the
turn-pulse shake configurable via timing-config and target only cards.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Tag deal container with class so cleanup() can find and remove it
- Remove .traveling-card and .deal-anim-container overlays in cleanup()
- Restore opacity/visibility on cards hidden mid-animation
- Reset all animation flags (dealAnimationInProgress, etc.) in showLobby()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Less aggressive draw hint: waits 5 seconds before first shake,
then shakes for 300ms every 2 seconds with slightly less movement.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reduce overlap offset from 1.15 to 0.65 so the held card sits at the
DRAW/DISCARD label level rather than up in the opponents area.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Position the held card a full card height above the deck (1.15x offset)
so it sits in the space between opponents and the draw/discard piles.
All three position calculations (app.js x2, card-animations.js) are
synced so draw animations land at the correct held position.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update getHoldingRect() in card-animations.js and the second held card
positioning path in app.js to use the same reduced overlap offset on
mobile portrait. All three places that compute the held position now
use 0.15 on mobile-portrait vs 0.35 on desktop/landscape.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add renderGame() guard during deal animation to prevent DOM destruction
mid-animation causing cards to pile up at wrong positions
- Push lobby content below fixed auth-bar (padding 15px -> 50px top)
- Scale player card font-size to 1.5rem/1.3rem for readable text on mobile
- Add full mobile portrait layout: bottom drawers, compact header, responsive
card grid sizing, safe-area insets, and mobile detection via matchMedia
- Add cardFontSize() helper for consistent proportional font scaling
- Add mobile bottom bar with drawer toggles for standings/scores
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove scale(1.15) size jump on held card, keep gold border/glow highlight.
Set animation card font-size proportionally to card width so text matches
across deck, hand, and opponent card sizes. Animate font-size during swaps
so text scales smoothly as cards travel between different-sized positions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Client-side scoring (points badge and score tally animation) ignored
house rules that modify pair behavior. Extract shared
calculateColumnScores() helper that mirrors server logic for
eagle_eye, negative_pairs_keep_value, wolfpack, four_of_a_kind,
and one_eyed_jacks rules. Server now sends scoring_rules flags
in game state.
Also fix opponent flip animation card font-size matching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix discard pile "do-si-do" race condition when CPU draws from discard
- Add isDrawAnimating flag for opponent draw animations
- Skip STEP 2 (discard detection) when draw from discard detected
- Fix deal animation using wrong rect (was using whole player area)
- Add player area highlight when it's their turn (green glow)
- Clear opponent animation flags when your_turn message received
- Hide discard pile during draw-from-discard animation
- Add comprehensive debug logging for animation flags
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace CSS transitions with anime.js for all card animations
- Create card-animations.js as single source for all animation logic
- Remove draw-animations.js (merged into card-animations.js)
- Strip CSS transitions from card elements to prevent conflicts
- Fix held card appearing before draw animation completes
- Make opponent/CPU animations match local player behavior
- Add subtle shake effect for turn indicator (replaces brightness pulse)
- Speed up flip animations by 30% for snappier feel
- Remove unnecessary pulse effects after draws/swaps
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>