Commit graph

15 commits

Author SHA1 Message Date
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
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
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
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
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
d5a9dadc5d feat(stats): add tournament-to-date stats tab 2026-06-14 21:38:01 -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
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