Compare commits

..

23 Commits

Author SHA1 Message Date
semantic-release-bot
7ea8399745 chore(abacus-react): release v2.9.0 [skip ci]
# [2.9.0](https://github.com/antialias/soroban-abacus-flashcards/compare/abacus-react-v2.8.3...abacus-react-v2.9.0) (2025-11-05)

### Bug Fixes

* **docker:** upgrade OpenSCAD to 2024.11 to fix CGAL intersection bug ([e1bcd24](e1bcd24169))
* **guide:** increase abacus sizes - they were too small ([1074624](1074624b2f))
* **guide:** make abacus sizes consistent and add nav spacing ([bea4842](bea4842a29))
* **guide:** remove inner containers and tighten margins ([7e54c6f](7e54c6f4fc))
* **layout:** add systematic spacing for fixed nav bar ([4559fb1](4559fb121d))
* **layout:** remove wrapper, use utility class for nav spacing ([247c3d9](247c3d9874))
* **nav:** restrict transparent hero styling to home page only ([fab227d](fab227d686))

### Features

* **3d-abacus:** change default columns from 13 to 4 ([cd15c70](cd15c70a25))
* add client-side OpenSCAD WASM support for 3D preview ([eaaf17c](eaaf17cd4c))
2025-11-05 14:46:28 +00:00
Thomas Hallock
e0585b8ac7 chore: update pnpm lockfile for openscad-wasm-prebuilt
Add lockfile entries for openscad-wasm-prebuilt package.

This complements commit af9c1add which added the dependency to package.json.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 08:45:02 -06:00
Thomas Hallock
ec887c895c chore: update Claude Code auto-approvals for abacus-react
Add additional auto-approved commands to improve Claude Code workflow:
- git log/tag operations
- pnpm dev server
- biome formatting
- TypeScript compilation
- GitHub API access
- WebSearch and WebFetch
- npm/pnpm package management

These are safe, read-only, or routine development operations.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 08:43:53 -06:00
Thomas Hallock
e08fdfd676 docs: clarify dev server management in Claude Code instructions
Update developer guidelines to be more explicit about dev server handling:
- Add pnpm dev to the list of forbidden commands
- Explicitly forbid killing processes on port 3000
- Emphasize that the user manages the dev server, not Claude Code
- Improve clarity with bold formatting

This prevents Claude Code from interfering with user-managed dev processes.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 08:43:52 -06:00
Thomas Hallock
eaaf17cd4c feat: add client-side OpenSCAD WASM support for 3D preview
Migrate 3D abacus preview generation from server-side OpenSCAD to client-side
WASM execution using web workers.

Changes:
- Add openscad-wasm-prebuilt dependency for browser-based rendering
- Refactor STLPreview to use web worker for non-blocking WASM execution
- Create openscad.worker.ts for isolated 3D model generation
- Add abacus-inline.scad template for parametric abacus generation
- Improve preview debouncing (500ms) and error handling

Benefits:
- No server-side OpenSCAD dependency required
- Faster preview updates (no network roundtrip)
- Better UX with non-blocking worker execution
- Consistent rendering across environments

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 08:43:52 -06:00
Thomas Hallock
32f51ae739 refactor: remove debug console.log statements
Clean up debugging output from production code:
- Remove bead click analysis logging from InteractiveAbacus
- Remove sessionStorage operation logging from HomeHeroContext

These were useful during development but should not be in production.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 08:43:52 -06:00
Thomas Hallock
59d594c939 chore: run biome formatting
Apply automated formatting fixes:
- Add trailing commas for consistency
- Break long lines for readability
- Normalize indentation
- Remove extraneous blank lines

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 08:43:52 -06:00
semantic-release-bot
1db779c49f 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-11-05)

### Features

