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).
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.
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
- 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
- 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>
- 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>
- 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>
- 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>
- 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>
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>
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.
- 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
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>