Commit graph

46 commits

Author SHA1 Message Date
c246117545 feat(bracket): redesign with wallchart, radial orbit, and rounds pager
Center-out wallchart layout (computeWallchartLayout), radial orbit view with
circular flag tokens, and mobile rounds pager with button navigation (Steps 1–3).
Stadium-night art direction, SVG connectors, fit-to-chart zoom, escalating card
heat toward the Final, dual gold-real/blue-sim champion celebration paths.
Adds bracket view toggle with persistent wc2026_prefs.bracketView storage.
2026-07-03 22:09:49 -03:00
adb8cce441 feat(groups): add best third-placed teams ranking table
Ranks the 12 third-placed teams across groups (Pts -> GD -> GF -> id) and marks the top 8 that advance to the R32. Full-width section below the group cards in the Grupos tab, gated on all 12 groups finished (omitted from the DOM otherwise). Reuses .standings-table styling, header tooltips and the favorite-row highlight: gold rows + check for the 8 qualified, muted rows for 9-12, a dashed cut line between. computeThirdPlaceRanking() only ranks for display; the slot->group allocation stays in bracket-config.json. Bumps APP_VERSION to v1.0.3 (also covers the hero knockout-resolution fix).
2026-06-28 13:16:14 -03:00
7b404e678f fix(hero): resolve knockout matchup teams (R32+ showed "A definir")
The home hero read match.homeTeam/awayTeam directly; knockout matches (ids 73-104) carry only bracketRef and resolve teams at runtime, so once the next match became an R32 game the hero showed "A definir vs A definir". Resolve via resolveBracketTeams(match) like schedule cards and the modal; heroTeamHTML now takes a {team,label} slot.
2026-06-28 12:51:57 -03:00
71f7490e0f feat(stats): rotate tied teams in leader cards + new metric cards
Leader cards (Best attack/defense, Most clean sheets) now rotate through every
team tied on the headline metric instead of showing only the top one, and three
new cards are added: Most wins, Most goals conceded, Best goal difference.

- group by the metric value alone; order within the group by existing tiebreakers
- auto-advance (3.5s), pause on hover/focus, off under prefers-reduced-motion
- discrete edge arrows with a full-height side click strip; wrap-around
- dots indicator up to 8 tied teams, else an i/n counter; single team = plain card
- bump APP_VERSION to v1.0.2
2026-06-19 10:03:51 -03:00
fd7d644a66 fix(data): replace DATA_VERSION cache-buster with minute-rounded timestamp 2026-06-18 18:25:49 -03:00
412cca8a59 data: update 18/06/2026 19:00 SUIxBIH 4x1 2026-06-18 18:06:04 -03:00
7747a1c562 data: update 18/06/2026 16:00 CZExRSA 1x1 2026-06-18 15:08:06 -03:00
ca06816bc9 fix: decressed pool interval 90 to 60 seconds 2026-06-18 14:25:59 -03:00
51778431cf data: update 18/06/2026 11:56 UZBxCOL 1x3 2026-06-18 11:56:46 -03:00
6a4fae8283 data: update 17/06/2026 22:05 GANxPAN 1x0 2026-06-17 22:05:39 -03:00
18004fb970 data: update 17/06/2026 19:07 ENGxCRO 4x2 2026-06-17 19:08:06 -03:00
592f14504e data: update 17/06/2026 17:02 AUSxJOR 3x1 & PORxCON 1x1 2026-06-17 17:06:11 -03:00
6f67acb43f refactor(footer): version-managed app display
- Add APP_VERSION constant for easy version bumping
- Update EN/PT footer to show version instead of JSON reference
- Simplifies footer maintenance: bump one line in i18n.js
2026-06-17 11:41:15 -03:00
9c62cbd7c1 fix(stats): sub-nav edge fades + scrollspy jump on chip click
- Edge fades like the header tabs: chips moved into an inner scroll track so
  the fade mask only affects the chips, leaving the pill background/rounded
  ends crisp. updateSubnavFades toggles fade-left/right from the track's
  overflow (on track scroll, resize, setActiveChip, init).
- Scrollspy no longer jumps when a chip is clicked: the page-scroll spy is
  suppressed for the duration of the programmatic smooth-scroll (700ms; 0 under
  reduced-motion), so the clicked chip stays active instead of flipping back to
  the old section mid-animation and forward again.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 11:26:05 -03:00
b12110b2a5 feat(stats): team comparator with diverging bars (Stage F)
- New Comparator sub-nav section (available once >=1 match played). Two team
  selects (all 48, alphabetical), defaulting to the top-2 ranked teams; the
  choice survives langchange (module-level cmpA/cmpB).
- Diverging mirrored bars: A grows left from the centre metric label, B right;
  each row scales to max(a,b) so the longer bar is the higher value, and the
  higher side's number is gold. Metrics P/W/GF/GA/CS/Pts (all non-negative).
  cmp-grow scaleX animation from the centre edge; off under reduced-motion.
