# Changelog

All notable user-visible changes to Ultimate Hattrick. Format follows
[Keep a Changelog](https://keepachangelog.com/) and the project uses
semantic versioning.

## [0.19.0] - 2026-07-16

### Added
- **Competition labels in Match orders.** Each selected game now identifies
  its competition - including your league name, Cup or Tournament - in the
  game picker and the Team orders screen, with kick-off and home/away context.
- **More than one upcoming match in Match analysis.** League, cup and other
  active fixtures now appear as separate cards, each opening the analysis for
  that exact game.

### Changed
- **Match analysis uses saved orders.** Unconditional substitutions, swaps and
  individual behaviour changes now influence the forecast according to when
  they are scheduled. Conditional orders remain visible as scenario-dependent
  plans instead of being incorrectly assumed to trigger.

### Fixed
- **Match times now follow your local timezone reliably.** CHPP's CE(S)T
  timestamps are converted correctly, including the London daylight-saving
  offset.
- **Live match state stays in sync.** Ongoing matches remain visible in the
  live banner, Match orders, Match analysis and Live area until full time;
  finished matches no longer look upcoming or ongoing after a sync.
- **Match Analysis respects Light mode.** The page now uses the manager's
  selected theme rather than forcing the dark editorial shell.
- **Orders stay attached to the selected fixture.** When games share a
  kick-off time, Lineup and Team orders continue to show the game you chose.

## [0.18.0] - 2026-07-15

### Added
- **Live ticker player links and sound.** Your players' names in event copy,
  starting lineups and substitutions open their profile drawer, with a
  user-controlled sound cue for new live updates.
- **Team-by-team live signals.** Live goals, chances, cards, injuries and
  substitutions are shown separately for the home and away teams.
- **Richer event ticker labels.** Match-end results, possession, dominance,
  player awards, attendance, added time, cards and tactical changes now use
  meaningful labels and icons, including when Hattrick sends no event copy.

## [0.17.0] - 2026-07-14

### Added
- **Live match centre.** Follow senior, youth and tournament games from
  kick-off through full time with live scores, event updates, starting
  lineups and substitutions.
- **Live match banner.** When one of your games is in progress, a compact
  alert appears at the top of every page with the score and a direct link to
  the match centre. It works on phones as well as larger screens.
- **More match-centre stats.** When available, live match pages now include
  possession, chance distribution, sector ratings, formations, tactics,
  venue and attendance alongside the ticker.
- **Live goal alerts.** Receive a push notification when one of your live
  games scores, with a direct link back to the match centre. Goal alerts can
  be managed in Settings → Notifications.
- **Live navigation.** A new Live area shows active matches and the next
  synced fixture, including a kick-off countdown.

### Changed
- **Live fixtures now respect local time.** Upcoming matches are shown until
  kick-off, while finished and stale fixtures drop out of the live list.
- **Match times now follow your chosen timezone.** Kick-offs and live-match
  timestamps are converted correctly from Hattrick time, so a Europe/London
  setting shows the actual local time rather than a Central European offset.
- **Match analysis now includes the ticker recap.** Played matches show
  readable event text, goals, starting elevens and substitutions.
- **Youth live matches now have their own centre.** The youth sidebar, mobile
  navigation and goal alerts stay in the youth context throughout.

## [0.16.0] - 2026-07-14

### Added
- **Display currency.** Settings → Currency lets a manager read the whole app
  in a currency other than the one Hattrick assigned them. Cash, the weekly
  P&L, asking prices, wages, the wage chart, the AI search budget and the
  weekly-finances push all follow the choice. Conversion uses Hattrick's own
  fixed rates, so a figure shown here is exactly what the manager you're
  negotiating with sees in game - which is the point: it makes amounts
  quotable between managers in different countries. Defaults to "Use my
  Hattrick currency", so nothing changes unless you pick something.

### Fixed
- **Transfer-market heuristics no longer assume the manager is English.** The
  wage bands behind the smart-fit score, the suggested budget for each squad
  gap, and the max-price filter ladder were all authored as pound amounts but
  compared against figures in the manager's own currency. For anyone outside
  England they were off by their currency's rate - a Swedish manager's wages
  are ~15× the same player's figure in pounds, so essentially every listing
  read as "wage over budget". These are now held in SEK and converted for
  display. Fit rankings will shift for non-GBP managers; they were wrong
  before.
- The youth promotion fee was hardcoded as `£2,000` regardless of currency.

## [0.15.5] - 2026-07-14

### Fixed
- **Matches handles the CHPP rollover window.** When `leaguedetails` has
  reset every club to zero played while `worlddetails` and `leaguefixtures`
  still report the completed prior season, the page now treats the current
  season as unstarted and suppresses stale scores and chart history.
- **League season identity now comes from `leaguelevels`.** During a reset,
  the sync uses the league-wide current-season value and requests
  `leaguefixtures` explicitly for that season instead of trusting a stale
  default response.

## [0.15.4] - 2026-07-14

### Fixed
- **Season rollover now works even when league context lags.** If the current
  `leaguefixtures` response has moved to the new season before `worlddetails`,
  the fixture sync advances the team season, resets the matchday to 1 and
  clears recent results so the Matches page cannot continue showing the prior
  season's timeline.

## [0.15.3] - 2026-07-14

### Fixed
- **Matches now resets cleanly at a new season.** Matchday 1 starts at zero
  completed matchdays, position history and cumulative league charts no longer
  replay the previous season, and stale fixture scores are ignored until the
  current-season fixture sync completes.
- **Current-season history is cleared when CHPP reports a season rollover.**
  Standings, recent results and fixtures are treated as season-scoped data;
  archived seasons remain available through the season picker.

## [0.15.2] - 2026-07-14

### Added
- **More useful lineup bench previews.** Desktop bench rows now show each
  player's full TSI alongside their position, form, stamina and fit score, with
  a dedicated profile button that opens the existing player-detail drawer
  without triggering a lineup swap.

## [0.15.1] - 2026-07-14

### Changed
- **Lineup chat can now make reviewed changes.** Follow-up instructions in the
  AI lineup conversation can propose player, shape, tactic and role changes;
  the manager sees a summary and explicitly applies the update. The conversation
  streams on desktop and mobile and is grounded in the latest manually edited XI.
- **Friendly development is enforced and visible.** Recognized friendlies now
  show the active training focus on the lineup screen, and AI results that drop
  a protected trainee or move them out of a useful training position fall back
  to the development-first deterministic pick.

### Fixed
- **Manual tweaks after an AI pick now persist correctly.** Moving a substitute
  onto the pitch also moves the displaced starter into that bench position,
  removes duplicate bench entries, saves immediately, and invalidates any stale
  chat proposal that was based on the previous XI.

## [0.15.0] - 2026-07-14

### Added
- **A fast, streaming squad adviser.** The Squad page now has an Ask AI panel
  for player-specific questions such as who should play in friendlies or which
  skills are worth developing. Answers stream in as they are written, history
  stays in the browser session for each team, and the adviser is strictly
  read-only: it cannot change a lineup or recreate Hattrick's training planner.
- **Manual senior training context for AI advice.** Settings now lets managers
  choose a current training focus and add a short note. This is explicitly
  manager-supplied context because CHPP does not expose the active senior
  training state to the app.
- **Youth academies can be switched directly.** Managers with multiple youth
  teams can now jump between academies from the same team switcher, including
  the desktop sidebar and mobile nav.
- **Transfer player IDs now open Hattrick.** Transfer search results link the
  player ID straight to hattrick.org, making quick inspection less fiddly.

### Changed
- **AI now treats friendlies as development matches.** With the new setting on
  by default, AI lineup picks for recognized friendlies favour useful training
  positions, healthy younger rotation players and players who missed the latest
  synced match. AI team orders preserve priority trainees' minutes rather than
  substituting them early, while competitive matches keep their existing
  win-first selection behavior.
- **Feature requests now require a reply email when the account has none.** If
  a manager still only has a synthetic `@hattrick.local` address, the feedback
  widget asks for a real reply address before accepting a feature request, so
  shipped requests can be followed up.
- **First-run setup now requires a real email and explicit marketing choice.**
  New Hattrick sign-ins must provide a contact email before entering the app,
  and product-news email is collected as a visible opt-in during onboarding.

## [0.14.1] - 2026-07-06

### Fixed
- **Additional teams now sync as themselves.** Refreshing a secondary club now
  keeps every step pinned to that club, including team details and economy, so
  managers with multiple teams no longer get stuck on "Synced never" while the
  sidebar keeps showing "(syncing)".
- **Push notifications are clearer for multi-team managers.** Team-derived
  pushes now include the club name, use team-specific notification tags so
  events from different clubs do not replace each other, and deep-link with the
  triggering team selected after validating it belongs to the manager.

## [0.14.0] - 2026-07-05

### Added
- **More things to be notified about.** Push notifications used to cover only
  match events (kick-off, full time, orders due). They now also cover the parts
  of the week that happen away from the pitch, each an independent toggle in
  Settings → Notifications:
  - **Injuries & fitness** - a ping when one of your players picks up an injury,
    and again when they're back to full fitness.
  - **Youth ready to promote** - when an academy player crosses the promotion
    gate (Hattrick says they're ready, or they pass 17), so a prospect never
    ages out unnoticed. Opens the Youth Tactician.
  - **Weekly finances** - your economy update once Hattrick settles the books:
    the week's profit or loss and what's in the bank.
  - **League position** - when your place in the table moves up or down after a
    round of fixtures.
  - **News & new features** - the occasional note from the team behind the app
    (new features, new plans), broadcast to everyone who leaves it switched on.

  All are on by default and opt-out per type; like the match notifications they
  are discovered as a side effect of the normal sync, so nothing new polls
  Hattrick, and the very first sync seeds a silent baseline so enabling a type
  never replays history.
- **Impersonate ("view as user") for support debugging.** From the `/uh-admin`
  Users table, an operator can now step into a manager's session with a single
  "View as" click and see the app exactly as they do - dashboard, squad, lineup,
  the lot - which makes "can't reproduce it" reports reproducible. It's strictly
  safe: while impersonating, all *write-back* to the manager's real account is
  blocked - lineup submission to Hattrick, preference changes and account
  deletion are refused - so looking can't change anyone's team or settings. You
  *can* run a live **Refresh** to pull their current Hattrick data into the
  snapshot (the pill reads "Refresh (live)") to reproduce sync issues; that's an
  inbound read only. A loud banner sits at the top of every screen with a
  one-click exit, and the mode evaporates the moment the admin session ends.

## [0.13.4] - 2026-07-03

### Changed
- **Youth potential scoring has another Scoutrick calibration pass.** The
  scorer now applies a final correction from the visible Scoutrick comparison
  patterns: overall-skill reports, sparse low-cap profiles, late 17-year-olds
  and isolated keeper prospects are weighted separately.
- **The Youth Squad explains the score.** A collapsible note below the table now
  explains which signals feed the estimate, why keeper scores get a `*`, and why
  hidden current skill is not treated as future potential.

## [0.13.3] - 2026-07-03

### Fixed
- **Youth potential scores now handle late sparse profiles better.** Older
  youth players with no overall scout score and only a few revealed caps are
  now discounted more heavily, bringing Gregg Bennett-style profiles much
  closer to their Scoutrick score without flattening fully revealed prospects.

## [0.13.2] - 2026-07-03

### Fixed
- **Youth potential scores are closer to Scoutrick for sparse profiles.**
  Current-only skills no longer drive the absolute potential score when their
  caps are still hidden, isolated low caps are kept in the poor band, and
  goalkeeper prospects now need set pieces / defending support before they
  score like complete keeper prospects.

## [0.13.1] - 2026-07-03

### Added
- **Youth squad potential scores.** The Youth Squad now includes a
  Scoutrick-style score column, with familiar score bands and a `*` marker when
  the goalkeeper formula is used. Open a player drawer to see the same score
  alongside their cap and source context.

### Changed
- **Youth Squad and Match Orders now better match the senior screens.** The
  academy versions use the same calmer table, drawer and order-review language
  as the senior team pages, while keeping the youth-specific controls for caps,
  promotion timing and academy orders.

### Fixed
- **Youth scores no longer overrate sparse profiles.** Current skills whose
  caps are still hidden now count only as weak evidence of absolute potential,
  and the scorer uses scout overall-skill reports as a separate signal. That
  keeps one-cap profiles from jumping above better-confirmed prospects.

## [0.13.0] - 2026-06-29

### Added
- **Squad Report - a whole-team read across every game you've played.** A new
  page under Match Analysis (open it from the "Squad Report" link on the index)
  that stops looking at one fixture at a time and characterises your team as a
  whole: your strongest and weakest sectors, how those sectors actually fare
  against real opponents, which flank leaks the most chances, and where your
  squad depth runs thin (lines carried by a single capable player, ageing cores,
  stacked injuries). It also names **players to move on** - buried, past-peak
  squad members who'll likely never feature, so you can stop paying a wage and
  free a slot. With AI enabled it adds a written scout briefing on top; without
  it, you still get the full numbers-and-callouts read.
- **Manage more than one team.** Managers with multiple senior clubs can now
  switch between them from the sidebar (and the mobile drawer). Pick a club and
  the whole app - dashboard, lineup, matches, everything - follows. If you only
  have one team, nothing changes.
- **Rate-the-site popup.** After a few days of use, a small dismissible card
  invites managers to rate Ultimate Hattrick 1-5 stars (with an optional
  comment). Ratings are stored as tickets and show up in the `/uh-admin` Tickets
  inbox under a new "Ratings" filter; the prompt never nags - once a user rates
  or dismisses it, it's gone for good (with a softer "maybe later" snooze too).
- **A "What's new" popup.** When a new version ships, a small dismissible card
  highlights the user-relevant changes from the changelog, so you don't have to
  go hunting to see what's changed. It shows once per release, then gets out of
  the way (the full changelog is still a click away).
- **The "Next match" card now shows the competition.** As well as the opponent,
  venue and kick-off, the dashboard now names the competition - and for league
  games the round, e.g. *"Round 14 · Tavern Masters League"* - so you can tell a
  league night from a cup tie or friendly at a glance.
- **A "notifications are working" confirmation.** The first time you enable push
  notifications, you now get an immediate welcome push confirming they're set up,
  instead of waiting for a match to finish to find out.
- **"Last active" column in the admin users table.** Each account's most recent
  activity is now tracked (throttled to one write every few minutes) and shown
  in `/uh-admin`, so it's easy to see who's actually using the app.
- **Feedback is now stored as triageable tickets, not just an email.** Every
  submission from the in-app feedback widget is saved as a ticket (with a new
  Bug / Feature / Other type selector) and listed under a new **Tickets** tab in
  `/uh-admin`, with the same status filters and resolve / ignore / delete triage
  as the bug tracker. The owner still gets an email notification, the submitter
  now gets a short confirmation, and - because the ticket is saved first - a mail
  outage no longer loses the feedback.
- **All ten Hattrick formations are now selectable.** The lineup and team-orders
  screens previously offered only five shapes (3-5-2, 4-4-2, 4-3-3, 5-3-2,
  3-4-3); the remaining five - 2-5-3, 4-5-1, 5-2-3, 5-4-1 and 5-5-0 - are now
  available too, so you can set up a back five or a lone striker without
  fighting the pitch. The formation buttons are now derived from the canonical
  shape list rather than a hand-maintained array, so the senior, mobile and
  team-orders screens stay in lockstep.
- **Bug tracker in uh-admin.** Unhandled Laravel exceptions and CHPP API errors
  (bad responses, transport failures, error codes) are now captured into an
  `error_logs` table and surfaced under `/uh-admin/errors`. Each bug records the
  request that caused it - method, URL, headers and payload for app errors, or
  the CHPP file, params and response for API failures - with secrets (auth
  tokens, cookies, passwords) redacted before storage. Repeated errors are
  grouped by fingerprint with an occurrence count and first/last-seen times, and
  can be resolved, ignored or deleted. Captured bugs auto-prune after 90 days.

### Changed
- **The homepage now leads straight to Hattrick sign-in.** With CHPP access in
  place, the old beta-request email form is gone - the nav, hero and footer
  calls-to-action all link to Hattrick OAuth sign-in. (The app itself is still
  flagged beta.)
- **Tidier mobile order flow.** The lineup / team-orders flow on phones has had
  its layouts tightened so the pitch and controls sit better on small screens.

### Fixed
- **The dashboard no longer says "sync opponent" after you've already synced.**
  When a next opponent is a brand-new or friendlies-only side, Hattrick hasn't
  published the sector ratings the prediction needs - so the Win probability /
  Expected goals stay blank. The card now explains that honestly ("opponent
  unrated - new or friendlies-only side") instead of wrongly implying you still
  need to sync.
- **A lineup synced in an unsupported formation no longer collapses to a 3-5-2.**
  Playing e.g. a 5-2-3 in Hattrick used to sync in, read its label correctly,
  but render a 3-5-2 pitch - the central defenders and forwards had nowhere to
  go, so they looked missing and couldn't be edited. With every Hattrick shape
  now defined, the synced formation maps to its real slots. A regression test
  asserts each shape's slot list actually spells out its defenders-midfielders-
  forwards label.
- **A first team sync no longer trips the app's own request limiter.** The
  per-user CHPP budget defaulted to 30 requests / 5 min, but a full sync fires
  35-50 calls in a burst, so it ran out partway and surfaced a "couldn't fetch"
  error. The budget is now a generous runaway-only backstop (600 / 5 min by
  default, still overridable via `HATTRICK_RATE_LIMIT_MAX`).
- **Submitting orders no longer logs a false "submission not confirmed" bug
  when Hattrick is rate-limiting.** A synchronous order submit that hit the CHPP
  per-user request budget was silently dropped - the underlying job tried to
  release back to the queue (a no-op when run synchronously) and returned
  without confirming the write, so the review screen reported a misleading
  `RuntimeException` to the bug tracker. Rate-limit errors now surface a clear
  "try again in N seconds" message on both the senior and youth submit paths,
  and are no longer recorded as bugs.
- **A clearer message when match orders need Hattrick Supporter.** Submitting
  orders without a Supporter subscription used to fail opaquely; the app now
  explains that Hattrick gates that action behind Supporter, keeps your lineup
  saved locally, and no longer logs it as a bug.
- **Sync failures no longer hide behind "Up to date".** If any step of a team
  sync fails, the refresh button and welcome screen now show a plain-language
  error card (and skip the needless auto-reload) instead of quietly claiming
  everything is current.
- **The right-flank toggle no longer vanishes in 3-back formations.** In 3-5-2
  and 3-4-3, switching one flank to a wing-back used to hide the whole flank
  toggle row - including the other side's button. Both flank toggles now stay
  visible on the senior and mobile lineup screens whatever you've picked.

## [0.12.0] - 2026-06-14

### Removed
- **Training planner removed (senior and youth).** Hattrick now treats training
  development and skill tracking as an HT Supporter feature, so - following a
  direct CHPP ruling - Ultimate Hattrick can no longer offer it. The Training
  screens, their navigation entries, and the underlying CHPP training
  sync/submit have all been removed, and `set_training` is no longer requested
  at sign-in. One side effect: team spirit and confidence (which Hattrick only
  exposes through the training data) are no longer fed into the AI Tactician and
  AI auto-pick; those features fall back cleanly to the remaining match factors,
  and match predictions are unaffected.

### Changed
- **Accessibility and interface-polish pass across the app.** A broad,
  presentation-only sweep: consolidated design tokens (spacing, radii, semantic
  result colours), full `prefers-reduced-motion` support, and a shared button
  component with proper hover/focus/disabled states. Modals, the player drawer,
  and the order-confirmation toasts are now announced as dialogs with focus
  handling and Escape-to-close; form controls, the global search box, AI chat
  inputs, and the Settings toggles/segmented controls gained accessible labels;
  the active navigation item is exposed to screen readers; and the Squad table's
  player rows are now keyboard-operable. The Review screen's send-readiness
  checklist now shows a clear word and icon for each item instead of relying on
  colour alone.

### Fixed
- **Honest, current copy and figures.** Replaced leftover mockup/placeholder
  values with real data or honest wording: the dashboard's "surprise risk" note
  now uses the real draw probability, the Lineup "Tactician" teaser no longer
  shows a fabricated quote, and the youth Scouts header no longer shows a
  made-up slot count. Corrected stale sign-in copy (live version number, removed
  an outdated "AI coming soon" line and a dead settings link), fixed "3th" →
  "3rd" league-position ordinals, an illegible disabled button and a
  near-invisible label, and assorted dashes and wording.

## [0.11.0] - 2026-06-09

### Added
- **Push notifications + installable PWA.** Ultimate Hattrick can now be
  added to your Home Screen (iOS/Android) or installed in a desktop browser,
  and send web-push notifications. The first notification fires when one of
  your games finishes - senior league/cup/friendly/tournament and youth - and
  tapping it opens that match's analysis. Manage it under **Settings →
  Notifications**: "Enable on this device" requests permission and registers
  the browser, and a per-type toggle list controls what you're notified about
  (built to grow as more notification types ship). On iPhone, add the app to
  your Home Screen first - iOS only delivers web push to an installed PWA.
  Notifications remain dormant until push notifications are configured.

## [0.10.0] - 2026-06-08

### Added
- **Youth academy: AI features brought across from the senior side.** Three
  additions, all behind the same AI setting with deterministic / offline
  fallbacks:
    - **Youth match analysis** - a new Match-analysis screen under the youth nav
      listing finished youth league matches, each opening a per-match page with
      an AI summary and a "Discuss this match" chat.
  - **Youth Tactician chat** - a multi-turn "Ask the Youth Tactician" thread
    alongside the existing game plan, grounded in the promote/release/XI advice
    and respecting hidden skills (never invents potential).
  - **Youth AI lineup pick** - an "✦ AI pick" on the youth Match-orders screen:
    a deterministic baseline XI refined by Claude, with a one-line rationale.
- **Match analysis: "Discuss this match" AI chat.** The past-match analysis
  page now has a multi-turn chat under the AI summary - ask why you conceded,
  whether your tactics fit the opponent, or what you'd change, and get answers
  grounded in that match's sector ratings, goals and possession (plus the
  pre-match prediction and the generated summary, when present). One-click
  starter questions seed the thread; it persists per match across refreshes.
  Mirrors the AI Tactician chat, with the same setting and a clean offline
  fallback when AI is unavailable.
- **Transfers: weekly net breakdown.** The "This week's net" tile (formerly
  "Wage headroom") now itemises the figure - income, player wages, and staff
  costs - so the single net number isn't a mystery. Falls back gracefully
  until economy data has synced.

### Changed
- **Mobile UI overhaul across multiple pages.** Fixes layout overflow and
  improves usability on narrow (375px) viewports:
  - **Mobile header now sticks to the top** while scrolling - the hamburger
    nav is always reachable. The now-redundant desktop section-title bar is
    hidden on phones (the section label already appears in the nav pill).
  - **Tactician** - the 320px opponent sidebar and briefing/chat panel stack
    vertically instead of leaving 55px for the main column.
  - **Match analysis · Upcoming** - the 88px match score moves below the
    team name headline on mobile, and the h1 scales down to fit. The sector
    comparison table gets horizontal scroll so its five-column layout stays
    readable.
  - **Youth · Team orders** - the five-column substitution rows reflow to a
    two-column grid (minute + player name pairs), and the six-column add-sub
    form stacks vertically so every field is full-width.
  - **Youth · Match analysis** - side padding reduced to match other mobile
    pages so the opponent name and date have more room.
  - **Youth · Past match page** - the scoreboard headline, h1 score, AI
    summary bullets, and AI generate prompt all collapse to single-column on
    mobile.
- **Transfers: clearer bids messaging.** The "Open auctions" tile and "Your
  bids" tab now explain that Hattrick's API only reports your bid on a player
  when that player appears in a search result - there's no global list of
  every auction you're in.
- **Transfers: mobile polish.** The AI Search card now stacks on a phone
  instead of overflowing, and the results tabs (including "Your bids") wrap so
  every tab stays reachable.
- **Match analysis (index): mobile table.** On narrow phones the played-matches
  list now gives the opponent name room instead of crushing it to zero width.
- **Matches: real "Position by matchday" chart.** The chart previously
  synthesized every team's line (and ignored goal difference for your own), so
  teams could share a slot. It now replays the real league table after each
  matchday from CHPP fixture results, ordered by points → goal difference →
  goals scored, so positions are accurate and ties are broken properly. Falls
  back to the old approximation only when fixtures haven't synced.
- **Matches: position chart on mobile** now scrolls horizontally at a readable
  width instead of squashing eight lines and their labels into a phone.

### Fixed
- **Match analysis: opening a tournament/youth match showed the wrong game.**
  A CHPP `MatchID` is only unique *within* a source system, but the past-match
  view always fetched with `sourceSystem=hattrick` - so opening a tournament
  (or youth) result loaded the unrelated regular-league match that happens to
  share that id, complete with a foreign opponent, score and date. The match's
  real source system is now carried from the matches list through to the
  matchdetails / live / lineup fetches. As a safety net, a report is no longer
  stored if your team didn't actually play in the fetched match (it falls back
  to the "couldn't load" state), and `match_reports` are now keyed per source
  system so two same-id matches can't collide on one row.
- **Match analysis: "beat the model" is now real.** The past-match
  predicted-vs-actual comparison previously copied the actual result into the
  "predicted" column, so the HatStats delta was always `+0`. It now computes a
  genuine pre-match forecast (your anchor ratings vs the opponent's cached
  ratings), matching the index screen, and hides the badge entirely when no
  prediction is available.
- **Match analysis: removed a stray model id** from the AI-summary footer; it
  now reads a neutral "AI" label.

### Removed
- **Match analysis: the live event ticker** is gone from the past-match page -
  Hattrick only serves the live ticker while a match is in your active tracking
  session, so it could never populate for a finished game. The goals timeline
  and top performers (both from `matchdetails`) remain.

## [0.9.0] - 2026-05-31

### Added
- **Real team-stats history & charts.** New synced time-series: every sync
  now records a daily TSI / wage / Power Rating snapshot and backfills +
  records your finished matches' CHPP sector ratings (with derived HatStats).
  The dashboard "Team statistics" chart plots your real HatStats, Defence,
  Attack, Midfield, goals, TSI, weekly wage and Power Rating over time - the
  last of the mock chart data is gone. Each metric appears once it has at
  least two real data points; until then the chart shows its empty state.
- **Power Rating** is now synced from `teamdetails` onto the team.

## [0.8.8] - 2026-05-31

### Changed
- **Dashboard charts are now real, not mock.** The team-statistics chart plots
  your actual goals scored & conceded from synced matches. Charts the app
  can't back with real history yet (youth trends, and the league-ratings
  comparison) show an honest "not enough history yet" note instead of the
  fabricated trends they used to display. Removed the mock data behind them.

