Commit Graph

1949 Commits

Author SHA1 Message Date
semantic-release-bot a65cc8ad50 chore(release): 4.68.0 [skip ci]
## [4.68.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.67.1...v4.68.0) (2025-10-23)

### Features

* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))

### Bug Fixes

* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* **card-sorting:** add overflow hidden to clip rounded corners ([84c66fe](84c66feec6))
* **card-sorting:** preserve card positions on pause/resume ([0d8af09](0d8af09517))
* **card-sorting:** prevent duplicate START_GAME moves on Play Again ([a0b14f8](a0b14f87e9))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* **qr-button:** improve layout and z-index ([646a422](646a4228d0))
* **qr-button:** increase mini QR code size to 80px ([61ac737](61ac7378bd))
* **qr-button:** increase mini QR code to 84px ([3fae5ea](3fae5ea6fa))
* **qr-button:** make button square and increase QR size ([dc2d466](dc2d46663b))
* **qr-button:** match height of stacked buttons ([81f202d](81f202d215))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))

### Code Refactoring

* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))

### Documentation

* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* update workflow to require manual testing before commits ([0991796](0991796f1e))
2025-10-23 19:45:42 +00:00
Thomas Hallock 84c66feec6 fix(card-sorting): add overflow hidden to clip rounded corners
Add overflow: 'hidden' to card container to properly clip the abacus
SVG content within the rounded border radius. This prevents the SVG
from bleeding through at the corners.

Also remove temporary debug logging that was added in previous commit.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 14:44:24 -05:00
semantic-release-bot 3ba33b48ac chore(release): 4.68.0 [skip ci]
## [4.68.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.67.1...v4.68.0) (2025-10-23)

### Features

* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))

### Bug Fixes

* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* **card-sorting:** preserve card positions on pause/resume ([0d8af09](0d8af09517))
* **card-sorting:** prevent duplicate START_GAME moves on Play Again ([a0b14f8](a0b14f87e9))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* **qr-button:** improve layout and z-index ([646a422](646a4228d0))
* **qr-button:** increase mini QR code size to 80px ([61ac737](61ac7378bd))
* **qr-button:** increase mini QR code to 84px ([3fae5ea](3fae5ea6fa))
* **qr-button:** make button square and increase QR size ([dc2d466](dc2d46663b))
* **qr-button:** match height of stacked buttons ([81f202d](81f202d215))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))

### Code Refactoring

* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))

### Documentation

* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* update workflow to require manual testing before commits ([0991796](0991796f1e))
2025-10-23 19:43:11 +00:00
Thomas Hallock 9f5d4ccdf8 debug: add console logging for card position restoration
Add temporary logging to diagnose why card positions aren't being
properly restored when pausing and resuming the game.

This will be reverted after diagnosing the issue.
2025-10-23 14:41:56 -05:00
semantic-release-bot 23b072ab8f chore(release): 4.68.0 [skip ci]
## [4.68.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.67.1...v4.68.0) (2025-10-23)

### Features

* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))

### Bug Fixes

* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* **card-sorting:** preserve card positions on pause/resume ([0d8af09](0d8af09517))
* **card-sorting:** prevent duplicate START_GAME moves on Play Again ([a0b14f8](a0b14f87e9))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* **qr-button:** improve layout and z-index ([646a422](646a4228d0))
* **qr-button:** increase mini QR code size to 80px ([61ac737](61ac7378bd))
* **qr-button:** increase mini QR code to 84px ([3fae5ea](3fae5ea6fa))
* **qr-button:** make button square and increase QR size ([dc2d466](dc2d46663b))
* **qr-button:** match height of stacked buttons ([81f202d](81f202d215))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))

### Code Refactoring

* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))

### Documentation

* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* update workflow to require manual testing before commits ([0991796](0991796f1e))
2025-10-23 19:40:56 +00:00
Thomas Hallock a0b14f87e9 fix(card-sorting): prevent duplicate START_GAME moves on Play Again
Fix issue where clicking "Play Again" simultaneously on multiple windows
would generate different card sets on each window:

- Add guard in startGame() to prevent sending START_GAME if already in playing phase
- Add 500ms debounce check using gameStartTime to prevent rapid duplicate sends
- Add state.gamePhase and state.gameStartTime to startGame dependencies

