- Add portraitHappy/portraitUpset helpers to react to game events
- Track army snapshotted counts on attack phase entry
- Trigger upset emotion when a player loses >8 armies in a turn
- Show happy emotion on continent capture or defeating 5+ defender armies
- Show happy on successful card trades (human and AI)
- Enable opponent portrait intros in Risk
- Remove deprecated setPortraitThinking method
feat(paigow): widen card spread in comparison modal
- Add MODAL_CARD_SPREAD constant (55px) for clearer card visibility
- Use modal spread in slotX calculation for comparison display
- Move Next Round button up 200px for better centering
feat(opponents): add Jerry conversation audio references
- Add "convo" array to Jerry's opponent entry
- Reference maurice and mario conversation audio files
- Add customizable playfield backgrounds with localStorage persistence
- Display multiplier labels on gold (1.5x) and diamond (2x) tiles
- Replace simple fade-in refill with Bejeweled-style falling tile animations
- Swap SUBMIT and CLEAR button positions for better UX
- Add new opponents (Gerome, Fireball, Natasha) with voice lines and convo files
- Reduce conversation interval from 60-300s to 20-200s
- Enable DEBUG_CONVOS for development
- Add sprite images, speech audio, and animation videos for Nadia and
The Smasher opponents
- Update opponents.json with new character definitions and speech cues
- Fix 2048 UI: reposition buttons and add Leave button
- Replace star collection with target-square coverage for Pudding Monsters
- New 3-star medal system: min(targets covered, par-based efficiency)
- Add "Reset Progress" buttons to Pudding Monsters and Rush Hour level select
- Add reset API endpoint for puzzle progress
- Add Beth and Blackwind opponents with idle/happy/upset animations
- Update puddingmonsters.json levels with target squares instead of stars
- Introduce Balam (spriteIndex 16) and Steve (spriteIndex 17) as new opponents
- Include full speech configurations (intro, happy, upset, pick) for both characters
- Add 12 new MP3 speech files for Jerry (intro, happy, upset, pick)
- Update opponents.json to include Jerry's speech configuration
- Fix HoldemLogic to exclude folded players from seat order calculation
- Add new `pick` audio clips for each opponent in `opponents.json` and corresponding MP3 files
- Implement a spectrum visualizer overlay for opponent portraits that activates during pick speech playback
- Integrate `SpeechQueue` to handle opponent pick audio with start/stop callbacks for the visualizer
- Add `setMenuMusicVolume` utility and adjust menu music volume during opponent selection
- Prevent speech/visualizer triggers during initial scene load and game start sequences
- Add 22 new MP3 speech files for characters Jeff and Fireball
- Update public/data/opponents.json to include speech arrays for both characters
- Each character now has intro, happy, and upset speech categories with 2-5 variations
- Add speech assets and configuration for Brad and Mario
- Update opponents.json with new speech arrays for intro, happy, and upset states
- Prevent discarding cards while cards are staged in Phase 10
- Add visual feedback (_shakeStagingButtons) when staging rules are violated
- Add _hasStagedCards helper to check staging group state
- Move staged cards back to hand if user attempts to discard during staging
- Introduce a canvas-based audio visualizer overlay on opponent portraits that activates during speech playback
- Update `SpeechQueue` to support `onStart` and `onEnd` callbacks for hooking into audio events
- Modify `Portrait` to trigger the visualizer with emotion-specific colors (blue for intro, green for happy, red for upset)
- Add `speech` metadata to `opponents.json` for Ethel and Bernie, defining available intro/happy/upset audio clips
- Ensure proper cleanup of visualizer state and resources on portrait destruction
- Implement `SpeechQueue` to manage opponent dialogue clips
- Add `speech` configuration to opponent data (Cy-Bro, Victor, Croc) with intro, happy, and upset states
- Trigger random speech clips in `Portrait.js` based on emotion and a 60% probability
- Play intro speech clips when opponent portraits are created
- Update `MusicPlayer` volume to 0.15 and clean up formatting/whitespace