## [0.8.7] - 2026-05-31

### Fixed
- **Swept out leftover design-mockup data.** Removed hardcoded placeholder
  values that several screens showed when real data wasn't available: the
  Training page's fabricated "recommendations" and sample match history /
  planner opponents and scores, a fixed "17:00" kick-off on every Matches
  row, and the youth Friendly page's invented opponent suggestions. Panels
  now show real data or an honest neutral/"coming soon" state.

## [0.8.6] - 2026-05-31

### Fixed
- **Lineup page showed hardcoded numbers.** The "Match probability"
  win/draw/loss bar (and its bogus "Monte Carlo · 5,000 sims" label) and the
  match-meta strip (opponent, date, kick-off, venue, weather) were static
  mockup values. They now use the real engine prediction and lineup data -
  win/draw/loss come from the Poisson model and the opponent/kick-off/venue
  are live. The fake weather row (never synced) is gone.

## [0.8.5] - 2026-05-31

### Fixed
- **Dashboard next-match prediction was a hardcoded mockup.** The dashboard's
  "Next match" card showed fixed sample numbers (149 HatStats, 61% win, a stub
  opponent and weather) that disagreed with the live Match Analysis page. It
  now uses the same engine and real data - opponent, home/away, kick-off,
  HatStats, win probability and expected goals all match Match Analysis.