Now only the first client to click "Play Again" will generate cards, and
all other clients will be blocked from sending duplicate START_GAME moves
within the debounce window, ensuring all windows see the same cards.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 14:39:46 -05:00
semantic-release-bot 561599b672 chore(release): 4.68.0 [skip ci]
## [4.68.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.67.1...v4.68.0) (2025-10-23)

### Features

* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))

### Bug Fixes

* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* **card-sorting:** preserve card positions on pause/resume ([0d8af09](0d8af09517))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* **qr-button:** improve layout and z-index ([646a422](646a4228d0))
* **qr-button:** increase mini QR code size to 80px ([61ac737](61ac7378bd))
* **qr-button:** increase mini QR code to 84px ([3fae5ea](3fae5ea6fa))
* **qr-button:** make button square and increase QR size ([dc2d466](dc2d46663b))
* **qr-button:** match height of stacked buttons ([81f202d](81f202d215))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))

### Code Refactoring

* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))

### Documentation

* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* update workflow to require manual testing before commits ([0991796](0991796f1e))
2025-10-23 19:38:24 +00:00
Thomas Hallock 0d8af09517 fix(card-sorting): preserve card positions on pause/resume
Fix card positions getting randomized when pausing and resuming game:
- Add cardPositions to pausedGameState type in types.ts
- Save cardPositions in GO_TO_SETUP validator and Provider optimistic update
- Restore cardPositions in RESUME_GAME validator and Provider optimistic update
- Fix React hooks rule violation: move useSpring call before early return

Now when you go to setup and resume the game, all cards return to their
exact positions instead of being randomly scattered.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 14:37:10 -05:00
semantic-release-bot 3e8dbad979 chore(release): 4.68.0 [skip ci]
## [4.68.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.67.1...v4.68.0) (2025-10-23)

### Features

* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))

### Bug Fixes

* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* **qr-button:** improve layout and z-index ([646a422](646a4228d0))
* **qr-button:** increase mini QR code size to 80px ([61ac737](61ac7378bd))
* **qr-button:** increase mini QR code to 84px ([3fae5ea](3fae5ea6fa))
* **qr-button:** make button square and increase QR size ([dc2d466](dc2d46663b))
* **qr-button:** match height of stacked buttons ([81f202d](81f202d215))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))

### Code Refactoring

* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))

### Documentation

* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* update workflow to require manual testing before commits ([0991796](0991796f1e))
2025-10-23 19:34:50 +00:00
Thomas Hallock c367e0ceec feat(card-sorting): add react-spring animations for real-time sync
Add smooth physics-based animations for card and arrow movements:
- Add @react-spring/web dependency
- Create AnimatedCard component with spring animations
- Create AnimatedArrow component with spring animations
- Add viewport resize handling with debounced isResizing flag
- Conditionally disable animations during drag and resize (immediate mode)
- Enable spring animations only for socket position updates
- Add throttled position syncing (100ms) during drag operations
- Convert all positioning to viewport percentages (0-100)
- Track viewport dimensions and reposition cards on resize

Cards and arrows now smoothly animate when positions update from other
connected windows, while maintaining instant feedback during local
drag operations and viewport resizes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 14:33:30 -05:00
Thomas Hallock f6ed4a27a2 feat(card-sorting): add updateCardPositions action to Provider
Add updateCardPositions action and optimistic update handler:
- Add updateCardPositions callback that sends UPDATE_CARD_POSITIONS moves
- Add optimistic update case for position updates
- Fix card shuffle bug: shuffle on client before sending to server
- Remove double-shuffle in optimistic START_GAME handler
- Clean up unnecessary dependencies in useCallback hooks

This enables throttled real-time position updates during drag operations
that sync across all connected browser windows.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 14:33:30 -05:00
Thomas Hallock 656f5a7838 feat(card-sorting): add CardPosition type and position syncing
Add viewport-relative position tracking for card-sorting game:
- Add CardPosition interface (x, y as % of viewport, rotation, zIndex)
- Add UPDATE_CARD_POSITIONS move type
- Add validateUpdateCardPositions validator method
- Add cardPositions array to CardSortingState

This enables real-time card position syncing across browser windows
using percentage-based coordinates that work across different viewport sizes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 14:33:30 -05:00
semantic-release-bot 5d6c800cee chore(release): 4.68.0 [skip ci]
## [4.68.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.67.1...v4.68.0) (2025-10-23)