- On select change only the bars panel re-renders (keeps focus, replays the
  animation).
- Players side intentionally NOT shipped: a disabled toggle would be a dead
  control (violates the graceful-degradation rule). The Teams/Players toggle
  arrives in Stage H with players.json.
- i18n comparatorTitle/cmpTeamA/cmpTeamB (EN/PT); CSS for the comparator.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 10:58:24 -03:00
e69ea7bd4d feat(stats): Records section + format-48 debuts band (Stage D)
- New Records sub-nav section (always available): match-record cards plus the
  format-48 debuts band. Sub-nav now Overview / Teams / Records.
- Moved the biggest-win card out of Teams into Records (it is a match record);
  Teams keeps team-level cards (win streak, champion path). Records shows
  biggest win + highest-scoring match (both -> openMatchModal), with the
  high-score card deduped when it is the same match as the biggest win.
- computeRecords gains highestScoringMatch. New recordsSectionHTML /
  highScoreCardHTML / formatDebutsHTML.
- Format debuts band: 48 teams, 104 matches, 12 groups, Round of 32, 8 best
  thirds, and (post-final) first champion of the 48-team era. Counts derived
  from data, champion from the verdict.
- i18n recordsTitle/highScoreMatch/formatDebutsTitle/debut* (EN/PT); CSS for
  .stats-subhead and the .debut-band.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 00:33:59 -03:00
8a521575aa feat(stats): final ranking 1-48, favorite highlight, team records (Stage C)
- Canonical final ranking: each team carries a .rank from the stage-reached
  chain (champion>runner-up>3rd>4th>QF>R16>R32>group, then pts>GD>GF>id),
  computed from REAL knockout results only (simulation never moves it). The #
  column shows this rank and is the default sort; it stays canonical when
  sorting other columns, and clicking # returns to it.
- Favorite-team row highlight (gold inset border + tint); re-renders on
  favchange. No stars in the table (highlight-only, like the bracket).
- Team record cards: biggest win (-> openMatchModal), longest win streak
  (>=2, else hidden), and champion's path (R32->Final route, gated on the
  verdict, rows -> openMatchModal). Each degrades away when its data is null.
- stats.js imports getFavorites (storage) + openMatchModal (modal). i18n
  tip.rank/stats.rankCol/biggestWin/winStreak/championPath (EN/PT); CSS for
  .row-fav, record cards, champion path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 00:22:24 -03:00
beac60518f Merge branch 'master' into feature/stats-final-screen 2026-06-17 00:08:54 -03:00
1312d2327a data: update 16/06/2026 00:05 ARGxALG 3x0 2026-06-17 00:06:02 -03:00
61e0bb0d0a feat(stats): verdict hero + goals-by-round chart (Stage B)
- Verdict hero: champion (trophy + flag + name) and a 2/3/4 podium
  (runner-up/3rd/4th) above the shared count-up tiles. Gated on the REAL
  final via computeVerdict() — getBracketTree()'s FINAL node must be a real
  finished result (!simulated), so a user's simulated champion never leaks
  into the verdict. Third/fourth from the third-place match, independently.
  Falls back to the existing aggregate 'in progress' hero until the final is
  in, so an early merge stays correct.
- Goals-by-round chart beside goals-by-stage: group stage split into its 3
  matchdays (derived per group; no matchday field exists) plus each knockout
  round. Hidden until >=2 rounds have data so it never duplicates the
  goals-by-stage Group bar early on.
- stats.js imports getBracketTree from bracket.js (4th circular import with
  app.js, render-time only). i18n stats.goalsByRound/matchday/verditTitle/
  runnerUp/thirdPlace/fourthPlace (EN/PT); verdict-hero CSS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 19:46:57 -03:00
387fab3c8b feat(stats): degradation engine + scrollspy sub-nav (Stage A)
Scaffold the post-Cup stats screen (.agents/stats-screen-plan.md) on the
feature/stats-final-screen branch.

- loadData(): fault-tolerant optional data layers (players, player-events,
  awards, keeper-stats, curiosities, all-time-baselines) via loadOptional() —
  an absent/404 file defaults to empty SILENTLY (graceful degradation, keeps
  the console clean), warning only on a present-but-malformed file. The 6 core
  files still throw on failure.
- stats.js SECTIONS registry: a section and its sub-nav chip render only when
  available(model) holds, else they are omitted from the DOM entirely (no
  placeholder / no coming-soon). Overview/Teams live; the 4 future sections
  stay dark until later stages.
- Sticky scrollspy sub-nav: hash-safe anchor chips (preventDefault +
  scrollIntoView, never touch location.hash so the tab router does not bounce
  to Home); position-based scrollspy with an explicit page-bottom -> last
  section rule (robust on short pages). --header-h kept live via a
  ResizeObserver so the nav sticks correctly under the variable-height header.