### Changed
- **AI auto-pick now works cleanly on mobile.** Tapping *Auto · AI* on the
  mobile lineup applies the pick directly and shows a phone-friendly
  explanation (the AI's reasoning), instead of opening the cramped desktop
  side-by-side compare modal.

## [0.8.4] - 2026-05-31

### Added
- **AI weighs your team's match factors.** The auto-pick and Tactician now
  consider your team spirit (which drives midfield/possession), confidence
  (which drives attack), and whether you're playing home or away - so the
  shape, tactic and attitude suit the situation, not just the player ratings.

## [0.8.3] - 2026-05-31

### Changed
- **AI is happy to leave a good lineup alone.** The auto-pick no longer invents
  tweaks for the sake of it - if your XI is already strong, it keeps it exactly
  and the comparison popup says so in plain, friendly language ("Already spot
  on - nothing to change") instead of nudging you to keep refining.
- **Livelier "thinking" popup.** While the AI works (it can take more than a few
  seconds), the progress popup now cycles through several status messages on
  Lineup, Team Orders and Tactician rather than showing one fixed line.

## [0.8.2] - 2026-05-31

### Fixed
- **Lineup tooltips now show.** Hover tooltips on the pitch cards (fit score,
  specialty, form/stamina/loyalty, energy, last-match rating) were being
  clipped by the card's own clipping box, so they never appeared. The card no
  longer clips its tooltips (and grows to fit content rather than hiding it),
  and the pitch lets them through.

## [0.8.1] - 2026-05-31

### Fixed
- **Youth dashboard activity feed.** The "Youth activity" panel showed a fixed
  list of sample events (the demo academy's) to everyone. It now reflects your
  own academy: recent match results, players who are ready to promote, scouts
  out on a trip, and your top prospect - with a tidy empty state when there's
  nothing yet.

## [0.8.0] - 2026-05-31

### Added
- **First-login onboarding (`/welcome`).** New managers now land on a guided
  welcome screen that runs the first Hattrick sync while collecting a few
  quick preferences (appearance, AI features, default match orders), then
  drops them into a fully-loaded dashboard. Re-openable any time from
  Settings → Sync & refresh → "Replay intro".
- **Plain-language sync progress.** The data sync now narrates each step in
  friendly terms ("Rounding up the squad", "Scouting the opposition") behind
  a progress bar, instead of a terse technical pill.
- **Refresh progress lightbox.** Hitting Refresh on the dashboard now opens a
  centered progress card that fills step-by-step with that same narration,
  then reloads with fresh data when it's done (or offers a manual reload if
  you've turned auto-reload off).
- **AI progress popup.** Using AI on the Lineup, Team Orders or Tactician page
  now opens a popup that shows the AI working, then its explanation - the
  reasoning for the pick or orders, or the pre-match briefing - instead of a
  silent button that just said "Thinking…".
- **Team Orders AI explains itself.** Auto-picked match orders now come with a
  short note on why each substitution/order was chosen.
- **Admins & an AI debug bar.** Operators can flag specific accounts as admins
  from the uh-admin dashboard; admins get a debug bar showing the exact prompt
  sent to, and response received from, the AI on each screen (also browsable in
  the uh-admin "Recent AI Calls" log).

### Changed
- **Transfers on mobile.** The transfer market now leads with the listings on
  a phone: the desktop filter bar, squad-needs sidebar and empty detail pane
  are replaced by the floating Filters pill, the filter sheet and the
  full-screen player overlay, and the top KPI strip is tidied so nothing is
  cramped or stranded.
- **Team Orders AI respects the 3-order limit.** AI-generated match orders are
  now capped at 3 in total (Hattrick's maximum), matching the manual editor,
  instead of occasionally proposing more than can be submitted.
- **Smarter match-day AI prompts.** The Tactician and lineup AI now reason with
  Hattrick's possession / scoring-chance formula, so their suggestions line up
  more closely with the in-app match predictor.
- **"AI" everywhere.** The app now refers to its smart features simply as "AI"
  rather than naming the underlying model.

### Fixed
- **Brief team mix-up right after sign-up.** A freshly connected account could
  momentarily see another manager's team while its own first sync was still
  running; the app now shows a tidy onboarding state until your own team is
  ready.
- **Tactician no longer shows its briefing twice.** The pre-match briefing now
  appears once, in the chat thread, rather than as a duplicate card alongside
  it.
- **Tactician no longer gets stuck on "Thinking…".** The generate flow has a
  reliable progress popup with an escape hatch, so a slow or failed request
  can't leave the page hanging.
- **AI lineup now refreshes team orders.** Running the AI auto-pick on the
  Lineup page replaces the previous match orders with the new plan, instead of
  leaving stale orders (built for the old XI) behind.

## [0.7.0] - 2026-05-29

### Added
- **AI strategy presets.** Settings now has a dedicated **AI** section with
  the master toggle plus a senior-team and youth-team strategy (preset
  dropdown + optional free-text note). The chosen approach is threaded into
  every Claude feature - AI Tactician, auto-pick, AI transfer search and
  Youth Tactician - so advice is tailored to how the manager wants to play.
- **Weighted youth potential score.** `YouthPotential` now computes a
  numeric absolute-potential score (with a keeper-formula variant, flagged
  with a `*`) and uses it as the ranking signal across the youth squad,
  dashboard, Tactician and the youth academy advice screens.
- **Nationality filter on the transfer market.** The manual filters gain a
  Nationality dropdown, and listings/detail now show the country name instead
  of the raw id.
- **Public landing page.** Homepage with beta access form, Cloudflare
  Turnstile captcha, and Mailgun email delivery.
- **Admin usage dashboard.** Per-user AI usage tracking with the ability to
  disable AI per user.
- **AI cost cap.** Non-owner users capped at $0.50/month in AI token spend.
  Uses per-model pricing (Opus, Sonnet, Haiku) for accurate cost tracking.
- **Dark/light mode toggle in topbar.** Quick-cycle theme button (system,
  light, dark) alongside the search bar on every page. Persists to user
  settings automatically.

### Changed
- User-facing CHPP endpoint references replaced with friendlier "Hattrick"
  or "Hattrick API" language throughout. Homepage FAQ retains the CHPP name
  since it's the official program.
- Em dashes in prose copy replaced with hyphens for consistency.
- Background sync section in Settings now shows a "work in progress" note
  with the 15m/Hourly options disabled.
- Tactician card on the Lineup page now links to the Tactician page.
- Beta form now submits without a page reload.

### Fixed
- **Youth promotion eligibility.** A player is eligible only when CHPP's
  `CanBePromotedIn` has counted down to zero. Dropped the incorrect
  `|| age >= 17` shortcut that flagged recently-arrived 17-year-olds as
  READY.
- **Transfer nationality filter crash.** `$countries` was not passed from
  the Transfers component's `render()` method, causing an undefined variable
  error on the `/transfers` page.
- Removed misleading "Send a scout next week to reveal a skill cap." on the
  youth squad page.
- Fixed settings crash, admin dark mode, AI prompt, and email template
  issues.
- Mailgun email delivery is now available.

## [0.6.0] - 2026-05-27

### Added
- **League fixtures via CHPP.** New `leaguefixtures` endpoint + DTO +
  `SyncLeagueFixturesJob` writes the full series schedule (every team,
  every matchday, with scores) to `teams.league_fixtures`. The matches
  screen prefers this over the synthetic round-robin when present.
- **Season selector** in the matches masthead. Pick a past season →
  fetches and caches into `teams.seasons_archive[$season]`. Standings
  and position chart stay current-season only (CHPP doesn't expose
  historical standings).
- **Training via CHPP.** New `training` endpoint covers both fetch
  (`actionType=view` → `SyncTrainingJob`) and submit
  (`actionType=setTraining` → `SubmitTrainingJob`). The training
  screen now reads the live morale / confidence / coach for the KPI
  strip and gets a **Save to Hattrick** button that pushes the chosen
  type / intensity / stamina-share to CHPP. `set_training` scope is
  requested at OAuth time; missing scope surfaces a re-link banner.
- **Confidence forecast** on the training spirit chart. Dashed
  ink-blue line that mirrors the TS forecast - both update live with
  intensity/attitude changes.
- **SVG tooltips** on the matches position chart (team + position +
  points + form) and on every spirit chart point (TS, confidence,
  forecast - with full denomination + intensity + attitude context).
- **Standings column tooltips** - hover P / W / D / L / GF / GA / GD /
  Pts / HS to see what each column means.
- **Sync progress** in the refresh pill - shows "Players (3/10)"
  with a thin progress bar as the bundle works through its steps.

### Changed
- Matches position chart now uses CSS-var colours so position 1
  remains readable in dark mode (was black-on-black).
- Past matchdays in the fixtures grid say "Matchday" instead of
  "Upcoming matchday".
- Relegation zone shading no longer overshoots the chart bottom.
- Training spirit chart's past matchday chips now pull real scores
  from `team->recent_matches` instead of hard-coded demo data.

### Fixed
- `teams.league_level_unit_id` is now persisted by `TeamMapper` so
  the new fixtures sync job can call CHPP without re-fetching team
  details first.

## [0.5.0] - 2026-05-27

### Added
- **Stage 4 - League view.** `/matches` rewritten from the simple
  finished/upcoming tab list into the design's editorial season view:
  masthead (season · division · matchdays played), 4-cell
  promo/relegation KPI banner, full standings table with shield, form
  dots, HatStats and zone strips, position-by-matchday SVG chart with
  your team thick and on top, 14-matchday fixtures grid (next matchday
  outlined oxblood).
- **Stage 4 - Training (`/training`).** New screen: team-spirit
  masthead, KPI strip (current TS, confidence, MD9 forecast, coach),
  large past-plus-forecast spirit chart, and an editable 5-matchday
  planner. Intensity slider and PIC/N/MOTS attitude buttons drive an
  Alpine model so the forecast curve and per-row predicted TS update
  live as you drag. Auto-fill / Reset shortcuts.
- **Skill training what-if panel** on the training screen. Pick one
  of the 11 Hattrick training types (Goalkeeping → Set pieces), set
  intensity and stamina-share sliders, and the panel shows which
  squad players are eligible (full vs partial effect), an average
  weeks-to-next-level, and a per-player forecast card with progress
  bar - all reactive, no save needed.
- `App\Services\Hattrick\TrainingTypes` - the 11 training types as a
  pure service, plus `eligible()` and `weeksToPop()` helpers that
  apply the wiki's age / intensity / stamina-share modifiers.

### Changed
- Sidebar "Training" link is now wired to a real route.
- Matches screen's `setTab()` options updated to `all / yours /
  upcoming` to match the new fixtures-grid segmented filter.

## [0.4.0] - 2026-05-27

### Added
- CHANGELOG + automatic version pip in the page footer (sourced from
  the repo's `VERSION` file via `App\Support\AppVersion`).
- Tactician page (`/tactician`) with AI-generated pre-match briefing,
  opponent ratings card, suggested formation/tactic/attitude chip,
  "Apply suggested lineup" button, and a multi-turn chat that uses the
  same Anthropic key.
- AI two-pass auto-pick: deterministic Selector runs first, then
  AiSelector improves on that baseline with reasoning. Lineup page
  shows a side-by-side compare overlay with the diff highlighted.
- Position swap team-order type (CHPP orderType 3).
- `SyncPlayerLastMatchJob` + `MatchLineupFinished` endpoint to
  populate the squad's Last-match rating column from CHPP.
- Squad: 13 toggle-on behaviour-variant fit columns (CD Off, CD TW,
  WB Def/Off/TM, IM Def/Off/TW, W Def/Off/TM, FW Def/TW).
- Squad: green "FIT" pill in the Status column for healthy players.
- "Pull from CHPP" button on Match detail when no local lineup exists.
- Best-position label now reflects behaviour variants (e.g. "Inner
  midfielder · Offensive") when a variant beats the base profile.
- Days-until-kickoff badge in the sidebar next to Match orders.
- Dashboard "Match preview" button now links to `/match-analysis`
  (and reads as such).

### Changed
- **Skill scale fixed.** Player sync no longer halves CHPP values.
  Skills (gk/df/pm/pa/wi/sc/sp + experience + loyalty + leadership)
  now store on the 0-20 Hattrick ladder; form 0-8; stamina 0-9.
  Denominations table extended to the full 0-20 range. Bar widths
  and colour thresholds rescaled.
- AI Tactician prompt embeds the deterministic scoring formula
  (PositionFit weights, RatingsCalculator sector math, tactic +
  attitude multipliers) and ships opponent sector ratings in the
  user message.
- Auto pick no longer defaults to MOTS; the deterministic grid can't
  see MOTS' stamina cost so it now picks Normal. AI Tactician can
  still suggest MOTS / PIC.
- AI compare overlay relabelled "Algorithmic" → "Auto pick" and now
  counts subs / backup subs / penalty takers / pre-programmed team
  orders alongside the XI diff.
- Team orders UI restricted to Substitution / Behaviour change /
  Position swap. Legacy formation/tactic rows are deleted on first
  view (CHPP `setmatchorder` only honours orderType 1 + 3).
- Squad tooltips render below the trigger so they don't get clipped
  by the page-shell's `overflow: hidden`.
- Lineup pitch card: bar widths, fit thresholds, and the metadata
  strip rescaled to the new 0-20 ladder; xp/ldr/last now fits one
  line; card height bumped to 132px; "open detail" icon button
  surfaces the player drawer.

### Fixed
- Loyalty / Experience / Leadership progress bars no longer overflow
  the pitch card (they were computed at `val / 10` against the new
  0-20 scale).
- Player drawer skill bars filled at the right ratio (was clipping
  at 50% for skills ≥ 10).

## [0.3.0] - 2026-05-25

### Added
- CHPP `setmatchorder` submission end-to-end. Lineup serializer
  ships captain / set-pieces / substitutions / individual orders.
- Opponent ratings sync + match prediction engine.
- Auto-pick (algorithmic) and AI auto-pick (Claude) on the Lineup
  page.
- Mobile-only Team Orders editor.

## [0.2.0] - 2026-05-24

### Added
- Initial Hattrick OAuth + CHPP client.
- Squad / Lineup / Team Orders pages, desktop layouts.
- Player and match sync jobs.
