# Five Letters — a daily word game (★★)

Build a daily five-letter word game. Everyone who opens it on the same date gets the same secret word, with no server: the word is picked from a list using the date as a seed. You get six guesses. After each guess the tiles flip and turn green (right letter, right place), yellow (in the word, wrong place) or grey (not in the word). An on-screen keyboard shows what you know about each letter. When you finish, one button shares your result as a grid of coloured squares, with no letters, so friends can compare without spoilers. Your streak is kept on this device. A hard mode forces you to use every hint you have found.

## Done looks like

- A 6 by 5 grid and an on-screen keyboard. Physical keyboard works too: letters, Backspace, Enter.
- A guess that is not five letters, or not in the word list, shakes the row and shows "Not in word list". It does not use up a guess.
- Scoring handles repeated letters correctly (see milestone 2 for the exact test cases).
- Two different browsers on the same date get the same word. The next local day gives a new word.
- Add-on: reloading the page in the middle of a game keeps the board exactly as it was.
- A stats panel shows games played, win percentage, current streak, best streak and a bar chart of guesses needed.
- Add-on: share produces text like `Five Letters 214 4/6` followed by rows of green, yellow and dark square emoji. It uses `navigator.share` on phones and copies to the clipboard elsewhere, with a "Copied" message.
- Hard mode is a toggle. With it on, a guess must keep every green letter in place and include every yellow letter.
- Works offline once loaded. No console errors.

## Constraints

- Static files, no build step: `index.html`, `style.css`, `game.js`, `words.js`. No frameworks.
- `words.js` exports two lists: `ANSWERS` (common, friendly five-letter words; nothing offensive) and `ALLOWED` (every accepted guess, which includes all answers). Start with at least 300 answers. A small check script must prove every entry is five lower-case letters a to z with no duplicates.
- Do not download a word list without asking me first and checking its licence.
- The daily word: take the local date (year, month, day, not UTC), count whole days since 2026-01-01, and use that day number. Shuffle `ANSWERS` once with a seeded random number generator (for example mulberry32 with a fixed seed), then pick `shuffled[day % ANSWERS.length]`. The puzzle number in the share text is the day number.
- All state in localStorage under keys starting `five.`. No server, no network calls, no tracking, no accounts.
- Colours must also be told apart by shape or label for colour-blind players (a high-contrast option at least).
- Phone works: the grid and keyboard fit a 360 px wide screen without scrolling.

## Milestones

1. **Grid and typing.** Draw the empty grid. Typing fills the current row, Backspace removes, Enter submits a full row (no scoring yet).
   Check: you can type five letters, delete one, retype, press Enter, and the next row becomes active.
2. **Scoring, with tests.** Write `score(guess, answer)` returning five marks: green, yellow or grey. Use two passes: greens first, then yellows counted against the letters left over. Add `tests.html` that runs the cases and prints pass or fail. Cases: answer `abbey`, guess `babes` gives yellow, yellow, green, green, grey. Answer `lever`, guess `eeeee` gives grey, green, grey, green, grey. Answer `crane`, guess `crane` gives five greens.
   Check: `tests.html` shows every case passing.
3. **Word list and the daily word.** Add `words.js` and the check script. Reject guesses not in `ALLOWED`. Pick today's word from the date as described.
   Check: the check script passes; open the game in two different browsers and both have the same answer (show it with `?debug=1`).
4. **Keyboard and reveal.** On-screen keyboard that types into the grid. Tiles flip one after another when a row is scored. Keys take the best colour known for that letter. Win and lose messages.
   Check: on a phone you can play a whole game with the on-screen keyboard, and a key that was green never turns back to yellow.
5. **Hard mode and polish.** Hard mode toggle (it can only be switched on before the first guess of the day). A high-contrast colour option. A countdown to the next word on the end screen.
   Check: in hard mode, a guess that drops a green letter is refused with a message naming the letter and position.
> That is the whole game, for one day at a time. The next two make it remember and let you show off.
6. **Save and stats.** Save the board after every guess. Track played, wins, current streak, best streak and guess distribution. A streak breaks if you miss a day or lose.
   Check: reload mid-game and the board is unchanged; finish a game and the stats panel updates.
7. **Share.** Build the share text from the marks only. `navigator.share` if available, clipboard otherwise.
   Check: paste the result into a chat: it shows the puzzle number, your score and the coloured grid, and no letters.

## Stretch

- A practice mode with a random word that does not touch your streak.
- A six-letter weekend edition with its own list and seed.
- A "how did everyone do" chart: a Worker and KV that count only how many guesses each player needed that day, no names. KV allows 1,000 writes a day on the free plan, so this suits a group of friends, not the whole internet.
- Animations for a win: tiles bounce one after another.
- A short definition shown after the game, written into the word list so no network is needed.
- A themed word list for one week (animals, food, space).

## Leave out

- Accounts, a server, ads.
- Fetching words from an online dictionary.
- Copying another game's name, look or word list.

Start by reading WRITING.md and the guide chapter on data if you need storage.