- flagImg() monogram fallback: a broken flag SVG becomes a 3-letter code span,
  never a broken-image icon.
- i18n stats.nav* keys (EN/PT); stats.css for sub-nav / section / fallback.

No DATA_VERSION bump (no deployed data changed). No index.html change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 19:36:32 -03:00
8afbcac9c5 data: update 16/06/2026 19:00 FRAxSEN 3x1 2026-06-16 19:00:12 -03:00
1f23daf120 perf(app): optimize countdown rendering and hero clock polling 2026-06-16 15:54:33 -03:00
715ecedbcb feat(pwa): add Tier 1 support — installable app with manifest and icons 2026-06-16 15:09:34 -03:00
ae95812269 data: update 16/06/2026 01:00 IRNxNZL 2x2 2026-06-16 00:24:04 -03:00
5b1707a764 feat(app): poll results.json for live updates without reload 2026-06-16 00:12:50 -03:00
c937671fdd data: update 15/06/2026 22:00 KSAxURU 1x1 2026-06-15 22:41:26 -03:00
425c27fa37 data: update 15/06/2026 18:00 BELxEGY 1x1 2026-06-15 18:04:56 -03:00
8886dcf098 data: update match 13 result and stats (ESP 0-0 CPV) 2026-06-15 15:34:48 -03:00
ad6d7ea616 fix(header): two-row layout with scrollable tabs below 1100px 2026-06-15 15:27:10 -03:00
6e33142c96 feat(hero): display simultaneous group-final matches with shared timer
findFeaturedMatch → findFeaturedMatches: returns all matches sharing the
earliest kickoff, enabling the hero to show 2+ simultaneous group-final games
(same phase, shared time/countdown). renderHero splits single-match (unchanged
DOM) vs multi-match (stacked with dividers). heroMatchupHTML extracted for
reusable matchup layout.

CSS: .hero-matchups/match/divider/time for vertical stacking and shared time.
i18n: hero.nextMatches (EN/PT) for multi-match label.
2026-06-15 14:52:10 -03:00
99ea02a604 feat(schedule): add occurrence filter with pending result status 2026-06-15 14:33:33 -03:00
18d6066849 data: update match 12 result and stats (SWE 5-1 TUN)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 02:13:33 -03:00
fd71bd2c48 feat(hero): advance countdown by clock without JSON updates
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 02:07:29 -03:00
3e9a60bb9e data: update matches 10-11 results and stats (NED 2-2 JPN, CIV 1-0 ECU) 2026-06-14 22:08:46 -03:00
d5a9dadc5d feat(stats): add tournament-to-date stats tab 2026-06-14 21:38:01 -03:00
ba81e49eac data: update match 9 results and stats (GER 7-1 CUW) 2026-06-14 16:03:35 -03:00
74fa8603f4 data: update match 8 results and stats (AUS 2-0 TUR)
- Match 8 finished: Australia 2-0 Turkey
- Added statistics: possession 28/72, shots 9/30, cards 0/1
- Verified in preview with correct modal display
- Updated project memory with refresh entry and sources
- Bumped DATA_VERSION to 2026-06-14-rev1 for cache busting
2026-06-14 03:01:04 -03:00
e94aa09ce5 refactor(stadiums): clean up SVG illustrations and fix image aspect ratio
- Remove card chrome (background rect, text duplicates, accent bars) from all 17 stadium SVGs
- Crop viewBox tightly to illustration (~10px padding) and remove fixed width/height attributes
- Update .stadium-img aspect ratio from 16/9 to 4/3 to match cropped SVG ratios and prevent aggressive object-fit clipping
2026-06-14 01:06:14 -03:00
da8a8838c6 feat(cache): add cache-busting version for data files 2026-06-14 00:06:37 -03:00
08c224ec3e feat(modal): display match stats when available 2026-06-13 23:23:18 -03:00
0ebb66120c assets(flags): replace placeholder flags with realistic designs
Replaces 48 placeholder flag SVGs (simple boxes with country codes) with realistic, detailed flag designs.
2026-06-13 11:57:45 -03:00
5c5169d838 chore(assets): sync SVG assets with real 2026 world cup qualifiers
Replace flag SVGs for 10 fictional teams with 10 new qualifiers (BIH, CZE, RSA,
CUW, CPV, HAI, IRQ, NOR, SWE, COD). Remove 14 unused stadium SVGs for venues not
in the 16-stadium tournament roster.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-12 22:38:28 -03:00
c664c5e02e style: adjust grid layout and fix team name text wrapping 2026-06-12 21:13:10 -03:00
39f5881d33 feat: add world cup 2026 hub spa with bracket simulation and i18n 2026-06-12 16:12:14 -03:00
c7088bc31b feat(data): add mock tournament dataset and placeholder artwork 2026-06-12 16:12:02 -03:00