### Features

* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))

### Bug Fixes

* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* **qr-button:** improve layout and z-index ([646a422](646a4228d0))
* **qr-button:** increase mini QR code size to 80px ([61ac737](61ac7378bd))
* **qr-button:** increase mini QR code to 84px ([3fae5ea](3fae5ea6fa))
* **qr-button:** make button square and increase QR size ([dc2d466](dc2d46663b))
* **qr-button:** match height of stacked buttons ([81f202d](81f202d215))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))

### Code Refactoring

* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))

### Documentation

* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* update workflow to require manual testing before commits ([0991796](0991796f1e))
2025-10-23 18:22:24 +00:00
Thomas Hallock e4df8432b9 refactor(card-sorting): send complete card sequence instead of individual moves
Simplified architecture: instead of sending individual INSERT_CARD moves
sequentially (which caused race conditions), the client now owns the card
arrangement entirely and sends the complete final sequence in CHECK_SOLUTION.

Changes:
- PlayingPhaseDrag: Send full sequence when clicking "Done"
- Provider: Update checkSolution to accept optional finalSequence parameter
- Validator: Accept and use finalSequence in CHECK_SOLUTION validation
- Validator: Save finalSequence to placedCards for results display
- Remove sequential INSERT_CARD flow complexity

This eliminates:
- Sequential move processing
- Race conditions between INSERT_CARD moves
- Need for complex optimistic locking in card placement
- Version conflicts during rapid card insertion

The client-side spatial arrangement is the source of truth, sent once
to the server for validation and scoring.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 13:21:06 -05:00
Thomas Hallock fbcde2505f fix(arcade): add automatic retry for version conflict rejections
When a move is rejected due to a version conflict (optimistic locking),
automatically retry the move after a brief delay. This handles the case
where moves arrive faster than the database can commit them.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 13:21:06 -05:00
Thomas Hallock 71fd66d96a fix(arcade): implement optimistic locking in session manager
Add version-based optimistic locking to prevent race conditions when
multiple moves arrive rapidly. The database update now checks that the
version hasn't changed since the move was validated, preventing moves
from overwriting each other with stale state.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 13:21:06 -05:00
Thomas Hallock 3d8da2348b docs: add deployment verification guidelines to prevent false positives
Add critical guidelines for verifying NAS deployments to .claude/CLAUDE.md
to prevent assuming deployment is complete just because the website is online.

**Key additions:**
- GitHub Actions success does not equal NAS deployment
- Always verify deployed commit SHA matches origin/main HEAD
- Commands for checking actual deployed commit
- Checklist for confirming deployment completion
- How to report deployment gaps clearly

**Prevents common mistake:**
Seeing https://abaci.one online and assuming new code is deployed
without verifying the commit SHA.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 13:21:06 -05:00
semantic-release-bot ff1964b069 chore(release): 4.68.0 [skip ci]
## [4.68.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.67.1...v4.68.0) (2025-10-23)

### Features

* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))

### Bug Fixes

* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* **qr-button:** improve layout and z-index ([646a422](646a4228d0))
* **qr-button:** increase mini QR code size to 80px ([61ac737](61ac7378bd))
* **qr-button:** increase mini QR code to 84px ([3fae5ea](3fae5ea6fa))
* **qr-button:** make button square and increase QR size ([dc2d466](dc2d46663b))
* **qr-button:** match height of stacked buttons ([81f202d](81f202d215))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))

### Documentation

* update workflow to require manual testing before commits ([0991796](0991796f1e))
2025-10-23 15:37:15 +00:00
Thomas Hallock 3fae5ea6fa fix(qr-button): increase mini QR code to 84px
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:35:22 -05:00
Thomas Hallock 61ac7378bd fix(qr-button): increase mini QR code size to 80px
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:35:22 -05:00
Thomas Hallock 81f202d215 fix(qr-button): match height of stacked buttons
- Change from width-based to height-based sizing (height: 100%)
- Button now takes full height of parent container
- Increase QR code from 52px to 72px to fill larger button
- Button remains square with aspectRatio: 1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:35:22 -05:00
Thomas Hallock dc2d46663b fix(qr-button): make button square and increase QR size
- Set button width to 100% with aspectRatio 1 for perfect square
- Reduce padding to 4px for tighter fit
- Increase mini QR code from 40px to 52px for better visibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:35:22 -05:00
Thomas Hallock 646a4228d0 fix(qr-button): improve layout and z-index
- Stack room code and share link vertically on left
- Place square QR button on right, spanning both rows
- Show mini QR code (40px) in button instead of emoji
- Fix popover z-index to appear above dropdown menu (z: 10000)
- Reduce button padding for more compact appearance

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:35:22 -05:00
Thomas Hallock 349290ac6a feat(room-share): add QR code button for easy mobile joining
Add a QR code sharing option alongside existing copy buttons.
When clicked, opens a popover with:
- QR code encoding the room's share URL
- "Scan to Join" heading
- Clickable copy button for the URL

