Return to lobby (replay without recreating the room):
- lobby:return (host): reset to lobby, scores to 0, keep players + tracks
- client: end screen has "Rejouer" (host) + "Quitter"; store clears transient
game state whenever the room goes back to lobby
Contributor has nothing to input:
- round:start carries a private `mine: true` to the contributor only (via
RoundStart.secretPlayerId targeted emit); they're excluded from eligible
voters. Client shows a "fais-les se tromper" card instead of the vote form.
Editable track submission:
- submitTrack ack returns trackId + youtubeId; new blindtest:removeTrack
- lobby shows submitted tracks as cards (YouTube thumbnail + title) with delete
Verified e2e (3 players): add/remove, private mine flag, return-to-lobby reset.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mixed mode (default):
- gameType is now mixed | quiz | blindtest, default "mixed"; the lobby
interleaves quiz + blindtest rounds so modes alternate
- lobby reworked: 3-way game-type switch, quiz count and/or blindtest config
+ track submission shown per selected type
Free-text quiz questions:
- quiz supports the `free` format (e.g. maths) alongside mcq/truefalse:
payload without choices, {text} vote, tolerant matching on acceptedAnswers
- shared QuizQuestionPayload.choices optional; reveal truth carries answer
- match util moved to game/match.ts (shared by quiz + blindtest)
- repo/seed include free + acceptedAnswers; in-code bank gains free questions
- client quiz view renders a text input for free questions
Mode-aware transitions:
- RoundTransition themed per mode (colors/label/emoji); announces the mode
on change (quiz <-> blindtest), lighter teaser within the same mode
- custom media buckets per mode: assets/transitions/{quiz,blindtest}/ + shared
- store tracks roundModeChanged
Verified e2e: mixed game alternates quiz/blindtest to completion; free-text
scoring covered by tests (22 pass).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Server (option 2 — don't eat answer time):
- engine: leadMs prep delay (default 1600ms) before the clock starts; the
round timer now fires at lead + duration, and scoring uses the post-lead
start so the speed bonus spans the full answer window
- shared: round:start carries startsAt (answers begin) alongside endsAt
- engine test passes leadMs:0
Client:
- Countdown shows the full duration (no ticking) until startsAt, then counts
down — so the WarioWare transition plays in full without stealing time
- store/ActiveRound carry startsAt
Custom transition media:
- RoundTransition auto-loads any gif/webp/apng/png/avif dropped in
src/assets/transitions/ (import.meta.glob), plays one at random per round,
falls back to the Framer animation when none are present
- README documenting how to add animations
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- RoundTransition overlay: fullscreen colored wipe-in, spinning sunburst,
big bouncing "QUESTION N" + "PRÊT ?!", then wipe-out (Framer Motion)
- store: roundKey counter incremented on round:start
- rendered at RoomPage, keyed by roundKey so it plays once per round
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- store: boomKey counter + boom() action
- Countdown fires boom() once when it reaches 0 (timer expiry only)
- Boom component (portal to body) plays a fullscreen white flash + giant 💥
- rendered at RoomPage level, keyed by boomKey so it plays fully (independent
of the countdown unmounting on reveal) and replays each round
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>