diff --git a/.agents/TODO.md b/.agents/TODO.md index bff599e..fc39be8 100644 --- a/.agents/TODO.md +++ b/.agents/TODO.md @@ -60,9 +60,10 @@ Use checkboxes to track progress. Items marked **πŸ”΄ BLOCKER** prevent release; ## 6. Post-launch (real data) ### 🟑 IMPORTANT -- [ ] Replace mock `data/*.json` with real World Cup 2026 data -- [ ] Fill `thirdPlaceAssignment` in `bracket-config.json` after group stage -- [ ] Real stadium photos + team flag SVGs in `assets/images/` +- [x] ~~Replace mock `data/*.json` with real World Cup 2026 data~~ (2026-06-12 β€” full migration + smoke test; see project-memory) +- [ ] Fill `thirdPlaceAssignment` in `bracket-config.json` after group stage ends (~2026-06-27; slot β†’ allowed-groups table in project-memory) +- [ ] Update `results.json` as the tournament progresses (USA–PAR kicked off 2026-06-13 01:00 UTC, still `scheduled` in data) +- [ ] Real stadium photos + team flag SVGs in `assets/images/` (10 new-team flags created 2026-06-12 in placeholder style) --- diff --git a/.agents/project-map.md b/.agents/project-map.md index 6bef875..bece4d2 100644 --- a/.agents/project-map.md +++ b/.agents/project-map.md @@ -2,7 +2,7 @@ Navigation map of the codebase. Use this to find which file owns a concern before reading code. -> **Status 2026-06-12 (steps 1–10 + 12 done):** everything works β€” all views, bracket interactions, simulation, responsive/a11y pass, favorites, time toggle, challenge, share link, `.ics` export. Remaining: step 11 (full README + acceptance checklist). Spec source of truth: `world-cup-2026-hub-spec-en.md` + `complement-spec-worldcup2026-en.md` (complement **wins on conflict**). +> **Status 2026-06-12 (all 12 steps + real-data migration done):** everything works with **real World Cup 2026 data** β€” all views, bracket interactions, simulation, responsive/a11y pass, favorites, time toggle, challenge, share link, `.ics` export. Remaining: keep `results.json` current, fill `thirdPlaceAssignment` after the group stage (~Jun 27), Lighthouse run + GitHub Pages deploy. Spec source of truth: `world-cup-2026-hub-spec-en.md` + `complement-spec-worldcup2026-en.md` (complement **wins on conflict**). --- @@ -41,17 +41,23 @@ worldcup2026/ β”‚ β”‚ └── calendar.js .ics export (RFC 5545, CRLF, Blob download) β”‚ └── images/ Team flag SVGs, stadium placeholders β”‚ -β”œβ”€β”€ data/ All content β€” the only thing edited for real data -β”‚ β”œβ”€β”€ teams.json 48 teams: { id, name, flag } -β”‚ β”œβ”€β”€ groups.json { "A": [4 team ids], ... } Γ— 12 (A–L) -β”‚ β”œβ”€β”€ matches.json 104 matches; UTC times; knockout uses bracketRef -β”‚ β”œβ”€β”€ results.json { matchId, homeScore, awayScore, penalties?, status } -β”‚ β”œβ”€β”€ stadiums.json ~30 stadiums: { id, name, city, capacity, image, timezone } -β”‚ └── bracket-config.json β˜… 16 R32 slot definitions + thirdPlaceAssignment β€” +β”œβ”€β”€ data/ All content β€” REAL WC2026 data since 2026-06-12 +β”‚ β”œβ”€β”€ teams.json 48 real qualifiers: { id, name, flag } (FIFA codes) +β”‚ β”œβ”€β”€ groups.json Official draw { "A": [4 team ids], ... } Γ— 12 (A–L) +β”‚ β”œβ”€β”€ matches.json 104 real fixtures; UTC times; ids 1–72 chronological +β”‚ β”‚ group games, 73–104 = FIFA match numbers (bracketRef) +β”‚ β”œβ”€β”€ results.json { matchId, homeScore, awayScore, penalties?, status } β€” +β”‚ β”‚ update as the tournament progresses +β”‚ β”œβ”€β”€ stadiums.json 16 real venues: { id, name, city, capacity, image, timezone } +β”‚ └── bracket-config.json β˜… official R32 structure + thirdPlaceAssignment (all null) β€” β”‚ the ONLY file to edit once real 3rd places are known +β”‚ (slot β†’ allowed-groups table in project-memory.md) β”‚ β”œβ”€β”€ README.md Setup, GitHub Pages deploy, JSON maintenance guide -β”œβ”€β”€ how-update.md Real-data migration runbook (mock β†’ real WC2026 data/*.json) +β”œβ”€β”€ how-update.md Real-data migration runbook (mock β†’ real β€” DONE 2026-06-12) +β”œβ”€β”€ how-refresh-data.md β˜… Daily refresh runbook during the tournament: +β”‚ results.json scores/status + one-time +β”‚ thirdPlaceAssignment; everything else frozen β”œβ”€β”€ world-cup-2026-hub-spec-en.md Main spec └── complement-spec-worldcup2026-en.md Complement spec (precedence on conflict) ``` @@ -123,7 +129,8 @@ matches.json time (UTC) ── formatMatchTime(match, stadium, mode) | Where is simulation state stored/cleared? | `localStorage` key `wc2026_simulation`, via `assets/js/storage.js` | | Where do I change colors/theme? | CSS variables at the top of `assets/css/style.css` | | Where do I add a stadium? | `data/stadiums.json` + image in `assets/images/` | -| How do I replace mock data with real WC2026 data? | `how-update.md` (root) β€” schemas, order of operations, integrity checklist | +| How do I replace mock data with real WC2026 data? | `how-update.md` (root) β€” done 2026-06-12; kept as schema reference | +| How do I update scores during the tournament? | `how-refresh-data.md` (root) β€” daily results.json routine + thirdPlaceAssignment how-to | --- diff --git a/.agents/project-memory.md b/.agents/project-memory.md index 928c48e..8ed2136 100644 --- a/.agents/project-memory.md +++ b/.agents/project-memory.md @@ -170,18 +170,41 @@ Static web app showing the FIFA World Cup 2026 (Mexico/USA/Canada, 48 teams) β€” **Symptom if forgotten:** works locally, 404s on GitHub Pages **Solution:** use relative paths (`data/matches.json`, `assets/...`) everywhere +### 8. Claude Preview: resize beyond the native window breaks clicks/screenshots +**Where:** Claude Preview panel, `preview_resize` wider than the native window (~791 CSS px) +**Why:** viewport emulation desyncs the capture/click surface from the page (screenshots show the page squeezed in the left half; `preview_click` lands on wrong coordinates and silently does nothing) +**Symptom if forgotten:** "clicks don't work" / half-black screenshots at desktop widths, wasted debugging β€” the app itself is fine (`preview_eval` geometry confirms) +**Solution:** at emulated widths > native, navigate via `preview_eval` + exported `navigateTo()` and verify geometry via eval/inspect; trust screenshots only at widths ≀ native. `preview_resize preset: desktop` resets to native and fixes clicks. + --- ## Patterns for future changes ### How to update real-world data (scores, schedule) -1. Edit `data/results.json` (scores/status) or `data/matches.json` (schedule). +Follow `how-refresh-data.md` (project root). In short: +1. Edit `data/results.json` (scores/status) or `data/matches.json` (schedule, rare). 2. Once group stage ends: fill `data/bracket-config.json` β†’ `thirdPlaceAssignment` (slot β†’ group letter). Nothing else changes. ### Real-data migration (2026-06-12) - `how-update.md` (project root) is the full runbook for replacing mock `data/*.json` with real World Cup 2026 data: file-by-file schemas, order of operations (stadiums β†’ teams β†’ groups β†’ bracket-config.round32 β†’ matches β†’ results β†’ thirdPlaceAssignment), and a cross-file integrity checklist (group membership, id ranges, bracketRef uniqueness, stadium name/city matches). - Flags one open decision: `stadiums.json` has 30 entries (original bid shortlist) vs. the 16 venues actually used by the real tournament β€” confirm with user whether to trim before/while editing `matches.json`. +### Real-data migration DONE (2026-06-12) +- **All 6 `data/*.json` files now hold real WC2026 data.** Sources: Wikipedia per-group + knockout-stage articles (primary; local kickoff times with explicit UTC offsets), cross-checked vs ESPN/NBC/FOX/olympics.com/lumenfield.com. Full smoke test + desktop/mobile layout pass, console clean. +- **Stadiums trimmed 30 β†’ 16** (user decision). Cities use FIFA host-city names ("New York/New Jersey", "San Francisco Bay Area", "Boston"), not suburb names (East Rutherford, Santa Clara, Foxborough) β€” `matches.json` and `stadiums.json` must keep matching exactly. +- **Match ids:** group matches 1–72 are *chronological by UTC kickoff* (β‰  6-per-group blocks); knockout ids 73–104 are FIFA's official match numbers. +- **bracket-config app-order ↔ FIFA mapping:** R32-1..16 = FIFA matches 74, 77, 73, 75, 83, 84, 81, 82, 76, 78, 79, 80, 86, 88, 85, 87 (ordering chosen so the app's sequential pairing reproduces the official R16/QF/SF progression). +- **Third-place slots β†’ allowed groups** (for filling `thirdPlaceAssignment` after the group stage, per official draw): slot 1 (M74) A/B/C/D/F Β· slot 2 (M77) C/D/F/G/H Β· slot 3 (M81) B/E/F/I/J Β· slot 4 (M82) A/E/H/I/J Β· slot 5 (M79) C/E/F/H/I Β· slot 6 (M80) E/H/I/J/K Β· slot 7 (M85) E/F/G/I/J Β· slot 8 (M87) D/E/I/J/L. Each group letter may appear in only one slot. +- **Results as of 2026-06-12:** ids 1–3 finished (MEX 2–0 RSA, KOR 2–1 CZE, CAN 1–1 BIH); USA–PAR (id 4) kicked off 01:00 UTC Jun 13 β€” first thing to update next session. +- **Single-source caveat:** R16 match 94 (Jul 6, Lumen Field) time 17:00 PDT per Wikipedia; one ESPN summary implied 14:00 PDT. Re-verify when R16 nears. +- **New-team flags** created in the house placeholder style: RSA, CZE, BIH, HAI, CUW, SWE, CPV, NOR, IRQ, COD; 24 unreferenced mock SVGs deleted (10 flags + 14 stadiums). Exactly 48 flags + 16 stadium images remain. +- **Tiebreak note:** with all tiebreakers equal the app falls back to team-id alphabetical (e.g. BIH above CAN on 1 pt) β€” may differ from FIFA's published order (fair-play points / drawing of lots), acceptable by design. +- Mock-data sections above (β€œMock data design”, hero live-match note for match 61) are now historical. + +### Daily refresh runbook (2026-06-12) +- **`how-refresh-data.md` (project root) is the runbook for all updates during the tournament** β€” read it before touching any `data/*.json` from now on. It defines: daily `results.json` routine (scores/status, two-source rule, penalties only on ids 73–104), the one-time `thirdPlaceAssignment` fill (~Jun 27–28, slot β†’ allowed-groups table), and the frozen files (stadiums/teams/groups/round32/assets/code β€” never edit). +- `how-update.md` stays as the schema reference for the (completed) mock β†’ real migration; `how-refresh-data.md` supersedes it for day-to-day work. + ### How to add a UI label 1. Add the key to both `en` and `pt` dicts in `assets/js/i18n.js`. 2. Use `t("key")` at the render site β€” never hardcode the string.