- Put emoji (🤔/☕) and phrase on same line in header
- Add random phrases for auto-pause: "This one's a thinker!", "Brain at
work!", "Deep thoughts happening...", etc.
- Horizontal layout with avatar on left, title/timer on right
- Smaller avatar (56px) for more compact layout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Consolidate the stacked header elements into a cleaner layout:
- Single title: "This one's a thinker!" or "Break Time!"
- Timer integrated inline below title instead of separate pill
- Removed redundant name repetition and "Taking a Thinking Break!"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove the "Smart thinking to take a break" element to declutter the
paused modal layout.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Switch from Panda CSS to inline styles for the resume button to ensure
the green background and white text are properly applied.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add an × close button in the top-right corner of the stats visualization
panel instead of toggling "hide" text in the main paragraph.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove "We Know Your Rhythm!" heading (creepy)
- Combine explanation text above the bar: "Usually you take X. This one
took longer, so we paused to check in."
- Hide stats visualization behind low-key "really?" toggle
- Make resume button much more prominent with deeper green, border,
larger padding, and stronger shadow
- Make "end session" button less prominent with smaller text, muted
color, and stop emoji
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Only show the rhythm/stats panel when we have enough data to display
meaningful statistics. For the default 5-minute timeout case (before
we've collected enough samples), just show the standard pause UI.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace hand-rolled duration formatting with Intl.NumberFormat using
the 'unit' style. This leverages browser-native localization for
pluralization (1 second vs 2 seconds) and proper formatting.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Redesign SessionPausedModal to be approachable for children while
maintaining high-fidelity statistical information:
- New visual components:
- SpeedMeter: shows average response time vs variation range
- SampleDots: visualizes progress toward learning user's rhythm (5 samples)
- Educational framing:
- "We Know Your Rhythm!" when we have enough samples
- "Learning Your Rhythm..." when collecting data
- "Taking a Thinking Break!" instead of clinical "paused" language
- Friendly UI improvements:
- Contextual emoji thought bubbles (🤔 for auto-pause, ☕ for manual)
- Encouraging messages ("Smart thinking to take a break!")
- "Keep Going!" button instead of "Resume"
- Progress bar with gradient styling
- Statistical transparency:
- Shows "Usually you take about X seconds" for mean
- Visual representation of standard deviation as "wiggle room"
- Explains why the pause happened in child-friendly terms
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add auto-pause when response time exceeds mean + 2σ (or 5min default)
- Track pause reason (manual vs auto-timeout) and timing info
- Display live-updating pause duration counter
- Show statistical details: sample count, mean, std dev, threshold
- For insufficient data, show "need X more problems for personalized timing"
- Add comprehensive Storybook stories for all pause scenarios
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add auto-pause when user takes too long on a problem
- Uses mean + 2 standard deviations of response times when ≥5 problems
- Falls back to 5 minute timeout otherwise
- Clamped between 30 seconds and 5 minutes
- Fix docked abacus to auto-scale to match problem dimensions
- AbacusDock now uses width: 100% and measured problem height
- MyAbacus calculates effectiveScaleFactor based on container size
- Animations use consistent scale calculations
- Fix bug: session paused modal no longer shows on page reload
- Fix bug: help mode now exits when both overlay and panel are dismissed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Force show submit button when abacus is docked (user needs manual submit)
- Disable auto-help when docked; trigger help on submit for prefix sums
- Fix dock animation to measure actual destination position
- Keep problem centered when dock appears/disappears (absolute positioning)
- Use scaleFactor prop for natural abacus sizing instead of manual calculations
- Clean up unused dock size tracking and scale calculation code
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement FLIP-style animation for the abacus docking feature:
- Measure viewport positions of button and dock using getBoundingClientRect
- Use react-spring to animate position, size, scale, and border-radius
- Add chromeOpacity spring value to smoothly fade button styling
(background, border, shadow, backdrop-blur) during transitions
- Animation layer renders as fixed-position overlay during transition
- Docking: button chrome fades out as abacus flies to dock
- Undocking: button chrome fades in as abacus returns to corner
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add AbacusDock component that allows the floating MyAbacus to dock into
designated areas within the UI:
- New AbacusDock component with configurable props (columns, showNumbers,
value, defaultValue, onValueChange, interactive, animated)
- MyAbacus can now render as: hero, button, open overlay, or docked
- Click floating button when dock is visible to dock the abacus
- Undock button appears in top-right of docked abacus
- Practice sessions use dock for answer input (auto-submit on correct answer)
- Dock sizing now matches problem height with responsive widths
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Change /practice/[studentId]/session to /practice/[studentId] since the
active session page is at the root [studentId] path, not a /session subfolder.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Use fixed height with minWidth and pill-shaped border-radius so badges expand horizontally for multi-digit numbers while staying circular for single digits.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Wire up time estimation utility to StartPracticeModal for per-mode problem counts
- Add problem count indicators: underneath emojis in collapsed view, badges on mode boxes in expanded view
- Ensure badges are always circular (aspect-ratio: 1)
- Add full-width progress bar to PracticeSubNav HUD with mode indicator and "X left" display
- Add SessionPausedModal for pause state handling
- Refactor ActiveSession to remove internal HUD (moved to sub-nav)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add CSS to push main content away from the keypad:
- Landscape (small screens): padding-right on body and margin-right on
nav/header/active-session to avoid the 100px right-side keypad
- Portrait: padding-bottom on body for the bottom keypad
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Use max-height: 500px constraint to only switch to the two-column
landscape layout on small screens (phones). On tablets and larger
screens in landscape, keep the horizontal bar at the bottom.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Panda CSS @media queries in object syntax weren't working reliably.
Use raw CSS string with proper @media (orientation: landscape) rule
to toggle between portrait and landscape keypad containers.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When submit button isn't shown, omit it entirely from the layout
instead of using a hidden spacer. This lets the remaining buttons
flex to fill the full width.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added explicit width: 100% and max-width: none to override
react-simple-keyboard defaults that may constrain width.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
NumericKeypad improvements:
- Fixed position: bottom bar in portrait, right panel in landscape
- Uses react-simple-keyboard with key-like styling (raised, press effect)
- Persists once shown even if physical keyboard detected
Skill detection refactoring:
- Unified all skill analysis through generateUnifiedInstructionSequence
- Removed ~210 lines of dead column-based analysis code
- Added cascading carry/borrow detection for consecutive ten complements
- Ported test cases from columnAnalysis.test.ts to skillDetection.test.ts
abacus-react:
- Added server-side compatible static exports
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fix bugs where five complement skills were incorrectly detected when the
heaven bead was already active:
Addition: When adding 1-4 results in 6-9 and currentDigit >= 5, no five
complement is needed - just add earth beads directly.
Subtraction: When ten complement addition crosses 5 boundary but
currentDigit >= 5, no five complement is needed for the addition part.
Also includes UX improvements from previous session:
- Dream sequence: show target value for 1s then fade out after help completion
- Clear answer boxes on help abacus dismiss
- Handle typing during help mode
Add comprehensive unit tests for column analysis functions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add crossfade animation between answer boxes and help abacus (1s enter, 300ms dismiss)
- Preserve user's prefix sum in answer boxes during fade-out transition
- Clear answer boxes after help abacus entrance transition completes
- Add dismiss button to help abacus with tooltip suppression on dismiss
- Add keyboard shortcuts (Escape/Delete/Backspace) to exit help mode
- Typing while in help mode dismisses help and starts fresh input
- Add independent dismiss controls for help abacus and help panel
- Fix tooltip remaining visible when help abacus is dismissed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove the fallback that was silently generating random problems when
skill-based generation failed. Instead, throw ProblemGenerationError
with detailed constraint information so issues can be addressed.
The analyzeRequiredSkills function should only be used for tests or
stories, not in production where we need accurate skill tracking.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add skill complexity budget system with base costs per skill type:
- Basic skills: 0 (trivial bead movements)
- Five complements: 1 (single mental substitution)
- Ten complements: 2 (cross-column operations)
- Cascading operations: 3 (multi-column)
- Add per-term complexity debug overlay in VerticalProblem (toggle via visual debug mode)
- Shows total cost per term and individual skill costs
- Highlights over-budget terms in red
- Make session structure parts toggleable in configure page:
- Can enable/disable abacus, visualization, and linear parts
- Time estimates, problem counts adjust dynamically
- At least one part must remain enabled
- Fix max terms per problem not being respected:
- generateSingleProblem was hardcoding 3-5 terms
- Now properly uses minTerms/maxTerms from constraints
- Set visualization complexity budget to 3 (more restrictive)
- Hide complexity badges for zero-cost (basic) skills in ManualSkillSelector
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Visualization problems now use 2-4 terms (75% of abacus's 3-6 terms)
to make them easier since students don't have the physical abacus
to help track their mental calculations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add advanced.cascadingCarry and advanced.cascadingBorrow skills for
detecting when carry/borrow propagates across 2+ consecutive columns
(e.g., 999 + 1 = 1000 or 1000 - 1 = 999)
- Update VerticalProblem help UX: replace answer boxes with help abacus
instead of floating above terms (less confusing for kids)
- Dim terms already in prefix sum at 40% opacity when in help mode
- Enlarge current-help arrow indicator to 1.75rem
- Add "Advanced Multi-Column Operations" category to ManualSkillSelector
so teachers can manually enable these skills
- Add unit tests for cascading regrouping detection (21 tests)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Calculate prefix sums (intermediate values) when determining maxDigits
- Ensures kids can enter step-by-step solutions that may be larger than final answer
- Example: 100-99=1 now has 3 answer boxes to accommodate entering "100" first
Also adds Playground story for testing any term sequence with:
- Textarea input with smart parsing of negatives
- Display of all prefix sums and max digits needed
- Interactive answer input
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add subtraction problem generation alongside addition
- Generator now uses signed terms (negative = subtraction)
- Update analyzeRequiredSkills to handle mixed operations
- Remove dead generateSkillTrace function (replaced by provenance)
- Add ProblemGeneratorAudit story for debugging skill analysis
- Display subtraction terms in red with proper +/- signs in audit UI
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Regenerate pnpm-lock.yaml to fix CI deployment failure.
The lockfile was out of sync causing "ERR_PNPM_OUTDATED_LOCKFILE"
in GitHub Actions when running with frozen-lockfile.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Extends session duration choices from [5, 10, 15, 20] to [5, 10, 15, 20, 30, 45] minutes, allowing for longer practice sessions with more problems.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Make ProgressDashboard session-aware with single primary CTA
- No session: "Start Practice →" (blue)
- Active session: "Resume Practice →" (green) with progress count
- Single "Start over" link replaces redundant Abandon/Regenerate buttons
- Add skill mismatch warning inline in level card
- Add masteredSkillIds to session_plans for mismatch detection
- Fix getActiveSessionPlan to check completedAt IS NULL (fixes loop bug)
- Remove separate Active Session Card from dashboard (now integrated)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major fix: Session planner now uses the student's actual mastered skills
from the database instead of hardcoded phase-based constraints.
Changes:
- Add buildConstraintsFromMasteredSkills() to convert student skill records
to problem generator constraints
- Session planner fetches mastered skills and passes them to problem generator
- Skills set via ManualSkillSelector now actually affect generated problems
- Remove unused buildChallengeConstraints() function
- Fix findStrugglingSkills() signature (remove unused param)
Also includes supporting changes from previous session:
- Add setMasteredSkills() to progress-manager for persisting skills
- Add PUT endpoint to skills/route.ts for saving mastered skills
- Display mastered skills in session configure preview
- Add "View All Planned Problems" section to SessionSummary
- Sync ManualSkillSelector state when modal opens
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Routes are now independent views, not exclusive states:
- /dashboard: always accessible (view stats during session)
- /configure: always accessible (prep next session during session)
- /summary: always accessible (shows in-progress partial results,
completed session, or empty state)
Only /practice/[studentId] retains guards since it requires an
active in-progress session to render a problem.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Restructure practice routes so each route represents valid state
- /practice/[studentId] now ONLY shows the current problem
- New /dashboard route for progress view
- New /summary route with guards (can't view mid-session)
- Combine configure + plan review into single unified page with:
- Duration selector that updates preview in real-time
- Live problem count and session structure preview
- Single "Let's Go!" button that generates + starts session
- Replace two-stage flow with instant feedback UX
- Delete StudentPracticeClient (replaced by simpler PracticeClient)
- Add getMostRecentCompletedSession for summary page
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove dead code from abandoned 3D printing initiative:
- Delete jobManager.ts (had unbounded memory growth)
- Delete openscad.worker.ts (unused)
- Delete 3D model files from public/
- Remove openscad-wasm-prebuilt dependency
- Clean up doc references
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The /resume page was showing stale session data when navigating mid-session.
Now uses useActiveSessionPlan with server props as initialData, so cached
session data from the active practice session takes priority.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The stop button wasn't working because endEarly.data was not included
in the currentPlan derivation chain. When the mutation completed with
the updated plan (completedAt set), the view didn't update to 'summary'.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create /practice/[studentId]/resume route for returning students
- Student selector navigates to /resume instead of main practice page
- /resume shows "Welcome back" card with session progress
- Clicking "Continue" navigates to /practice/[studentId] (goes straight to practice)
- Clicking "Start Fresh" abandons session and goes to /configure
- Main practice page no longer shows welcome card (goes straight to practicing)
- Reloading mid-session stays in practice (no welcome card)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update useActiveSessionPlan to accept initialData from server props
- Page now fetches its own data if cache is empty (no abstraction hole)
- Three loading scenarios handled:
1. Cache populated (from ConfigureClient mutation): instant display
2. Cache miss: fetches from API with loading state
3. Direct page load: uses server props as initialData
- Add loading view while fetching session plan
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add scroll: false to all router.push() calls in practice pages
- Add scroll={false} to Link component in not-found page
- Fixes Next.js warning about auto-scroll with fixed position header
- Add mobile-web-app-capable meta tag alongside deprecated apple-mobile-web-app-capable
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, typing "3" for problem [2, 1, 30, 10, 1] with prefix sums
[2, 3, 33, 43, 44] would immediately show help for prefix sum 3 because
the code only checked if "3" was a digit-prefix of the final answer (44).
Now it correctly checks if "3" could be a digit-prefix of ANY later prefix
sum (33 in this case), making it ambiguous and allowing the user to continue
typing "33" to get help for that prefix instead.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>