Uses qrcode.react library with Radix UI popover component.
Button styled with orange gradient to differentiate from existing
blue link and purple code copy buttons.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:35:22 -05:00
Thomas Hallock 5927f61c3c fix(room-info): hide Leave Room button when user is alone
Hide the "Leave Room" button when the user is the only member in the
room. Leaving when you're alone doesn't make conceptual sense - it
would just auto-create another empty room.

The button now only appears when roomData.members.length > 1.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:35:22 -05:00
Thomas Hallock ff88c3a1b8 feat(arcade): auto-create room when user has none
When users visit /arcade without an active room, automatically create
a new room named "My Room" with open access. This prevents the
navigation loop where users were stuck seeing "No active room found"
with a link back to /arcade.

This auto-creation happens in two scenarios:
- First time visiting /arcade
- After leaving a room

The room is created with:
- Name: "My Room" (neutral, not implying solo-only)
- Access mode: open (user can invite others)
- No game selected (user chooses from game selection screen)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:35:22 -05:00
Thomas Hallock 0991796f1e docs: update workflow to require manual testing before commits
Added critical workflow change: Claude must STOP after passing pre-commit
checks and WAIT for user to manually test before committing/pushing.

This prevents auto-commits of code that passes linting but doesn't work.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:35:22 -05:00
Thomas Hallock 83d0ba26f5 feat(create-room): replace hardcoded game grid with dynamic Radix Select dropdown
Replaced the hardcoded 3-game grid with a beautiful, dynamic dropdown that:
- Automatically shows all games from getAvailableGames() registry
- No more manual updates needed when adding new games
- Card Sorting now appears in the modal (was missing before)

UI Improvements:
- Fancy Radix UI Select component with rich game cards
- Each game shows: large emoji icon, title, description, player count, difficulty
- Color-coded selection highlights matching game's brand color
- Optional game selection - users can "choose later" on game page

UX Enhancements:
- Smooth CSS scrolling with scroll-behavior: smooth
- Absolutely positioned scroll indicators (no jitter)
- Green ▲▼ arrows show when more content available
- Smart positioning with collision detection (never clips viewport)
- maxHeight: 50vh, collisionPadding: 30px for small screens
- Hover effects on scroll arrows and game cards

Technical:
- Uses react-spring animated components for polish
- Radix Select for accessibility and keyboard navigation
- Single source of truth: game registry manifest data

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:35:22 -05:00
semantic-release-bot 2004835bc8 chore(release): 4.67.2 [skip ci]
## [4.67.2](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.67.1...v4.67.2) (2025-10-23)

### Bug Fixes

* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
2025-10-23 13:47:26 +00:00
Thomas Hallock e1258ee041 fix(complement-race): prevent delivery move thrashing in steam sprint mode
Fixed race condition where duplicate DELIVER_PASSENGER moves were sent
to the server when a car remained at a station across multiple frames.

Root cause: The cleanup effect was removing passengers from
pendingDeliveryRef before the optimistic state update propagated,
allowing the same delivery to be attempted multiple times.

Solution: Keep passengers in pendingDeliveryRef for the entire route
duration. Only clear on route change, not on state updates.

Changes:
- Add pendingDeliveryRef to track pending deliveries across frames
- Skip delivery if passenger already has pending request
- Remove premature cleanup of pendingDeliveryRef
- Add unit test to document the race condition

Fixes the console spam of "Move rejected: Player does not have this passenger"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 08:46:04 -05:00
semantic-release-bot 09df96922e chore(release): 4.67.1 [skip ci]
## [4.67.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.67.0...v4.67.1) (2025-10-22)

