All paths serve index.html so React Router handles routing.
Fixes 404 on page refresh for routes like /home, /game, etc.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Swipe left/right on the carousel viewport to navigate songs.
50px threshold prevents accidental triggers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Give actions and actionsRow a fixed min-height so the sponsors
section stays in place when switching between camera/fullscreen.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Speed up hacker effect (2x frames at 25ms instead of 3x at 40ms).
Team members randomly reorder every 3 seconds with a fade-in
animation. No member is ranked above another.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Letters scramble randomly then converge left-to-right to the final
text. Each element has a staggered delay for a cascade reveal
effect: title → hackathon name → section headers → members/tech.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show 'BIGGEST LITTLE HACKATHON 2026' under the title. Replace
generic 'special thanks' with a sponsors section showing all
six logos (UNR, Bently Nevada, Microsoft, Ridgeline, Coffee n
Comics, Type III) with links and hover effects.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reduce padding, gaps, score font size, and margins so the full
page fits within 100vh without overflow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use framingHint from the gesture engine to tell the user exactly
what's out of frame — head or feet — instead of a generic message.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Require 1 second after autopause before accepting arms-out gesture,
preventing stale gesture signals from immediately unpausing.
Messages now reflect actual calibration state:
- framing: "I can't see your feet! Step back."
- paused: uses framingHint or "I lost you! Step back into frame."
- ready (waiting for unpause): "Raise your arms to continue!"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Calibration skips pos-center when resuming from paused state, so
the previous approach never allowed unpause. Now watches the gesture
signal directly — arms-out while autopaused triggers resume.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Autopause now stays active until user raises arms (pos-center→ready
transition). Simply stepping back into frame keeps the game paused.
Score HUD stacked vertically — combo sits above score so it doesn't
shift the score horizontally when appearing/disappearing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Resume requires 500ms of stable 'ready' calibration before
unpausing, preventing flicker when arms-out is detected briefly.
Pause message now varies by calibration state:
- framing: "I can't see your feet! Step back."
- paused: "Raise your arms to continue!"
- ready (resuming): "Resuming..."
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Debounce same-direction steps within 200ms to prevent a single
physical step from consuming two arrows. Log step events with
arrow count and match details.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Perfect window: 120ms → 180ms, Good window: 280ms → 350ms.
This makes perfect detection match the visual arrow position better.
Remove the logic that marked the nearest future arrow as a miss
when stepping with nothing in range. Now premature steps are
simply ignored instead of punishing the player.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show softer wording ('might be janky') with a Continue Anyway
button to bypass the warning.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Check WebGL renderer for SwiftShader/software indicators. If
detected, show a red warning telling the user to enable GPU
acceleration in browser settings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show "PAUSED — I can't see you! Step back into frame." when the
game auto-pauses. Hide the red framing line once the game has
started so only the pause message appears.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove combo from ArrowGame's top-left ag-score div. Track combo
in GamePage and display it as "Nx" in pink next to the score in
the bottom HUD, above the progress bar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Commas followed by comments (e.g. ', // measure 1') were not
recognized as measure separators, causing all notes to be parsed
as a single measure with compressed timing. This is why all arrows
spawned at once on most songs (except Get Lucky which had plain
commas).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Logs audio lifecycle (loadstart, loadeddata, canplaythrough, error,
ended), active transitions, arrow spawning, calibration changes,
and periodic state dumps. LOG button in top-right copies all logs
to clipboard for debugging.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Arrows: update CSS lane color selectors to match new positions
(30/40/60/70% instead of 12.5/37.5/62.5/87.5%).
Audio: wait for canplaythrough event before attempting play(). This
fixes songs other than Get Lucky failing because the audio wasn't
buffered yet (Get Lucky worked because the preview cached it).
Auto-pause: track autoPaused state based on calibrationStatus. When
the user leaves frame (calibration goes to paused/framing), the game
pauses with "I lost track of you" message. Auto-resumes when they
return to frame.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace fragile multi-effect coordination with one effect + one
interval that polls activeRef for state transitions. No more
missed play() calls from effects not re-running.
Added console.log for: effect init/cleanup, first play, resume,
pause, and play success.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: pause/resume effect depended only on [active]. If active
was already true when chartNotes loaded, the audio loading effect
created the audio but the pause/resume effect never re-ran to play
it — songStartRef stayed null, no arrows spawned.
Fix: audio loading effect now tries to play immediately if active is
already true (via activeRef). Pause/resume effect handles both first
play (songStartRef null) and resume (pausedAtRef > 0) cases.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: three separate effects (audio load, pause/resume, spawn)
with overlapping deps caused race conditions — spawn interval could
start with stale refs, active toggling would recreate intervals
losing spawn state, and random mode could fire before chart loaded.
Fix: single effect for audio + spawn lifecycle (depends only on
chartNotes/audioUrl, not active). Spawn interval runs continuously
and checks songStartRef. Separate pause/resume effect depends only
on active, shifts arrow timestamps on resume. Removed random mode
fallback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use gameStarted (latched true once ready) instead of gameReady for
the ArrowGame active prop. Once the game starts, calibration status
changes no longer interrupt gameplay.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On resume, shift all existing arrow targetTimes forward by the
pause duration so they don't immediately register as misses.
Track pause timestamp to compute the exact offset.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows a small button in the bottom-right corner on all screens.
Listens to fullscreenchange events and hides when already fullscreen.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Score: move to bottom center above progress bar, remove key-based
remounting that caused layout shifts. Delta now fades in place.
Progress bar: magenta gradient bar at the very bottom showing song
progress via onProgress callback from ArrowGame.
Pause: decouple audio lifecycle from active prop so pausing doesn't
reset the song. Audio pauses/resumes cleanly with timing preserved.
Auto-pause: once game has started, show "I lost track of you" when
calibration pauses instead of the calibration overlay. Suppresses
"ARMS OUT" text during gameplay.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consider store results valid when a song is selected, not just when
score > 0. Prevents fallback to DEFAULT_SCORE on early finish.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show 'ENABLE CAMERA' button first with a hint explaining why. After
permission is granted, webcam shows as background and fullscreen/
windowed buttons appear. If denied, show error with retry option.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Embed the camera stream into the page as a low-opacity mirrored
background. This makes the permission prompt feel integrated rather
than a random browser popup. Stream is cleaned up on unmount.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prompt for webcam access early so the permission dialog appears
before the user reaches the game. Stream is immediately stopped
after permission is granted.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>