* **3d-abacus:** change default columns from 13 to 4 ([cd15c70](cd15c70a25))
* **abacus-react:** add AbacusStatic for React Server Components ([3b8e864](3b8e864cfa))
* **abacus-react:** add core utility functions for state management ([e65541c](e65541c100))
* **abacus-react:** add layout and educational props ([35bbcec](35bbcecb9e))
* **abacus-react:** add pre-defined theme presets ([cf1f950](cf1f950c7c))
* **abacus-react:** add React hooks for abacus calculations ([de038d2](de038d2afc))
* **abacus-react:** add separate /static export path for React Server Components ([ed69f6b](ed69f6b917))
* **abacus-react:** add shared dimension calculator for consistent sizing ([e5ba772](e5ba772fde))
* **abacus-react:** export new utilities, hooks, and themes ([ce4e44d](ce4e44d630))
* **abacus:** add nativeAbacusNumbers setting to schema and UI ([79f7347](79f7347d48))
* add 3D printing support for abacus models ([dafdfdd](dafdfdd233))
* add comprehensive metadata, SEO, and make AbacusReact SSR-compatible ([0922ea1](0922ea10b7))
* add comprehensive Storybook coverage and migration guide ([7a4a37e](7a4a37ec6d))
* add game preview system with mock arcade environment ([25880cc](25880cc7e4))
* add per-player stats tracking system ([613301c](613301cd13))
* add Strategy & Tactics section to Rithmomachia guide ([81ead65](81ead65680))
* add unified trophy abacus with hero mode integration ([6620418](6620418a70))
* **arcade:** add ability to deactivate remote players without kicking user ([3628426](3628426a56))
* **arcade:** add native abacus numbers support to pressure gauge ([1d525c7](1d525c7b53))
* **arcade:** add Rithmomachia (Battle of Numbers) game ([2fc0a05](2fc0a05f7f))
* **arcade:** add yjs-demo collaborative game and Yjs persistence layer ([d568955](d568955d6a))
* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add activity feed notifications for collaborative mode ([1461414](1461414ef4))
* **card-sorting:** add auto-submit countdown for perfect sequences ([780a716](780a7161bc))
* **card-sorting:** add bezier curves to connecting arrows ([4d8e873](4d8e873358))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add collapsible stats sidebar for spectators ([6527c26](6527c26a81))
* **card-sorting:** add game mode selector UI to setup phase ([d25b888](d25b888ffb))
* **card-sorting:** add GameMode type system for multiplayer support ([fd76533](fd765335ef))
* **card-sorting:** add green border to correctly positioned cards ([16fca86](16fca86b76)), closes [#22c55](https://github.com/antialias/soroban-abacus-flashcards/issues/22c55)
* **card-sorting:** add player emoji indicators on moving cards ([3a82099](3a82099757))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add smooth transition to drop shadow ([b0b93d0](b0b93d0175))
* **card-sorting:** add spectator mode UI enhancements ([ee7345d](ee7345d641)), closes [#6366f1](https://github.com/antialias/soroban-abacus-flashcards/issues/6366f1) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add team scoring UI for collaborative mode ([ed6f177](ed6f177914)), closes [#a78](https://github.com/antialias/soroban-abacus-flashcards/issues/a78) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **card-sorting:** auto-arrange prefix/suffix cards in corners ([4ba7f24](4ba7f24717))
* **card-sorting:** fade correctly positioned cards to 50% opacity ([7028cfc](7028cfc511))
* **card-sorting:** gentler spring animation for locked cards ([47189cb](47189cb6e7))
* **card-sorting:** implement continuous bezier curve paths ([2d93024](2d9302410f))
* **card-sorting:** improve card distribution for natural scattered look ([0b0503f](0b0503f035))
* **card-sorting:** make player emoji fill entire card background ([2e7a02c](2e7a02c9e4))
* **card-sorting:** optimize results screen for mobile ([d188789](d188789069))
* **card-sorting:** redesign setup screen with modern UI ([73cf967](73cf967492))
* **card-sorting:** scale correctly positioned cards to 50% ([222dc55](222dc555fa))
* **card-sorting:** shrink/fade cards in correct suffix as well ([8f6feec](8f6feec4f2))
* **card-sorting:** smooth spring transition from game table to results grid ([c5f39d5](c5f39d51eb))
* **card-sorting:** wrap prefix/suffix cards to multiple rows ([e3184dd](e3184dd0d4))
* complete 3D enhancement integration for all three proposals ([5ac55cc](5ac55cc149))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* dynamic day-of-month favicon using subprocess pattern ([4d0795a](4d0795a9df))
* dynamically crop favicon to active beads for maximum size ([5670322](567032296a))
* enable 3D enhancement on hero/open MyAbacus modes ([37e330f](37e330f26e))
* **games:** add autoplay and improve carousel layout ([9f51edf](9f51edfaa9))
* **games:** add horizontal scroll support to carousels ([a224abb](a224abb6f6))
* **games:** add rotating games hero carousel ([24231e6](24231e6b2e))
* **i18n:** add dynamic locale switching without page reload ([fe9bfea](fe9bfeabf9))
* **i18n:** add global language selector to navigation ([0506360](0506360117))
* **i18n:** add homepage translations for all supported languages ([8c9d35a](8c9d35a3b4))
* **i18n:** add Old High German (goh) language support ([b334a15](b334a15255))
* **i18n:** complete Old High German translations for all locales ([0b06a1c](0b06a1ce00))
* **i18n:** internationalize games page and tutorial content ([4253964](4253964af1))
* **i18n:** internationalize homepage with English translations ([40cff14](40cff143c7))
* **i18n:** migrate from react-i18next to next-intl ([9016b76](9016b76024))
* **i18n:** update games page hero section copy ([6333c60](6333c60352))
* install embla-carousel-autoplay for games carousel ([946e5d1](946e5d1910))
* install embla-carousel-react for player profile carousel ([642ae95](642ae95738))
* internationalize guide page with 6 languages ([e9c320b](e9c320bb10))
* internationalize tutorial player ([26d41cf](26d41cfd05))
* optimize card sorting for mobile displays ([b443ee9](b443ee9cdc))
* Redesign Rithmomachia setup page with dramatic medieval theme ([6ae4d13](6ae4d13dc7))
* **rithmomachia:** add 80% opacity to guide modal when not hovered ([4a78485](4a78485d2e))
* **rithmomachia:** add CaptureContext for capture dialog state management ([d7eb957](d7eb957a8d))
* **rithmomachia:** add ghost panel preview for guide docking ([c0d6526](c0d6526d30))
* **rithmomachia:** add guide docking with resizable panels ([f457f1a](f457f1a1c2))
* **rithmomachia:** add helper piece selection for mathematical captures ([cae3359](cae3359587))
* **rithmomachia:** add helpful error messages for failed captures ([b172440](b172440a41))
* **rithmomachia:** add initial board visual to guide Overview section ([d42bcff](d42bcff0d9))
* **rithmomachia:** Add interactive playing guide modal ([3121d82](3121d8240a))
* **rithmomachia:** add number bond visualization and helper placeholders ([82d8913](82d89131f0))
* **rithmomachia:** add ratio capture example to guide ([9150b0c](9150b0c678))
* **rithmomachia:** add standalone guide page route ([3fcc79f](3fcc79fe9e))
* **rithmomachia:** add useBoardLayout hook for centralized layout calculations ([27f1c98](27f1c989d5))
* **rithmomachia:** add usePieceSelection hook for selection state management ([275f401](275f401e3c))
* **rithmomachia:** add visual board examples to Capture section ([74bc3c0](74bc3c0dcf))
* **rithmomachia:** add visual board examples to Harmony section ([1d5f01c](1d5f01c966))
* **rithmomachia:** add visual winning example to Victory section ([b7fac78](b7fac78829))
* **rithmomachia:** auto-size tab labels with react-textfit ([9fd5406](9fd54067ce))
* **rithmomachia:** cycle through valid helpers with dynamic number tooltips ([4829e41](4829e41ea1))
* **rithmomachia:** enhance capture relation UI with smooth animations ([0a30801](0a308016e9))
* **rithmomachia:** enhance Harmony section with comprehensive content ([f555856](f5558563ea))
* **rithmomachia:** enhance Pieces section with visual examples and pyramid details ([55aff82](55aff829f4))
* **rithmomachia:** enhance Pyramid section with comprehensive details ([9fde1ef](9fde1ef9e7))
* **rithmomachia:** guide defaults to docked right on open ([11f674d](11f674d542))
* **rithmomachia:** improve guide pieces section layout ([a270bfc](a270bfc0cc))
* **rithmomachia:** improve guide UX and add persistence ([b314740](b314740697))
* **rithmomachia:** improve roster status notice UX ([e27df45](e27df45256))
* **rithmomachia:** integrate roster warning into game nav ([8a11594](8a11594203))
* **rithmomachia:** make guide modal ultra-responsive down to 150px width ([0474197](04741971b2))
* **rithmomachia:** recreate original guide modal header layout ([2489695](24896957d0))
* **rithmomachia:** show capture error on hover instead of click ([339b678](339b6780f6))
* **rithmomachia:** show pyramid face numbers on hover instead of selection ([b0c4523](b0c4523c0b))
* **rithmomachia:** show pyramid face numbers when selected ([5c186f3](5c186f3947))
* **rithmomachia:** show pyramid face numbers when selected with subtle animation ([5c2ddbe](5c2ddbef05))
* **rithmomachia:** show real preview layout when dragging guide to dock ([17d2460](17d2460a87))
* **rithmomachia:** simplify guide language for clarity ([85cb630](85cb630add))
* **rithmomachia:** skip helper selection UI and auto-select first valid helper ([be2a00e](be2a00e8b3))
* **rithmomachia:** Update harmony system to classical three-piece proportions ([08c9762](08c97620f5))
* **rithmomachia:** Update to traditional board setup with 25 pieces per side ([0769eaa](0769eaaa1d))
* **rithmomachia:** use actual piece SVGs in number bond with 2.5s rotation animation ([976a7de](976a7de949))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))
* show rithmomachia turn in nav ([7c89bfe](7c89bfef9c))
* switch to royal color theme with transparent background ([944ad65](944ad6574e)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#f59e0](https://github.com/antialias/soroban-abacus-flashcards/issues/f59e0) [#a855f7](https://github.com/antialias/soroban-abacus-flashcards/issues/a855f7) [#7e22](https://github.com/antialias/soroban-abacus-flashcards/issues/7e22)
* **web:** add test page for AbacusStatic RSC compatibility ([903dea2](903dea2584))
* **web:** add test page for AbacusStatic Server Component ([3588d5a](3588d5acde))
* **web:** add Typst-based preview endpoint with React Suspense ([599a758](599a758471))
* **web:** add year abacus to calendar header and make grid bolder ([867c7ee](867c7ee172)), closes [#333](https://github.com/antialias/soroban-abacus-flashcards/issues/333)
* **web:** improve calendar abacus preview styling ([8439727](8439727b15))
* **web:** optimize monthly calendar for single-page layout ([b277a89](b277a89415))
* **web:** redesign monthly calendar as single composite SVG ([8ce8038](8ce8038bae))

### Bug Fixes

* **abacus-react:** add data-testid attributes back to beads for testing ([23ae1b0](23ae1b0c6f))
* **abacus-react:** correct column highlighting offset in AbacusStatic ([0641eb7](0641eb719e))
* **abacus-react:** fix animations by preventing component remounting ([be7d4c4](be7d4c4713))
* **abacus-react:** restore original AbacusReact measurements and positioning ([88c0baa](88c0baaad9))
* add xmlns to AbacusStatic for Typst SVG parsing ([98cd019](98cd019d4a))
* adjust hero abacus position to avoid covering subtitle ([f03d341](f03d341314))
* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** allow deactivating players from users who left the room ([7c1c2d7](7c1c2d7beb))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* board rotation now properly fills height in portrait mode ([b5a96ea](b5a96eaeb1))
* **card-sorting:** add border radius to outer card container ([a922eba](a922eba73c))
* **card-sorting:** add debug logging for spring animations ([d42947e](d42947eb8d))
* **card-sorting:** add missing gameMode support after hard reset ([a832325](a832325deb))
* **card-sorting:** add missing useMemo import ([949d76d](949d76d844))
* **card-sorting:** add overflow hidden to clip rounded corners ([84c66fe](84c66feec6))
* **card-sorting:** adjust connecting paths for scaled cards ([829c741](829c741e55))
* **card-sorting:** adjust game board for spectator panels ([fc5cf12](fc5cf1216f))
* **card-sorting:** adjust viewport dimensions for spectator panels ([4dce16c](4dce16cca4))
* **card-sorting:** animate cards from game board to results grid ([17d45fe](17d45fe88c))
* **card-sorting:** correct suffix card detection in auto-arrange ([d02ab59](d02ab5922c))
* **card-sorting:** enable card scaling for spectators ([6b095c3](6b095c3383))
* **card-sorting:** enable New Game button during active gameplay ([f3f6eca](f3f6eca1db))
* **card-sorting:** end drag immediately when card becomes locked ([ae45298](ae45298ec4))
* **card-sorting:** filter local player from emoji overlays on dragged cards ([dc2d94a](dc2d94aaa5))
* **card-sorting:** fix results panel layout to not cover cards ([4b4fbfe](4b4fbfef32))
* **card-sorting:** hide activity notifications in spectator mode ([5cca279](5cca279687))
* **card-sorting:** keep arrow sequence numbers upright ([79c9469](79c94699fa))
* **card-sorting:** lock correctly positioned prefix/suffix cards ([170abed](170abed231))
* **card-sorting:** lock spring positions after initial animation completes ([275cc62](275cc62a52))
* **card-sorting:** New Game now restarts with same settings instantly ([f3687ed](f3687ed236))
* **card-sorting:** only shrink/fade cards in correct prefix ([51368c6](51368c6ec5))
* **card-sorting:** preserve card positions on pause/resume ([0d8af09](0d8af09517))
* **card-sorting:** preserve rotation when starting drag ([3364144](3364144fb6))
* **card-sorting:** prevent duplicate START_GAME moves on Play Again ([a0b14f8](a0b14f87e9))
* **card-sorting:** prevent ghost movements with proper optimistic updates ([bd014be](bd014bec4f))
* **card-sorting:** prevent infinite loop when all cards are correct ([34785f4](34785f466f))
* **card-sorting:** prevent infinite loop with tolerance-based position comparison ([627b873](627b873382))
* **card-sorting:** prevent position jump when clicking rotated cards ([564a00f](564a00f82b))
* **card-sorting:** prevent replaying own movements from server ([308168a](308168a7fb))
* **card-sorting:** prevent springs from reinitializing on window resize ([30953b8](30953b8c4a))
* **card-sorting:** prevent springs from resetting after animation ([8aff60c](8aff60ce3f))
* **card-sorting:** remove hasAnimatedRef logic causing backwards animation ([a44aa5a](a44aa5a4c2))
* **card-sorting:** remove remaining reveal numbers references ([15c53ea](15c53ea4eb))
* **card-sorting:** restore prefix/suffix card shrinking visual feedback ([f5fb4d7](f5fb4d7b76))
* **card-sorting:** show only active players in team members section ([fa9f1a5](fa9f1a568f))
* **card-sorting:** smooth scale animation while dragging cards ([0eefc33](0eefc332ac))
* **card-sorting:** stabilize inferred sequence for locked cards during drag ([b0cd194](b0cd194838))
* **card-sorting:** use empty deps array for useSprings to prevent recreation ([cee399e](cee399ed15))
* **card-sorting:** use ref to track initialized state and prevent re-animation ([f389afa](f389afa831))
* **card-sorting:** use same coordinate system for game board and results ([6972fdf](6972fdf110))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* configure favicon metadata and improve bead visibility ([e1369fa](e1369fa275))
* copy entire packages/core and packages/templates ([0ccada0](0ccada0ca7))
* correct hero abacus scroll direction to flow with page content ([4232746](423274657c))
* correct Typst template path in Dockerfile ([4c518de](4c518decb7))
* delete existing user sessions before creating new ones ([0cced47](0cced47a0f))
* **docker:** add scripts, abacus-react, and tsx for production calendar generation ([33eb90e](33eb90e316))
* **docker:** upgrade OpenSCAD to 2024.11 to fix CGAL intersection bug ([e1bcd24](e1bcd24169))
* extract pure SVG content from AbacusReact renders ([b07f1c4](b07f1c4216))
* **games:** prevent horizontal page scroll from carousel overflow ([5a8c98f](5a8c98fc10))
* **games:** smooth scroll feel for carousel wheel navigation ([f80a73b](f80a73b35c))
* **games:** use specific transition properties for smooth carousel loop ([187271e](187271e515))
* **guide:** increase abacus sizes - they were too small ([1074624](1074624b2f))
* **guide:** make abacus sizes consistent and add nav spacing ([bea4842](bea4842a29))
* **guide:** remove inner containers and tighten margins ([7e54c6f](7e54c6f4fc))
* **i18n:** eliminate FOUC by loading messages server-side ([4d4d930](4d4d930bd3))
* **i18n:** use useMessages() for tutorial translations ([95b0105](95b0105ca3))
* include column posts in favicon bounding box ([0b2f481](0b2f48106a))
* increase server update debounce to 2000ms for low bandwidth ([633ff12](633ff12750))
* Integrate threshold input into Point Victory card ([b29bbee](b29bbeefca))
* **layout:** add systematic spacing for fixed nav bar ([4559fb1](4559fb121d))
* **layout:** remove wrapper, use utility class for nav spacing ([247c3d9](247c3d9874))
* mark dynamic routes as force-dynamic to prevent static generation errors ([d7b35d9](d7b35d9544))
* **nav:** restrict transparent hero styling to home page only ([fab227d](fab227d686))
* **nav:** show full navigation on /games page ([d3fe6ac](d3fe6acbb0))
* **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))
* reduce padding to minimize gap below last bead ([0e529be](0e529be789))
* remove distracting parallax and wobble 3D effects ([28a2d40](28a2d40996))
* remove wobble physics and enhance wood grain visibility ([5d97673](5d97673406))
* resolve z-index layering and hero abacus visibility issues ([ed9a050](ed9a050d64))
* rewrite 3D stories to use props instead of CSS wrappers ([26bdb11](26bdb11237))
* **rithmomachia:** add missing i18next dependencies ([91154d9](91154d9364))
* **rithmomachia:** add missing pyramid section keys to Japanese (ja.json) ([dae615e](dae615ee72))
* **rithmomachia:** adjust error dialog sizing to prevent text clipping ([cda1126](cda1126cb0))
* **rithmomachia:** adjust roster notice position to not overlap nav ([7093223](709322373a))
* **rithmomachia:** change undock icon to pop-out arrow ([2a91748](2a91748493))
* **rithmomachia:** correct board dimensions to 16x8 and restore original layout values ([cfac277](cfac277505))
* **rithmomachia:** Correct board setup to match reference image exactly ([618e563](618e56358d))
* **rithmomachia:** correct makeMove parameter types for capture handling ([aafb64f](aafb64f3e3))
* **rithmomachia:** fix guide modal resize drift by calculating from initial state ([1bcd99c](1bcd99c949))
* **rithmomachia:** fix harmony section translation structure for hi/ja/es ([14259a1](14259a19a9))
* **rithmomachia:** fix modal resizing zoom issue ([4fa20f4](4fa20f44cb))
* **rithmomachia:** Fix TypeScript errors in playing guide modal ([4834ece](4834ece98e))
* **rithmomachia:** handle pyramid pieces in hover error tooltip ([56f3164](56f3164155))
* **rithmomachia:** implement proper board cropping and highlighting in guide ([d0a8fcd](d0a8fcdea6))
* **rithmomachia:** improve guide modal tab navigation at narrow widths ([a673177](a673177bec))
* **rithmomachia:** reconnect player assignment UI and fix setup layout ([a1a0374](a1a0374fac))
* **rithmomachia:** render guide as docked in preview panel ([190f8cf](190f8cf302))
* **rithmomachia:** show actual values in tooltips for non-helper relations ([774c6b0](774c6b0ce7))
* **rithmomachia:** show guest-friendly message when they can't fix too many players ([54bfd2f](54bfd2fac8))
* **rithmomachia:** smooth guide dragging from docked state without jump ([8f4a79c](8f4a79c9b0))
* **rithmomachia:** validate move path before showing capture error on hover ([bd49964](bd49964186))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))
* separate horizontal and vertical bounding box logic ([83090df](83090df4df))
* tolerate OpenSCAD CGAL warnings if output file is created ([88993f3](88993f3662))
* **tutorial:** correct column validation for bead highlights ([9ba1824](9ba1824226))
* **tutorial:** fix overlay rendering, arrow indicators, and bead visibility ([a804316](a80431608d))
* use absolute positioning for hero abacus to eliminate scroll lag ([096104b](096104b094))
* use Debian base for deps stage to match runner for binary compatibility ([f8fe6e4](f8fe6e4a41))
* use default BOSL2 branch instead of non-existent v2.0.0 tag ([f4ffc5b](f4ffc5b027))
* use nested SVG viewBox for actual cropping, not just scaling ([440b492](440b492e85))
* various game improvements and UI enhancements ([b67cf61](b67cf610c5))
* **web,docker:** add --format flag for Typst and upgrade to v0.13.0 ([19b9d7a](19b9d7a74f))
* **web:** add dynamic export to rithmomachia page ([329e623](329e623212))
* **web:** fix Typst PDF generation path resolution ([7ce1287](7ce1287525))
* **web:** generate styled-system artifacts during build ([293390a](293390ae35))
* **web:** move react-dom/server import to API route to satisfy Next.js ([00a8bc3](00a8bc3e5e))
* **web:** move tsx to production dependencies for calendar generation ([ffae9c1](ffae9c1bdb))
* **web:** prevent abacus overlap in composite calendar ([448f93c](448f93c1e2)), closes [#f0f0f0](https://github.com/antialias/soroban-abacus-flashcards/issues/f0f0f0)
* **web:** use AbacusStatic for calendar SVG generation ([08c6a41](08c6a419e2))
* **web:** use dynamic import for react-dom/server in API route ([4f93c7d](4f93c7d996))
* **web:** use nested SVG elements to prevent coordinate space conflicts ([f9cbee8](f9cbee8fcd))

### Performance Improvements

* optimize Docker image size to reduce build failures ([9ca3106](9ca3106361))

### Code Refactoring

* **card-sorting:** remove reveal numbers feature ([ea5e3e8](ea5e3e838b))
* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))
* **games:** implement carousel, fix victories bug, add conditional stats ([82c133f](82c133f742))
* **games:** move page title to nav bar ([712ee58](712ee58e59))
* **games:** remove redundant subtitle below nav ([ad5bb87](ad5bb87325))
* **games:** remove wheel scrolling, enable overflow visible carousel ([876513c](876513c9cc))
* **layout:** make nav height truly self-referential ([9886302](98863026b7))
* reorganize Harmony and Victory guide sections ([fb629c4](fb629c44ea))
* restructure /create page into hub with sub-pages ([b91b23d](b91b23d95f))
* **rithmomachia:** extract board and capture components (phase 2+3) ([a0a867b](a0a867b271))
* **rithmomachia:** extract CaptureErrorDialog component (Phase 2 partial) ([f0a066d](f0a066d8f0))
* **rithmomachia:** extract constants and coordinate utilities (Phase 1) ([eace0ed](eace0ed529))
* **rithmomachia:** extract guide sections into separate files ([765525d](765525dc45))
* **rithmomachia:** extract hooks (phase 5) ([324a659](324a65992f))
* **rithmomachia:** extract phase components (phase 4) ([11364f6](11364f6394))
* **rithmomachia:** extract reusable components from SetupPhase ([3abc325](3abc325ea2))
* **rithmomachia:** make setup phase UI more compact ([e55f848](e55f848a26))
* **rithmomachia:** redesign error notification with modern UI ([dfeeb0e](dfeeb0e0db)), closes [#1e293](https://github.com/antialias/soroban-abacus-flashcards/issues/1e293) [#0f172](https://github.com/antialias/soroban-abacus-flashcards/issues/0f172) [#f1f5f9](https://github.com/antialias/soroban-abacus-flashcards/issues/f1f5f9)
* **rithmomachia:** simplify capture error dialog to one-liner ([82a5eb2](82a5eb2e4b))
* **rithmomachia:** Update board setup to authoritative CSV layout ([0471da5](0471da598d))
* **rithmomachia:** update capture components to use CaptureContext ([2ab6ab5](2ab6ab5799))
* **rithmomachia:** use useBoardLayout and usePieceSelection in BoardDisplay ([0ab7a1d](0ab7a1df32))
* use AbacusReact for dynamic Open Graph image ([9c20f12](9c20f12bac))
* **web:** import utility functions from abacus-react ([7228bbc](7228bbc2eb))
* **web:** move calendar generators to src/utils for proper compilation ([379698f](379698fea3))
* **web:** return calendar SVG preview with PDF generation ([14a5de0](14a5de0dfa))
* **web:** use ABACUS_THEMES instead of manual style definitions ([9f7f001](9f7f001d74))
* **web:** use client-side React rendering for live calendar preview ([f880cbe](f880cbe4bf))
* **web:** use compact prop for inline mini-abacus ([ff1d60a](ff1d60a233))
* **web:** use direct function imports instead of execSync for calendar generation ([9f1715f](9f1715f085))
* **web:** use stdin/stdout for Typst compilation ([06f68cc](06f68cc74c))

### Documentation

* **abacus-react:** add Storybook stories for AbacusStatic ([4f9dc46](4f9dc4666d))
* **abacus-react:** add Storybook stories for new features ([6a1cec0](6a1cec06a7))
* **abacus-react:** export AbacusStatic and update README ([74f2d97](74f2d97434))
* **abacus-react:** update documentation for new features ([35d8734](35d8734a3a))
* **abacus-react:** update README with /static import path for RSC ([72a4c2b](72a4c2b80c))
* add 3D enhancement documentation to README ([cc96802](cc96802df8))
* add critical section on never adding tsx to production dependencies ([770cfc3](770cfc3aca))
* add database migration guide and playing guide modal spec ([5a29af7](5a29af78e2))
* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* **card-sorting:** add comprehensive multiplayer plan ([008ccea](008ccead0f))
* **rithmomachia:** Add concise one-page playing guide ([e3c1f10](e3c1f10233))
* update workflow to require manual testing before commits ([0991796](0991796f1e))

### Styles

* **rithmomachia:** improve divider styling and make tabs responsive ([88ca35e](88ca35e044)), closes [#e5e7](https://github.com/antialias/soroban-abacus-flashcards/issues/e5e7) [#9ca3](https://github.com/antialias/soroban-abacus-flashcards/issues/9ca3)
* **rithmomachia:** improve pyramid face numbers visibility and contrast ([94e5e6a](94e5e6a268)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#b45309](https://github.com/antialias/soroban-abacus-flashcards/issues/b45309)
* **rithmomachia:** increase pyramid face numbers size and boldness ([7bf2d73](7bf2d730d3))

### Tests

* trigger compose-updater deployment test ([2b06aae](2b06aae394))
* verify compose-updater automatic deployment cycle ([af0552c](af0552ccd9))
2025-11-05 02:02:24 +00:00
Thomas Hallock
cd15c70a25 feat(3d-abacus): change default columns from 13 to 4
4 columns is a more practical default for initial preview and printing.
13 columns produces very large files and takes longer to render.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 19:57:51 -06:00
semantic-release-bot
602c648adc 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-11-05)

### Features

* **abacus-react:** add AbacusStatic for React Server Components ([3b8e864](3b8e864cfa))
* **abacus-react:** add core utility functions for state management ([e65541c](e65541c100))
* **abacus-react:** add layout and educational props ([35bbcec](35bbcecb9e))
* **abacus-react:** add pre-defined theme presets ([cf1f950](cf1f950c7c))
* **abacus-react:** add React hooks for abacus calculations ([de038d2](de038d2afc))
* **abacus-react:** add separate /static export path for React Server Components ([ed69f6b](ed69f6b917))
* **abacus-react:** add shared dimension calculator for consistent sizing ([e5ba772](e5ba772fde))
* **abacus-react:** export new utilities, hooks, and themes ([ce4e44d](ce4e44d630))
* **abacus:** add nativeAbacusNumbers setting to schema and UI ([79f7347](79f7347d48))
* add 3D printing support for abacus models ([dafdfdd](dafdfdd233))
* add comprehensive metadata, SEO, and make AbacusReact SSR-compatible ([0922ea1](0922ea10b7))
* add comprehensive Storybook coverage and migration guide ([7a4a37e](7a4a37ec6d))
* add game preview system with mock arcade environment ([25880cc](25880cc7e4))
* add per-player stats tracking system ([613301c](613301cd13))
* add Strategy & Tactics section to Rithmomachia guide ([81ead65](81ead65680))
* add unified trophy abacus with hero mode integration ([6620418](6620418a70))
* **arcade:** add ability to deactivate remote players without kicking user ([3628426](3628426a56))
* **arcade:** add native abacus numbers support to pressure gauge ([1d525c7](1d525c7b53))
* **arcade:** add Rithmomachia (Battle of Numbers) game ([2fc0a05](2fc0a05f7f))
* **arcade:** add yjs-demo collaborative game and Yjs persistence layer ([d568955](d568955d6a))
* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add activity feed notifications for collaborative mode ([1461414](1461414ef4))
* **card-sorting:** add auto-submit countdown for perfect sequences ([780a716](780a7161bc))
* **card-sorting:** add bezier curves to connecting arrows ([4d8e873](4d8e873358))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add collapsible stats sidebar for spectators ([6527c26](6527c26a81))
* **card-sorting:** add game mode selector UI to setup phase ([d25b888](d25b888ffb))
* **card-sorting:** add GameMode type system for multiplayer support ([fd76533](fd765335ef))
* **card-sorting:** add green border to correctly positioned cards ([16fca86](16fca86b76)), closes [#22c55](https://github.com/antialias/soroban-abacus-flashcards/issues/22c55)
* **card-sorting:** add player emoji indicators on moving cards ([3a82099](3a82099757))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add smooth transition to drop shadow ([b0b93d0](b0b93d0175))
* **card-sorting:** add spectator mode UI enhancements ([ee7345d](ee7345d641)), closes [#6366f1](https://github.com/antialias/soroban-abacus-flashcards/issues/6366f1) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add team scoring UI for collaborative mode ([ed6f177](ed6f177914)), closes [#a78](https://github.com/antialias/soroban-abacus-flashcards/issues/a78) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **card-sorting:** auto-arrange prefix/suffix cards in corners ([4ba7f24](4ba7f24717))
* **card-sorting:** fade correctly positioned cards to 50% opacity ([7028cfc](7028cfc511))
* **card-sorting:** gentler spring animation for locked cards ([47189cb](47189cb6e7))
* **card-sorting:** implement continuous bezier curve paths ([2d93024](2d9302410f))
* **card-sorting:** improve card distribution for natural scattered look ([0b0503f](0b0503f035))
* **card-sorting:** make player emoji fill entire card background ([2e7a02c](2e7a02c9e4))
* **card-sorting:** optimize results screen for mobile ([d188789](d188789069))
* **card-sorting:** redesign setup screen with modern UI ([73cf967](73cf967492))
* **card-sorting:** scale correctly positioned cards to 50% ([222dc55](222dc555fa))
* **card-sorting:** shrink/fade cards in correct suffix as well ([8f6feec](8f6feec4f2))
* **card-sorting:** smooth spring transition from game table to results grid ([c5f39d5](c5f39d51eb))
* **card-sorting:** wrap prefix/suffix cards to multiple rows ([e3184dd](e3184dd0d4))
* complete 3D enhancement integration for all three proposals ([5ac55cc](5ac55cc149))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* dynamic day-of-month favicon using subprocess pattern ([4d0795a](4d0795a9df))
* dynamically crop favicon to active beads for maximum size ([5670322](567032296a))
* enable 3D enhancement on hero/open MyAbacus modes ([37e330f](37e330f26e))
* **games:** add autoplay and improve carousel layout ([9f51edf](9f51edfaa9))
* **games:** add horizontal scroll support to carousels ([a224abb](a224abb6f6))
* **games:** add rotating games hero carousel ([24231e6](24231e6b2e))
* **i18n:** add dynamic locale switching without page reload ([fe9bfea](fe9bfeabf9))
* **i18n:** add global language selector to navigation ([0506360](0506360117))
* **i18n:** add homepage translations for all supported languages ([8c9d35a](8c9d35a3b4))
* **i18n:** add Old High German (goh) language support ([b334a15](b334a15255))
* **i18n:** complete Old High German translations for all locales ([0b06a1c](0b06a1ce00))
* **i18n:** internationalize games page and tutorial content ([4253964](4253964af1))
* **i18n:** internationalize homepage with English translations ([40cff14](40cff143c7))
* **i18n:** migrate from react-i18next to next-intl ([9016b76](9016b76024))
* **i18n:** update games page hero section copy ([6333c60](6333c60352))
* install embla-carousel-autoplay for games carousel ([946e5d1](946e5d1910))
* install embla-carousel-react for player profile carousel ([642ae95](642ae95738))
* internationalize guide page with 6 languages ([e9c320b](e9c320bb10))
* internationalize tutorial player ([26d41cf](26d41cfd05))
* optimize card sorting for mobile displays ([b443ee9](b443ee9cdc))
* Redesign Rithmomachia setup page with dramatic medieval theme ([6ae4d13](6ae4d13dc7))
* **rithmomachia:** add 80% opacity to guide modal when not hovered ([4a78485](4a78485d2e))
* **rithmomachia:** add CaptureContext for capture dialog state management ([d7eb957](d7eb957a8d))
* **rithmomachia:** add ghost panel preview for guide docking ([c0d6526](c0d6526d30))
* **rithmomachia:** add guide docking with resizable panels ([f457f1a](f457f1a1c2))
* **rithmomachia:** add helper piece selection for mathematical captures ([cae3359](cae3359587))
* **rithmomachia:** add helpful error messages for failed captures ([b172440](b172440a41))
* **rithmomachia:** add initial board visual to guide Overview section ([d42bcff](d42bcff0d9))
* **rithmomachia:** Add interactive playing guide modal ([3121d82](3121d8240a))
* **rithmomachia:** add number bond visualization and helper placeholders ([82d8913](82d89131f0))
* **rithmomachia:** add ratio capture example to guide ([9150b0c](9150b0c678))
* **rithmomachia:** add standalone guide page route ([3fcc79f](3fcc79fe9e))
* **rithmomachia:** add useBoardLayout hook for centralized layout calculations ([27f1c98](27f1c989d5))
* **rithmomachia:** add usePieceSelection hook for selection state management ([275f401](275f401e3c))
* **rithmomachia:** add visual board examples to Capture section ([74bc3c0](74bc3c0dcf))
* **rithmomachia:** add visual board examples to Harmony section ([1d5f01c](1d5f01c966))
* **rithmomachia:** add visual winning example to Victory section ([b7fac78](b7fac78829))
* **rithmomachia:** auto-size tab labels with react-textfit ([9fd5406](9fd54067ce))
* **rithmomachia:** cycle through valid helpers with dynamic number tooltips ([4829e41](4829e41ea1))
* **rithmomachia:** enhance capture relation UI with smooth animations ([0a30801](0a308016e9))
* **rithmomachia:** enhance Harmony section with comprehensive content ([f555856](f5558563ea))
* **rithmomachia:** enhance Pieces section with visual examples and pyramid details ([55aff82](55aff829f4))
* **rithmomachia:** enhance Pyramid section with comprehensive details ([9fde1ef](9fde1ef9e7))
* **rithmomachia:** guide defaults to docked right on open ([11f674d](11f674d542))
* **rithmomachia:** improve guide pieces section layout ([a270bfc](a270bfc0cc))
* **rithmomachia:** improve guide UX and add persistence ([b314740](b314740697))
* **rithmomachia:** improve roster status notice UX ([e27df45](e27df45256))
* **rithmomachia:** integrate roster warning into game nav ([8a11594](8a11594203))
* **rithmomachia:** make guide modal ultra-responsive down to 150px width ([0474197](04741971b2))
* **rithmomachia:** recreate original guide modal header layout ([2489695](24896957d0))
* **rithmomachia:** show capture error on hover instead of click ([339b678](339b6780f6))
* **rithmomachia:** show pyramid face numbers on hover instead of selection ([b0c4523](b0c4523c0b))
* **rithmomachia:** show pyramid face numbers when selected ([5c186f3](5c186f3947))
* **rithmomachia:** show pyramid face numbers when selected with subtle animation ([5c2ddbe](5c2ddbef05))
* **rithmomachia:** show real preview layout when dragging guide to dock ([17d2460](17d2460a87))
* **rithmomachia:** simplify guide language for clarity ([85cb630](85cb630add))
* **rithmomachia:** skip helper selection UI and auto-select first valid helper ([be2a00e](be2a00e8b3))
* **rithmomachia:** Update harmony system to classical three-piece proportions ([08c9762](08c97620f5))
* **rithmomachia:** Update to traditional board setup with 25 pieces per side ([0769eaa](0769eaaa1d))
* **rithmomachia:** use actual piece SVGs in number bond with 2.5s rotation animation ([976a7de](976a7de949))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))
* show rithmomachia turn in nav ([7c89bfe](7c89bfef9c))
* switch to royal color theme with transparent background ([944ad65](944ad6574e)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#f59e0](https://github.com/antialias/soroban-abacus-flashcards/issues/f59e0) [#a855f7](https://github.com/antialias/soroban-abacus-flashcards/issues/a855f7) [#7e22](https://github.com/antialias/soroban-abacus-flashcards/issues/7e22)
* **web:** add test page for AbacusStatic RSC compatibility ([903dea2](903dea2584))
* **web:** add test page for AbacusStatic Server Component ([3588d5a](3588d5acde))
* **web:** add Typst-based preview endpoint with React Suspense ([599a758](599a758471))
* **web:** add year abacus to calendar header and make grid bolder ([867c7ee](867c7ee172)), closes [#333](https://github.com/antialias/soroban-abacus-flashcards/issues/333)
* **web:** improve calendar abacus preview styling ([8439727](8439727b15))
* **web:** optimize monthly calendar for single-page layout ([b277a89](b277a89415))
* **web:** redesign monthly calendar as single composite SVG ([8ce8038](8ce8038bae))

### Bug Fixes

* **abacus-react:** add data-testid attributes back to beads for testing ([23ae1b0](23ae1b0c6f))
* **abacus-react:** correct column highlighting offset in AbacusStatic ([0641eb7](0641eb719e))
* **abacus-react:** fix animations by preventing component remounting ([be7d4c4](be7d4c4713))
* **abacus-react:** restore original AbacusReact measurements and positioning ([88c0baa](88c0baaad9))
* add xmlns to AbacusStatic for Typst SVG parsing ([98cd019](98cd019d4a))
* adjust hero abacus position to avoid covering subtitle ([f03d341](f03d341314))
* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** allow deactivating players from users who left the room ([7c1c2d7](7c1c2d7beb))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* board rotation now properly fills height in portrait mode ([b5a96ea](b5a96eaeb1))
* **card-sorting:** add border radius to outer card container ([a922eba](a922eba73c))
* **card-sorting:** add debug logging for spring animations ([d42947e](d42947eb8d))
* **card-sorting:** add missing gameMode support after hard reset ([a832325](a832325deb))
* **card-sorting:** add missing useMemo import ([949d76d](949d76d844))
* **card-sorting:** add overflow hidden to clip rounded corners ([84c66fe](84c66feec6))
* **card-sorting:** adjust connecting paths for scaled cards ([829c741](829c741e55))
* **card-sorting:** adjust game board for spectator panels ([fc5cf12](fc5cf1216f))
* **card-sorting:** adjust viewport dimensions for spectator panels ([4dce16c](4dce16cca4))
* **card-sorting:** animate cards from game board to results grid ([17d45fe](17d45fe88c))
* **card-sorting:** correct suffix card detection in auto-arrange ([d02ab59](d02ab5922c))
* **card-sorting:** enable card scaling for spectators ([6b095c3](6b095c3383))
* **card-sorting:** enable New Game button during active gameplay ([f3f6eca](f3f6eca1db))
* **card-sorting:** end drag immediately when card becomes locked ([ae45298](ae45298ec4))
* **card-sorting:** filter local player from emoji overlays on dragged cards ([dc2d94a](dc2d94aaa5))
* **card-sorting:** fix results panel layout to not cover cards ([4b4fbfe](4b4fbfef32))
* **card-sorting:** hide activity notifications in spectator mode ([5cca279](5cca279687))
* **card-sorting:** keep arrow sequence numbers upright ([79c9469](79c94699fa))
* **card-sorting:** lock correctly positioned prefix/suffix cards ([170abed](170abed231))
* **card-sorting:** lock spring positions after initial animation completes ([275cc62](275cc62a52))
* **card-sorting:** New Game now restarts with same settings instantly ([f3687ed](f3687ed236))
* **card-sorting:** only shrink/fade cards in correct prefix ([51368c6](51368c6ec5))
* **card-sorting:** preserve card positions on pause/resume ([0d8af09](0d8af09517))
* **card-sorting:** preserve rotation when starting drag ([3364144](3364144fb6))
* **card-sorting:** prevent duplicate START_GAME moves on Play Again ([a0b14f8](a0b14f87e9))
* **card-sorting:** prevent ghost movements with proper optimistic updates ([bd014be](bd014bec4f))
* **card-sorting:** prevent infinite loop when all cards are correct ([34785f4](34785f466f))
* **card-sorting:** prevent infinite loop with tolerance-based position comparison ([627b873](627b873382))
* **card-sorting:** prevent position jump when clicking rotated cards ([564a00f](564a00f82b))
* **card-sorting:** prevent replaying own movements from server ([308168a](308168a7fb))
* **card-sorting:** prevent springs from reinitializing on window resize ([30953b8](30953b8c4a))
* **card-sorting:** prevent springs from resetting after animation ([8aff60c](8aff60ce3f))
* **card-sorting:** remove hasAnimatedRef logic causing backwards animation ([a44aa5a](a44aa5a4c2))
* **card-sorting:** remove remaining reveal numbers references ([15c53ea](15c53ea4eb))
* **card-sorting:** restore prefix/suffix card shrinking visual feedback ([f5fb4d7](f5fb4d7b76))
* **card-sorting:** show only active players in team members section ([fa9f1a5](fa9f1a568f))
* **card-sorting:** smooth scale animation while dragging cards ([0eefc33](0eefc332ac))
* **card-sorting:** stabilize inferred sequence for locked cards during drag ([b0cd194](b0cd194838))
* **card-sorting:** use empty deps array for useSprings to prevent recreation ([cee399e](cee399ed15))
* **card-sorting:** use ref to track initialized state and prevent re-animation ([f389afa](f389afa831))
* **card-sorting:** use same coordinate system for game board and results ([6972fdf](6972fdf110))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* configure favicon metadata and improve bead visibility ([e1369fa](e1369fa275))
* copy entire packages/core and packages/templates ([0ccada0](0ccada0ca7))
* correct hero abacus scroll direction to flow with page content ([4232746](423274657c))
* correct Typst template path in Dockerfile ([4c518de](4c518decb7))
* delete existing user sessions before creating new ones ([0cced47](0cced47a0f))
* **docker:** add scripts, abacus-react, and tsx for production calendar generation ([33eb90e](33eb90e316))
* **docker:** upgrade OpenSCAD to 2024.11 to fix CGAL intersection bug ([e1bcd24](e1bcd24169))
* extract pure SVG content from AbacusReact renders ([b07f1c4](b07f1c4216))
* **games:** prevent horizontal page scroll from carousel overflow ([5a8c98f](5a8c98fc10))
* **games:** smooth scroll feel for carousel wheel navigation ([f80a73b](f80a73b35c))
* **games:** use specific transition properties for smooth carousel loop ([187271e](187271e515))
* **guide:** increase abacus sizes - they were too small ([1074624](1074624b2f))
* **guide:** make abacus sizes consistent and add nav spacing ([bea4842](bea4842a29))
* **guide:** remove inner containers and tighten margins ([7e54c6f](7e54c6f4fc))
* **i18n:** eliminate FOUC by loading messages server-side ([4d4d930](4d4d930bd3))
* **i18n:** use useMessages() for tutorial translations ([95b0105](95b0105ca3))
* include column posts in favicon bounding box ([0b2f481](0b2f48106a))
* increase server update debounce to 2000ms for low bandwidth ([633ff12](633ff12750))
* Integrate threshold input into Point Victory card ([b29bbee](b29bbeefca))
* **layout:** add systematic spacing for fixed nav bar ([4559fb1](4559fb121d))
* **layout:** remove wrapper, use utility class for nav spacing ([247c3d9](247c3d9874))
* mark dynamic routes as force-dynamic to prevent static generation errors ([d7b35d9](d7b35d9544))
* **nav:** restrict transparent hero styling to home page only ([fab227d](fab227d686))
* **nav:** show full navigation on /games page ([d3fe6ac](d3fe6acbb0))
* **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))
* reduce padding to minimize gap below last bead ([0e529be](0e529be789))
* remove distracting parallax and wobble 3D effects ([28a2d40](28a2d40996))
* remove wobble physics and enhance wood grain visibility ([5d97673](5d97673406))
* resolve z-index layering and hero abacus visibility issues ([ed9a050](ed9a050d64))
* rewrite 3D stories to use props instead of CSS wrappers ([26bdb11](26bdb11237))
* **rithmomachia:** add missing i18next dependencies ([91154d9](91154d9364))
* **rithmomachia:** add missing pyramid section keys to Japanese (ja.json) ([dae615e](dae615ee72))
* **rithmomachia:** adjust error dialog sizing to prevent text clipping ([cda1126](cda1126cb0))
* **rithmomachia:** adjust roster notice position to not overlap nav ([7093223](709322373a))
* **rithmomachia:** change undock icon to pop-out arrow ([2a91748](2a91748493))
* **rithmomachia:** correct board dimensions to 16x8 and restore original layout values ([cfac277](cfac277505))
* **rithmomachia:** Correct board setup to match reference image exactly ([618e563](618e56358d))
* **rithmomachia:** correct makeMove parameter types for capture handling ([aafb64f](aafb64f3e3))
* **rithmomachia:** fix guide modal resize drift by calculating from initial state ([1bcd99c](1bcd99c949))
* **rithmomachia:** fix harmony section translation structure for hi/ja/es ([14259a1](14259a19a9))
* **rithmomachia:** fix modal resizing zoom issue ([4fa20f4](4fa20f44cb))
* **rithmomachia:** Fix TypeScript errors in playing guide modal ([4834ece](4834ece98e))
* **rithmomachia:** handle pyramid pieces in hover error tooltip ([56f3164](56f3164155))
* **rithmomachia:** implement proper board cropping and highlighting in guide ([d0a8fcd](d0a8fcdea6))
* **rithmomachia:** improve guide modal tab navigation at narrow widths ([a673177](a673177bec))
* **rithmomachia:** reconnect player assignment UI and fix setup layout ([a1a0374](a1a0374fac))
* **rithmomachia:** render guide as docked in preview panel ([190f8cf](190f8cf302))
* **rithmomachia:** show actual values in tooltips for non-helper relations ([774c6b0](774c6b0ce7))
* **rithmomachia:** show guest-friendly message when they can't fix too many players ([54bfd2f](54bfd2fac8))
* **rithmomachia:** smooth guide dragging from docked state without jump ([8f4a79c](8f4a79c9b0))
* **rithmomachia:** validate move path before showing capture error on hover ([bd49964](bd49964186))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))
* separate horizontal and vertical bounding box logic ([83090df](83090df4df))
* tolerate OpenSCAD CGAL warnings if output file is created ([88993f3](88993f3662))
* **tutorial:** correct column validation for bead highlights ([9ba1824](9ba1824226))
* **tutorial:** fix overlay rendering, arrow indicators, and bead visibility ([a804316](a80431608d))
* use absolute positioning for hero abacus to eliminate scroll lag ([096104b](096104b094))
* use Debian base for deps stage to match runner for binary compatibility ([f8fe6e4](f8fe6e4a41))
* use default BOSL2 branch instead of non-existent v2.0.0 tag ([f4ffc5b](f4ffc5b027))
* use nested SVG viewBox for actual cropping, not just scaling ([440b492](440b492e85))
* various game improvements and UI enhancements ([b67cf61](b67cf610c5))
* **web,docker:** add --format flag for Typst and upgrade to v0.13.0 ([19b9d7a](19b9d7a74f))
* **web:** add dynamic export to rithmomachia page ([329e623](329e623212))
* **web:** fix Typst PDF generation path resolution ([7ce1287](7ce1287525))
* **web:** generate styled-system artifacts during build ([293390a](293390ae35))
* **web:** move react-dom/server import to API route to satisfy Next.js ([00a8bc3](00a8bc3e5e))
* **web:** move tsx to production dependencies for calendar generation ([ffae9c1](ffae9c1bdb))
* **web:** prevent abacus overlap in composite calendar ([448f93c](448f93c1e2)), closes [#f0f0f0](https://github.com/antialias/soroban-abacus-flashcards/issues/f0f0f0)
* **web:** use AbacusStatic for calendar SVG generation ([08c6a41](08c6a419e2))
* **web:** use dynamic import for react-dom/server in API route ([4f93c7d](4f93c7d996))
* **web:** use nested SVG elements to prevent coordinate space conflicts ([f9cbee8](f9cbee8fcd))

### Performance Improvements

* optimize Docker image size to reduce build failures ([9ca3106](9ca3106361))

### Code Refactoring

* **card-sorting:** remove reveal numbers feature ([ea5e3e8](ea5e3e838b))
* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))
* **games:** implement carousel, fix victories bug, add conditional stats ([82c133f](82c133f742))
* **games:** move page title to nav bar ([712ee58](712ee58e59))
* **games:** remove redundant subtitle below nav ([ad5bb87](ad5bb87325))
* **games:** remove wheel scrolling, enable overflow visible carousel ([876513c](876513c9cc))
* **layout:** make nav height truly self-referential ([9886302](98863026b7))
* reorganize Harmony and Victory guide sections ([fb629c4](fb629c44ea))
* restructure /create page into hub with sub-pages ([b91b23d](b91b23d95f))
* **rithmomachia:** extract board and capture components (phase 2+3) ([a0a867b](a0a867b271))
* **rithmomachia:** extract CaptureErrorDialog component (Phase 2 partial) ([f0a066d](f0a066d8f0))
* **rithmomachia:** extract constants and coordinate utilities (Phase 1) ([eace0ed](eace0ed529))
* **rithmomachia:** extract guide sections into separate files ([765525d](765525dc45))
* **rithmomachia:** extract hooks (phase 5) ([324a659](324a65992f))
* **rithmomachia:** extract phase components (phase 4) ([11364f6](11364f6394))
* **rithmomachia:** extract reusable components from SetupPhase ([3abc325](3abc325ea2))
* **rithmomachia:** make setup phase UI more compact ([e55f848](e55f848a26))
* **rithmomachia:** redesign error notification with modern UI ([dfeeb0e](dfeeb0e0db)), closes [#1e293](https://github.com/antialias/soroban-abacus-flashcards/issues/1e293) [#0f172](https://github.com/antialias/soroban-abacus-flashcards/issues/0f172) [#f1f5f9](https://github.com/antialias/soroban-abacus-flashcards/issues/f1f5f9)
* **rithmomachia:** simplify capture error dialog to one-liner ([82a5eb2](82a5eb2e4b))
* **rithmomachia:** Update board setup to authoritative CSV layout ([0471da5](0471da598d))
* **rithmomachia:** update capture components to use CaptureContext ([2ab6ab5](2ab6ab5799))
* **rithmomachia:** use useBoardLayout and usePieceSelection in BoardDisplay ([0ab7a1d](0ab7a1df32))
* use AbacusReact for dynamic Open Graph image ([9c20f12](9c20f12bac))
* **web:** import utility functions from abacus-react ([7228bbc](7228bbc2eb))
* **web:** move calendar generators to src/utils for proper compilation ([379698f](379698fea3))
* **web:** return calendar SVG preview with PDF generation ([14a5de0](14a5de0dfa))
* **web:** use ABACUS_THEMES instead of manual style definitions ([9f7f001](9f7f001d74))
* **web:** use client-side React rendering for live calendar preview ([f880cbe](f880cbe4bf))
* **web:** use compact prop for inline mini-abacus ([ff1d60a](ff1d60a233))
* **web:** use direct function imports instead of execSync for calendar generation ([9f1715f](9f1715f085))
* **web:** use stdin/stdout for Typst compilation ([06f68cc](06f68cc74c))

### Documentation

* **abacus-react:** add Storybook stories for AbacusStatic ([4f9dc46](4f9dc4666d))
* **abacus-react:** add Storybook stories for new features ([6a1cec0](6a1cec06a7))
* **abacus-react:** export AbacusStatic and update README ([74f2d97](74f2d97434))
* **abacus-react:** update documentation for new features ([35d8734](35d8734a3a))
* **abacus-react:** update README with /static import path for RSC ([72a4c2b](72a4c2b80c))
* add 3D enhancement documentation to README ([cc96802](cc96802df8))
* add critical section on never adding tsx to production dependencies ([770cfc3](770cfc3aca))
* add database migration guide and playing guide modal spec ([5a29af7](5a29af78e2))
* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* **card-sorting:** add comprehensive multiplayer plan ([008ccea](008ccead0f))
* **rithmomachia:** Add concise one-page playing guide ([e3c1f10](e3c1f10233))
* update workflow to require manual testing before commits ([0991796](0991796f1e))

### Styles

* **rithmomachia:** improve divider styling and make tabs responsive ([88ca35e](88ca35e044)), closes [#e5e7](https://github.com/antialias/soroban-abacus-flashcards/issues/e5e7) [#9ca3](https://github.com/antialias/soroban-abacus-flashcards/issues/9ca3)
* **rithmomachia:** improve pyramid face numbers visibility and contrast ([94e5e6a](94e5e6a268)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#b45309](https://github.com/antialias/soroban-abacus-flashcards/issues/b45309)
* **rithmomachia:** increase pyramid face numbers size and boldness ([7bf2d73](7bf2d730d3))

### Tests

* trigger compose-updater deployment test ([2b06aae](2b06aae394))
* verify compose-updater automatic deployment cycle ([af0552c](af0552ccd9))
2025-11-05 01:53:31 +00:00
Thomas Hallock
e1bcd24169 fix(docker): upgrade OpenSCAD to 2024.11 to fix CGAL intersection bug
The old OpenSCAD 2021.01 from Debian repos has CGAL bugs that cause
intersection operations to fail with "assertion violation" errors.

This was breaking the 3D abacus creator which uses intersection()
to create the mirrored book-fold design.

Changes:
- Add openscad-builder stage to download and extract OpenSCAD 2024.11.18 AppImage
- Remove old openscad from apt packages
- Add Qt5 and graphics runtime dependencies for new OpenSCAD
- Copy new OpenSCAD binary and libraries to runner stage
- Set LD_LIBRARY_PATH for OpenSCAD libraries

Testing on prod showed "CGAL ERROR: assertion violation" in intersection
operations, producing incomplete 1.8K STL files instead of multi-MB files.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 19:49:03 -06:00
semantic-release-bot
2df4423684 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-11-05)

### Features

* **abacus-react:** add AbacusStatic for React Server Components ([3b8e864](3b8e864cfa))
* **abacus-react:** add core utility functions for state management ([e65541c](e65541c100))
* **abacus-react:** add layout and educational props ([35bbcec](35bbcecb9e))
* **abacus-react:** add pre-defined theme presets ([cf1f950](cf1f950c7c))
* **abacus-react:** add React hooks for abacus calculations ([de038d2](de038d2afc))
* **abacus-react:** add separate /static export path for React Server Components ([ed69f6b](ed69f6b917))
* **abacus-react:** add shared dimension calculator for consistent sizing ([e5ba772](e5ba772fde))
* **abacus-react:** export new utilities, hooks, and themes ([ce4e44d](ce4e44d630))
* **abacus:** add nativeAbacusNumbers setting to schema and UI ([79f7347](79f7347d48))
* add 3D printing support for abacus models ([dafdfdd](dafdfdd233))
* add comprehensive metadata, SEO, and make AbacusReact SSR-compatible ([0922ea1](0922ea10b7))
* add comprehensive Storybook coverage and migration guide ([7a4a37e](7a4a37ec6d))
* add game preview system with mock arcade environment ([25880cc](25880cc7e4))
* add per-player stats tracking system ([613301c](613301cd13))
* add Strategy & Tactics section to Rithmomachia guide ([81ead65](81ead65680))
* add unified trophy abacus with hero mode integration ([6620418](6620418a70))
* **arcade:** add ability to deactivate remote players without kicking user ([3628426](3628426a56))
* **arcade:** add native abacus numbers support to pressure gauge ([1d525c7](1d525c7b53))
* **arcade:** add Rithmomachia (Battle of Numbers) game ([2fc0a05](2fc0a05f7f))
* **arcade:** add yjs-demo collaborative game and Yjs persistence layer ([d568955](d568955d6a))
* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add activity feed notifications for collaborative mode ([1461414](1461414ef4))
* **card-sorting:** add auto-submit countdown for perfect sequences ([780a716](780a7161bc))
* **card-sorting:** add bezier curves to connecting arrows ([4d8e873](4d8e873358))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add collapsible stats sidebar for spectators ([6527c26](6527c26a81))
* **card-sorting:** add game mode selector UI to setup phase ([d25b888](d25b888ffb))
* **card-sorting:** add GameMode type system for multiplayer support ([fd76533](fd765335ef))
* **card-sorting:** add green border to correctly positioned cards ([16fca86](16fca86b76)), closes [#22c55](https://github.com/antialias/soroban-abacus-flashcards/issues/22c55)
* **card-sorting:** add player emoji indicators on moving cards ([3a82099](3a82099757))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add smooth transition to drop shadow ([b0b93d0](b0b93d0175))
* **card-sorting:** add spectator mode UI enhancements ([ee7345d](ee7345d641)), closes [#6366f1](https://github.com/antialias/soroban-abacus-flashcards/issues/6366f1) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add team scoring UI for collaborative mode ([ed6f177](ed6f177914)), closes [#a78](https://github.com/antialias/soroban-abacus-flashcards/issues/a78) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **card-sorting:** auto-arrange prefix/suffix cards in corners ([4ba7f24](4ba7f24717))
* **card-sorting:** fade correctly positioned cards to 50% opacity ([7028cfc](7028cfc511))
* **card-sorting:** gentler spring animation for locked cards ([47189cb](47189cb6e7))
* **card-sorting:** implement continuous bezier curve paths ([2d93024](2d9302410f))
* **card-sorting:** improve card distribution for natural scattered look ([0b0503f](0b0503f035))
* **card-sorting:** make player emoji fill entire card background ([2e7a02c](2e7a02c9e4))
* **card-sorting:** optimize results screen for mobile ([d188789](d188789069))
* **card-sorting:** redesign setup screen with modern UI ([73cf967](73cf967492))
* **card-sorting:** scale correctly positioned cards to 50% ([222dc55](222dc555fa))
* **card-sorting:** shrink/fade cards in correct suffix as well ([8f6feec](8f6feec4f2))
* **card-sorting:** smooth spring transition from game table to results grid ([c5f39d5](c5f39d51eb))
* **card-sorting:** wrap prefix/suffix cards to multiple rows ([e3184dd](e3184dd0d4))
* complete 3D enhancement integration for all three proposals ([5ac55cc](5ac55cc149))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* dynamic day-of-month favicon using subprocess pattern ([4d0795a](4d0795a9df))
* dynamically crop favicon to active beads for maximum size ([5670322](567032296a))
* enable 3D enhancement on hero/open MyAbacus modes ([37e330f](37e330f26e))
* **games:** add autoplay and improve carousel layout ([9f51edf](9f51edfaa9))
* **games:** add horizontal scroll support to carousels ([a224abb](a224abb6f6))
* **games:** add rotating games hero carousel ([24231e6](24231e6b2e))
* **i18n:** add dynamic locale switching without page reload ([fe9bfea](fe9bfeabf9))
* **i18n:** add global language selector to navigation ([0506360](0506360117))
* **i18n:** add homepage translations for all supported languages ([8c9d35a](8c9d35a3b4))
* **i18n:** add Old High German (goh) language support ([b334a15](b334a15255))
* **i18n:** complete Old High German translations for all locales ([0b06a1c](0b06a1ce00))
* **i18n:** internationalize games page and tutorial content ([4253964](4253964af1))
* **i18n:** internationalize homepage with English translations ([40cff14](40cff143c7))
* **i18n:** migrate from react-i18next to next-intl ([9016b76](9016b76024))
* **i18n:** update games page hero section copy ([6333c60](6333c60352))
* install embla-carousel-autoplay for games carousel ([946e5d1](946e5d1910))
* install embla-carousel-react for player profile carousel ([642ae95](642ae95738))
* internationalize guide page with 6 languages ([e9c320b](e9c320bb10))
* internationalize tutorial player ([26d41cf](26d41cfd05))
* optimize card sorting for mobile displays ([b443ee9](b443ee9cdc))
* Redesign Rithmomachia setup page with dramatic medieval theme ([6ae4d13](6ae4d13dc7))
* **rithmomachia:** add 80% opacity to guide modal when not hovered ([4a78485](4a78485d2e))
* **rithmomachia:** add CaptureContext for capture dialog state management ([d7eb957](d7eb957a8d))
* **rithmomachia:** add ghost panel preview for guide docking ([c0d6526](c0d6526d30))
* **rithmomachia:** add guide docking with resizable panels ([f457f1a](f457f1a1c2))
* **rithmomachia:** add helper piece selection for mathematical captures ([cae3359](cae3359587))
* **rithmomachia:** add helpful error messages for failed captures ([b172440](b172440a41))
* **rithmomachia:** add initial board visual to guide Overview section ([d42bcff](d42bcff0d9))
* **rithmomachia:** Add interactive playing guide modal ([3121d82](3121d8240a))
* **rithmomachia:** add number bond visualization and helper placeholders ([82d8913](82d89131f0))
* **rithmomachia:** add ratio capture example to guide ([9150b0c](9150b0c678))
* **rithmomachia:** add standalone guide page route ([3fcc79f](3fcc79fe9e))
* **rithmomachia:** add useBoardLayout hook for centralized layout calculations ([27f1c98](27f1c989d5))
* **rithmomachia:** add usePieceSelection hook for selection state management ([275f401](275f401e3c))
* **rithmomachia:** add visual board examples to Capture section ([74bc3c0](74bc3c0dcf))
* **rithmomachia:** add visual board examples to Harmony section ([1d5f01c](1d5f01c966))
* **rithmomachia:** add visual winning example to Victory section ([b7fac78](b7fac78829))
* **rithmomachia:** auto-size tab labels with react-textfit ([9fd5406](9fd54067ce))
* **rithmomachia:** cycle through valid helpers with dynamic number tooltips ([4829e41](4829e41ea1))
* **rithmomachia:** enhance capture relation UI with smooth animations ([0a30801](0a308016e9))
* **rithmomachia:** enhance Harmony section with comprehensive content ([f555856](f5558563ea))
* **rithmomachia:** enhance Pieces section with visual examples and pyramid details ([55aff82](55aff829f4))
* **rithmomachia:** enhance Pyramid section with comprehensive details ([9fde1ef](9fde1ef9e7))
* **rithmomachia:** guide defaults to docked right on open ([11f674d](11f674d542))
* **rithmomachia:** improve guide pieces section layout ([a270bfc](a270bfc0cc))
* **rithmomachia:** improve guide UX and add persistence ([b314740](b314740697))
* **rithmomachia:** improve roster status notice UX ([e27df45](e27df45256))
* **rithmomachia:** integrate roster warning into game nav ([8a11594](8a11594203))
* **rithmomachia:** make guide modal ultra-responsive down to 150px width ([0474197](04741971b2))
* **rithmomachia:** recreate original guide modal header layout ([2489695](24896957d0))
* **rithmomachia:** show capture error on hover instead of click ([339b678](339b6780f6))
* **rithmomachia:** show pyramid face numbers on hover instead of selection ([b0c4523](b0c4523c0b))
* **rithmomachia:** show pyramid face numbers when selected ([5c186f3](5c186f3947))
* **rithmomachia:** show pyramid face numbers when selected with subtle animation ([5c2ddbe](5c2ddbef05))
* **rithmomachia:** show real preview layout when dragging guide to dock ([17d2460](17d2460a87))
* **rithmomachia:** simplify guide language for clarity ([85cb630](85cb630add))
* **rithmomachia:** skip helper selection UI and auto-select first valid helper ([be2a00e](be2a00e8b3))
* **rithmomachia:** Update harmony system to classical three-piece proportions ([08c9762](08c97620f5))
* **rithmomachia:** Update to traditional board setup with 25 pieces per side ([0769eaa](0769eaaa1d))
* **rithmomachia:** use actual piece SVGs in number bond with 2.5s rotation animation ([976a7de](976a7de949))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))
* show rithmomachia turn in nav ([7c89bfe](7c89bfef9c))
* switch to royal color theme with transparent background ([944ad65](944ad6574e)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#f59e0](https://github.com/antialias/soroban-abacus-flashcards/issues/f59e0) [#a855f7](https://github.com/antialias/soroban-abacus-flashcards/issues/a855f7) [#7e22](https://github.com/antialias/soroban-abacus-flashcards/issues/7e22)
* **web:** add test page for AbacusStatic RSC compatibility ([903dea2](903dea2584))
* **web:** add test page for AbacusStatic Server Component ([3588d5a](3588d5acde))
* **web:** add Typst-based preview endpoint with React Suspense ([599a758](599a758471))
* **web:** add year abacus to calendar header and make grid bolder ([867c7ee](867c7ee172)), closes [#333](https://github.com/antialias/soroban-abacus-flashcards/issues/333)
* **web:** improve calendar abacus preview styling ([8439727](8439727b15))
* **web:** optimize monthly calendar for single-page layout ([b277a89](b277a89415))
* **web:** redesign monthly calendar as single composite SVG ([8ce8038](8ce8038bae))

### Bug Fixes

* **abacus-react:** add data-testid attributes back to beads for testing ([23ae1b0](23ae1b0c6f))
* **abacus-react:** correct column highlighting offset in AbacusStatic ([0641eb7](0641eb719e))
* **abacus-react:** fix animations by preventing component remounting ([be7d4c4](be7d4c4713))
* **abacus-react:** restore original AbacusReact measurements and positioning ([88c0baa](88c0baaad9))
* add xmlns to AbacusStatic for Typst SVG parsing ([98cd019](98cd019d4a))
* adjust hero abacus position to avoid covering subtitle ([f03d341](f03d341314))
* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** allow deactivating players from users who left the room ([7c1c2d7](7c1c2d7beb))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* board rotation now properly fills height in portrait mode ([b5a96ea](b5a96eaeb1))
* **card-sorting:** add border radius to outer card container ([a922eba](a922eba73c))
* **card-sorting:** add debug logging for spring animations ([d42947e](d42947eb8d))
* **card-sorting:** add missing gameMode support after hard reset ([a832325](a832325deb))
* **card-sorting:** add missing useMemo import ([949d76d](949d76d844))
* **card-sorting:** add overflow hidden to clip rounded corners ([84c66fe](84c66feec6))
* **card-sorting:** adjust connecting paths for scaled cards ([829c741](829c741e55))
* **card-sorting:** adjust game board for spectator panels ([fc5cf12](fc5cf1216f))
* **card-sorting:** adjust viewport dimensions for spectator panels ([4dce16c](4dce16cca4))
* **card-sorting:** animate cards from game board to results grid ([17d45fe](17d45fe88c))
* **card-sorting:** correct suffix card detection in auto-arrange ([d02ab59](d02ab5922c))
* **card-sorting:** enable card scaling for spectators ([6b095c3](6b095c3383))
* **card-sorting:** enable New Game button during active gameplay ([f3f6eca](f3f6eca1db))
* **card-sorting:** end drag immediately when card becomes locked ([ae45298](ae45298ec4))
* **card-sorting:** filter local player from emoji overlays on dragged cards ([dc2d94a](dc2d94aaa5))
* **card-sorting:** fix results panel layout to not cover cards ([4b4fbfe](4b4fbfef32))
* **card-sorting:** hide activity notifications in spectator mode ([5cca279](5cca279687))
* **card-sorting:** keep arrow sequence numbers upright ([79c9469](79c94699fa))
* **card-sorting:** lock correctly positioned prefix/suffix cards ([170abed](170abed231))
* **card-sorting:** lock spring positions after initial animation completes ([275cc62](275cc62a52))
* **card-sorting:** New Game now restarts with same settings instantly ([f3687ed](f3687ed236))
* **card-sorting:** only shrink/fade cards in correct prefix ([51368c6](51368c6ec5))
* **card-sorting:** preserve card positions on pause/resume ([0d8af09](0d8af09517))
* **card-sorting:** preserve rotation when starting drag ([3364144](3364144fb6))
* **card-sorting:** prevent duplicate START_GAME moves on Play Again ([a0b14f8](a0b14f87e9))
* **card-sorting:** prevent ghost movements with proper optimistic updates ([bd014be](bd014bec4f))
* **card-sorting:** prevent infinite loop when all cards are correct ([34785f4](34785f466f))
* **card-sorting:** prevent infinite loop with tolerance-based position comparison ([627b873](627b873382))
* **card-sorting:** prevent position jump when clicking rotated cards ([564a00f](564a00f82b))
* **card-sorting:** prevent replaying own movements from server ([308168a](308168a7fb))
* **card-sorting:** prevent springs from reinitializing on window resize ([30953b8](30953b8c4a))
* **card-sorting:** prevent springs from resetting after animation ([8aff60c](8aff60ce3f))
* **card-sorting:** remove hasAnimatedRef logic causing backwards animation ([a44aa5a](a44aa5a4c2))
* **card-sorting:** remove remaining reveal numbers references ([15c53ea](15c53ea4eb))
* **card-sorting:** restore prefix/suffix card shrinking visual feedback ([f5fb4d7](f5fb4d7b76))
* **card-sorting:** show only active players in team members section ([fa9f1a5](fa9f1a568f))
* **card-sorting:** smooth scale animation while dragging cards ([0eefc33](0eefc332ac))
* **card-sorting:** stabilize inferred sequence for locked cards during drag ([b0cd194](b0cd194838))
* **card-sorting:** use empty deps array for useSprings to prevent recreation ([cee399e](cee399ed15))
* **card-sorting:** use ref to track initialized state and prevent re-animation ([f389afa](f389afa831))
* **card-sorting:** use same coordinate system for game board and results ([6972fdf](6972fdf110))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* configure favicon metadata and improve bead visibility ([e1369fa](e1369fa275))
* copy entire packages/core and packages/templates ([0ccada0](0ccada0ca7))
* correct hero abacus scroll direction to flow with page content ([4232746](423274657c))
* correct Typst template path in Dockerfile ([4c518de](4c518decb7))
* delete existing user sessions before creating new ones ([0cced47](0cced47a0f))
* **docker:** add scripts, abacus-react, and tsx for production calendar generation ([33eb90e](33eb90e316))
* extract pure SVG content from AbacusReact renders ([b07f1c4](b07f1c4216))
* **games:** prevent horizontal page scroll from carousel overflow ([5a8c98f](5a8c98fc10))
* **games:** smooth scroll feel for carousel wheel navigation ([f80a73b](f80a73b35c))
* **games:** use specific transition properties for smooth carousel loop ([187271e](187271e515))
* **guide:** increase abacus sizes - they were too small ([1074624](1074624b2f))
* **guide:** make abacus sizes consistent and add nav spacing ([bea4842](bea4842a29))
* **guide:** remove inner containers and tighten margins ([7e54c6f](7e54c6f4fc))
* **i18n:** eliminate FOUC by loading messages server-side ([4d4d930](4d4d930bd3))
* **i18n:** use useMessages() for tutorial translations ([95b0105](95b0105ca3))
* include column posts in favicon bounding box ([0b2f481](0b2f48106a))
* increase server update debounce to 2000ms for low bandwidth ([633ff12](633ff12750))
* Integrate threshold input into Point Victory card ([b29bbee](b29bbeefca))
* **layout:** add systematic spacing for fixed nav bar ([4559fb1](4559fb121d))
* **layout:** remove wrapper, use utility class for nav spacing ([247c3d9](247c3d9874))
* mark dynamic routes as force-dynamic to prevent static generation errors ([d7b35d9](d7b35d9544))
* **nav:** restrict transparent hero styling to home page only ([fab227d](fab227d686))
* **nav:** show full navigation on /games page ([d3fe6ac](d3fe6acbb0))
* **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))
* reduce padding to minimize gap below last bead ([0e529be](0e529be789))
* remove distracting parallax and wobble 3D effects ([28a2d40](28a2d40996))
* remove wobble physics and enhance wood grain visibility ([5d97673](5d97673406))
* resolve z-index layering and hero abacus visibility issues ([ed9a050](ed9a050d64))
* rewrite 3D stories to use props instead of CSS wrappers ([26bdb11](26bdb11237))
* **rithmomachia:** add missing i18next dependencies ([91154d9](91154d9364))
* **rithmomachia:** add missing pyramid section keys to Japanese (ja.json) ([dae615e](dae615ee72))
* **rithmomachia:** adjust error dialog sizing to prevent text clipping ([cda1126](cda1126cb0))
* **rithmomachia:** adjust roster notice position to not overlap nav ([7093223](709322373a))
* **rithmomachia:** change undock icon to pop-out arrow ([2a91748](2a91748493))
* **rithmomachia:** correct board dimensions to 16x8 and restore original layout values ([cfac277](cfac277505))
* **rithmomachia:** Correct board setup to match reference image exactly ([618e563](618e56358d))
* **rithmomachia:** correct makeMove parameter types for capture handling ([aafb64f](aafb64f3e3))
* **rithmomachia:** fix guide modal resize drift by calculating from initial state ([1bcd99c](1bcd99c949))
* **rithmomachia:** fix harmony section translation structure for hi/ja/es ([14259a1](14259a19a9))
* **rithmomachia:** fix modal resizing zoom issue ([4fa20f4](4fa20f44cb))
* **rithmomachia:** Fix TypeScript errors in playing guide modal ([4834ece](4834ece98e))
* **rithmomachia:** handle pyramid pieces in hover error tooltip ([56f3164](56f3164155))
* **rithmomachia:** implement proper board cropping and highlighting in guide ([d0a8fcd](d0a8fcdea6))
* **rithmomachia:** improve guide modal tab navigation at narrow widths ([a673177](a673177bec))
* **rithmomachia:** reconnect player assignment UI and fix setup layout ([a1a0374](a1a0374fac))
* **rithmomachia:** render guide as docked in preview panel ([190f8cf](190f8cf302))
* **rithmomachia:** show actual values in tooltips for non-helper relations ([774c6b0](774c6b0ce7))
* **rithmomachia:** show guest-friendly message when they can't fix too many players ([54bfd2f](54bfd2fac8))
* **rithmomachia:** smooth guide dragging from docked state without jump ([8f4a79c](8f4a79c9b0))
* **rithmomachia:** validate move path before showing capture error on hover ([bd49964](bd49964186))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))
* separate horizontal and vertical bounding box logic ([83090df](83090df4df))
* tolerate OpenSCAD CGAL warnings if output file is created ([88993f3](88993f3662))
* **tutorial:** correct column validation for bead highlights ([9ba1824](9ba1824226))
* **tutorial:** fix overlay rendering, arrow indicators, and bead visibility ([a804316](a80431608d))
* use absolute positioning for hero abacus to eliminate scroll lag ([096104b](096104b094))
* use Debian base for deps stage to match runner for binary compatibility ([f8fe6e4](f8fe6e4a41))
* use default BOSL2 branch instead of non-existent v2.0.0 tag ([f4ffc5b](f4ffc5b027))
* use nested SVG viewBox for actual cropping, not just scaling ([440b492](440b492e85))
* various game improvements and UI enhancements ([b67cf61](b67cf610c5))
* **web,docker:** add --format flag for Typst and upgrade to v0.13.0 ([19b9d7a](19b9d7a74f))
* **web:** add dynamic export to rithmomachia page ([329e623](329e623212))
* **web:** fix Typst PDF generation path resolution ([7ce1287](7ce1287525))
* **web:** generate styled-system artifacts during build ([293390a](293390ae35))
* **web:** move react-dom/server import to API route to satisfy Next.js ([00a8bc3](00a8bc3e5e))
* **web:** move tsx to production dependencies for calendar generation ([ffae9c1](ffae9c1bdb))
* **web:** prevent abacus overlap in composite calendar ([448f93c](448f93c1e2)), closes [#f0f0f0](https://github.com/antialias/soroban-abacus-flashcards/issues/f0f0f0)
* **web:** use AbacusStatic for calendar SVG generation ([08c6a41](08c6a419e2))
* **web:** use dynamic import for react-dom/server in API route ([4f93c7d](4f93c7d996))
* **web:** use nested SVG elements to prevent coordinate space conflicts ([f9cbee8](f9cbee8fcd))

### Performance Improvements

* optimize Docker image size to reduce build failures ([9ca3106](9ca3106361))

### Code Refactoring

* **card-sorting:** remove reveal numbers feature ([ea5e3e8](ea5e3e838b))
* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))
* **games:** implement carousel, fix victories bug, add conditional stats ([82c133f](82c133f742))
* **games:** move page title to nav bar ([712ee58](712ee58e59))
* **games:** remove redundant subtitle below nav ([ad5bb87](ad5bb87325))
* **games:** remove wheel scrolling, enable overflow visible carousel ([876513c](876513c9cc))
* **layout:** make nav height truly self-referential ([9886302](98863026b7))
* reorganize Harmony and Victory guide sections ([fb629c4](fb629c44ea))
* restructure /create page into hub with sub-pages ([b91b23d](b91b23d95f))
* **rithmomachia:** extract board and capture components (phase 2+3) ([a0a867b](a0a867b271))
* **rithmomachia:** extract CaptureErrorDialog component (Phase 2 partial) ([f0a066d](f0a066d8f0))
* **rithmomachia:** extract constants and coordinate utilities (Phase 1) ([eace0ed](eace0ed529))
* **rithmomachia:** extract guide sections into separate files ([765525d](765525dc45))
* **rithmomachia:** extract hooks (phase 5) ([324a659](324a65992f))
* **rithmomachia:** extract phase components (phase 4) ([11364f6](11364f6394))
* **rithmomachia:** extract reusable components from SetupPhase ([3abc325](3abc325ea2))
* **rithmomachia:** make setup phase UI more compact ([e55f848](e55f848a26))
* **rithmomachia:** redesign error notification with modern UI ([dfeeb0e](dfeeb0e0db)), closes [#1e293](https://github.com/antialias/soroban-abacus-flashcards/issues/1e293) [#0f172](https://github.com/antialias/soroban-abacus-flashcards/issues/0f172) [#f1f5f9](https://github.com/antialias/soroban-abacus-flashcards/issues/f1f5f9)
* **rithmomachia:** simplify capture error dialog to one-liner ([82a5eb2](82a5eb2e4b))
* **rithmomachia:** Update board setup to authoritative CSV layout ([0471da5](0471da598d))
* **rithmomachia:** update capture components to use CaptureContext ([2ab6ab5](2ab6ab5799))
* **rithmomachia:** use useBoardLayout and usePieceSelection in BoardDisplay ([0ab7a1d](0ab7a1df32))
* use AbacusReact for dynamic Open Graph image ([9c20f12](9c20f12bac))
* **web:** import utility functions from abacus-react ([7228bbc](7228bbc2eb))
* **web:** move calendar generators to src/utils for proper compilation ([379698f](379698fea3))
* **web:** return calendar SVG preview with PDF generation ([14a5de0](14a5de0dfa))
* **web:** use ABACUS_THEMES instead of manual style definitions ([9f7f001](9f7f001d74))
* **web:** use client-side React rendering for live calendar preview ([f880cbe](f880cbe4bf))
* **web:** use compact prop for inline mini-abacus ([ff1d60a](ff1d60a233))
* **web:** use direct function imports instead of execSync for calendar generation ([9f1715f](9f1715f085))
* **web:** use stdin/stdout for Typst compilation ([06f68cc](06f68cc74c))

### Documentation

* **abacus-react:** add Storybook stories for AbacusStatic ([4f9dc46](4f9dc4666d))
* **abacus-react:** add Storybook stories for new features ([6a1cec0](6a1cec06a7))
* **abacus-react:** export AbacusStatic and update README ([74f2d97](74f2d97434))
* **abacus-react:** update documentation for new features ([35d8734](35d8734a3a))
* **abacus-react:** update README with /static import path for RSC ([72a4c2b](72a4c2b80c))
* add 3D enhancement documentation to README ([cc96802](cc96802df8))
* add critical section on never adding tsx to production dependencies ([770cfc3](770cfc3aca))
* add database migration guide and playing guide modal spec ([5a29af7](5a29af78e2))
* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* **card-sorting:** add comprehensive multiplayer plan ([008ccea](008ccead0f))
* **rithmomachia:** Add concise one-page playing guide ([e3c1f10](e3c1f10233))
* update workflow to require manual testing before commits ([0991796](0991796f1e))

### Styles

* **rithmomachia:** improve divider styling and make tabs responsive ([88ca35e](88ca35e044)), closes [#e5e7](https://github.com/antialias/soroban-abacus-flashcards/issues/e5e7) [#9ca3](https://github.com/antialias/soroban-abacus-flashcards/issues/9ca3)
* **rithmomachia:** improve pyramid face numbers visibility and contrast ([94e5e6a](94e5e6a268)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#b45309](https://github.com/antialias/soroban-abacus-flashcards/issues/b45309)
* **rithmomachia:** increase pyramid face numbers size and boldness ([7bf2d73](7bf2d730d3))

### Tests

* trigger compose-updater deployment test ([2b06aae](2b06aae394))
* verify compose-updater automatic deployment cycle ([af0552c](af0552ccd9))
2025-11-05 01:44:57 +00:00
Thomas Hallock
7e54c6f4fc fix(guide): remove inner containers and tighten margins
- Remove white/gray bordered inner containers around abacuses
- Center abacuses directly in cards using flex
- Reduce card padding from p:4 to p:2
- Tighten margins between elements (mb:3→mb:2)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 19:40:26 -06:00
semantic-release-bot
8a170833f3 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-11-05)

### Features

* **abacus-react:** add AbacusStatic for React Server Components ([3b8e864](3b8e864cfa))
* **abacus-react:** add core utility functions for state management ([e65541c](e65541c100))
* **abacus-react:** add layout and educational props ([35bbcec](35bbcecb9e))
* **abacus-react:** add pre-defined theme presets ([cf1f950](cf1f950c7c))
* **abacus-react:** add React hooks for abacus calculations ([de038d2](de038d2afc))
* **abacus-react:** add separate /static export path for React Server Components ([ed69f6b](ed69f6b917))
* **abacus-react:** add shared dimension calculator for consistent sizing ([e5ba772](e5ba772fde))
* **abacus-react:** export new utilities, hooks, and themes ([ce4e44d](ce4e44d630))
* **abacus:** add nativeAbacusNumbers setting to schema and UI ([79f7347](79f7347d48))
* add 3D printing support for abacus models ([dafdfdd](dafdfdd233))
* add comprehensive metadata, SEO, and make AbacusReact SSR-compatible ([0922ea1](0922ea10b7))
* add comprehensive Storybook coverage and migration guide ([7a4a37e](7a4a37ec6d))
* add game preview system with mock arcade environment ([25880cc](25880cc7e4))
* add per-player stats tracking system ([613301c](613301cd13))
* add Strategy & Tactics section to Rithmomachia guide ([81ead65](81ead65680))
* add unified trophy abacus with hero mode integration ([6620418](6620418a70))
* **arcade:** add ability to deactivate remote players without kicking user ([3628426](3628426a56))
* **arcade:** add native abacus numbers support to pressure gauge ([1d525c7](1d525c7b53))
* **arcade:** add Rithmomachia (Battle of Numbers) game ([2fc0a05](2fc0a05f7f))
* **arcade:** add yjs-demo collaborative game and Yjs persistence layer ([d568955](d568955d6a))
* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add activity feed notifications for collaborative mode ([1461414](1461414ef4))
* **card-sorting:** add auto-submit countdown for perfect sequences ([780a716](780a7161bc))
* **card-sorting:** add bezier curves to connecting arrows ([4d8e873](4d8e873358))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add collapsible stats sidebar for spectators ([6527c26](6527c26a81))
* **card-sorting:** add game mode selector UI to setup phase ([d25b888](d25b888ffb))
* **card-sorting:** add GameMode type system for multiplayer support ([fd76533](fd765335ef))
* **card-sorting:** add green border to correctly positioned cards ([16fca86](16fca86b76)), closes [#22c55](https://github.com/antialias/soroban-abacus-flashcards/issues/22c55)
* **card-sorting:** add player emoji indicators on moving cards ([3a82099](3a82099757))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add smooth transition to drop shadow ([b0b93d0](b0b93d0175))
* **card-sorting:** add spectator mode UI enhancements ([ee7345d](ee7345d641)), closes [#6366f1](https://github.com/antialias/soroban-abacus-flashcards/issues/6366f1) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add team scoring UI for collaborative mode ([ed6f177](ed6f177914)), closes [#a78](https://github.com/antialias/soroban-abacus-flashcards/issues/a78) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **card-sorting:** auto-arrange prefix/suffix cards in corners ([4ba7f24](4ba7f24717))
* **card-sorting:** fade correctly positioned cards to 50% opacity ([7028cfc](7028cfc511))
* **card-sorting:** gentler spring animation for locked cards ([47189cb](47189cb6e7))
* **card-sorting:** implement continuous bezier curve paths ([2d93024](2d9302410f))
* **card-sorting:** improve card distribution for natural scattered look ([0b0503f](0b0503f035))
* **card-sorting:** make player emoji fill entire card background ([2e7a02c](2e7a02c9e4))
* **card-sorting:** optimize results screen for mobile ([d188789](d188789069))
* **card-sorting:** redesign setup screen with modern UI ([73cf967](73cf967492))
* **card-sorting:** scale correctly positioned cards to 50% ([222dc55](222dc555fa))
* **card-sorting:** shrink/fade cards in correct suffix as well ([8f6feec](8f6feec4f2))
* **card-sorting:** smooth spring transition from game table to results grid ([c5f39d5](c5f39d51eb))
* **card-sorting:** wrap prefix/suffix cards to multiple rows ([e3184dd](e3184dd0d4))
* complete 3D enhancement integration for all three proposals ([5ac55cc](5ac55cc149))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* dynamic day-of-month favicon using subprocess pattern ([4d0795a](4d0795a9df))
* dynamically crop favicon to active beads for maximum size ([5670322](567032296a))
* enable 3D enhancement on hero/open MyAbacus modes ([37e330f](37e330f26e))
* **games:** add autoplay and improve carousel layout ([9f51edf](9f51edfaa9))
* **games:** add horizontal scroll support to carousels ([a224abb](a224abb6f6))
* **games:** add rotating games hero carousel ([24231e6](24231e6b2e))
* **i18n:** add dynamic locale switching without page reload ([fe9bfea](fe9bfeabf9))
* **i18n:** add global language selector to navigation ([0506360](0506360117))
* **i18n:** add homepage translations for all supported languages ([8c9d35a](8c9d35a3b4))
* **i18n:** add Old High German (goh) language support ([b334a15](b334a15255))
* **i18n:** complete Old High German translations for all locales ([0b06a1c](0b06a1ce00))
* **i18n:** internationalize games page and tutorial content ([4253964](4253964af1))
* **i18n:** internationalize homepage with English translations ([40cff14](40cff143c7))
* **i18n:** migrate from react-i18next to next-intl ([9016b76](9016b76024))
* **i18n:** update games page hero section copy ([6333c60](6333c60352))
* install embla-carousel-autoplay for games carousel ([946e5d1](946e5d1910))
* install embla-carousel-react for player profile carousel ([642ae95](642ae95738))
* internationalize guide page with 6 languages ([e9c320b](e9c320bb10))
* internationalize tutorial player ([26d41cf](26d41cfd05))
* optimize card sorting for mobile displays ([b443ee9](b443ee9cdc))
* Redesign Rithmomachia setup page with dramatic medieval theme ([6ae4d13](6ae4d13dc7))
* **rithmomachia:** add 80% opacity to guide modal when not hovered ([4a78485](4a78485d2e))
* **rithmomachia:** add CaptureContext for capture dialog state management ([d7eb957](d7eb957a8d))
* **rithmomachia:** add ghost panel preview for guide docking ([c0d6526](c0d6526d30))
* **rithmomachia:** add guide docking with resizable panels ([f457f1a](f457f1a1c2))
* **rithmomachia:** add helper piece selection for mathematical captures ([cae3359](cae3359587))
* **rithmomachia:** add helpful error messages for failed captures ([b172440](b172440a41))
* **rithmomachia:** add initial board visual to guide Overview section ([d42bcff](d42bcff0d9))
* **rithmomachia:** Add interactive playing guide modal ([3121d82](3121d8240a))
* **rithmomachia:** add number bond visualization and helper placeholders ([82d8913](82d89131f0))
* **rithmomachia:** add ratio capture example to guide ([9150b0c](9150b0c678))
* **rithmomachia:** add standalone guide page route ([3fcc79f](3fcc79fe9e))
* **rithmomachia:** add useBoardLayout hook for centralized layout calculations ([27f1c98](27f1c989d5))
* **rithmomachia:** add usePieceSelection hook for selection state management ([275f401](275f401e3c))
* **rithmomachia:** add visual board examples to Capture section ([74bc3c0](74bc3c0dcf))
* **rithmomachia:** add visual board examples to Harmony section ([1d5f01c](1d5f01c966))
* **rithmomachia:** add visual winning example to Victory section ([b7fac78](b7fac78829))
* **rithmomachia:** auto-size tab labels with react-textfit ([9fd5406](9fd54067ce))
* **rithmomachia:** cycle through valid helpers with dynamic number tooltips ([4829e41](4829e41ea1))
* **rithmomachia:** enhance capture relation UI with smooth animations ([0a30801](0a308016e9))
* **rithmomachia:** enhance Harmony section with comprehensive content ([f555856](f5558563ea))
* **rithmomachia:** enhance Pieces section with visual examples and pyramid details ([55aff82](55aff829f4))
* **rithmomachia:** enhance Pyramid section with comprehensive details ([9fde1ef](9fde1ef9e7))
* **rithmomachia:** guide defaults to docked right on open ([11f674d](11f674d542))
* **rithmomachia:** improve guide pieces section layout ([a270bfc](a270bfc0cc))
* **rithmomachia:** improve guide UX and add persistence ([b314740](b314740697))
* **rithmomachia:** improve roster status notice UX ([e27df45](e27df45256))
* **rithmomachia:** integrate roster warning into game nav ([8a11594](8a11594203))
* **rithmomachia:** make guide modal ultra-responsive down to 150px width ([0474197](04741971b2))
* **rithmomachia:** recreate original guide modal header layout ([2489695](24896957d0))
* **rithmomachia:** show capture error on hover instead of click ([339b678](339b6780f6))
* **rithmomachia:** show pyramid face numbers on hover instead of selection ([b0c4523](b0c4523c0b))
* **rithmomachia:** show pyramid face numbers when selected ([5c186f3](5c186f3947))
* **rithmomachia:** show pyramid face numbers when selected with subtle animation ([5c2ddbe](5c2ddbef05))
* **rithmomachia:** show real preview layout when dragging guide to dock ([17d2460](17d2460a87))
* **rithmomachia:** simplify guide language for clarity ([85cb630](85cb630add))
* **rithmomachia:** skip helper selection UI and auto-select first valid helper ([be2a00e](be2a00e8b3))
* **rithmomachia:** Update harmony system to classical three-piece proportions ([08c9762](08c97620f5))
* **rithmomachia:** Update to traditional board setup with 25 pieces per side ([0769eaa](0769eaaa1d))
* **rithmomachia:** use actual piece SVGs in number bond with 2.5s rotation animation ([976a7de](976a7de949))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))
* show rithmomachia turn in nav ([7c89bfe](7c89bfef9c))
* switch to royal color theme with transparent background ([944ad65](944ad6574e)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#f59e0](https://github.com/antialias/soroban-abacus-flashcards/issues/f59e0) [#a855f7](https://github.com/antialias/soroban-abacus-flashcards/issues/a855f7) [#7e22](https://github.com/antialias/soroban-abacus-flashcards/issues/7e22)
* **web:** add test page for AbacusStatic RSC compatibility ([903dea2](903dea2584))
* **web:** add test page for AbacusStatic Server Component ([3588d5a](3588d5acde))
* **web:** add Typst-based preview endpoint with React Suspense ([599a758](599a758471))
* **web:** add year abacus to calendar header and make grid bolder ([867c7ee](867c7ee172)), closes [#333](https://github.com/antialias/soroban-abacus-flashcards/issues/333)
* **web:** improve calendar abacus preview styling ([8439727](8439727b15))
* **web:** optimize monthly calendar for single-page layout ([b277a89](b277a89415))
* **web:** redesign monthly calendar as single composite SVG ([8ce8038](8ce8038bae))

### Bug Fixes

* **abacus-react:** add data-testid attributes back to beads for testing ([23ae1b0](23ae1b0c6f))
* **abacus-react:** correct column highlighting offset in AbacusStatic ([0641eb7](0641eb719e))
* **abacus-react:** fix animations by preventing component remounting ([be7d4c4](be7d4c4713))
* **abacus-react:** restore original AbacusReact measurements and positioning ([88c0baa](88c0baaad9))
* add xmlns to AbacusStatic for Typst SVG parsing ([98cd019](98cd019d4a))
* adjust hero abacus position to avoid covering subtitle ([f03d341](f03d341314))
* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** allow deactivating players from users who left the room ([7c1c2d7](7c1c2d7beb))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* board rotation now properly fills height in portrait mode ([b5a96ea](b5a96eaeb1))
* **card-sorting:** add border radius to outer card container ([a922eba](a922eba73c))
* **card-sorting:** add debug logging for spring animations ([d42947e](d42947eb8d))
* **card-sorting:** add missing gameMode support after hard reset ([a832325](a832325deb))
* **card-sorting:** add missing useMemo import ([949d76d](949d76d844))
* **card-sorting:** add overflow hidden to clip rounded corners ([84c66fe](84c66feec6))
* **card-sorting:** adjust connecting paths for scaled cards ([829c741](829c741e55))
* **card-sorting:** adjust game board for spectator panels ([fc5cf12](fc5cf1216f))
* **card-sorting:** adjust viewport dimensions for spectator panels ([4dce16c](4dce16cca4))
* **card-sorting:** animate cards from game board to results grid ([17d45fe](17d45fe88c))
* **card-sorting:** correct suffix card detection in auto-arrange ([d02ab59](d02ab5922c))
* **card-sorting:** enable card scaling for spectators ([6b095c3](6b095c3383))
* **card-sorting:** enable New Game button during active gameplay ([f3f6eca](f3f6eca1db))
* **card-sorting:** end drag immediately when card becomes locked ([ae45298](ae45298ec4))
* **card-sorting:** filter local player from emoji overlays on dragged cards ([dc2d94a](dc2d94aaa5))
* **card-sorting:** fix results panel layout to not cover cards ([4b4fbfe](4b4fbfef32))
* **card-sorting:** hide activity notifications in spectator mode ([5cca279](5cca279687))
* **card-sorting:** keep arrow sequence numbers upright ([79c9469](79c94699fa))
* **card-sorting:** lock correctly positioned prefix/suffix cards ([170abed](170abed231))
* **card-sorting:** lock spring positions after initial animation completes ([275cc62](275cc62a52))
* **card-sorting:** New Game now restarts with same settings instantly ([f3687ed](f3687ed236))
* **card-sorting:** only shrink/fade cards in correct prefix ([51368c6](51368c6ec5))
* **card-sorting:** preserve card positions on pause/resume ([0d8af09](0d8af09517))
* **card-sorting:** preserve rotation when starting drag ([3364144](3364144fb6))
* **card-sorting:** prevent duplicate START_GAME moves on Play Again ([a0b14f8](a0b14f87e9))
* **card-sorting:** prevent ghost movements with proper optimistic updates ([bd014be](bd014bec4f))
* **card-sorting:** prevent infinite loop when all cards are correct ([34785f4](34785f466f))
* **card-sorting:** prevent infinite loop with tolerance-based position comparison ([627b873](627b873382))
* **card-sorting:** prevent position jump when clicking rotated cards ([564a00f](564a00f82b))
* **card-sorting:** prevent replaying own movements from server ([308168a](308168a7fb))
* **card-sorting:** prevent springs from reinitializing on window resize ([30953b8](30953b8c4a))
* **card-sorting:** prevent springs from resetting after animation ([8aff60c](8aff60ce3f))
* **card-sorting:** remove hasAnimatedRef logic causing backwards animation ([a44aa5a](a44aa5a4c2))
* **card-sorting:** remove remaining reveal numbers references ([15c53ea](15c53ea4eb))
* **card-sorting:** restore prefix/suffix card shrinking visual feedback ([f5fb4d7](f5fb4d7b76))
* **card-sorting:** show only active players in team members section ([fa9f1a5](fa9f1a568f))
* **card-sorting:** smooth scale animation while dragging cards ([0eefc33](0eefc332ac))
* **card-sorting:** stabilize inferred sequence for locked cards during drag ([b0cd194](b0cd194838))
* **card-sorting:** use empty deps array for useSprings to prevent recreation ([cee399e](cee399ed15))
* **card-sorting:** use ref to track initialized state and prevent re-animation ([f389afa](f389afa831))
* **card-sorting:** use same coordinate system for game board and results ([6972fdf](6972fdf110))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* configure favicon metadata and improve bead visibility ([e1369fa](e1369fa275))
* copy entire packages/core and packages/templates ([0ccada0](0ccada0ca7))
* correct hero abacus scroll direction to flow with page content ([4232746](423274657c))
* correct Typst template path in Dockerfile ([4c518de](4c518decb7))
* delete existing user sessions before creating new ones ([0cced47](0cced47a0f))
* **docker:** add scripts, abacus-react, and tsx for production calendar generation ([33eb90e](33eb90e316))
* extract pure SVG content from AbacusReact renders ([b07f1c4](b07f1c4216))
* **games:** prevent horizontal page scroll from carousel overflow ([5a8c98f](5a8c98fc10))
* **games:** smooth scroll feel for carousel wheel navigation ([f80a73b](f80a73b35c))
* **games:** use specific transition properties for smooth carousel loop ([187271e](187271e515))
* **guide:** increase abacus sizes - they were too small ([1074624](1074624b2f))
* **guide:** make abacus sizes consistent and add nav spacing ([bea4842](bea4842a29))
* **i18n:** eliminate FOUC by loading messages server-side ([4d4d930](4d4d930bd3))
* **i18n:** use useMessages() for tutorial translations ([95b0105](95b0105ca3))
* include column posts in favicon bounding box ([0b2f481](0b2f48106a))
* increase server update debounce to 2000ms for low bandwidth ([633ff12](633ff12750))
* Integrate threshold input into Point Victory card ([b29bbee](b29bbeefca))
* **layout:** add systematic spacing for fixed nav bar ([4559fb1](4559fb121d))
* **layout:** remove wrapper, use utility class for nav spacing ([247c3d9](247c3d9874))
* mark dynamic routes as force-dynamic to prevent static generation errors ([d7b35d9](d7b35d9544))
* **nav:** restrict transparent hero styling to home page only ([fab227d](fab227d686))
* **nav:** show full navigation on /games page ([d3fe6ac](d3fe6acbb0))
* **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))
* reduce padding to minimize gap below last bead ([0e529be](0e529be789))
* remove distracting parallax and wobble 3D effects ([28a2d40](28a2d40996))
* remove wobble physics and enhance wood grain visibility ([5d97673](5d97673406))
* resolve z-index layering and hero abacus visibility issues ([ed9a050](ed9a050d64))
* rewrite 3D stories to use props instead of CSS wrappers ([26bdb11](26bdb11237))
* **rithmomachia:** add missing i18next dependencies ([91154d9](91154d9364))
* **rithmomachia:** add missing pyramid section keys to Japanese (ja.json) ([dae615e](dae615ee72))
* **rithmomachia:** adjust error dialog sizing to prevent text clipping ([cda1126](cda1126cb0))
* **rithmomachia:** adjust roster notice position to not overlap nav ([7093223](709322373a))
* **rithmomachia:** change undock icon to pop-out arrow ([2a91748](2a91748493))
* **rithmomachia:** correct board dimensions to 16x8 and restore original layout values ([cfac277](cfac277505))
* **rithmomachia:** Correct board setup to match reference image exactly ([618e563](618e56358d))
* **rithmomachia:** correct makeMove parameter types for capture handling ([aafb64f](aafb64f3e3))
* **rithmomachia:** fix guide modal resize drift by calculating from initial state ([1bcd99c](1bcd99c949))
* **rithmomachia:** fix harmony section translation structure for hi/ja/es ([14259a1](14259a19a9))
* **rithmomachia:** fix modal resizing zoom issue ([4fa20f4](4fa20f44cb))
* **rithmomachia:** Fix TypeScript errors in playing guide modal ([4834ece](4834ece98e))
* **rithmomachia:** handle pyramid pieces in hover error tooltip ([56f3164](56f3164155))
* **rithmomachia:** implement proper board cropping and highlighting in guide ([d0a8fcd](d0a8fcdea6))
* **rithmomachia:** improve guide modal tab navigation at narrow widths ([a673177](a673177bec))
* **rithmomachia:** reconnect player assignment UI and fix setup layout ([a1a0374](a1a0374fac))
* **rithmomachia:** render guide as docked in preview panel ([190f8cf](190f8cf302))
* **rithmomachia:** show actual values in tooltips for non-helper relations ([774c6b0](774c6b0ce7))
* **rithmomachia:** show guest-friendly message when they can't fix too many players ([54bfd2f](54bfd2fac8))
* **rithmomachia:** smooth guide dragging from docked state without jump ([8f4a79c](8f4a79c9b0))
* **rithmomachia:** validate move path before showing capture error on hover ([bd49964](bd49964186))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))
* separate horizontal and vertical bounding box logic ([83090df](83090df4df))
* tolerate OpenSCAD CGAL warnings if output file is created ([88993f3](88993f3662))
* **tutorial:** correct column validation for bead highlights ([9ba1824](9ba1824226))
* **tutorial:** fix overlay rendering, arrow indicators, and bead visibility ([a804316](a80431608d))
* use absolute positioning for hero abacus to eliminate scroll lag ([096104b](096104b094))
* use Debian base for deps stage to match runner for binary compatibility ([f8fe6e4](f8fe6e4a41))
* use default BOSL2 branch instead of non-existent v2.0.0 tag ([f4ffc5b](f4ffc5b027))
* use nested SVG viewBox for actual cropping, not just scaling ([440b492](440b492e85))
* various game improvements and UI enhancements ([b67cf61](b67cf610c5))
* **web,docker:** add --format flag for Typst and upgrade to v0.13.0 ([19b9d7a](19b9d7a74f))
* **web:** add dynamic export to rithmomachia page ([329e623](329e623212))
* **web:** fix Typst PDF generation path resolution ([7ce1287](7ce1287525))
* **web:** generate styled-system artifacts during build ([293390a](293390ae35))
* **web:** move react-dom/server import to API route to satisfy Next.js ([00a8bc3](00a8bc3e5e))
* **web:** move tsx to production dependencies for calendar generation ([ffae9c1](ffae9c1bdb))
* **web:** prevent abacus overlap in composite calendar ([448f93c](448f93c1e2)), closes [#f0f0f0](https://github.com/antialias/soroban-abacus-flashcards/issues/f0f0f0)
* **web:** use AbacusStatic for calendar SVG generation ([08c6a41](08c6a419e2))
* **web:** use dynamic import for react-dom/server in API route ([4f93c7d](4f93c7d996))
* **web:** use nested SVG elements to prevent coordinate space conflicts ([f9cbee8](f9cbee8fcd))

### Performance Improvements

* optimize Docker image size to reduce build failures ([9ca3106](9ca3106361))

### Code Refactoring

* **card-sorting:** remove reveal numbers feature ([ea5e3e8](ea5e3e838b))
* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))
* **games:** implement carousel, fix victories bug, add conditional stats ([82c133f](82c133f742))
* **games:** move page title to nav bar ([712ee58](712ee58e59))
* **games:** remove redundant subtitle below nav ([ad5bb87](ad5bb87325))
* **games:** remove wheel scrolling, enable overflow visible carousel ([876513c](876513c9cc))
* **layout:** make nav height truly self-referential ([9886302](98863026b7))
* reorganize Harmony and Victory guide sections ([fb629c4](fb629c44ea))
* restructure /create page into hub with sub-pages ([b91b23d](b91b23d95f))
* **rithmomachia:** extract board and capture components (phase 2+3) ([a0a867b](a0a867b271))
* **rithmomachia:** extract CaptureErrorDialog component (Phase 2 partial) ([f0a066d](f0a066d8f0))
* **rithmomachia:** extract constants and coordinate utilities (Phase 1) ([eace0ed](eace0ed529))
* **rithmomachia:** extract guide sections into separate files ([765525d](765525dc45))
* **rithmomachia:** extract hooks (phase 5) ([324a659](324a65992f))
* **rithmomachia:** extract phase components (phase 4) ([11364f6](11364f6394))
* **rithmomachia:** extract reusable components from SetupPhase ([3abc325](3abc325ea2))
* **rithmomachia:** make setup phase UI more compact ([e55f848](e55f848a26))
* **rithmomachia:** redesign error notification with modern UI ([dfeeb0e](dfeeb0e0db)), closes [#1e293](https://github.com/antialias/soroban-abacus-flashcards/issues/1e293) [#0f172](https://github.com/antialias/soroban-abacus-flashcards/issues/0f172) [#f1f5f9](https://github.com/antialias/soroban-abacus-flashcards/issues/f1f5f9)
* **rithmomachia:** simplify capture error dialog to one-liner ([82a5eb2](82a5eb2e4b))
* **rithmomachia:** Update board setup to authoritative CSV layout ([0471da5](0471da598d))
* **rithmomachia:** update capture components to use CaptureContext ([2ab6ab5](2ab6ab5799))
* **rithmomachia:** use useBoardLayout and usePieceSelection in BoardDisplay ([0ab7a1d](0ab7a1df32))
* use AbacusReact for dynamic Open Graph image ([9c20f12](9c20f12bac))
* **web:** import utility functions from abacus-react ([7228bbc](7228bbc2eb))
* **web:** move calendar generators to src/utils for proper compilation ([379698f](379698fea3))
* **web:** return calendar SVG preview with PDF generation ([14a5de0](14a5de0dfa))
* **web:** use ABACUS_THEMES instead of manual style definitions ([9f7f001](9f7f001d74))
* **web:** use client-side React rendering for live calendar preview ([f880cbe](f880cbe4bf))
* **web:** use compact prop for inline mini-abacus ([ff1d60a](ff1d60a233))
* **web:** use direct function imports instead of execSync for calendar generation ([9f1715f](9f1715f085))
* **web:** use stdin/stdout for Typst compilation ([06f68cc](06f68cc74c))

### Documentation

* **abacus-react:** add Storybook stories for AbacusStatic ([4f9dc46](4f9dc4666d))
* **abacus-react:** add Storybook stories for new features ([6a1cec0](6a1cec06a7))
* **abacus-react:** export AbacusStatic and update README ([74f2d97](74f2d97434))
* **abacus-react:** update documentation for new features ([35d8734](35d8734a3a))
* **abacus-react:** update README with /static import path for RSC ([72a4c2b](72a4c2b80c))
* add 3D enhancement documentation to README ([cc96802](cc96802df8))
* add critical section on never adding tsx to production dependencies ([770cfc3](770cfc3aca))
* add database migration guide and playing guide modal spec ([5a29af7](5a29af78e2))
* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* **card-sorting:** add comprehensive multiplayer plan ([008ccea](008ccead0f))
* **rithmomachia:** Add concise one-page playing guide ([e3c1f10](e3c1f10233))
* update workflow to require manual testing before commits ([0991796](0991796f1e))

### Styles

* **rithmomachia:** improve divider styling and make tabs responsive ([88ca35e](88ca35e044)), closes [#e5e7](https://github.com/antialias/soroban-abacus-flashcards/issues/e5e7) [#9ca3](https://github.com/antialias/soroban-abacus-flashcards/issues/9ca3)
* **rithmomachia:** improve pyramid face numbers visibility and contrast ([94e5e6a](94e5e6a268)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#b45309](https://github.com/antialias/soroban-abacus-flashcards/issues/b45309)
* **rithmomachia:** increase pyramid face numbers size and boldness ([7bf2d73](7bf2d730d3))

### Tests

* trigger compose-updater deployment test ([2b06aae](2b06aae394))
* verify compose-updater automatic deployment cycle ([af0552c](af0552ccd9))
2025-11-05 01:35:43 +00:00
Thomas Hallock
1074624b2f fix(guide): increase abacus sizes - they were too small
Previously made them smaller when user wanted them larger.
Now: single-digit 200×400px, multi-digit 320×350px, both with scaleFactor 1.2

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 19:31:08 -06:00
semantic-release-bot
1021efb715 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-11-05)

### Features

* **abacus-react:** add AbacusStatic for React Server Components ([3b8e864](3b8e864cfa))
* **abacus-react:** add core utility functions for state management ([e65541c](e65541c100))
* **abacus-react:** add layout and educational props ([35bbcec](35bbcecb9e))
* **abacus-react:** add pre-defined theme presets ([cf1f950](cf1f950c7c))
* **abacus-react:** add React hooks for abacus calculations ([de038d2](de038d2afc))
* **abacus-react:** add separate /static export path for React Server Components ([ed69f6b](ed69f6b917))
* **abacus-react:** add shared dimension calculator for consistent sizing ([e5ba772](e5ba772fde))
* **abacus-react:** export new utilities, hooks, and themes ([ce4e44d](ce4e44d630))
* **abacus:** add nativeAbacusNumbers setting to schema and UI ([79f7347](79f7347d48))
* add 3D printing support for abacus models ([dafdfdd](dafdfdd233))
* add comprehensive metadata, SEO, and make AbacusReact SSR-compatible ([0922ea1](0922ea10b7))
* add comprehensive Storybook coverage and migration guide ([7a4a37e](7a4a37ec6d))
* add game preview system with mock arcade environment ([25880cc](25880cc7e4))
* add per-player stats tracking system ([613301c](613301cd13))
* add Strategy & Tactics section to Rithmomachia guide ([81ead65](81ead65680))
* add unified trophy abacus with hero mode integration ([6620418](6620418a70))
* **arcade:** add ability to deactivate remote players without kicking user ([3628426](3628426a56))
* **arcade:** add native abacus numbers support to pressure gauge ([1d525c7](1d525c7b53))
* **arcade:** add Rithmomachia (Battle of Numbers) game ([2fc0a05](2fc0a05f7f))
* **arcade:** add yjs-demo collaborative game and Yjs persistence layer ([d568955](d568955d6a))
* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add activity feed notifications for collaborative mode ([1461414](1461414ef4))
* **card-sorting:** add auto-submit countdown for perfect sequences ([780a716](780a7161bc))
* **card-sorting:** add bezier curves to connecting arrows ([4d8e873](4d8e873358))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add collapsible stats sidebar for spectators ([6527c26](6527c26a81))
* **card-sorting:** add game mode selector UI to setup phase ([d25b888](d25b888ffb))
* **card-sorting:** add GameMode type system for multiplayer support ([fd76533](fd765335ef))
* **card-sorting:** add green border to correctly positioned cards ([16fca86](16fca86b76)), closes [#22c55](https://github.com/antialias/soroban-abacus-flashcards/issues/22c55)
* **card-sorting:** add player emoji indicators on moving cards ([3a82099](3a82099757))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add smooth transition to drop shadow ([b0b93d0](b0b93d0175))
* **card-sorting:** add spectator mode UI enhancements ([ee7345d](ee7345d641)), closes [#6366f1](https://github.com/antialias/soroban-abacus-flashcards/issues/6366f1) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add team scoring UI for collaborative mode ([ed6f177](ed6f177914)), closes [#a78](https://github.com/antialias/soroban-abacus-flashcards/issues/a78) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **card-sorting:** auto-arrange prefix/suffix cards in corners ([4ba7f24](4ba7f24717))
* **card-sorting:** fade correctly positioned cards to 50% opacity ([7028cfc](7028cfc511))
* **card-sorting:** gentler spring animation for locked cards ([47189cb](47189cb6e7))
* **card-sorting:** implement continuous bezier curve paths ([2d93024](2d9302410f))
* **card-sorting:** improve card distribution for natural scattered look ([0b0503f](0b0503f035))
* **card-sorting:** make player emoji fill entire card background ([2e7a02c](2e7a02c9e4))
* **card-sorting:** optimize results screen for mobile ([d188789](d188789069))
* **card-sorting:** redesign setup screen with modern UI ([73cf967](73cf967492))
* **card-sorting:** scale correctly positioned cards to 50% ([222dc55](222dc555fa))
* **card-sorting:** shrink/fade cards in correct suffix as well ([8f6feec](8f6feec4f2))
* **card-sorting:** smooth spring transition from game table to results grid ([c5f39d5](c5f39d51eb))
* **card-sorting:** wrap prefix/suffix cards to multiple rows ([e3184dd](e3184dd0d4))
* complete 3D enhancement integration for all three proposals ([5ac55cc](5ac55cc149))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* dynamic day-of-month favicon using subprocess pattern ([4d0795a](4d0795a9df))
* dynamically crop favicon to active beads for maximum size ([5670322](567032296a))
* enable 3D enhancement on hero/open MyAbacus modes ([37e330f](37e330f26e))
* **games:** add autoplay and improve carousel layout ([9f51edf](9f51edfaa9))
* **games:** add horizontal scroll support to carousels ([a224abb](a224abb6f6))
* **games:** add rotating games hero carousel ([24231e6](24231e6b2e))
* **i18n:** add dynamic locale switching without page reload ([fe9bfea](fe9bfeabf9))
* **i18n:** add global language selector to navigation ([0506360](0506360117))
* **i18n:** add homepage translations for all supported languages ([8c9d35a](8c9d35a3b4))
* **i18n:** add Old High German (goh) language support ([b334a15](b334a15255))
* **i18n:** complete Old High German translations for all locales ([0b06a1c](0b06a1ce00))
* **i18n:** internationalize games page and tutorial content ([4253964](4253964af1))
* **i18n:** internationalize homepage with English translations ([40cff14](40cff143c7))
* **i18n:** migrate from react-i18next to next-intl ([9016b76](9016b76024))
* **i18n:** update games page hero section copy ([6333c60](6333c60352))
* install embla-carousel-autoplay for games carousel ([946e5d1](946e5d1910))
* install embla-carousel-react for player profile carousel ([642ae95](642ae95738))
* internationalize guide page with 6 languages ([e9c320b](e9c320bb10))
* internationalize tutorial player ([26d41cf](26d41cfd05))
* optimize card sorting for mobile displays ([b443ee9](b443ee9cdc))
* Redesign Rithmomachia setup page with dramatic medieval theme ([6ae4d13](6ae4d13dc7))
* **rithmomachia:** add 80% opacity to guide modal when not hovered ([4a78485](4a78485d2e))
* **rithmomachia:** add CaptureContext for capture dialog state management ([d7eb957](d7eb957a8d))
* **rithmomachia:** add ghost panel preview for guide docking ([c0d6526](c0d6526d30))
* **rithmomachia:** add guide docking with resizable panels ([f457f1a](f457f1a1c2))
* **rithmomachia:** add helper piece selection for mathematical captures ([cae3359](cae3359587))
* **rithmomachia:** add helpful error messages for failed captures ([b172440](b172440a41))
* **rithmomachia:** add initial board visual to guide Overview section ([d42bcff](d42bcff0d9))
* **rithmomachia:** Add interactive playing guide modal ([3121d82](3121d8240a))
* **rithmomachia:** add number bond visualization and helper placeholders ([82d8913](82d89131f0))
* **rithmomachia:** add ratio capture example to guide ([9150b0c](9150b0c678))
* **rithmomachia:** add standalone guide page route ([3fcc79f](3fcc79fe9e))
* **rithmomachia:** add useBoardLayout hook for centralized layout calculations ([27f1c98](27f1c989d5))
* **rithmomachia:** add usePieceSelection hook for selection state management ([275f401](275f401e3c))
* **rithmomachia:** add visual board examples to Capture section ([74bc3c0](74bc3c0dcf))
* **rithmomachia:** add visual board examples to Harmony section ([1d5f01c](1d5f01c966))
* **rithmomachia:** add visual winning example to Victory section ([b7fac78](b7fac78829))
* **rithmomachia:** auto-size tab labels with react-textfit ([9fd5406](9fd54067ce))
* **rithmomachia:** cycle through valid helpers with dynamic number tooltips ([4829e41](4829e41ea1))
* **rithmomachia:** enhance capture relation UI with smooth animations ([0a30801](0a308016e9))
* **rithmomachia:** enhance Harmony section with comprehensive content ([f555856](f5558563ea))
* **rithmomachia:** enhance Pieces section with visual examples and pyramid details ([55aff82](55aff829f4))
* **rithmomachia:** enhance Pyramid section with comprehensive details ([9fde1ef](9fde1ef9e7))
* **rithmomachia:** guide defaults to docked right on open ([11f674d](11f674d542))
* **rithmomachia:** improve guide pieces section layout ([a270bfc](a270bfc0cc))
* **rithmomachia:** improve guide UX and add persistence ([b314740](b314740697))
* **rithmomachia:** improve roster status notice UX ([e27df45](e27df45256))
* **rithmomachia:** integrate roster warning into game nav ([8a11594](8a11594203))
* **rithmomachia:** make guide modal ultra-responsive down to 150px width ([0474197](04741971b2))
* **rithmomachia:** recreate original guide modal header layout ([2489695](24896957d0))
* **rithmomachia:** show capture error on hover instead of click ([339b678](339b6780f6))
* **rithmomachia:** show pyramid face numbers on hover instead of selection ([b0c4523](b0c4523c0b))
* **rithmomachia:** show pyramid face numbers when selected ([5c186f3](5c186f3947))
* **rithmomachia:** show pyramid face numbers when selected with subtle animation ([5c2ddbe](5c2ddbef05))
* **rithmomachia:** show real preview layout when dragging guide to dock ([17d2460](17d2460a87))
* **rithmomachia:** simplify guide language for clarity ([85cb630](85cb630add))
* **rithmomachia:** skip helper selection UI and auto-select first valid helper ([be2a00e](be2a00e8b3))
* **rithmomachia:** Update harmony system to classical three-piece proportions ([08c9762](08c97620f5))
* **rithmomachia:** Update to traditional board setup with 25 pieces per side ([0769eaa](0769eaaa1d))
* **rithmomachia:** use actual piece SVGs in number bond with 2.5s rotation animation ([976a7de](976a7de949))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))
* show rithmomachia turn in nav ([7c89bfe](7c89bfef9c))
* switch to royal color theme with transparent background ([944ad65](944ad6574e)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#f59e0](https://github.com/antialias/soroban-abacus-flashcards/issues/f59e0) [#a855f7](https://github.com/antialias/soroban-abacus-flashcards/issues/a855f7) [#7e22](https://github.com/antialias/soroban-abacus-flashcards/issues/7e22)
* **web:** add test page for AbacusStatic RSC compatibility ([903dea2](903dea2584))
* **web:** add test page for AbacusStatic Server Component ([3588d5a](3588d5acde))
* **web:** add Typst-based preview endpoint with React Suspense ([599a758](599a758471))
* **web:** add year abacus to calendar header and make grid bolder ([867c7ee](867c7ee172)), closes [#333](https://github.com/antialias/soroban-abacus-flashcards/issues/333)
* **web:** improve calendar abacus preview styling ([8439727](8439727b15))
* **web:** optimize monthly calendar for single-page layout ([b277a89](b277a89415))
* **web:** redesign monthly calendar as single composite SVG ([8ce8038](8ce8038bae))

### Bug Fixes

* **abacus-react:** add data-testid attributes back to beads for testing ([23ae1b0](23ae1b0c6f))
* **abacus-react:** correct column highlighting offset in AbacusStatic ([0641eb7](0641eb719e))
* **abacus-react:** fix animations by preventing component remounting ([be7d4c4](be7d4c4713))
* **abacus-react:** restore original AbacusReact measurements and positioning ([88c0baa](88c0baaad9))
* add xmlns to AbacusStatic for Typst SVG parsing ([98cd019](98cd019d4a))
* adjust hero abacus position to avoid covering subtitle ([f03d341](f03d341314))
* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** allow deactivating players from users who left the room ([7c1c2d7](7c1c2d7beb))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* board rotation now properly fills height in portrait mode ([b5a96ea](b5a96eaeb1))
* **card-sorting:** add border radius to outer card container ([a922eba](a922eba73c))
* **card-sorting:** add debug logging for spring animations ([d42947e](d42947eb8d))
* **card-sorting:** add missing gameMode support after hard reset ([a832325](a832325deb))
* **card-sorting:** add missing useMemo import ([949d76d](949d76d844))
* **card-sorting:** add overflow hidden to clip rounded corners ([84c66fe](84c66feec6))
* **card-sorting:** adjust connecting paths for scaled cards ([829c741](829c741e55))
* **card-sorting:** adjust game board for spectator panels ([fc5cf12](fc5cf1216f))
* **card-sorting:** adjust viewport dimensions for spectator panels ([4dce16c](4dce16cca4))
* **card-sorting:** animate cards from game board to results grid ([17d45fe](17d45fe88c))
* **card-sorting:** correct suffix card detection in auto-arrange ([d02ab59](d02ab5922c))
* **card-sorting:** enable card scaling for spectators ([6b095c3](6b095c3383))
* **card-sorting:** enable New Game button during active gameplay ([f3f6eca](f3f6eca1db))
* **card-sorting:** end drag immediately when card becomes locked ([ae45298](ae45298ec4))
* **card-sorting:** filter local player from emoji overlays on dragged cards ([dc2d94a](dc2d94aaa5))
* **card-sorting:** fix results panel layout to not cover cards ([4b4fbfe](4b4fbfef32))
* **card-sorting:** hide activity notifications in spectator mode ([5cca279](5cca279687))
* **card-sorting:** keep arrow sequence numbers upright ([79c9469](79c94699fa))
* **card-sorting:** lock correctly positioned prefix/suffix cards ([170abed](170abed231))
* **card-sorting:** lock spring positions after initial animation completes ([275cc62](275cc62a52))
* **card-sorting:** New Game now restarts with same settings instantly ([f3687ed](f3687ed236))
* **card-sorting:** only shrink/fade cards in correct prefix ([51368c6](51368c6ec5))
* **card-sorting:** preserve card positions on pause/resume ([0d8af09](0d8af09517))
* **card-sorting:** preserve rotation when starting drag ([3364144](3364144fb6))
* **card-sorting:** prevent duplicate START_GAME moves on Play Again ([a0b14f8](a0b14f87e9))
* **card-sorting:** prevent ghost movements with proper optimistic updates ([bd014be](bd014bec4f))
* **card-sorting:** prevent infinite loop when all cards are correct ([34785f4](34785f466f))
* **card-sorting:** prevent infinite loop with tolerance-based position comparison ([627b873](627b873382))
* **card-sorting:** prevent position jump when clicking rotated cards ([564a00f](564a00f82b))
* **card-sorting:** prevent replaying own movements from server ([308168a](308168a7fb))
* **card-sorting:** prevent springs from reinitializing on window resize ([30953b8](30953b8c4a))
* **card-sorting:** prevent springs from resetting after animation ([8aff60c](8aff60ce3f))
* **card-sorting:** remove hasAnimatedRef logic causing backwards animation ([a44aa5a](a44aa5a4c2))
* **card-sorting:** remove remaining reveal numbers references ([15c53ea](15c53ea4eb))
* **card-sorting:** restore prefix/suffix card shrinking visual feedback ([f5fb4d7](f5fb4d7b76))
* **card-sorting:** show only active players in team members section ([fa9f1a5](fa9f1a568f))
* **card-sorting:** smooth scale animation while dragging cards ([0eefc33](0eefc332ac))
* **card-sorting:** stabilize inferred sequence for locked cards during drag ([b0cd194](b0cd194838))
* **card-sorting:** use empty deps array for useSprings to prevent recreation ([cee399e](cee399ed15))
* **card-sorting:** use ref to track initialized state and prevent re-animation ([f389afa](f389afa831))
* **card-sorting:** use same coordinate system for game board and results ([6972fdf](6972fdf110))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* configure favicon metadata and improve bead visibility ([e1369fa](e1369fa275))
* copy entire packages/core and packages/templates ([0ccada0](0ccada0ca7))
* correct hero abacus scroll direction to flow with page content ([4232746](423274657c))
* correct Typst template path in Dockerfile ([4c518de](4c518decb7))
* delete existing user sessions before creating new ones ([0cced47](0cced47a0f))
* **docker:** add scripts, abacus-react, and tsx for production calendar generation ([33eb90e](33eb90e316))
* extract pure SVG content from AbacusReact renders ([b07f1c4](b07f1c4216))
* **games:** prevent horizontal page scroll from carousel overflow ([5a8c98f](5a8c98fc10))
* **games:** smooth scroll feel for carousel wheel navigation ([f80a73b](f80a73b35c))
* **games:** use specific transition properties for smooth carousel loop ([187271e](187271e515))
* **guide:** make abacus sizes consistent and add nav spacing ([bea4842](bea4842a29))
* **i18n:** eliminate FOUC by loading messages server-side ([4d4d930](4d4d930bd3))
* **i18n:** use useMessages() for tutorial translations ([95b0105](95b0105ca3))
* include column posts in favicon bounding box ([0b2f481](0b2f48106a))
* increase server update debounce to 2000ms for low bandwidth ([633ff12](633ff12750))
* Integrate threshold input into Point Victory card ([b29bbee](b29bbeefca))
* **layout:** add systematic spacing for fixed nav bar ([4559fb1](4559fb121d))
* **layout:** remove wrapper, use utility class for nav spacing ([247c3d9](247c3d9874))
* mark dynamic routes as force-dynamic to prevent static generation errors ([d7b35d9](d7b35d9544))
* **nav:** restrict transparent hero styling to home page only ([fab227d](fab227d686))
* **nav:** show full navigation on /games page ([d3fe6ac](d3fe6acbb0))
* **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))
* reduce padding to minimize gap below last bead ([0e529be](0e529be789))
* remove distracting parallax and wobble 3D effects ([28a2d40](28a2d40996))
* remove wobble physics and enhance wood grain visibility ([5d97673](5d97673406))
* resolve z-index layering and hero abacus visibility issues ([ed9a050](ed9a050d64))
* rewrite 3D stories to use props instead of CSS wrappers ([26bdb11](26bdb11237))
* **rithmomachia:** add missing i18next dependencies ([91154d9](91154d9364))
* **rithmomachia:** add missing pyramid section keys to Japanese (ja.json) ([dae615e](dae615ee72))
* **rithmomachia:** adjust error dialog sizing to prevent text clipping ([cda1126](cda1126cb0))
* **rithmomachia:** adjust roster notice position to not overlap nav ([7093223](709322373a))
* **rithmomachia:** change undock icon to pop-out arrow ([2a91748](2a91748493))
* **rithmomachia:** correct board dimensions to 16x8 and restore original layout values ([cfac277](cfac277505))
* **rithmomachia:** Correct board setup to match reference image exactly ([618e563](618e56358d))
* **rithmomachia:** correct makeMove parameter types for capture handling ([aafb64f](aafb64f3e3))
* **rithmomachia:** fix guide modal resize drift by calculating from initial state ([1bcd99c](1bcd99c949))
* **rithmomachia:** fix harmony section translation structure for hi/ja/es ([14259a1](14259a19a9))
* **rithmomachia:** fix modal resizing zoom issue ([4fa20f4](4fa20f44cb))
* **rithmomachia:** Fix TypeScript errors in playing guide modal ([4834ece](4834ece98e))
* **rithmomachia:** handle pyramid pieces in hover error tooltip ([56f3164](56f3164155))
* **rithmomachia:** implement proper board cropping and highlighting in guide ([d0a8fcd](d0a8fcdea6))
* **rithmomachia:** improve guide modal tab navigation at narrow widths ([a673177](a673177bec))
* **rithmomachia:** reconnect player assignment UI and fix setup layout ([a1a0374](a1a0374fac))
* **rithmomachia:** render guide as docked in preview panel ([190f8cf](190f8cf302))
* **rithmomachia:** show actual values in tooltips for non-helper relations ([774c6b0](774c6b0ce7))
* **rithmomachia:** show guest-friendly message when they can't fix too many players ([54bfd2f](54bfd2fac8))
* **rithmomachia:** smooth guide dragging from docked state without jump ([8f4a79c](8f4a79c9b0))
* **rithmomachia:** validate move path before showing capture error on hover ([bd49964](bd49964186))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))
* separate horizontal and vertical bounding box logic ([83090df](83090df4df))
* tolerate OpenSCAD CGAL warnings if output file is created ([88993f3](88993f3662))
* **tutorial:** correct column validation for bead highlights ([9ba1824](9ba1824226))
* **tutorial:** fix overlay rendering, arrow indicators, and bead visibility ([a804316](a80431608d))
* use absolute positioning for hero abacus to eliminate scroll lag ([096104b](096104b094))
* use Debian base for deps stage to match runner for binary compatibility ([f8fe6e4](f8fe6e4a41))
* use default BOSL2 branch instead of non-existent v2.0.0 tag ([f4ffc5b](f4ffc5b027))
* use nested SVG viewBox for actual cropping, not just scaling ([440b492](440b492e85))
* various game improvements and UI enhancements ([b67cf61](b67cf610c5))
* **web,docker:** add --format flag for Typst and upgrade to v0.13.0 ([19b9d7a](19b9d7a74f))
* **web:** add dynamic export to rithmomachia page ([329e623](329e623212))
* **web:** fix Typst PDF generation path resolution ([7ce1287](7ce1287525))
* **web:** generate styled-system artifacts during build ([293390a](293390ae35))
* **web:** move react-dom/server import to API route to satisfy Next.js ([00a8bc3](00a8bc3e5e))
* **web:** move tsx to production dependencies for calendar generation ([ffae9c1](ffae9c1bdb))
* **web:** prevent abacus overlap in composite calendar ([448f93c](448f93c1e2)), closes [#f0f0f0](https://github.com/antialias/soroban-abacus-flashcards/issues/f0f0f0)
* **web:** use AbacusStatic for calendar SVG generation ([08c6a41](08c6a419e2))
* **web:** use dynamic import for react-dom/server in API route ([4f93c7d](4f93c7d996))
* **web:** use nested SVG elements to prevent coordinate space conflicts ([f9cbee8](f9cbee8fcd))

### Performance Improvements

* optimize Docker image size to reduce build failures ([9ca3106](9ca3106361))

### Code Refactoring

* **card-sorting:** remove reveal numbers feature ([ea5e3e8](ea5e3e838b))
* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))
* **games:** implement carousel, fix victories bug, add conditional stats ([82c133f](82c133f742))
* **games:** move page title to nav bar ([712ee58](712ee58e59))
* **games:** remove redundant subtitle below nav ([ad5bb87](ad5bb87325))
* **games:** remove wheel scrolling, enable overflow visible carousel ([876513c](876513c9cc))
* **layout:** make nav height truly self-referential ([9886302](98863026b7))
* reorganize Harmony and Victory guide sections ([fb629c4](fb629c44ea))
* restructure /create page into hub with sub-pages ([b91b23d](b91b23d95f))
* **rithmomachia:** extract board and capture components (phase 2+3) ([a0a867b](a0a867b271))
* **rithmomachia:** extract CaptureErrorDialog component (Phase 2 partial) ([f0a066d](f0a066d8f0))
* **rithmomachia:** extract constants and coordinate utilities (Phase 1) ([eace0ed](eace0ed529))
* **rithmomachia:** extract guide sections into separate files ([765525d](765525dc45))
* **rithmomachia:** extract hooks (phase 5) ([324a659](324a65992f))
* **rithmomachia:** extract phase components (phase 4) ([11364f6](11364f6394))
* **rithmomachia:** extract reusable components from SetupPhase ([3abc325](3abc325ea2))
* **rithmomachia:** make setup phase UI more compact ([e55f848](e55f848a26))
* **rithmomachia:** redesign error notification with modern UI ([dfeeb0e](dfeeb0e0db)), closes [#1e293](https://github.com/antialias/soroban-abacus-flashcards/issues/1e293) [#0f172](https://github.com/antialias/soroban-abacus-flashcards/issues/0f172) [#f1f5f9](https://github.com/antialias/soroban-abacus-flashcards/issues/f1f5f9)
* **rithmomachia:** simplify capture error dialog to one-liner ([82a5eb2](82a5eb2e4b))
* **rithmomachia:** Update board setup to authoritative CSV layout ([0471da5](0471da598d))
* **rithmomachia:** update capture components to use CaptureContext ([2ab6ab5](2ab6ab5799))
* **rithmomachia:** use useBoardLayout and usePieceSelection in BoardDisplay ([0ab7a1d](0ab7a1df32))
* use AbacusReact for dynamic Open Graph image ([9c20f12](9c20f12bac))
* **web:** import utility functions from abacus-react ([7228bbc](7228bbc2eb))
* **web:** move calendar generators to src/utils for proper compilation ([379698f](379698fea3))
* **web:** return calendar SVG preview with PDF generation ([14a5de0](14a5de0dfa))
* **web:** use ABACUS_THEMES instead of manual style definitions ([9f7f001](9f7f001d74))
* **web:** use client-side React rendering for live calendar preview ([f880cbe](f880cbe4bf))
* **web:** use compact prop for inline mini-abacus ([ff1d60a](ff1d60a233))
* **web:** use direct function imports instead of execSync for calendar generation ([9f1715f](9f1715f085))
* **web:** use stdin/stdout for Typst compilation ([06f68cc](06f68cc74c))

### Documentation

* **abacus-react:** add Storybook stories for AbacusStatic ([4f9dc46](4f9dc4666d))
* **abacus-react:** add Storybook stories for new features ([6a1cec0](6a1cec06a7))
* **abacus-react:** export AbacusStatic and update README ([74f2d97](74f2d97434))
* **abacus-react:** update documentation for new features ([35d8734](35d8734a3a))
* **abacus-react:** update README with /static import path for RSC ([72a4c2b](72a4c2b80c))
* add 3D enhancement documentation to README ([cc96802](cc96802df8))
* add critical section on never adding tsx to production dependencies ([770cfc3](770cfc3aca))
* add database migration guide and playing guide modal spec ([5a29af7](5a29af78e2))
* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* **card-sorting:** add comprehensive multiplayer plan ([008ccea](008ccead0f))
* **rithmomachia:** Add concise one-page playing guide ([e3c1f10](e3c1f10233))
* update workflow to require manual testing before commits ([0991796](0991796f1e))

### Styles

* **rithmomachia:** improve divider styling and make tabs responsive ([88ca35e](88ca35e044)), closes [#e5e7](https://github.com/antialias/soroban-abacus-flashcards/issues/e5e7) [#9ca3](https://github.com/antialias/soroban-abacus-flashcards/issues/9ca3)
* **rithmomachia:** improve pyramid face numbers visibility and contrast ([94e5e6a](94e5e6a268)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#b45309](https://github.com/antialias/soroban-abacus-flashcards/issues/b45309)
* **rithmomachia:** increase pyramid face numbers size and boldness ([7bf2d73](7bf2d730d3))

### Tests

* trigger compose-updater deployment test ([2b06aae](2b06aae394))
* verify compose-updater automatic deployment cycle ([af0552c](af0552ccd9))
2025-11-05 01:30:56 +00:00
Thomas Hallock
bea4842a29 fix(guide): make abacus sizes consistent and add nav spacing
Fixed inconsistent abacus sizing in guide:
- Replaced aspect ratio containers with fixed dimensions
- Single-digit abacuses: 120px × 240px (consistent vertical layout)
- Multi-digit abacuses: 180px × 200px (horizontal layout)
- Added inner wrapper div for proper AbacusReact sizing
- Centered containers with mx: 'auto'
- Adjusted scale factors for better fit (0.7 and 0.8)

Also added with-fixed-nav class to guide page to prevent white bar
under navigation.

Fixes: Inconsistent abacus sizes in guide page screenshot

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 19:26:25 -06:00
semantic-release-bot
bf1ed6890a 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-11-05)

### Features

* **abacus-react:** add AbacusStatic for React Server Components ([3b8e864](3b8e864cfa))
* **abacus-react:** add core utility functions for state management ([e65541c](e65541c100))
* **abacus-react:** add layout and educational props ([35bbcec](35bbcecb9e))
* **abacus-react:** add pre-defined theme presets ([cf1f950](cf1f950c7c))
* **abacus-react:** add React hooks for abacus calculations ([de038d2](de038d2afc))
* **abacus-react:** add separate /static export path for React Server Components ([ed69f6b](ed69f6b917))
* **abacus-react:** add shared dimension calculator for consistent sizing ([e5ba772](e5ba772fde))
* **abacus-react:** export new utilities, hooks, and themes ([ce4e44d](ce4e44d630))
* **abacus:** add nativeAbacusNumbers setting to schema and UI ([79f7347](79f7347d48))
* add 3D printing support for abacus models ([dafdfdd](dafdfdd233))
* add comprehensive metadata, SEO, and make AbacusReact SSR-compatible ([0922ea1](0922ea10b7))
* add comprehensive Storybook coverage and migration guide ([7a4a37e](7a4a37ec6d))
* add game preview system with mock arcade environment ([25880cc](25880cc7e4))
* add per-player stats tracking system ([613301c](613301cd13))
* add Strategy & Tactics section to Rithmomachia guide ([81ead65](81ead65680))
* add unified trophy abacus with hero mode integration ([6620418](6620418a70))
* **arcade:** add ability to deactivate remote players without kicking user ([3628426](3628426a56))
* **arcade:** add native abacus numbers support to pressure gauge ([1d525c7](1d525c7b53))
* **arcade:** add Rithmomachia (Battle of Numbers) game ([2fc0a05](2fc0a05f7f))
* **arcade:** add yjs-demo collaborative game and Yjs persistence layer ([d568955](d568955d6a))
* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add activity feed notifications for collaborative mode ([1461414](1461414ef4))
* **card-sorting:** add auto-submit countdown for perfect sequences ([780a716](780a7161bc))
* **card-sorting:** add bezier curves to connecting arrows ([4d8e873](4d8e873358))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add collapsible stats sidebar for spectators ([6527c26](6527c26a81))
* **card-sorting:** add game mode selector UI to setup phase ([d25b888](d25b888ffb))
* **card-sorting:** add GameMode type system for multiplayer support ([fd76533](fd765335ef))
* **card-sorting:** add green border to correctly positioned cards ([16fca86](16fca86b76)), closes [#22c55](https://github.com/antialias/soroban-abacus-flashcards/issues/22c55)
* **card-sorting:** add player emoji indicators on moving cards ([3a82099](3a82099757))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add smooth transition to drop shadow ([b0b93d0](b0b93d0175))
* **card-sorting:** add spectator mode UI enhancements ([ee7345d](ee7345d641)), closes [#6366f1](https://github.com/antialias/soroban-abacus-flashcards/issues/6366f1) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add team scoring UI for collaborative mode ([ed6f177](ed6f177914)), closes [#a78](https://github.com/antialias/soroban-abacus-flashcards/issues/a78) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **card-sorting:** auto-arrange prefix/suffix cards in corners ([4ba7f24](4ba7f24717))
* **card-sorting:** fade correctly positioned cards to 50% opacity ([7028cfc](7028cfc511))
* **card-sorting:** gentler spring animation for locked cards ([47189cb](47189cb6e7))
* **card-sorting:** implement continuous bezier curve paths ([2d93024](2d9302410f))
* **card-sorting:** improve card distribution for natural scattered look ([0b0503f](0b0503f035))
* **card-sorting:** make player emoji fill entire card background ([2e7a02c](2e7a02c9e4))
* **card-sorting:** optimize results screen for mobile ([d188789](d188789069))
* **card-sorting:** redesign setup screen with modern UI ([73cf967](73cf967492))
* **card-sorting:** scale correctly positioned cards to 50% ([222dc55](222dc555fa))
* **card-sorting:** shrink/fade cards in correct suffix as well ([8f6feec](8f6feec4f2))
* **card-sorting:** smooth spring transition from game table to results grid ([c5f39d5](c5f39d51eb))
* **card-sorting:** wrap prefix/suffix cards to multiple rows ([e3184dd](e3184dd0d4))
* complete 3D enhancement integration for all three proposals ([5ac55cc](5ac55cc149))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* dynamic day-of-month favicon using subprocess pattern ([4d0795a](4d0795a9df))
* dynamically crop favicon to active beads for maximum size ([5670322](567032296a))
* enable 3D enhancement on hero/open MyAbacus modes ([37e330f](37e330f26e))
* **games:** add autoplay and improve carousel layout ([9f51edf](9f51edfaa9))
* **games:** add horizontal scroll support to carousels ([a224abb](a224abb6f6))
* **games:** add rotating games hero carousel ([24231e6](24231e6b2e))
* **i18n:** add dynamic locale switching without page reload ([fe9bfea](fe9bfeabf9))
* **i18n:** add global language selector to navigation ([0506360](0506360117))
* **i18n:** add homepage translations for all supported languages ([8c9d35a](8c9d35a3b4))
* **i18n:** add Old High German (goh) language support ([b334a15](b334a15255))
* **i18n:** complete Old High German translations for all locales ([0b06a1c](0b06a1ce00))
* **i18n:** internationalize games page and tutorial content ([4253964](4253964af1))
* **i18n:** internationalize homepage with English translations ([40cff14](40cff143c7))
* **i18n:** migrate from react-i18next to next-intl ([9016b76](9016b76024))
* **i18n:** update games page hero section copy ([6333c60](6333c60352))
* install embla-carousel-autoplay for games carousel ([946e5d1](946e5d1910))
* install embla-carousel-react for player profile carousel ([642ae95](642ae95738))
* internationalize guide page with 6 languages ([e9c320b](e9c320bb10))
* internationalize tutorial player ([26d41cf](26d41cfd05))
* optimize card sorting for mobile displays ([b443ee9](b443ee9cdc))
* Redesign Rithmomachia setup page with dramatic medieval theme ([6ae4d13](6ae4d13dc7))
* **rithmomachia:** add 80% opacity to guide modal when not hovered ([4a78485](4a78485d2e))
* **rithmomachia:** add CaptureContext for capture dialog state management ([d7eb957](d7eb957a8d))
* **rithmomachia:** add ghost panel preview for guide docking ([c0d6526](c0d6526d30))
* **rithmomachia:** add guide docking with resizable panels ([f457f1a](f457f1a1c2))
* **rithmomachia:** add helper piece selection for mathematical captures ([cae3359](cae3359587))
* **rithmomachia:** add helpful error messages for failed captures ([b172440](b172440a41))
* **rithmomachia:** add initial board visual to guide Overview section ([d42bcff](d42bcff0d9))
* **rithmomachia:** Add interactive playing guide modal ([3121d82](3121d8240a))
* **rithmomachia:** add number bond visualization and helper placeholders ([82d8913](82d89131f0))
* **rithmomachia:** add ratio capture example to guide ([9150b0c](9150b0c678))
* **rithmomachia:** add standalone guide page route ([3fcc79f](3fcc79fe9e))
* **rithmomachia:** add useBoardLayout hook for centralized layout calculations ([27f1c98](27f1c989d5))
* **rithmomachia:** add usePieceSelection hook for selection state management ([275f401](275f401e3c))
* **rithmomachia:** add visual board examples to Capture section ([74bc3c0](74bc3c0dcf))
* **rithmomachia:** add visual board examples to Harmony section ([1d5f01c](1d5f01c966))
* **rithmomachia:** add visual winning example to Victory section ([b7fac78](b7fac78829))
* **rithmomachia:** auto-size tab labels with react-textfit ([9fd5406](9fd54067ce))
* **rithmomachia:** cycle through valid helpers with dynamic number tooltips ([4829e41](4829e41ea1))
* **rithmomachia:** enhance capture relation UI with smooth animations ([0a30801](0a308016e9))
* **rithmomachia:** enhance Harmony section with comprehensive content ([f555856](f5558563ea))
* **rithmomachia:** enhance Pieces section with visual examples and pyramid details ([55aff82](55aff829f4))
* **rithmomachia:** enhance Pyramid section with comprehensive details ([9fde1ef](9fde1ef9e7))
* **rithmomachia:** guide defaults to docked right on open ([11f674d](11f674d542))
* **rithmomachia:** improve guide pieces section layout ([a270bfc](a270bfc0cc))
* **rithmomachia:** improve guide UX and add persistence ([b314740](b314740697))
* **rithmomachia:** improve roster status notice UX ([e27df45](e27df45256))
* **rithmomachia:** integrate roster warning into game nav ([8a11594](8a11594203))
* **rithmomachia:** make guide modal ultra-responsive down to 150px width ([0474197](04741971b2))
* **rithmomachia:** recreate original guide modal header layout ([2489695](24896957d0))
* **rithmomachia:** show capture error on hover instead of click ([339b678](339b6780f6))
* **rithmomachia:** show pyramid face numbers on hover instead of selection ([b0c4523](b0c4523c0b))
* **rithmomachia:** show pyramid face numbers when selected ([5c186f3](5c186f3947))
* **rithmomachia:** show pyramid face numbers when selected with subtle animation ([5c2ddbe](5c2ddbef05))
* **rithmomachia:** show real preview layout when dragging guide to dock ([17d2460](17d2460a87))
* **rithmomachia:** simplify guide language for clarity ([85cb630](85cb630add))
* **rithmomachia:** skip helper selection UI and auto-select first valid helper ([be2a00e](be2a00e8b3))
* **rithmomachia:** Update harmony system to classical three-piece proportions ([08c9762](08c97620f5))
* **rithmomachia:** Update to traditional board setup with 25 pieces per side ([0769eaa](0769eaaa1d))
* **rithmomachia:** use actual piece SVGs in number bond with 2.5s rotation animation ([976a7de](976a7de949))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))
* show rithmomachia turn in nav ([7c89bfe](7c89bfef9c))
* switch to royal color theme with transparent background ([944ad65](944ad6574e)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#f59e0](https://github.com/antialias/soroban-abacus-flashcards/issues/f59e0) [#a855f7](https://github.com/antialias/soroban-abacus-flashcards/issues/a855f7) [#7e22](https://github.com/antialias/soroban-abacus-flashcards/issues/7e22)
* **web:** add test page for AbacusStatic RSC compatibility ([903dea2](903dea2584))
* **web:** add test page for AbacusStatic Server Component ([3588d5a](3588d5acde))
* **web:** add Typst-based preview endpoint with React Suspense ([599a758](599a758471))
* **web:** add year abacus to calendar header and make grid bolder ([867c7ee](867c7ee172)), closes [#333](https://github.com/antialias/soroban-abacus-flashcards/issues/333)
* **web:** improve calendar abacus preview styling ([8439727](8439727b15))
* **web:** optimize monthly calendar for single-page layout ([b277a89](b277a89415))
* **web:** redesign monthly calendar as single composite SVG ([8ce8038](8ce8038bae))

### Bug Fixes

* **abacus-react:** add data-testid attributes back to beads for testing ([23ae1b0](23ae1b0c6f))
* **abacus-react:** correct column highlighting offset in AbacusStatic ([0641eb7](0641eb719e))
* **abacus-react:** fix animations by preventing component remounting ([be7d4c4](be7d4c4713))
* **abacus-react:** restore original AbacusReact measurements and positioning ([88c0baa](88c0baaad9))
* add xmlns to AbacusStatic for Typst SVG parsing ([98cd019](98cd019d4a))
* adjust hero abacus position to avoid covering subtitle ([f03d341](f03d341314))
* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** allow deactivating players from users who left the room ([7c1c2d7](7c1c2d7beb))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* board rotation now properly fills height in portrait mode ([b5a96ea](b5a96eaeb1))
* **card-sorting:** add border radius to outer card container ([a922eba](a922eba73c))
* **card-sorting:** add debug logging for spring animations ([d42947e](d42947eb8d))
* **card-sorting:** add missing gameMode support after hard reset ([a832325](a832325deb))
* **card-sorting:** add missing useMemo import ([949d76d](949d76d844))
* **card-sorting:** add overflow hidden to clip rounded corners ([84c66fe](84c66feec6))
* **card-sorting:** adjust connecting paths for scaled cards ([829c741](829c741e55))
* **card-sorting:** adjust game board for spectator panels ([fc5cf12](fc5cf1216f))
* **card-sorting:** adjust viewport dimensions for spectator panels ([4dce16c](4dce16cca4))
* **card-sorting:** animate cards from game board to results grid ([17d45fe](17d45fe88c))
* **card-sorting:** correct suffix card detection in auto-arrange ([d02ab59](d02ab5922c))
* **card-sorting:** enable card scaling for spectators ([6b095c3](6b095c3383))
* **card-sorting:** enable New Game button during active gameplay ([f3f6eca](f3f6eca1db))
* **card-sorting:** end drag immediately when card becomes locked ([ae45298](ae45298ec4))
* **card-sorting:** filter local player from emoji overlays on dragged cards ([dc2d94a](dc2d94aaa5))
* **card-sorting:** fix results panel layout to not cover cards ([4b4fbfe](4b4fbfef32))
* **card-sorting:** hide activity notifications in spectator mode ([5cca279](5cca279687))
* **card-sorting:** keep arrow sequence numbers upright ([79c9469](79c94699fa))
* **card-sorting:** lock correctly positioned prefix/suffix cards ([170abed](170abed231))
* **card-sorting:** lock spring positions after initial animation completes ([275cc62](275cc62a52))
* **card-sorting:** New Game now restarts with same settings instantly ([f3687ed](f3687ed236))
* **card-sorting:** only shrink/fade cards in correct prefix ([51368c6](51368c6ec5))
* **card-sorting:** preserve card positions on pause/resume ([0d8af09](0d8af09517))
* **card-sorting:** preserve rotation when starting drag ([3364144](3364144fb6))
* **card-sorting:** prevent duplicate START_GAME moves on Play Again ([a0b14f8](a0b14f87e9))
* **card-sorting:** prevent ghost movements with proper optimistic updates ([bd014be](bd014bec4f))
* **card-sorting:** prevent infinite loop when all cards are correct ([34785f4](34785f466f))
* **card-sorting:** prevent infinite loop with tolerance-based position comparison ([627b873](627b873382))
* **card-sorting:** prevent position jump when clicking rotated cards ([564a00f](564a00f82b))
* **card-sorting:** prevent replaying own movements from server ([308168a](308168a7fb))
* **card-sorting:** prevent springs from reinitializing on window resize ([30953b8](30953b8c4a))
* **card-sorting:** prevent springs from resetting after animation ([8aff60c](8aff60ce3f))
* **card-sorting:** remove hasAnimatedRef logic causing backwards animation ([a44aa5a](a44aa5a4c2))
* **card-sorting:** remove remaining reveal numbers references ([15c53ea](15c53ea4eb))
* **card-sorting:** restore prefix/suffix card shrinking visual feedback ([f5fb4d7](f5fb4d7b76))
* **card-sorting:** show only active players in team members section ([fa9f1a5](fa9f1a568f))
* **card-sorting:** smooth scale animation while dragging cards ([0eefc33](0eefc332ac))
* **card-sorting:** stabilize inferred sequence for locked cards during drag ([b0cd194](b0cd194838))
* **card-sorting:** use empty deps array for useSprings to prevent recreation ([cee399e](cee399ed15))
* **card-sorting:** use ref to track initialized state and prevent re-animation ([f389afa](f389afa831))
* **card-sorting:** use same coordinate system for game board and results ([6972fdf](6972fdf110))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* configure favicon metadata and improve bead visibility ([e1369fa](e1369fa275))
* copy entire packages/core and packages/templates ([0ccada0](0ccada0ca7))
* correct hero abacus scroll direction to flow with page content ([4232746](423274657c))
* correct Typst template path in Dockerfile ([4c518de](4c518decb7))
* delete existing user sessions before creating new ones ([0cced47](0cced47a0f))
* **docker:** add scripts, abacus-react, and tsx for production calendar generation ([33eb90e](33eb90e316))
* extract pure SVG content from AbacusReact renders ([b07f1c4](b07f1c4216))
* **games:** prevent horizontal page scroll from carousel overflow ([5a8c98f](5a8c98fc10))
* **games:** smooth scroll feel for carousel wheel navigation ([f80a73b](f80a73b35c))
* **games:** use specific transition properties for smooth carousel loop ([187271e](187271e515))
* **i18n:** eliminate FOUC by loading messages server-side ([4d4d930](4d4d930bd3))
* **i18n:** use useMessages() for tutorial translations ([95b0105](95b0105ca3))
* include column posts in favicon bounding box ([0b2f481](0b2f48106a))
* increase server update debounce to 2000ms for low bandwidth ([633ff12](633ff12750))
* Integrate threshold input into Point Victory card ([b29bbee](b29bbeefca))
* **layout:** add systematic spacing for fixed nav bar ([4559fb1](4559fb121d))
* **layout:** remove wrapper, use utility class for nav spacing ([247c3d9](247c3d9874))
* mark dynamic routes as force-dynamic to prevent static generation errors ([d7b35d9](d7b35d9544))
* **nav:** restrict transparent hero styling to home page only ([fab227d](fab227d686))
* **nav:** show full navigation on /games page ([d3fe6ac](d3fe6acbb0))
* **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))
* reduce padding to minimize gap below last bead ([0e529be](0e529be789))
* remove distracting parallax and wobble 3D effects ([28a2d40](28a2d40996))
* remove wobble physics and enhance wood grain visibility ([5d97673](5d97673406))
* resolve z-index layering and hero abacus visibility issues ([ed9a050](ed9a050d64))
* rewrite 3D stories to use props instead of CSS wrappers ([26bdb11](26bdb11237))
* **rithmomachia:** add missing i18next dependencies ([91154d9](91154d9364))
* **rithmomachia:** add missing pyramid section keys to Japanese (ja.json) ([dae615e](dae615ee72))
* **rithmomachia:** adjust error dialog sizing to prevent text clipping ([cda1126](cda1126cb0))
* **rithmomachia:** adjust roster notice position to not overlap nav ([7093223](709322373a))
* **rithmomachia:** change undock icon to pop-out arrow ([2a91748](2a91748493))
* **rithmomachia:** correct board dimensions to 16x8 and restore original layout values ([cfac277](cfac277505))
* **rithmomachia:** Correct board setup to match reference image exactly ([618e563](618e56358d))
* **rithmomachia:** correct makeMove parameter types for capture handling ([aafb64f](aafb64f3e3))
* **rithmomachia:** fix guide modal resize drift by calculating from initial state ([1bcd99c](1bcd99c949))
* **rithmomachia:** fix harmony section translation structure for hi/ja/es ([14259a1](14259a19a9))
* **rithmomachia:** fix modal resizing zoom issue ([4fa20f4](4fa20f44cb))
* **rithmomachia:** Fix TypeScript errors in playing guide modal ([4834ece](4834ece98e))
* **rithmomachia:** handle pyramid pieces in hover error tooltip ([56f3164](56f3164155))
* **rithmomachia:** implement proper board cropping and highlighting in guide ([d0a8fcd](d0a8fcdea6))
* **rithmomachia:** improve guide modal tab navigation at narrow widths ([a673177](a673177bec))
* **rithmomachia:** reconnect player assignment UI and fix setup layout ([a1a0374](a1a0374fac))
* **rithmomachia:** render guide as docked in preview panel ([190f8cf](190f8cf302))
* **rithmomachia:** show actual values in tooltips for non-helper relations ([774c6b0](774c6b0ce7))
* **rithmomachia:** show guest-friendly message when they can't fix too many players ([54bfd2f](54bfd2fac8))
* **rithmomachia:** smooth guide dragging from docked state without jump ([8f4a79c](8f4a79c9b0))
* **rithmomachia:** validate move path before showing capture error on hover ([bd49964](bd49964186))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))
* separate horizontal and vertical bounding box logic ([83090df](83090df4df))
* tolerate OpenSCAD CGAL warnings if output file is created ([88993f3](88993f3662))
* **tutorial:** correct column validation for bead highlights ([9ba1824](9ba1824226))
* **tutorial:** fix overlay rendering, arrow indicators, and bead visibility ([a804316](a80431608d))
* use absolute positioning for hero abacus to eliminate scroll lag ([096104b](096104b094))
* use Debian base for deps stage to match runner for binary compatibility ([f8fe6e4](f8fe6e4a41))
* use default BOSL2 branch instead of non-existent v2.0.0 tag ([f4ffc5b](f4ffc5b027))
* use nested SVG viewBox for actual cropping, not just scaling ([440b492](440b492e85))
* various game improvements and UI enhancements ([b67cf61](b67cf610c5))
* **web,docker:** add --format flag for Typst and upgrade to v0.13.0 ([19b9d7a](19b9d7a74f))
* **web:** add dynamic export to rithmomachia page ([329e623](329e623212))
* **web:** fix Typst PDF generation path resolution ([7ce1287](7ce1287525))
* **web:** generate styled-system artifacts during build ([293390a](293390ae35))
* **web:** move react-dom/server import to API route to satisfy Next.js ([00a8bc3](00a8bc3e5e))
* **web:** move tsx to production dependencies for calendar generation ([ffae9c1](ffae9c1bdb))
* **web:** prevent abacus overlap in composite calendar ([448f93c](448f93c1e2)), closes [#f0f0f0](https://github.com/antialias/soroban-abacus-flashcards/issues/f0f0f0)
* **web:** use AbacusStatic for calendar SVG generation ([08c6a41](08c6a419e2))
* **web:** use dynamic import for react-dom/server in API route ([4f93c7d](4f93c7d996))
* **web:** use nested SVG elements to prevent coordinate space conflicts ([f9cbee8](f9cbee8fcd))

### Performance Improvements

* optimize Docker image size to reduce build failures ([9ca3106](9ca3106361))

### Code Refactoring

* **card-sorting:** remove reveal numbers feature ([ea5e3e8](ea5e3e838b))
* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))
* **games:** implement carousel, fix victories bug, add conditional stats ([82c133f](82c133f742))
* **games:** move page title to nav bar ([712ee58](712ee58e59))
* **games:** remove redundant subtitle below nav ([ad5bb87](ad5bb87325))
* **games:** remove wheel scrolling, enable overflow visible carousel ([876513c](876513c9cc))
* **layout:** make nav height truly self-referential ([9886302](98863026b7))
* reorganize Harmony and Victory guide sections ([fb629c4](fb629c44ea))
* restructure /create page into hub with sub-pages ([b91b23d](b91b23d95f))
* **rithmomachia:** extract board and capture components (phase 2+3) ([a0a867b](a0a867b271))
* **rithmomachia:** extract CaptureErrorDialog component (Phase 2 partial) ([f0a066d](f0a066d8f0))
* **rithmomachia:** extract constants and coordinate utilities (Phase 1) ([eace0ed](eace0ed529))
* **rithmomachia:** extract guide sections into separate files ([765525d](765525dc45))
* **rithmomachia:** extract hooks (phase 5) ([324a659](324a65992f))
* **rithmomachia:** extract phase components (phase 4) ([11364f6](11364f6394))
* **rithmomachia:** extract reusable components from SetupPhase ([3abc325](3abc325ea2))
* **rithmomachia:** make setup phase UI more compact ([e55f848](e55f848a26))
* **rithmomachia:** redesign error notification with modern UI ([dfeeb0e](dfeeb0e0db)), closes [#1e293](https://github.com/antialias/soroban-abacus-flashcards/issues/1e293) [#0f172](https://github.com/antialias/soroban-abacus-flashcards/issues/0f172) [#f1f5f9](https://github.com/antialias/soroban-abacus-flashcards/issues/f1f5f9)
* **rithmomachia:** simplify capture error dialog to one-liner ([82a5eb2](82a5eb2e4b))
* **rithmomachia:** Update board setup to authoritative CSV layout ([0471da5](0471da598d))
* **rithmomachia:** update capture components to use CaptureContext ([2ab6ab5](2ab6ab5799))
* **rithmomachia:** use useBoardLayout and usePieceSelection in BoardDisplay ([0ab7a1d](0ab7a1df32))
* use AbacusReact for dynamic Open Graph image ([9c20f12](9c20f12bac))
* **web:** import utility functions from abacus-react ([7228bbc](7228bbc2eb))
* **web:** move calendar generators to src/utils for proper compilation ([379698f](379698fea3))
* **web:** return calendar SVG preview with PDF generation ([14a5de0](14a5de0dfa))
* **web:** use ABACUS_THEMES instead of manual style definitions ([9f7f001](9f7f001d74))
* **web:** use client-side React rendering for live calendar preview ([f880cbe](f880cbe4bf))
* **web:** use compact prop for inline mini-abacus ([ff1d60a](ff1d60a233))
* **web:** use direct function imports instead of execSync for calendar generation ([9f1715f](9f1715f085))
* **web:** use stdin/stdout for Typst compilation ([06f68cc](06f68cc74c))

### Documentation

* **abacus-react:** add Storybook stories for AbacusStatic ([4f9dc46](4f9dc4666d))
* **abacus-react:** add Storybook stories for new features ([6a1cec0](6a1cec06a7))
* **abacus-react:** export AbacusStatic and update README ([74f2d97](74f2d97434))
* **abacus-react:** update documentation for new features ([35d8734](35d8734a3a))
* **abacus-react:** update README with /static import path for RSC ([72a4c2b](72a4c2b80c))
* add 3D enhancement documentation to README ([cc96802](cc96802df8))
* add critical section on never adding tsx to production dependencies ([770cfc3](770cfc3aca))
* add database migration guide and playing guide modal spec ([5a29af7](5a29af78e2))
* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* **card-sorting:** add comprehensive multiplayer plan ([008ccea](008ccead0f))
* **rithmomachia:** Add concise one-page playing guide ([e3c1f10](e3c1f10233))
* update workflow to require manual testing before commits ([0991796](0991796f1e))

### Styles

* **rithmomachia:** improve divider styling and make tabs responsive ([88ca35e](88ca35e044)), closes [#e5e7](https://github.com/antialias/soroban-abacus-flashcards/issues/e5e7) [#9ca3](https://github.com/antialias/soroban-abacus-flashcards/issues/9ca3)
* **rithmomachia:** improve pyramid face numbers visibility and contrast ([94e5e6a](94e5e6a268)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#b45309](https://github.com/antialias/soroban-abacus-flashcards/issues/b45309)
* **rithmomachia:** increase pyramid face numbers size and boldness ([7bf2d73](7bf2d730d3))

### Tests

* trigger compose-updater deployment test ([2b06aae](2b06aae394))
* verify compose-updater automatic deployment cycle ([af0552c](af0552ccd9))
2025-11-05 01:19:35 +00:00
Thomas Hallock
247c3d9874 fix(layout): remove wrapper, use utility class for nav spacing
Better approach to fixed nav spacing:
- Removed wrapper div from PageWithNav (was creating white gap)
- Added .with-fixed-nav utility class in globals.css
- Pages apply class to their root element (with background)
- Padding is applied to the element with the background, not a wrapper

This prevents the white bar issue because the background element itself
has the padding, so the background extends under the nav properly.

Applied to calendar page as example. Other pages can add the class as needed.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 19:15:07 -06:00
Thomas Hallock
98863026b7 refactor(layout): make nav height truly self-referential
Improvements to the fixed nav spacing system:

1. Define nav heights as CSS variables in :root (globals.css):
   - --app-nav-height-full: 72px
   - --app-nav-height-minimal: 92px

2. Nav components reference and use these variables:
   - Set --app-nav-height to the appropriate variant
   - Use min-height based on the variable (circular reference)

3. Changed PageWithNav from padding to margin:
   - Prevents background gap under nav
   - Backgrounds now properly extend under the fixed nav

Single source of truth: Change values in globals.css and everything
updates automatically - both the nav sizing and the content spacing.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 19:11:49 -06:00
semantic-release-bot
58fc5d8912 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-11-05)

### Features

* **abacus-react:** add AbacusStatic for React Server Components ([3b8e864](3b8e864cfa))
* **abacus-react:** add core utility functions for state management ([e65541c](e65541c100))
* **abacus-react:** add layout and educational props ([35bbcec](35bbcecb9e))
* **abacus-react:** add pre-defined theme presets ([cf1f950](cf1f950c7c))
* **abacus-react:** add React hooks for abacus calculations ([de038d2](de038d2afc))
* **abacus-react:** add separate /static export path for React Server Components ([ed69f6b](ed69f6b917))
* **abacus-react:** add shared dimension calculator for consistent sizing ([e5ba772](e5ba772fde))
* **abacus-react:** export new utilities, hooks, and themes ([ce4e44d](ce4e44d630))
* **abacus:** add nativeAbacusNumbers setting to schema and UI ([79f7347](79f7347d48))
* add 3D printing support for abacus models ([dafdfdd](dafdfdd233))
* add comprehensive metadata, SEO, and make AbacusReact SSR-compatible ([0922ea1](0922ea10b7))
* add comprehensive Storybook coverage and migration guide ([7a4a37e](7a4a37ec6d))
* add game preview system with mock arcade environment ([25880cc](25880cc7e4))
* add per-player stats tracking system ([613301c](613301cd13))
* add Strategy & Tactics section to Rithmomachia guide ([81ead65](81ead65680))
* add unified trophy abacus with hero mode integration ([6620418](6620418a70))
* **arcade:** add ability to deactivate remote players without kicking user ([3628426](3628426a56))
* **arcade:** add native abacus numbers support to pressure gauge ([1d525c7](1d525c7b53))
* **arcade:** add Rithmomachia (Battle of Numbers) game ([2fc0a05](2fc0a05f7f))
* **arcade:** add yjs-demo collaborative game and Yjs persistence layer ([d568955](d568955d6a))
* **arcade:** auto-create room when user has none ([ff88c3a](ff88c3a1b8))
* **card-sorting:** add activity feed notifications for collaborative mode ([1461414](1461414ef4))
* **card-sorting:** add auto-submit countdown for perfect sequences ([780a716](780a7161bc))
* **card-sorting:** add bezier curves to connecting arrows ([4d8e873](4d8e873358))
* **card-sorting:** add CardPosition type and position syncing ([656f5a7](656f5a7838))
* **card-sorting:** add collapsible stats sidebar for spectators ([6527c26](6527c26a81))
* **card-sorting:** add game mode selector UI to setup phase ([d25b888](d25b888ffb))
* **card-sorting:** add GameMode type system for multiplayer support ([fd76533](fd765335ef))
* **card-sorting:** add green border to correctly positioned cards ([16fca86](16fca86b76)), closes [#22c55](https://github.com/antialias/soroban-abacus-flashcards/issues/22c55)
* **card-sorting:** add player emoji indicators on moving cards ([3a82099](3a82099757))
* **card-sorting:** add react-spring animations for real-time sync ([c367e0c](c367e0ceec))
* **card-sorting:** add smooth transition to drop shadow ([b0b93d0](b0b93d0175))
* **card-sorting:** add spectator mode UI enhancements ([ee7345d](ee7345d641)), closes [#6366f1](https://github.com/antialias/soroban-abacus-flashcards/issues/6366f1) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add team scoring UI for collaborative mode ([ed6f177](ed6f177914)), closes [#a78](https://github.com/antialias/soroban-abacus-flashcards/issues/a78) [#8b5cf6](https://github.com/antialias/soroban-abacus-flashcards/issues/8b5cf6)
* **card-sorting:** add updateCardPositions action to Provider ([f6ed4a2](f6ed4a27a2))
* **card-sorting:** auto-arrange prefix/suffix cards in corners ([4ba7f24](4ba7f24717))
* **card-sorting:** fade correctly positioned cards to 50% opacity ([7028cfc](7028cfc511))
* **card-sorting:** gentler spring animation for locked cards ([47189cb](47189cb6e7))
* **card-sorting:** implement continuous bezier curve paths ([2d93024](2d9302410f))
* **card-sorting:** improve card distribution for natural scattered look ([0b0503f](0b0503f035))
* **card-sorting:** make player emoji fill entire card background ([2e7a02c](2e7a02c9e4))
* **card-sorting:** optimize results screen for mobile ([d188789](d188789069))
* **card-sorting:** redesign setup screen with modern UI ([73cf967](73cf967492))
* **card-sorting:** scale correctly positioned cards to 50% ([222dc55](222dc555fa))
* **card-sorting:** shrink/fade cards in correct suffix as well ([8f6feec](8f6feec4f2))
* **card-sorting:** smooth spring transition from game table to results grid ([c5f39d5](c5f39d51eb))
* **card-sorting:** wrap prefix/suffix cards to multiple rows ([e3184dd](e3184dd0d4))
* complete 3D enhancement integration for all three proposals ([5ac55cc](5ac55cc149))
* **create-room:** replace hardcoded game grid with dynamic Radix Select dropdown ([83d0ba2](83d0ba26f5))
* dynamic day-of-month favicon using subprocess pattern ([4d0795a](4d0795a9df))
* dynamically crop favicon to active beads for maximum size ([5670322](567032296a))
* enable 3D enhancement on hero/open MyAbacus modes ([37e330f](37e330f26e))
* **games:** add autoplay and improve carousel layout ([9f51edf](9f51edfaa9))
* **games:** add horizontal scroll support to carousels ([a224abb](a224abb6f6))
* **games:** add rotating games hero carousel ([24231e6](24231e6b2e))
* **i18n:** add dynamic locale switching without page reload ([fe9bfea](fe9bfeabf9))
* **i18n:** add global language selector to navigation ([0506360](0506360117))
* **i18n:** add homepage translations for all supported languages ([8c9d35a](8c9d35a3b4))
* **i18n:** add Old High German (goh) language support ([b334a15](b334a15255))
* **i18n:** complete Old High German translations for all locales ([0b06a1c](0b06a1ce00))
* **i18n:** internationalize games page and tutorial content ([4253964](4253964af1))
* **i18n:** internationalize homepage with English translations ([40cff14](40cff143c7))
* **i18n:** migrate from react-i18next to next-intl ([9016b76](9016b76024))
* **i18n:** update games page hero section copy ([6333c60](6333c60352))
* install embla-carousel-autoplay for games carousel ([946e5d1](946e5d1910))
* install embla-carousel-react for player profile carousel ([642ae95](642ae95738))
* internationalize guide page with 6 languages ([e9c320b](e9c320bb10))
* internationalize tutorial player ([26d41cf](26d41cfd05))
* optimize card sorting for mobile displays ([b443ee9](b443ee9cdc))
* Redesign Rithmomachia setup page with dramatic medieval theme ([6ae4d13](6ae4d13dc7))
* **rithmomachia:** add 80% opacity to guide modal when not hovered ([4a78485](4a78485d2e))
* **rithmomachia:** add CaptureContext for capture dialog state management ([d7eb957](d7eb957a8d))
* **rithmomachia:** add ghost panel preview for guide docking ([c0d6526](c0d6526d30))
* **rithmomachia:** add guide docking with resizable panels ([f457f1a](f457f1a1c2))
* **rithmomachia:** add helper piece selection for mathematical captures ([cae3359](cae3359587))
* **rithmomachia:** add helpful error messages for failed captures ([b172440](b172440a41))
* **rithmomachia:** add initial board visual to guide Overview section ([d42bcff](d42bcff0d9))
* **rithmomachia:** Add interactive playing guide modal ([3121d82](3121d8240a))
* **rithmomachia:** add number bond visualization and helper placeholders ([82d8913](82d89131f0))
* **rithmomachia:** add ratio capture example to guide ([9150b0c](9150b0c678))
* **rithmomachia:** add standalone guide page route ([3fcc79f](3fcc79fe9e))
* **rithmomachia:** add useBoardLayout hook for centralized layout calculations ([27f1c98](27f1c989d5))
* **rithmomachia:** add usePieceSelection hook for selection state management ([275f401](275f401e3c))
* **rithmomachia:** add visual board examples to Capture section ([74bc3c0](74bc3c0dcf))
* **rithmomachia:** add visual board examples to Harmony section ([1d5f01c](1d5f01c966))
* **rithmomachia:** add visual winning example to Victory section ([b7fac78](b7fac78829))
* **rithmomachia:** auto-size tab labels with react-textfit ([9fd5406](9fd54067ce))
* **rithmomachia:** cycle through valid helpers with dynamic number tooltips ([4829e41](4829e41ea1))
* **rithmomachia:** enhance capture relation UI with smooth animations ([0a30801](0a308016e9))
* **rithmomachia:** enhance Harmony section with comprehensive content ([f555856](f5558563ea))
* **rithmomachia:** enhance Pieces section with visual examples and pyramid details ([55aff82](55aff829f4))
* **rithmomachia:** enhance Pyramid section with comprehensive details ([9fde1ef](9fde1ef9e7))
* **rithmomachia:** guide defaults to docked right on open ([11f674d](11f674d542))
* **rithmomachia:** improve guide pieces section layout ([a270bfc](a270bfc0cc))
* **rithmomachia:** improve guide UX and add persistence ([b314740](b314740697))
* **rithmomachia:** improve roster status notice UX ([e27df45](e27df45256))
* **rithmomachia:** integrate roster warning into game nav ([8a11594](8a11594203))
* **rithmomachia:** make guide modal ultra-responsive down to 150px width ([0474197](04741971b2))
* **rithmomachia:** recreate original guide modal header layout ([2489695](24896957d0))
* **rithmomachia:** show capture error on hover instead of click ([339b678](339b6780f6))
* **rithmomachia:** show pyramid face numbers on hover instead of selection ([b0c4523](b0c4523c0b))
* **rithmomachia:** show pyramid face numbers when selected ([5c186f3](5c186f3947))
* **rithmomachia:** show pyramid face numbers when selected with subtle animation ([5c2ddbe](5c2ddbef05))
* **rithmomachia:** show real preview layout when dragging guide to dock ([17d2460](17d2460a87))
* **rithmomachia:** simplify guide language for clarity ([85cb630](85cb630add))
* **rithmomachia:** skip helper selection UI and auto-select first valid helper ([be2a00e](be2a00e8b3))
* **rithmomachia:** Update harmony system to classical three-piece proportions ([08c9762](08c97620f5))
* **rithmomachia:** Update to traditional board setup with 25 pieces per side ([0769eaa](0769eaaa1d))
* **rithmomachia:** use actual piece SVGs in number bond with 2.5s rotation animation ([976a7de](976a7de949))
* **room-share:** add QR code button for easy mobile joining ([349290a](349290ac6a))
* show rithmomachia turn in nav ([7c89bfe](7c89bfef9c))
* switch to royal color theme with transparent background ([944ad65](944ad6574e)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#f59e0](https://github.com/antialias/soroban-abacus-flashcards/issues/f59e0) [#a855f7](https://github.com/antialias/soroban-abacus-flashcards/issues/a855f7) [#7e22](https://github.com/antialias/soroban-abacus-flashcards/issues/7e22)
* **web:** add test page for AbacusStatic RSC compatibility ([903dea2](903dea2584))
* **web:** add test page for AbacusStatic Server Component ([3588d5a](3588d5acde))
* **web:** add Typst-based preview endpoint with React Suspense ([599a758](599a758471))
* **web:** add year abacus to calendar header and make grid bolder ([867c7ee](867c7ee172)), closes [#333](https://github.com/antialias/soroban-abacus-flashcards/issues/333)
* **web:** improve calendar abacus preview styling ([8439727](8439727b15))
* **web:** optimize monthly calendar for single-page layout ([b277a89](b277a89415))
* **web:** redesign monthly calendar as single composite SVG ([8ce8038](8ce8038bae))

### Bug Fixes

* **abacus-react:** add data-testid attributes back to beads for testing ([23ae1b0](23ae1b0c6f))
* **abacus-react:** correct column highlighting offset in AbacusStatic ([0641eb7](0641eb719e))
* **abacus-react:** fix animations by preventing component remounting ([be7d4c4](be7d4c4713))
* **abacus-react:** restore original AbacusReact measurements and positioning ([88c0baa](88c0baaad9))
* add xmlns to AbacusStatic for Typst SVG parsing ([98cd019](98cd019d4a))
* adjust hero abacus position to avoid covering subtitle ([f03d341](f03d341314))
* **arcade:** add automatic retry for version conflict rejections ([fbcde25](fbcde2505f))
* **arcade:** allow deactivating players from users who left the room ([7c1c2d7](7c1c2d7beb))
* **arcade:** implement optimistic locking in session manager ([71fd66d](71fd66d96a))
* board rotation now properly fills height in portrait mode ([b5a96ea](b5a96eaeb1))
* **card-sorting:** add border radius to outer card container ([a922eba](a922eba73c))
* **card-sorting:** add debug logging for spring animations ([d42947e](d42947eb8d))
* **card-sorting:** add missing gameMode support after hard reset ([a832325](a832325deb))
* **card-sorting:** add missing useMemo import ([949d76d](949d76d844))
* **card-sorting:** add overflow hidden to clip rounded corners ([84c66fe](84c66feec6))
* **card-sorting:** adjust connecting paths for scaled cards ([829c741](829c741e55))
* **card-sorting:** adjust game board for spectator panels ([fc5cf12](fc5cf1216f))
* **card-sorting:** adjust viewport dimensions for spectator panels ([4dce16c](4dce16cca4))
* **card-sorting:** animate cards from game board to results grid ([17d45fe](17d45fe88c))
* **card-sorting:** correct suffix card detection in auto-arrange ([d02ab59](d02ab5922c))
* **card-sorting:** enable card scaling for spectators ([6b095c3](6b095c3383))
* **card-sorting:** enable New Game button during active gameplay ([f3f6eca](f3f6eca1db))
* **card-sorting:** end drag immediately when card becomes locked ([ae45298](ae45298ec4))
* **card-sorting:** filter local player from emoji overlays on dragged cards ([dc2d94a](dc2d94aaa5))
* **card-sorting:** fix results panel layout to not cover cards ([4b4fbfe](4b4fbfef32))
* **card-sorting:** hide activity notifications in spectator mode ([5cca279](5cca279687))
* **card-sorting:** keep arrow sequence numbers upright ([79c9469](79c94699fa))
* **card-sorting:** lock correctly positioned prefix/suffix cards ([170abed](170abed231))
* **card-sorting:** lock spring positions after initial animation completes ([275cc62](275cc62a52))
* **card-sorting:** New Game now restarts with same settings instantly ([f3687ed](f3687ed236))
* **card-sorting:** only shrink/fade cards in correct prefix ([51368c6](51368c6ec5))
* **card-sorting:** preserve card positions on pause/resume ([0d8af09](0d8af09517))
* **card-sorting:** preserve rotation when starting drag ([3364144](3364144fb6))
* **card-sorting:** prevent duplicate START_GAME moves on Play Again ([a0b14f8](a0b14f87e9))
* **card-sorting:** prevent ghost movements with proper optimistic updates ([bd014be](bd014bec4f))
* **card-sorting:** prevent infinite loop when all cards are correct ([34785f4](34785f466f))
* **card-sorting:** prevent infinite loop with tolerance-based position comparison ([627b873](627b873382))
* **card-sorting:** prevent position jump when clicking rotated cards ([564a00f](564a00f82b))
* **card-sorting:** prevent replaying own movements from server ([308168a](308168a7fb))
* **card-sorting:** prevent springs from reinitializing on window resize ([30953b8](30953b8c4a))
* **card-sorting:** prevent springs from resetting after animation ([8aff60c](8aff60ce3f))
* **card-sorting:** remove hasAnimatedRef logic causing backwards animation ([a44aa5a](a44aa5a4c2))
* **card-sorting:** remove remaining reveal numbers references ([15c53ea](15c53ea4eb))
* **card-sorting:** restore prefix/suffix card shrinking visual feedback ([f5fb4d7](f5fb4d7b76))
* **card-sorting:** show only active players in team members section ([fa9f1a5](fa9f1a568f))
* **card-sorting:** smooth scale animation while dragging cards ([0eefc33](0eefc332ac))
* **card-sorting:** stabilize inferred sequence for locked cards during drag ([b0cd194](b0cd194838))
* **card-sorting:** use empty deps array for useSprings to prevent recreation ([cee399e](cee399ed15))
* **card-sorting:** use ref to track initialized state and prevent re-animation ([f389afa](f389afa831))
* **card-sorting:** use same coordinate system for game board and results ([6972fdf](6972fdf110))
* **complement-race:** prevent delivery move thrashing in steam sprint mode ([e1258ee](e1258ee041))
* configure favicon metadata and improve bead visibility ([e1369fa](e1369fa275))
* copy entire packages/core and packages/templates ([0ccada0](0ccada0ca7))
* correct hero abacus scroll direction to flow with page content ([4232746](423274657c))
* correct Typst template path in Dockerfile ([4c518de](4c518decb7))
* delete existing user sessions before creating new ones ([0cced47](0cced47a0f))
* **docker:** add scripts, abacus-react, and tsx for production calendar generation ([33eb90e](33eb90e316))
* extract pure SVG content from AbacusReact renders ([b07f1c4](b07f1c4216))
* **games:** prevent horizontal page scroll from carousel overflow ([5a8c98f](5a8c98fc10))
* **games:** smooth scroll feel for carousel wheel navigation ([f80a73b](f80a73b35c))
* **games:** use specific transition properties for smooth carousel loop ([187271e](187271e515))
* **i18n:** eliminate FOUC by loading messages server-side ([4d4d930](4d4d930bd3))
* **i18n:** use useMessages() for tutorial translations ([95b0105](95b0105ca3))
* include column posts in favicon bounding box ([0b2f481](0b2f48106a))
* increase server update debounce to 2000ms for low bandwidth ([633ff12](633ff12750))
* Integrate threshold input into Point Victory card ([b29bbee](b29bbeefca))
* **layout:** add systematic spacing for fixed nav bar ([4559fb1](4559fb121d))
* mark dynamic routes as force-dynamic to prevent static generation errors ([d7b35d9](d7b35d9544))
* **nav:** restrict transparent hero styling to home page only ([fab227d](fab227d686))
* **nav:** show full navigation on /games page ([d3fe6ac](d3fe6acbb0))
* **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))
* reduce padding to minimize gap below last bead ([0e529be](0e529be789))
* remove distracting parallax and wobble 3D effects ([28a2d40](28a2d40996))
* remove wobble physics and enhance wood grain visibility ([5d97673](5d97673406))
* resolve z-index layering and hero abacus visibility issues ([ed9a050](ed9a050d64))
* rewrite 3D stories to use props instead of CSS wrappers ([26bdb11](26bdb11237))
* **rithmomachia:** add missing i18next dependencies ([91154d9](91154d9364))
* **rithmomachia:** add missing pyramid section keys to Japanese (ja.json) ([dae615e](dae615ee72))
* **rithmomachia:** adjust error dialog sizing to prevent text clipping ([cda1126](cda1126cb0))
* **rithmomachia:** adjust roster notice position to not overlap nav ([7093223](709322373a))
* **rithmomachia:** change undock icon to pop-out arrow ([2a91748](2a91748493))
* **rithmomachia:** correct board dimensions to 16x8 and restore original layout values ([cfac277](cfac277505))
* **rithmomachia:** Correct board setup to match reference image exactly ([618e563](618e56358d))
* **rithmomachia:** correct makeMove parameter types for capture handling ([aafb64f](aafb64f3e3))
* **rithmomachia:** fix guide modal resize drift by calculating from initial state ([1bcd99c](1bcd99c949))
* **rithmomachia:** fix harmony section translation structure for hi/ja/es ([14259a1](14259a19a9))
* **rithmomachia:** fix modal resizing zoom issue ([4fa20f4](4fa20f44cb))
* **rithmomachia:** Fix TypeScript errors in playing guide modal ([4834ece](4834ece98e))
* **rithmomachia:** handle pyramid pieces in hover error tooltip ([56f3164](56f3164155))
* **rithmomachia:** implement proper board cropping and highlighting in guide ([d0a8fcd](d0a8fcdea6))
* **rithmomachia:** improve guide modal tab navigation at narrow widths ([a673177](a673177bec))
* **rithmomachia:** reconnect player assignment UI and fix setup layout ([a1a0374](a1a0374fac))
* **rithmomachia:** render guide as docked in preview panel ([190f8cf](190f8cf302))
* **rithmomachia:** show actual values in tooltips for non-helper relations ([774c6b0](774c6b0ce7))
* **rithmomachia:** show guest-friendly message when they can't fix too many players ([54bfd2f](54bfd2fac8))
* **rithmomachia:** smooth guide dragging from docked state without jump ([8f4a79c](8f4a79c9b0))
* **rithmomachia:** validate move path before showing capture error on hover ([bd49964](bd49964186))
* **room-info:** hide Leave Room button when user is alone ([5927f61](5927f61c3c))
* separate horizontal and vertical bounding box logic ([83090df](83090df4df))
* tolerate OpenSCAD CGAL warnings if output file is created ([88993f3](88993f3662))
* **tutorial:** correct column validation for bead highlights ([9ba1824](9ba1824226))
* **tutorial:** fix overlay rendering, arrow indicators, and bead visibility ([a804316](a80431608d))
* use absolute positioning for hero abacus to eliminate scroll lag ([096104b](096104b094))
* use Debian base for deps stage to match runner for binary compatibility ([f8fe6e4](f8fe6e4a41))
* use default BOSL2 branch instead of non-existent v2.0.0 tag ([f4ffc5b](f4ffc5b027))
* use nested SVG viewBox for actual cropping, not just scaling ([440b492](440b492e85))
* various game improvements and UI enhancements ([b67cf61](b67cf610c5))
* **web,docker:** add --format flag for Typst and upgrade to v0.13.0 ([19b9d7a](19b9d7a74f))
* **web:** add dynamic export to rithmomachia page ([329e623](329e623212))
* **web:** fix Typst PDF generation path resolution ([7ce1287](7ce1287525))
* **web:** generate styled-system artifacts during build ([293390a](293390ae35))
* **web:** move react-dom/server import to API route to satisfy Next.js ([00a8bc3](00a8bc3e5e))
* **web:** move tsx to production dependencies for calendar generation ([ffae9c1](ffae9c1bdb))
* **web:** prevent abacus overlap in composite calendar ([448f93c](448f93c1e2)), closes [#f0f0f0](https://github.com/antialias/soroban-abacus-flashcards/issues/f0f0f0)
* **web:** use AbacusStatic for calendar SVG generation ([08c6a41](08c6a419e2))
* **web:** use dynamic import for react-dom/server in API route ([4f93c7d](4f93c7d996))
* **web:** use nested SVG elements to prevent coordinate space conflicts ([f9cbee8](f9cbee8fcd))

### Performance Improvements

* optimize Docker image size to reduce build failures ([9ca3106](9ca3106361))

### Code Refactoring

* **card-sorting:** remove reveal numbers feature ([ea5e3e8](ea5e3e838b))
* **card-sorting:** send complete card sequence instead of individual moves ([e4df843](e4df8432b9))
* **games:** implement carousel, fix victories bug, add conditional stats ([82c133f](82c133f742))
* **games:** move page title to nav bar ([712ee58](712ee58e59))
* **games:** remove redundant subtitle below nav ([ad5bb87](ad5bb87325))
* **games:** remove wheel scrolling, enable overflow visible carousel ([876513c](876513c9cc))
* reorganize Harmony and Victory guide sections ([fb629c4](fb629c44ea))
* restructure /create page into hub with sub-pages ([b91b23d](b91b23d95f))
* **rithmomachia:** extract board and capture components (phase 2+3) ([a0a867b](a0a867b271))
* **rithmomachia:** extract CaptureErrorDialog component (Phase 2 partial) ([f0a066d](f0a066d8f0))
* **rithmomachia:** extract constants and coordinate utilities (Phase 1) ([eace0ed](eace0ed529))
* **rithmomachia:** extract guide sections into separate files ([765525d](765525dc45))
* **rithmomachia:** extract hooks (phase 5) ([324a659](324a65992f))
* **rithmomachia:** extract phase components (phase 4) ([11364f6](11364f6394))
* **rithmomachia:** extract reusable components from SetupPhase ([3abc325](3abc325ea2))
* **rithmomachia:** make setup phase UI more compact ([e55f848](e55f848a26))
* **rithmomachia:** redesign error notification with modern UI ([dfeeb0e](dfeeb0e0db)), closes [#1e293](https://github.com/antialias/soroban-abacus-flashcards/issues/1e293) [#0f172](https://github.com/antialias/soroban-abacus-flashcards/issues/0f172) [#f1f5f9](https://github.com/antialias/soroban-abacus-flashcards/issues/f1f5f9)
* **rithmomachia:** simplify capture error dialog to one-liner ([82a5eb2](82a5eb2e4b))
* **rithmomachia:** Update board setup to authoritative CSV layout ([0471da5](0471da598d))
* **rithmomachia:** update capture components to use CaptureContext ([2ab6ab5](2ab6ab5799))
* **rithmomachia:** use useBoardLayout and usePieceSelection in BoardDisplay ([0ab7a1d](0ab7a1df32))
* use AbacusReact for dynamic Open Graph image ([9c20f12](9c20f12bac))
* **web:** import utility functions from abacus-react ([7228bbc](7228bbc2eb))
* **web:** move calendar generators to src/utils for proper compilation ([379698f](379698fea3))
* **web:** return calendar SVG preview with PDF generation ([14a5de0](14a5de0dfa))
* **web:** use ABACUS_THEMES instead of manual style definitions ([9f7f001](9f7f001d74))
* **web:** use client-side React rendering for live calendar preview ([f880cbe](f880cbe4bf))
* **web:** use compact prop for inline mini-abacus ([ff1d60a](ff1d60a233))
* **web:** use direct function imports instead of execSync for calendar generation ([9f1715f](9f1715f085))
* **web:** use stdin/stdout for Typst compilation ([06f68cc](06f68cc74c))

### Documentation

* **abacus-react:** add Storybook stories for AbacusStatic ([4f9dc46](4f9dc4666d))
* **abacus-react:** add Storybook stories for new features ([6a1cec0](6a1cec06a7))
* **abacus-react:** export AbacusStatic and update README ([74f2d97](74f2d97434))
* **abacus-react:** update documentation for new features ([35d8734](35d8734a3a))
* **abacus-react:** update README with /static import path for RSC ([72a4c2b](72a4c2b80c))
* add 3D enhancement documentation to README ([cc96802](cc96802df8))
* add critical section on never adding tsx to production dependencies ([770cfc3](770cfc3aca))
* add database migration guide and playing guide modal spec ([5a29af7](5a29af78e2))
* add deployment verification guidelines to prevent false positives ([3d8da23](3d8da2348b))
* **card-sorting:** add comprehensive multiplayer plan ([008ccea](008ccead0f))
* **rithmomachia:** Add concise one-page playing guide ([e3c1f10](e3c1f10233))
* update workflow to require manual testing before commits ([0991796](0991796f1e))

### Styles

* **rithmomachia:** improve divider styling and make tabs responsive ([88ca35e](88ca35e044)), closes [#e5e7](https://github.com/antialias/soroban-abacus-flashcards/issues/e5e7) [#9ca3](https://github.com/antialias/soroban-abacus-flashcards/issues/9ca3)
* **rithmomachia:** improve pyramid face numbers visibility and contrast ([94e5e6a](94e5e6a268)), closes [#fbbf24](https://github.com/antialias/soroban-abacus-flashcards/issues/fbbf24) [#b45309](https://github.com/antialias/soroban-abacus-flashcards/issues/b45309)
* **rithmomachia:** increase pyramid face numbers size and boldness ([7bf2d73](7bf2d730d3))

### Tests

* trigger compose-updater deployment test ([2b06aae](2b06aae394))
* verify compose-updater automatic deployment cycle ([af0552c](af0552ccd9))
2025-11-05 01:02:21 +00:00
Thomas Hallock
4559fb121d fix(layout): add systematic spacing for fixed nav bar
Prevent content from appearing underneath the fixed navigation by:
- Adding content wrapper in PageWithNav with top padding
- Using CSS variable --app-nav-height set by AppNavBar itself
- Different heights for full nav (72px) vs minimal nav (92px)

This systematically solves the fixed nav overlap issue for all pages
using PageWithNav without requiring per-page adjustments.

Fixes: Calendar creator title showing under nav

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 18:58:04 -06:00
Thomas Hallock
fab227d686 fix(nav): restrict transparent hero styling to home page only
The HomeHeroProvider is provided site-wide, and isHeroVisible defaults to
true. This caused the navigation to use transparent "hero mode" styling on
all pages, not just the home page when the hero is visible.

Added pathname check to ensure transparent styling and hidden branding only
apply when actually on the home page (pathname === '/') with a visible hero.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 18:54:16 -06:00
25 changed files with 2828 additions and 258 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -107,23 +107,60 @@ RUN mkdir -p /bosl2 && \
find . -type f ! -name "*.scad" -delete && \
find . -type d -empty -delete
# OpenSCAD builder stage - download and prepare newer OpenSCAD binary
FROM node:18-slim AS openscad-builder
RUN apt-get update && apt-get install -y --no-install-recommends \
wget \
ca-certificates \
file \
&& rm -rf /var/lib/apt/lists/*
# Download latest OpenSCAD AppImage and extract it
# Using 2024.11 which has CGAL fixes for intersection operations
RUN wget -q https://files.openscad.org/OpenSCAD-2024.11.18-x86_64.AppImage -O /tmp/openscad.AppImage && \
chmod +x /tmp/openscad.AppImage && \
cd /tmp && \
./openscad.AppImage --appimage-extract && \
mv squashfs-root/usr/bin/openscad /usr/local/bin/openscad && \
mv squashfs-root/usr/lib /usr/local/openscad-lib && \
chmod +x /usr/local/bin/openscad
# Production image - Using Debian base for OpenSCAD availability
FROM node:18-slim AS runner
WORKDIR /app
# Install ONLY runtime dependencies (no build tools)
# Using Debian because OpenSCAD is not available in Alpine repos
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 \
python3-pip \
qpdf \
openscad \
ca-certificates \
libgomp1 \
libglu1-mesa \
libglew2.2 \
libfreetype6 \
libfontconfig1 \
libharfbuzz0b \
libxml2 \
libzip4 \
libdouble-conversion3 \
libqt5core5a \
libqt5gui5 \
libqt5widgets5 \
libqt5concurrent5 \
libqt5multimedia5 \
libqt5network5 \
libqt5dbus5 \
&& rm -rf /var/lib/apt/lists/*
# Copy typst binary from typst-builder stage
COPY --from=typst-builder /usr/local/bin/typst /usr/local/bin/typst
# Copy newer OpenSCAD from openscad-builder stage
COPY --from=openscad-builder /usr/local/bin/openscad /usr/local/bin/openscad
COPY --from=openscad-builder /usr/local/openscad-lib /usr/local/openscad-lib
ENV LD_LIBRARY_PATH=/usr/local/openscad-lib:$LD_LIBRARY_PATH
# Copy minimized BOSL2 library from bosl2-builder stage
RUN mkdir -p /usr/share/openscad/libraries
COPY --from=bosl2-builder /bosl2 /usr/share/openscad/libraries/BOSL2

View File

@@ -126,13 +126,14 @@ When asked to make ANY changes:
**CRITICAL: The user manages running the dev server, NOT Claude Code.**
- ❌ DO NOT run `npm run dev` or `npm start`
- ❌ DO NOT run `pnpm dev`, `npm run dev`, or `npm start`
- ❌ DO NOT attempt to start, stop, or restart the dev server
- ❌ DO NOT kill processes on port 3000
- ❌ DO NOT use background Bash processes for the dev server
- ✅ Make code changes and let the user restart the server when needed
- ✅ You may run other commands like `npm run type-check`, `npm run lint`, etc.
The user will manually start/restart the dev server after you make changes.
**The user runs the dev server themselves.** The user will manually start/restart the dev server after you make changes.
## Details

View File

@@ -168,7 +168,5 @@
"ask": []
},
"enableAllProjectMcpServers": true,
"enabledMcpjsonServers": [
"sqlite"
]
"enabledMcpjsonServers": ["sqlite"]
}

View File

@@ -71,6 +71,7 @@
"next": "^14.2.32",
"next-auth": "5.0.0-beta.29",
"next-intl": "^4.4.0",
"openscad-wasm-prebuilt": "^1.2.0",
"python-bridge": "^1.1.0",
"qrcode.react": "^4.2.0",
"react": "^18.2.0",

View File

@@ -0,0 +1,47 @@
// Inline version of abacus.scad that doesn't require BOSL2
// This version uses a hardcoded bounding box size instead of the bounding_box() function
// ---- USER CUSTOMIZABLE PARAMETERS ----
// These can be overridden via command line: -D 'columns=7' etc.
columns = 13; // Total number of columns (1-13, mirrored book design)
scale_factor = 1.5; // Overall size scale (preserves aspect ratio)
// -----------------------------------------
stl_path = "/3d-models/simplified.abacus.stl";
// Known bounding box dimensions of the simplified.abacus.stl file
// These were measured from the original file
bbox_size = [186, 60, 120]; // [width, depth, height] in STL units
// Calculate parameters based on column count
// The full STL has 13 columns. We want columns/2 per side (mirrored).
total_columns_in_stl = 13;
columns_per_side = columns / 2;
width_scale = columns_per_side / total_columns_in_stl;
// Column spacing: distance between mirrored halves
units_per_column = bbox_size[0] / total_columns_in_stl; // ~14.3 units per column
column_spacing = columns_per_side * units_per_column;
// --- actual model ---
module imported() {
import(stl_path, convexity = 10);
}
// Create a bounding box manually instead of using BOSL2's bounding_box()
module bounding_box_manual() {
translate([-bbox_size[0]/2, -bbox_size[1]/2, -bbox_size[2]/2])
cube(bbox_size);
}
module half_abacus() {
intersection() {
scale([width_scale, 1, 1]) bounding_box_manual();
imported();
}
}
scale([scale_factor, scale_factor, scale_factor]) {
translate([column_spacing, 0, 0]) mirror([1,0,0]) half_abacus();
half_abacus();
}

View File

@@ -44,7 +44,7 @@ export async function POST(request: NextRequest) {
const calendarSvg = generateCalendarComposite({
month,
year,
renderToString: renderToStaticMarkup
renderToString: renderToStaticMarkup,
})
if (!calendarSvg || calendarSvg.trim().length === 0) {
throw new Error('Generated empty composite calendar SVG')
@@ -130,7 +130,7 @@ export async function POST(request: NextRequest) {
{
error: 'Failed to generate calendar',
message: errorMessage,
...(process.env.NODE_ENV === 'development' && { stack: errorStack })
...(process.env.NODE_ENV === 'development' && { stack: errorStack }),
},
{ status: 500 }
)

View File

@@ -42,7 +42,7 @@ export async function POST(request: NextRequest) {
const calendarSvg = generateCalendarComposite({
month,
year,
renderToString: renderToStaticMarkup
renderToString: renderToStaticMarkup,
})
writeFileSync(join(tempDir, 'calendar.svg'), calendarSvg)

View File

@@ -7,7 +7,7 @@ import { css } from '../../../../styled-system/css'
export default function ThreeDPrintPage() {
// New unified parameter system
const [columns, setColumns] = useState(13)
const [columns, setColumns] = useState(4)
const [scaleFactor, setScaleFactor] = useState(1.5)
const [widthMm, setWidthMm] = useState<number | undefined>(undefined)
const [format, setFormat] = useState<'stl' | '3mf' | 'scad'>('stl')

View File

@@ -10,7 +10,11 @@ interface CalendarPreviewProps {
previewSvg: string | null
}
async function fetchTypstPreview(month: number, year: number, format: string): Promise<string | null> {
async function fetchTypstPreview(
month: number,
year: number,
format: string
): Promise<string | null> {
const response = await fetch('/api/create/calendar/preview', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },

View File

@@ -42,7 +42,7 @@ export default function CalendarCreatorPage() {
const data = await response.json()
// Convert base64 PDF to blob and trigger download
const pdfBytes = Uint8Array.from(atob(data.pdf), c => c.charCodeAt(0))
const pdfBytes = Uint8Array.from(atob(data.pdf), (c) => c.charCodeAt(0))
const blob = new Blob([pdfBytes], { type: 'application/pdf' })
const url = window.URL.createObjectURL(blob)
const a = document.createElement('a')
@@ -54,7 +54,9 @@ export default function CalendarCreatorPage() {
document.body.removeChild(a)
} catch (error) {
console.error('Error generating calendar:', error)
alert(`Failed to generate calendar: ${error instanceof Error ? error.message : 'Unknown error'}`)
alert(
`Failed to generate calendar: ${error instanceof Error ? error.message : 'Unknown error'}`
)
} finally {
setIsGenerating(false)
}
@@ -64,12 +66,12 @@ export default function CalendarCreatorPage() {
<PageWithNav navTitle="Create" navEmoji="📅">
<div
data-component="calendar-creator"
className={css({
className={`with-fixed-nav ${css({
minHeight: '100vh',
bg: 'gray.900',
color: 'white',
padding: '2rem',
})}
})}`}
>
<div
className={css({

View File

@@ -3,6 +3,18 @@
/* Import Panda CSS generated styles */
@import "../../styled-system/styles.css";
/* Layout variables */
:root {
/* Navigation bar heights - used by both the nav itself and content padding */
--app-nav-height-full: 72px;
--app-nav-height-minimal: 92px;
}
/* Utility class for pages with fixed nav */
.with-fixed-nav {
padding-top: var(--app-nav-height, 80px);
}
/* Custom global styles */
body {
font-family:

View File

@@ -245,7 +245,7 @@ export function ReadingNumbersGuide() {
border: '1px solid',
borderColor: 'gray.200',
rounded: 'lg',
p: '4',
p: '2',
textAlign: 'center',
display: 'flex',
flexDirection: 'column',
@@ -257,27 +257,19 @@ export function ReadingNumbersGuide() {
fontSize: 'xl',
fontWeight: 'bold',
color: 'brand.600',
mb: '3',
mb: '2',
})}
>
{example.num}
</div>
{/* Aspect ratio container for soroban - roughly 1:3 ratio */}
<div
className={css({
width: '100%',
aspectRatio: '1/2.8',
maxW: '120px',
bg: 'white',
border: '1px solid',
borderColor: 'gray.300',
rounded: 'md',
mb: '3',
flex: '1',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
overflow: 'hidden',
my: '2',
})}
>
<AbacusReact
@@ -286,7 +278,7 @@ export function ReadingNumbersGuide() {
beadShape={appConfig.beadShape}
colorScheme={appConfig.colorScheme}
hideInactiveBeads={appConfig.hideInactiveBeads}
scaleFactor={0.8}
scaleFactor={1.2}
interactive={false}
showNumbers={false}
animated={true}
@@ -299,7 +291,7 @@ export function ReadingNumbersGuide() {
color: 'gray.600',
lineHeight: 'tight',
textAlign: 'center',
mt: 'auto',
mt: '2',
})}
>
{t(`singleDigits.examples.${example.descKey}`)}
@@ -469,7 +461,7 @@ export function ReadingNumbersGuide() {
border: '1px solid',
borderColor: 'blue.300',
rounded: 'lg',
p: '4',
p: '2',
textAlign: 'center',
display: 'flex',
flexDirection: 'column',
@@ -481,27 +473,19 @@ export function ReadingNumbersGuide() {
fontSize: '2xl',
fontWeight: 'bold',
color: 'blue.600',
mb: '3',
mb: '2',
})}
>
{example.num}
</div>
{/* Larger container for multi-digit numbers */}
<div
className={css({
width: '100%',
aspectRatio: '3/4',
maxW: '180px',
bg: 'gray.50',
border: '1px solid',
borderColor: 'blue.200',
rounded: 'md',
mb: '3',
flex: '1',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
overflow: 'hidden',
my: '2',
})}
>
<AbacusReact
@@ -510,7 +494,7 @@ export function ReadingNumbersGuide() {
beadShape={appConfig.beadShape}
colorScheme={appConfig.colorScheme}
hideInactiveBeads={appConfig.hideInactiveBeads}
scaleFactor={0.9}
scaleFactor={1.2}
interactive={false}
showNumbers={false}
animated={true}
@@ -523,6 +507,7 @@ export function ReadingNumbersGuide() {
color: 'blue.700',
lineHeight: 'relaxed',
textAlign: 'center',
mt: '2',
})}
>
{t(`multiDigit.examples.${example.descKey}`)}

View File

@@ -16,7 +16,7 @@ export default function GuidePage() {
return (
<PageWithNav navTitle={t('navTitle')} navEmoji="📖">
<div className={css({ minHeight: '100vh', bg: 'gray.50' })}>
<div className={`with-fixed-nav ${css({ minHeight: '100vh', bg: 'gray.50' })}`}>
{/* Hero Section */}
<div
className={css({

View File

@@ -14,8 +14,8 @@ export default function TestStaticAbacusPage() {
<div style={{ padding: '40px', maxWidth: '1200px', margin: '0 auto' }}>
<h1 style={{ marginBottom: '10px' }}>AbacusStatic Test (Server Component)</h1>
<p style={{ color: '#64748b', marginBottom: '30px' }}>
This page is a React Server Component - no &quot;use client&quot; directive!
All abacus displays below are rendered on the server with zero client-side JavaScript.
This page is a React Server Component - no &quot;use client&quot; directive! All abacus
displays below are rendered on the server with zero client-side JavaScript.
</p>
<div
@@ -39,26 +39,20 @@ export default function TestStaticAbacusPage() {
gap: '10px',
}}
>
<AbacusStatic
value={num}
columns="auto"
hideInactiveBeads
compact
scaleFactor={0.9}
/>
<span style={{ fontSize: '20px', fontWeight: 'bold', color: '#475569' }}>
{num}
</span>
<AbacusStatic value={num} columns="auto" hideInactiveBeads compact scaleFactor={0.9} />
<span style={{ fontSize: '20px', fontWeight: 'bold', color: '#475569' }}>{num}</span>
</div>
))}
</div>
<div style={{ marginTop: '40px', padding: '20px', background: '#f0fdf4', borderRadius: '8px' }}>
<div
style={{ marginTop: '40px', padding: '20px', background: '#f0fdf4', borderRadius: '8px' }}
>
<h2 style={{ marginTop: 0, color: '#166534' }}> Success!</h2>
<p style={{ color: '#15803d' }}>
If you can see the abacus displays above, then AbacusStatic is working correctly
in React Server Components. Check the page source - you&apos;ll see pure HTML/SVG with
no client-side hydration markers!
If you can see the abacus displays above, then AbacusStatic is working correctly in React
Server Components. Check the page source - you&apos;ll see pure HTML/SVG with no
client-side hydration markers!
</p>
</div>
</div>

View File

@@ -2,7 +2,7 @@
import { OrbitControls, Stage } from '@react-three/drei'
import { Canvas, useLoader } from '@react-three/fiber'
import { Suspense, useEffect, useState } from 'react'
import { Suspense, useEffect, useRef, useState } from 'react'
// @ts-expect-error - STLLoader doesn't have TypeScript declarations
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'
import { css } from '../../../styled-system/css'
@@ -30,68 +30,86 @@ export function STLPreview({ columns, scaleFactor }: STLPreviewProps) {
const [previewUrl, setPreviewUrl] = useState<string>('/3d-models/simplified.abacus.stl')
const [isGenerating, setIsGenerating] = useState(false)
const [error, setError] = useState<string | null>(null)
const workerRef = useRef<Worker | null>(null)
// Initialize worker
useEffect(() => {
let mounted = true
const worker = new Worker(new URL('../../workers/openscad.worker.ts', import.meta.url), {
type: 'module',
})
const generatePreview = async () => {
setIsGenerating(true)
setError(null)
worker.onmessage = (event: MessageEvent) => {
const { data } = event
try {
const response = await fetch('/api/abacus/preview', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ columns, scaleFactor }),
})
switch (data.type) {
case 'ready':
console.log('[STLPreview] Worker ready')
break
if (!response.ok) {
throw new Error('Failed to generate preview')
}
case 'result': {
// Create blob from STL data
const blob = new Blob([data.stl], { type: 'application/octet-stream' })
const objectUrl = URL.createObjectURL(blob)
// Convert response to blob and create object URL
const blob = await response.blob()
const objectUrl = URL.createObjectURL(blob)
if (mounted) {
// Revoke old URL if it exists
if (previewUrl && previewUrl.startsWith('blob:')) {
URL.revokeObjectURL(previewUrl)
}
setPreviewUrl(objectUrl)
} else {
// Component unmounted, clean up the URL
URL.revokeObjectURL(objectUrl)
}
} catch (err) {
if (mounted) {
const errorMessage = err instanceof Error ? err.message : 'Failed to generate preview'
// Check if this is an OpenSCAD not found error
if (
errorMessage.includes('openscad: command not found') ||
errorMessage.includes('Command failed: openscad')
) {
setError('OpenSCAD not installed (preview only available in production/Docker)')
// Fallback to showing the base STL
setPreviewUrl('/3d-models/simplified.abacus.stl')
} else {
setError(errorMessage)
}
console.error('Preview generation error:', err)
}
} finally {
if (mounted) {
setPreviewUrl(objectUrl)
setIsGenerating(false)
setError(null)
break
}
case 'error':
console.error('[STLPreview] Worker error:', data.error)
setError(data.error)
setIsGenerating(false)
// Fallback to showing the base STL
setPreviewUrl('/3d-models/simplified.abacus.stl')
break
default:
console.warn('[STLPreview] Unknown message type:', data)
}
}
// Debounce: Wait 1 second after parameters change before regenerating
const timeoutId = setTimeout(generatePreview, 1000)
worker.onerror = (error) => {
console.error('[STLPreview] Worker error:', error)
setError('Worker failed to load')
setIsGenerating(false)
}
workerRef.current = worker
return () => {
worker.terminate()
workerRef.current = null
// Clean up any blob URLs
if (previewUrl && previewUrl.startsWith('blob:')) {
URL.revokeObjectURL(previewUrl)
}
}
}, [])
// Trigger rendering when parameters change
useEffect(() => {
if (!workerRef.current) return
setIsGenerating(true)
setError(null)
// Debounce: Wait 500ms after parameters change before regenerating
const timeoutId = setTimeout(() => {
workerRef.current?.postMessage({
type: 'render',
columns,
scaleFactor,
})
}, 500)
return () => {
mounted = false
clearTimeout(timeoutId)
}
}, [columns, scaleFactor])

View File

@@ -495,6 +495,10 @@ function MinimalNav({
justifyContent: 'center',
alignItems: 'flex-start',
pointerEvents: 'none',
// Set active nav height for content to use
['--app-nav-height' as any]: 'var(--app-nav-height-minimal)',
// Use the variable for min-height to ensure consistency
minHeight: 'var(--app-nav-height-minimal)',
}}
>
{/* Hamburger Menu - positioned absolutely on left */}
@@ -568,6 +572,7 @@ export function AppNavBar({ variant = 'full', navSlot }: AppNavBarProps) {
const pathname = usePathname()
const router = useRouter()
const isArcadePage = pathname?.startsWith('/arcade')
const isHomePage = pathname === '/'
const { isFullscreen, toggleFullscreen, exitFullscreen } = useFullscreen()
// Try to get home hero context (if on homepage)
@@ -579,7 +584,7 @@ export function AppNavBar({ variant = 'full', navSlot }: AppNavBarProps) {
const subtitle = homeHero?.subtitle || fallbackSubtitle
// Show branding unless we're on homepage with visible hero
const showBranding = !homeHero || !homeHero.isHeroVisible
const showBranding = !isHomePage || !homeHero || !homeHero.isHeroVisible
// Auto-detect variant based on context
// Only arcade pages (not /games) should use minimal nav
@@ -600,12 +605,18 @@ export function AppNavBar({ variant = 'full', navSlot }: AppNavBarProps) {
)
}
// Check if we should use transparent styling (when hero is visible)
const isTransparent = homeHero?.isHeroVisible
// Check if we should use transparent styling (when hero is visible on home page)
const isTransparent = isHomePage && homeHero?.isHeroVisible
return (
<Tooltip.Provider delayDuration={200}>
<header
style={{
// Set active nav height for content to use
['--app-nav-height' as any]: 'var(--app-nav-height-full)',
// Use the variable for min-height to ensure consistency
minHeight: 'var(--app-nav-height-full)',
}}
className={css({
bg: isTransparent ? 'transparent' : 'rgba(0, 0, 0, 0.5)',
backdropFilter: isTransparent ? 'none' : 'blur(12px)',

View File

@@ -66,32 +66,6 @@ export function InteractiveAbacus({
const beadPosition = beadElement.getAttribute('data-bead-position')
const isActive = beadElement.getAttribute('data-bead-active') === '1'
console.log('Bead clicked:', {
beadType,
beadColumn,
beadPosition,
isActive,
})
console.log('Current value before click:', currentValue)
if (beadType === 'earth') {
const position = parseInt(beadPosition || '0', 10)
const placeValue = beadColumn
const columnPower = 10 ** placeValue
const currentDigit = Math.floor(currentValue / columnPower) % 10
const heavenContribution = Math.floor(currentDigit / 5) * 5
const earthContribution = currentDigit % 5
console.log('Earth bead analysis:', {
position,
beadColumn,
placeValue,
columnPower,
currentDigit,
heavenContribution,
earthContribution,
})
}
if (beadType === 'heaven') {
// Toggle heaven bead (worth 5)
// Now using place-value based column numbering: 0=ones, 1=tens, 2=hundreds
@@ -140,13 +114,6 @@ export function InteractiveAbacus({
newEarthContribution = position + 1
}
console.log('Earth bead calculation:', {
position,
isActive,
currentEarthContribution: earthContribution,
newEarthContribution,
})
// Calculate the new digit for this column
const newDigit = heavenContribution + newEarthContribution

View File

@@ -226,7 +226,6 @@ export function MyAbacus() {
/>
</div>
</div>
</div>
{/* Keyframes for animations */}

View File

@@ -53,49 +53,28 @@ export function HomeHeroProvider({ children }: { children: React.ReactNode }) {
// Load from sessionStorage after mount (client-only, no hydration mismatch)
useEffect(() => {
console.log('[HeroAbacus] Loading from sessionStorage...')
isLoadingFromStorage.current = true // Block saves during load
const saved = sessionStorage.getItem('heroAbacusValue')
console.log('[HeroAbacus] Saved value from storage:', saved)
if (saved) {
const parsedValue = parseInt(saved, 10)
console.log('[HeroAbacus] Parsed value:', parsedValue)
if (!Number.isNaN(parsedValue)) {
console.log('[HeroAbacus] Setting abacus value to:', parsedValue)
setAbacusValue(parsedValue)
}
} else {
console.log('[HeroAbacus] No saved value found, staying at 0')
}
// Use setTimeout to ensure the value has been set before we allow saves
setTimeout(() => {
isLoadingFromStorage.current = false
setIsAbacusLoaded(true)
console.log('[HeroAbacus] Load complete, allowing saves now and fading in')
}, 0)
}, [])
// Persist value to sessionStorage when it changes (but skip during load)
useEffect(() => {
console.log(
'[HeroAbacus] Save effect triggered. Value:',
abacusValue,
'isLoadingFromStorage:',
isLoadingFromStorage.current
)
if (!isLoadingFromStorage.current) {
console.log('[HeroAbacus] Saving to sessionStorage:', abacusValue)
sessionStorage.setItem('heroAbacusValue', abacusValue.toString())
console.log(
'[HeroAbacus] Saved successfully. Storage now contains:',
sessionStorage.getItem('heroAbacusValue')
)
} else {
console.log('[HeroAbacus] Skipping save (currently loading from storage)')
}
}, [abacusValue])

View File

@@ -3,7 +3,7 @@
* This prevents multi-page overflow - one image scales to fit
*/
import React from 'react'
import type React from 'react'
import { AbacusStatic, calculateAbacusDimensions } from '@soroban/abacus-react/static'
interface CalendarCompositeOptions {
@@ -13,8 +13,18 @@ interface CalendarCompositeOptions {
}
const MONTH_NAMES = [
'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December',
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
]
const WEEKDAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
@@ -33,84 +43,86 @@ export function generateCalendarComposite(options: CalendarCompositeOptions): st
const firstDayOfWeek = getFirstDayOfWeek(year, month)
const monthName = MONTH_NAMES[month - 1]
// Layout constants for US Letter aspect ratio (8.5 x 11)
const WIDTH = 850
const HEIGHT = 1100
const MARGIN = 50
const CONTENT_WIDTH = WIDTH - MARGIN * 2
const CONTENT_HEIGHT = HEIGHT - MARGIN * 2
// Layout constants for US Letter aspect ratio (8.5 x 11)
const WIDTH = 850
const HEIGHT = 1100
const MARGIN = 50
const CONTENT_WIDTH = WIDTH - MARGIN * 2
const CONTENT_HEIGHT = HEIGHT - MARGIN * 2
// Abacus natural size is 120x230 at scale=1
const ABACUS_NATURAL_WIDTH = 120
const ABACUS_NATURAL_HEIGHT = 230
// Abacus natural size is 120x230 at scale=1
const ABACUS_NATURAL_WIDTH = 120
const ABACUS_NATURAL_HEIGHT = 230
// Calculate how many columns needed for year
const yearColumns = Math.max(1, Math.ceil(Math.log10(year + 1)))
// Calculate how many columns needed for year
const yearColumns = Math.max(1, Math.ceil(Math.log10(year + 1)))
// Year abacus dimensions (calculate first to determine header height)
// Use the shared dimension calculator so we stay in sync with AbacusStatic
const { width: yearAbacusActualWidth, height: yearAbacusActualHeight } = calculateAbacusDimensions({
columns: yearColumns,
showNumbers: false,
columnLabels: [],
})
// Year abacus dimensions (calculate first to determine header height)
// Use the shared dimension calculator so we stay in sync with AbacusStatic
const { width: yearAbacusActualWidth, height: yearAbacusActualHeight } =
calculateAbacusDimensions({
columns: yearColumns,
showNumbers: false,
columnLabels: [],
})
const yearAbacusDisplayWidth = WIDTH * 0.15 // Display size on page
const yearAbacusDisplayHeight = (yearAbacusActualHeight / yearAbacusActualWidth) * yearAbacusDisplayWidth
const yearAbacusDisplayWidth = WIDTH * 0.15 // Display size on page
const yearAbacusDisplayHeight =
(yearAbacusActualHeight / yearAbacusActualWidth) * yearAbacusDisplayWidth
// Header - sized to fit month name + year abacus
const MONTH_NAME_HEIGHT = 40
const HEADER_HEIGHT = MONTH_NAME_HEIGHT + yearAbacusDisplayHeight + 20 // 20px spacing
const TITLE_Y = MARGIN + 35
const yearAbacusX = (WIDTH - yearAbacusDisplayWidth) / 2
const yearAbacusY = TITLE_Y + 10
// Header - sized to fit month name + year abacus
const MONTH_NAME_HEIGHT = 40
const HEADER_HEIGHT = MONTH_NAME_HEIGHT + yearAbacusDisplayHeight + 20 // 20px spacing
const TITLE_Y = MARGIN + 35
const yearAbacusX = (WIDTH - yearAbacusDisplayWidth) / 2
const yearAbacusY = TITLE_Y + 10
// Calendar grid
const GRID_START_Y = MARGIN + HEADER_HEIGHT
const GRID_HEIGHT = CONTENT_HEIGHT - HEADER_HEIGHT
const WEEKDAY_ROW_HEIGHT = 25
const DAY_GRID_HEIGHT = GRID_HEIGHT - WEEKDAY_ROW_HEIGHT
// Calendar grid
const GRID_START_Y = MARGIN + HEADER_HEIGHT
const GRID_HEIGHT = CONTENT_HEIGHT - HEADER_HEIGHT
const WEEKDAY_ROW_HEIGHT = 25
const DAY_GRID_HEIGHT = GRID_HEIGHT - WEEKDAY_ROW_HEIGHT
// 7 columns, up to 6 rows (35 cells max = 5 empty + 30 days worst case)
const CELL_WIDTH = CONTENT_WIDTH / 7
const DAY_CELL_HEIGHT = DAY_GRID_HEIGHT / 6
// 7 columns, up to 6 rows (35 cells max = 5 empty + 30 days worst case)
const CELL_WIDTH = CONTENT_WIDTH / 7
const DAY_CELL_HEIGHT = DAY_GRID_HEIGHT / 6
// Day abacus sizing - fit in cell with padding
const CELL_PADDING = 5
// Day abacus sizing - fit in cell with padding
const CELL_PADDING = 5
// Calculate max scale to fit in cell
const MAX_SCALE_X = (CELL_WIDTH - CELL_PADDING * 2) / ABACUS_NATURAL_WIDTH
const MAX_SCALE_Y = (DAY_CELL_HEIGHT - CELL_PADDING * 2) / ABACUS_NATURAL_HEIGHT
const ABACUS_SCALE = Math.min(MAX_SCALE_X, MAX_SCALE_Y) * 0.9 // 90% to leave breathing room
// Calculate max scale to fit in cell
const MAX_SCALE_X = (CELL_WIDTH - CELL_PADDING * 2) / ABACUS_NATURAL_WIDTH
const MAX_SCALE_Y = (DAY_CELL_HEIGHT - CELL_PADDING * 2) / ABACUS_NATURAL_HEIGHT
const ABACUS_SCALE = Math.min(MAX_SCALE_X, MAX_SCALE_Y) * 0.9 // 90% to leave breathing room
const SCALED_ABACUS_WIDTH = ABACUS_NATURAL_WIDTH * ABACUS_SCALE
const SCALED_ABACUS_HEIGHT = ABACUS_NATURAL_HEIGHT * ABACUS_SCALE
const SCALED_ABACUS_WIDTH = ABACUS_NATURAL_WIDTH * ABACUS_SCALE
const SCALED_ABACUS_HEIGHT = ABACUS_NATURAL_HEIGHT * ABACUS_SCALE
// Generate calendar grid
const calendarCells: (number | null)[] = []
for (let i = 0; i < firstDayOfWeek; i++) {
calendarCells.push(null)
}
for (let day = 1; day <= daysInMonth; day++) {
calendarCells.push(day)
}
// Generate calendar grid
const calendarCells: (number | null)[] = []
for (let i = 0; i < firstDayOfWeek; i++) {
calendarCells.push(null)
}
for (let day = 1; day <= daysInMonth; day++) {
calendarCells.push(day)
}
// Render individual abacus SVGs as complete SVG elements
function renderAbacusSVG(value: number, columns: number, scale: number): string {
return renderToString(
<AbacusStatic
value={value}
columns={columns}
scaleFactor={scale}
showNumbers={false}
frameVisible={true}
compact={false}
/>
)
}
// Render individual abacus SVGs as complete SVG elements
function renderAbacusSVG(value: number, columns: number, scale: number): string {
return renderToString(
<AbacusStatic
value={value}
columns={columns}
scaleFactor={scale}
showNumbers={false}
frameVisible={true}
compact={false}
/>
)
}
// Main composite SVG
const compositeSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="${WIDTH}" height="${HEIGHT}" viewBox="0 0 ${WIDTH} ${HEIGHT}">
// Main composite SVG
const compositeSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="${WIDTH}" height="${HEIGHT}" viewBox="0 0 ${WIDTH} ${HEIGHT}">
<!-- Background -->
<rect width="${WIDTH}" height="${HEIGHT}" fill="white"/>
@@ -130,11 +142,13 @@ const compositeSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="${WIDTH}" h
})()}
<!-- Weekday Headers -->
${WEEKDAYS.map((day, i) => `
${WEEKDAYS.map(
(day, i) => `
<text x="${MARGIN + i * CELL_WIDTH + CELL_WIDTH / 2}" y="${GRID_START_Y + 18}"
text-anchor="middle" font-family="Arial" font-size="14" font-weight="bold" fill="#555">
${day}
</text>`).join('')}
</text>`
).join('')}
<!-- Separator line under weekdays -->
<line x1="${MARGIN}" y1="${GRID_START_Y + WEEKDAY_ROW_HEIGHT}"
@@ -142,45 +156,49 @@ const compositeSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="${WIDTH}" h
stroke="#333" stroke-width="2"/>
<!-- Calendar Grid Cells -->
${calendarCells.map((day, index) => {
const row = Math.floor(index / 7)
const col = index % 7
const cellX = MARGIN + col * CELL_WIDTH
const cellY = GRID_START_Y + WEEKDAY_ROW_HEIGHT + row * DAY_CELL_HEIGHT
${calendarCells
.map((day, index) => {
const row = Math.floor(index / 7)
const col = index % 7
const cellX = MARGIN + col * CELL_WIDTH
const cellY = GRID_START_Y + WEEKDAY_ROW_HEIGHT + row * DAY_CELL_HEIGHT
return `
return `
<rect x="${cellX}" y="${cellY}" width="${CELL_WIDTH}" height="${DAY_CELL_HEIGHT}"
fill="none" stroke="#333" stroke-width="2"/>`
}).join('')}
})
.join('')}
<!-- Calendar Day Abaci -->
${calendarCells.map((day, index) => {
if (day === null) return ''
${calendarCells
.map((day, index) => {
if (day === null) return ''
const row = Math.floor(index / 7)
const col = index % 7
const cellX = MARGIN + col * CELL_WIDTH
const cellY = GRID_START_Y + WEEKDAY_ROW_HEIGHT + row * DAY_CELL_HEIGHT
const row = Math.floor(index / 7)
const col = index % 7
const cellX = MARGIN + col * CELL_WIDTH
const cellY = GRID_START_Y + WEEKDAY_ROW_HEIGHT + row * DAY_CELL_HEIGHT
// Center abacus in cell
const abacusCenterX = cellX + CELL_WIDTH / 2
const abacusCenterY = cellY + DAY_CELL_HEIGHT / 2
// Center abacus in cell
const abacusCenterX = cellX + CELL_WIDTH / 2
const abacusCenterY = cellY + DAY_CELL_HEIGHT / 2
// Offset to top-left corner of abacus (accounting for scaled size)
const abacusX = abacusCenterX - SCALED_ABACUS_WIDTH / 2
const abacusY = abacusCenterY - SCALED_ABACUS_HEIGHT / 2
// Offset to top-left corner of abacus (accounting for scaled size)
const abacusX = abacusCenterX - SCALED_ABACUS_WIDTH / 2
const abacusY = abacusCenterY - SCALED_ABACUS_HEIGHT / 2
// Render at scale=1 and let the nested SVG handle scaling via viewBox
const abacusSVG = renderAbacusSVG(day, 2, 1)
const svgContent = abacusSVG.replace(/<svg[^>]*>/, '').replace(/<\/svg>$/, '')
// Render at scale=1 and let the nested SVG handle scaling via viewBox
const abacusSVG = renderAbacusSVG(day, 2, 1)
const svgContent = abacusSVG.replace(/<svg[^>]*>/, '').replace(/<\/svg>$/, '')
return `
return `
<!-- Day ${day} (row ${row}, col ${col}) -->
<svg x="${abacusX}" y="${abacusY}" width="${SCALED_ABACUS_WIDTH}" height="${SCALED_ABACUS_HEIGHT}"
viewBox="0 0 ${ABACUS_NATURAL_WIDTH} ${ABACUS_NATURAL_HEIGHT}">
${svgContent}
</svg>`
}).join('')}
})
.join('')}
</svg>`
return compositeSVG

View File

@@ -0,0 +1,206 @@
/// <reference lib="webworker" />
import { createOpenSCAD } from 'openscad-wasm-prebuilt'
declare const self: DedicatedWorkerGlobalScope
let openscad: Awaited<ReturnType<typeof createOpenSCAD>> | null = null
let simplifiedStlData: ArrayBuffer | null = null
let isInitializing = false
let initPromise: Promise<void> | null = null
// Message types
interface RenderRequest {
type: 'render'
columns: number
scaleFactor: number
}
interface InitRequest {
type: 'init'
}
type WorkerRequest = RenderRequest | InitRequest
// Initialize OpenSCAD instance and load base STL file
async function initialize() {
if (openscad) return // Already initialized
if (isInitializing) return initPromise // Already initializing, return existing promise
isInitializing = true
initPromise = (async () => {
try {
console.log('[OpenSCAD Worker] Initializing...')
// Create OpenSCAD instance
openscad = await createOpenSCAD()
console.log('[OpenSCAD Worker] OpenSCAD WASM loaded')
// Fetch the simplified STL file once
const stlResponse = await fetch('/3d-models/simplified.abacus.stl')
if (!stlResponse.ok) {
throw new Error(`Failed to fetch STL: ${stlResponse.statusText}`)
}
simplifiedStlData = await stlResponse.arrayBuffer()
console.log('[OpenSCAD Worker] Simplified STL loaded', simplifiedStlData.byteLength, 'bytes')
self.postMessage({ type: 'ready' })
} catch (error) {
console.error('[OpenSCAD Worker] Initialization failed:', error)
self.postMessage({
type: 'error',
error: error instanceof Error ? error.message : 'Initialization failed',
})
throw error
} finally {
isInitializing = false
}
})()
return initPromise
}
async function render(columns: number, scaleFactor: number) {
// Wait for initialization if not ready
if (!openscad || !simplifiedStlData) {
await initialize()
}
if (!openscad || !simplifiedStlData) {
throw new Error('Worker not initialized')
}
try {
console.log(`[OpenSCAD Worker] Rendering with columns=${columns}, scaleFactor=${scaleFactor}`)
// Get low-level instance for filesystem access
const instance = openscad.getInstance()
// Create directory if it doesn't exist
try {
instance.FS.mkdir('/3d-models')
console.log('[OpenSCAD Worker] Created /3d-models directory')
} catch (e: any) {
// Check if it's EEXIST (directory already exists) - errno 20
if (e.errno === 20) {
console.log('[OpenSCAD Worker] /3d-models directory already exists')
} else {
console.error('[OpenSCAD Worker] Failed to create directory:', e)
throw new Error(`Failed to create /3d-models directory: ${e.message || e}`)
}
}
// Write STL file
instance.FS.writeFile('/3d-models/simplified.abacus.stl', new Uint8Array(simplifiedStlData))
console.log('[OpenSCAD Worker] Wrote simplified STL to filesystem')
// Generate the SCAD code with parameters
const scadCode = `
// Inline version of abacus.scad that doesn't require BOSL2
columns = ${columns};
scale_factor = ${scaleFactor};
stl_path = "/3d-models/simplified.abacus.stl";
// Known bounding box dimensions
bbox_size = [186, 60, 120];
// Calculate parameters
total_columns_in_stl = 13;
columns_per_side = columns / 2;
width_scale = columns_per_side / total_columns_in_stl;
units_per_column = bbox_size[0] / total_columns_in_stl;
column_spacing = columns_per_side * units_per_column;
// Model modules
module imported() {
import(stl_path, convexity = 10);
}
module bounding_box_manual() {
translate([-bbox_size[0]/2, -bbox_size[1]/2, -bbox_size[2]/2])
cube(bbox_size);
}
module half_abacus() {
intersection() {
scale([width_scale, 1, 1]) bounding_box_manual();
imported();
}
}
scale([scale_factor, scale_factor, scale_factor]) {
translate([column_spacing, 0, 0]) mirror([1,0,0]) half_abacus();
half_abacus();
}
`
// Use high-level renderToStl API
console.log('[OpenSCAD Worker] Calling renderToStl...')
const stlBuffer = await openscad.renderToStl(scadCode)
console.log('[OpenSCAD Worker] Rendering complete:', stlBuffer.byteLength, 'bytes')
// Send the result back
self.postMessage({
type: 'result',
stl: stlBuffer,
}, [stlBuffer]) // Transfer ownership of the buffer
// Clean up STL file
try {
instance.FS.unlink('/3d-models/simplified.abacus.stl')
} catch (e) {
// Ignore cleanup errors
}
} catch (error) {
console.error('[OpenSCAD Worker] Rendering failed:', error)
// Try to get more error details
let errorMessage = 'Rendering failed'
if (error instanceof Error) {
errorMessage = error.message
console.error('[OpenSCAD Worker] Error stack:', error.stack)
}
// Check if it's an Emscripten FS error
if (error && typeof error === 'object' && 'errno' in error) {
console.error('[OpenSCAD Worker] FS errno:', (error as any).errno)
console.error('[OpenSCAD Worker] FS error details:', error)
}
self.postMessage({
type: 'error',
error: errorMessage,
})
}
}
// Message handler
self.onmessage = async (event: MessageEvent<WorkerRequest>) => {
const { data } = event
try {
switch (data.type) {
case 'init':
await initialize()
break
case 'render':
await render(data.columns, data.scaleFactor)
break
default:
console.error('[OpenSCAD Worker] Unknown message type:', data)
}
} catch (error) {
console.error('[OpenSCAD Worker] Message handler error:', error)
self.postMessage({
type: 'error',
error: error instanceof Error ? error.message : 'Unknown error',
})
}
}
// Auto-initialize on worker start
initialize()

View File

@@ -17,7 +17,18 @@
"Bash(pnpm build:*)",
"Bash(pnpm --filter @soroban/web build:*)",
"Bash(pnpm tsc:*)",
"Bash(AbacusReact.tsx)"
"Bash(AbacusReact.tsx)",
"Bash(git log:*)",
"Bash(pnpm dev)",
"Bash(npx biome:*)",
"Bash(pnpm --filter @soroban/web tsc:*)",
"Bash(git tag:*)",
"Bash(gh api:*)",
"WebSearch",
"WebFetch(domain:schroer.ca)",
"WebFetch(domain:github.com)",
"Bash(npm search:*)",
"Bash(pnpm add:*)"
]
},
"enableAllProjectMcpServers": true,

View File

@@ -1,3 +1,22 @@
# [2.9.0](https://github.com/antialias/soroban-abacus-flashcards/compare/abacus-react-v2.8.3...abacus-react-v2.9.0) (2025-11-05)
### Bug Fixes
* **docker:** upgrade OpenSCAD to 2024.11 to fix CGAL intersection bug ([e1bcd24](https://github.com/antialias/soroban-abacus-flashcards/commit/e1bcd241691050fa05cd49e14c288b4b070a7d17))
* **guide:** increase abacus sizes - they were too small ([1074624](https://github.com/antialias/soroban-abacus-flashcards/commit/1074624b2fbce1d1d887dbd6326cf22eeb31dcec))
* **guide:** make abacus sizes consistent and add nav spacing ([bea4842](https://github.com/antialias/soroban-abacus-flashcards/commit/bea4842a29aa86ca4261b4ddd6150bacc8babc46))
* **guide:** remove inner containers and tighten margins ([7e54c6f](https://github.com/antialias/soroban-abacus-flashcards/commit/7e54c6f4fc5bc4daa6088eb3381d860a495776f2))
* **layout:** add systematic spacing for fixed nav bar ([4559fb1](https://github.com/antialias/soroban-abacus-flashcards/commit/4559fb121d0df954ebaf33616a5262c7ca633c6e))
* **layout:** remove wrapper, use utility class for nav spacing ([247c3d9](https://github.com/antialias/soroban-abacus-flashcards/commit/247c3d9874303f83641e599724a485eea8d5604a))
* **nav:** restrict transparent hero styling to home page only ([fab227d](https://github.com/antialias/soroban-abacus-flashcards/commit/fab227d6862672e8250b1c169b302fbae23ce4d2))
### Features
* **3d-abacus:** change default columns from 13 to 4 ([cd15c70](https://github.com/antialias/soroban-abacus-flashcards/commit/cd15c70a25c597c17ee5d2f816b1c85ba8ce4ce9))
* add client-side OpenSCAD WASM support for 3D preview ([eaaf17c](https://github.com/antialias/soroban-abacus-flashcards/commit/eaaf17cd4c675bfd40e0573b9c99f0c733d926aa))
## [2.8.3](https://github.com/antialias/soroban-abacus-flashcards/compare/abacus-react-v2.8.2...abacus-react-v2.8.3) (2025-11-05)

8
pnpm-lock.yaml generated
View File

@@ -188,6 +188,9 @@ importers:
next-intl:
specifier: ^4.4.0
version: 4.4.0(next@14.2.33(@babel/core@7.28.4)(@playwright/test@1.56.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(typescript@5.9.3)
openscad-wasm-prebuilt:
specifier: ^1.2.0
version: 1.2.0
python-bridge:
specifier: ^1.1.0
version: 1.1.0
@@ -7484,6 +7487,9 @@ packages:
resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
engines: {node: '>=12'}
openscad-wasm-prebuilt@1.2.0:
resolution: {integrity: sha512-JfXJlopHVHvsYiVYUKYDXkg8yOkABm8zclo8zPrSRBeeICR+fitesO6NRwBdAzSdbtOYh6Scmuz/XLyhllbzYA==}
optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
@@ -17737,6 +17743,8 @@ snapshots:
is-docker: 2.2.1
is-wsl: 2.2.0
openscad-wasm-prebuilt@1.2.0: {}
optionator@0.9.4:
dependencies:
deep-is: 0.1.4