### Bug Fixes

* **complement-race:** fix react-spring interpolation TypeScript errors ([0add9e4](0add9e4ef1))
2025-10-22 19:06:35 +00:00
Thomas Hallock 0add9e4ef1 fix(complement-race): fix react-spring interpolation TypeScript errors
Fixed TypeScript errors in transform interpolation by using correct react-spring
syntax: to([spring1, spring2, spring3], (a, b, c) => ...) instead of the
incorrect spring1.to((a, b, c) => ..., spring2, spring3) syntax.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 14:05:21 -05:00
semantic-release-bot 3eb85d7d72 chore(release): 4.67.0 [skip ci]
## [4.67.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.66.2...v4.67.0) (2025-10-22)

### Features

* **complement-race:** add react-spring animations to ghost trains for smooth movement ([eb3700a](eb3700a57d))
2025-10-22 18:52:16 +00:00
Thomas Hallock eb3700a57d feat(complement-race): add react-spring animations to ghost trains for smooth movement
Ghost trains now use react-spring animations to smoothly interpolate between
position updates (100ms intervals), eliminating the jerky/discrete movement.

Changes:
- Import useSpring, useSprings, and animated from @react-spring/web
- Convert locomotive and car positions to animated springs
- Use animated.g components for smooth transform interpolation
- Configure springs with tension:280, friction:60 for responsive smoothness

This provides buttery-smooth ghost train movement while receiving position
updates at 100ms intervals, fixing the "low resolution" appearance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 13:50:55 -05:00
semantic-release-bot e6c12e87e4 chore(release): 4.66.2 [skip ci]
## [4.66.2](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.66.1...v4.66.2) (2025-10-22)

### Bug Fixes

* **complement-race:** fix ghost train position update lag and reload position reset ([ad78a65](ad78a65ed7))
2025-10-22 18:44:19 +00:00
Thomas Hallock ad78a65ed7 fix(complement-race): fix ghost train position update lag and reload position reset
Fixed three critical multiplayer issues:

1. **Fixed interval restart bug**: Position broadcast interval was constantly restarting
   because useEffect depended on `compatibleState`, which changed on every position
   update. Now uses stable dependencies (`multiplayerState.gamePhase`, etc.)

2. **Increased broadcast frequency**: Changed from 200ms (5 Hz) to 100ms (10 Hz)
   for smoother ghost train movement during multiplayer races

3. **Fixed position reset on reload**: Client position now syncs from server's
   authoritative position when browser reloads, preventing trains from resetting
   to start of track

Additional fixes:
- Used refs for `sendMove` to prevent interval recreation
- Removed unused imports (useEffect from GhostTrain, SteamTrainJourney)
- Added strategic logging for position broadcast and reception

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 13:43:02 -05:00
Thomas Hallock b95fc1fdff debug(complement-race): add strategic logging to trace ghost train position updates
Removed all existing debug logs and added focused logging to identify why ghost
trains only update when players stop moving.

Strategic logging added:
- [POS_BROADCAST] Logs when position broadcast interval starts/stops
- [POS_BROADCAST] Throttled logging of position broadcasts (>2% change or 5s interval)
- [POS_RECEIVED] Logs when position updates are received from other players (>2% change)

This will help identify if:
1. Position broadcasts are being sent continuously during movement
2. Position updates are being received from the server
3. Updates are being processed and applied to ghost train positions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 13:20:59 -05:00
semantic-release-bot 79bc0e4c80 chore(release): 4.66.1 [skip ci]
## [4.66.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.66.0...v4.66.1) (2025-10-22)

### Bug Fixes

* **complement-race:** ensure continuous position broadcasting during train movement ([df60824](df60824f37))
2025-10-22 18:14:21 +00:00
Thomas Hallock df60824f37 fix(complement-race): ensure continuous position broadcasting during train movement
Fixed an issue where ghost trains only updated when players stopped moving.

Root cause: clientPosition in useEffect dependency array caused the
position broadcasting interval to restart on every position change,
creating gaps in broadcasts during continuous movement.

Solution:
- Use useRef to track latest clientPosition without triggering effect
- Keep ref synced with position via separate useEffect
- Read position from ref inside interval callback
- Remove clientPosition from broadcasting useEffect dependencies

