# Win State Findings

Primary files:

- `src/components/VictoryOverlay.tsx`
- `src/components/LoseOverlay.tsx`
- `src/store/gameStore.ts`
- `src/useLeaderboardSubmission.ts`
- `src/leaderboard.ts`

## VictoryOverlay Behavior

When the board becomes solved:

1. Store sets `status = "won"`.
2. Store computes `elapsedMs`.
3. Store computes score breakdown and writes `lastScoreDelta.breakdown`.
4. `StatusAudio` plays win sound.
5. `Board` starts a serpentine tile pop wave.
6. `VictoryOverlay` calls `runNextConfettiStyle()`.
7. Overlay waits 4000 ms before showing, unless the player taps early.
8. Score rows reveal in sequence.
9. Actions appear after the score story finishes.

Victory actions:

- Start Over - opens confirm dialog, then `nextPuzzle({ keepScore: false })`
- Continue - calls `nextPuzzle({ keepScore: true })`
- View leaderboard - opens `LeaderboardDialog`

## Score Breakdown

Win score rows are derived from `lastScoreDelta.breakdown`.

Rows can include:

- Words
- Board
- Moves left
- Time

Then the overlay shows:

- This round
- Previous
- Total Score

The store scoring constants are:

- `POINTS_PER_WORD = 10`
- `POINTS_PER_UNUSED_MOVE = 5`
- board completion bonus comes from board shape config
- time bonus uses `computeTimeBonus`

Note: the current code's `computeTimeBonus` differs from the older scoring spec. The code awards 30 for <= 30 seconds, then 20, 12, 6, 3, 0. Claude should follow current code unless product direction changes.

## Continue Flow

Continue means cumulative session score continues:

- next round increments
- score is preserved
- round score resets
- bonus slot may be awarded after a win
- board/puzzle/tile state resets for the next puzzle

Start Over means score resets to 0.

## Leaderboard Flow

Victory builds a leaderboard payload from:

- total score
- round
- puzzle id
- board width/height
- swap count
- swap limit
- bonus moves earned
- elapsed ms
- breakdown: words, board, movesLeft, time

It passes the payload to `useLeaderboardSubmission(submissionBase, user, visible)`.

If signed in:

- hook creates a leaderboard session token
- hook posts the score with the token
- server validates and records it

If signed out:

- hook state becomes `not-signed-in`
- current UI does not prominently show that state in the victory overlay
- leaderboard/account surfaces handle sign-in separately

Loss overlay also submits positive scores, but loss payload uses `roundScore` as words-only breakdown and zeroes board/moves/time.

## Visual Connection Opportunity

The win moment and leaderboard are currently adjacent but separate:

- Victory overlay has final score.
- `View leaderboard` opens a separate leaderboard modal.
- The leaderboard does not visually remember the just-earned score.

Good redesign opportunities:

- After victory, open leaderboard with the player's score emphasized.
- Animate the final score into a top/player card.
- Use the same green score typography across VictoryOverlay and LeaderboardDialog.
- Show "Recorded" or "Sign in to record" in the victory surface before or inside the leaderboard.
- Keep Continue visible or easy to return to if leaderboard opens from victory.

Implementation caution:

- Do not change score submission to a manual button without understanding one-use session semantics.
- Do not duplicate submission logic outside `useLeaderboardSubmission` unless the hook is intentionally refactored.