Now positions broadcast smoothly every 200ms regardless of movement state.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 13:12:59 -05:00
semantic-release-bot 543675340d chore(release): 4.66.0 [skip ci]
## [4.66.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.65.1...v4.66.0) (2025-10-22)

### Features

* **complement-race:** implement per-car adaptive opacity for ghost trains ([9b1d47d](9b1d47d4c7))
2025-10-22 18:07:48 +00:00
Thomas Hallock 9b1d47d4c7 feat(complement-race): implement per-car adaptive opacity for ghost trains
Ghost train cars now individually adjust opacity based on proximity to local
train, reducing visual clutter when overlapping while maintaining clarity
when separated.

Changes:
- Calculate local train car positions array in SteamTrainJourney
- Pass positions to GhostTrain for overlap detection
- Rewrite GhostTrain to render locomotive and each car separately
- Each car calculates opacity independently (0.35 when <20% from any local car, 1.0 otherwise)
- Smooth 0.3s CSS transitions between opacity states
- Overlap threshold: 20% of track length

Benefits:
- Reduced clutter when trains overlap
- Clear visibility when trains separated
- Per-car granularity for mixed scenarios

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 13:06:32 -05:00
semantic-release-bot 659464d3b4 chore(release): 4.65.1 [skip ci]
## [4.65.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.65.0...v4.65.1) (2025-10-22)

### Bug Fixes

* **complement-race:** use sendMove with correct parameters for position updates ([06cd94b](06cd94b24c))
2025-10-22 17:43:07 +00:00
Thomas Hallock 06cd94b24c fix(complement-race): use sendMove with correct parameters for position updates
Fixed ReferenceError where makeMove was undefined. The correct function
is sendMove from useArcadeSession, which requires playerId and userId
parameters in addition to the move type and data.

Changes:
- Changed makeMove to sendMove
- Added playerId and userId to the move object
- Added localPlayerId guard to prevent updates before player is identified
- Updated dependency array to include localPlayerId, viewerId, and sendMove

This fixes the runtime error preventing ghost trains from working.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 12:41:44 -05:00
semantic-release-bot ada0becee5 chore(release): 4.65.0 [skip ci]
## [4.65.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.64.2...v4.65.0) (2025-10-22)

### Features

* **complement-race:** implement position broadcasting for ghost trains ([c5fba5b](c5fba5b7dd))
2025-10-22 17:09:44 +00:00
Thomas Hallock c5fba5b7dd feat(complement-race): implement position broadcasting for ghost trains
Clients now broadcast their train position to server every 200ms,
allowing other clients to render ghost trains at correct locations.

Added UPDATE_POSITION move type and server-side validation to sync
client-calculated positions (from momentum physics) to server state.

This fixes the issue where ghost trains were rendering but invisible
because they all had position=0 from server.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 12:08:19 -05:00
semantic-release-bot c5bfcf990a chore(release): 4.64.2 [skip ci]
## [4.64.2](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.64.1...v4.64.2) (2025-10-22)

### Bug Fixes

* **complement-race:** use individual player positions for ghost trains ([00dc4b1](00dc4b1d06))
2025-10-22 16:22:55 +00:00
Thomas Hallock 00dc4b1d06 fix(complement-race): use individual player positions for ghost trains
Previously all ghost trains used the local player's trainPosition,
causing them to render at the same location (hidden behind local train).

Now each ghost train uses its own player.position from multiplayer state,
allowing them to be visible at different positions on the track.

Also added logging to show ghost train positions for debugging.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 11:21:28 -05:00
semantic-release-bot 76063884af chore(release): 4.64.1 [skip ci]
## [4.64.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.64.0...v4.64.1) (2025-10-22)

### Bug Fixes

* **complement-race:** use local player instead of first player for train display ([915d8a5](915d8a5343))
2025-10-22 16:15:59 +00:00
Thomas Hallock 915d8a5343 fix(complement-race): use local player instead of first player for train display
Previously used `firstActivePlayer` which could show the wrong player's
name/emoji on the local train in multiplayer sessions. Now explicitly
finds the local player using `isLocal` flag.

Also updated passenger filtering to only show passengers claimed by
the local player, not the first player in the list.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 11:14:33 -05:00
Thomas Hallock 028b0cb86f debug: use useEffect to log only on changes, not every frame 2025-10-22 11:11:04 -05:00