iTunes library now fetched from GB, US, Italy and New Zealand stores in parallel — all four run simultaneously via Promise.all so load time is unchanged
Albums are merged across all stores by collectionId, ensuring region-exclusive tracks are never missed regardless of where the player is based
Each album's tracks are fetched from its originating store, preventing cross-region preview URL mismatches
country=gb added to all API calls — fixes tracks missing from the US store (e.g. Find the Colour on Comfort in Sound)
Live and acoustic tracks no longer claim baseName in the deduplication seen set — previously this blocked the studio version of any song whose live version was processed first (fixed Find the Colour studio version disappearing)
Track name whitespace normalised on ingestion — iTunes double-spaces (e.g. "Lost & Found") collapsed to single space, fixing deduplication mismatches and autocomplete search
Named mixes now excluded from library (e.g. "Alan Moulder Mix", "Alt Mix") — space-prefixed " mix" filter avoids false matches on unrelated titles
SINGLES_EXCEPTIONS system introduced — tracks that exist only on compilations can be pinned to a preferred source album, blocking all other copies (used for Lost & Found → The Singles)
Compilation processing order fixed — The Singles now always processed before The Best Of, ensuring SINGLES_EXCEPTIONS preferred sources are claimed before duplicates arrive
Two separate "The Best Of" iTunes albums correctly handled — both blocked for Lost & Found once The Singles version is claimed
Play button now stays disabled and shows BUFFERING... until the audio canplay event fires — eliminates unresponsive clicks immediately after library load
Artificial 500ms delay before startRound() removed — game begins as soon as library crunch animation completes
4-second fallback enables play button if canplay never fires (e.g. slow connection)
setUI() no longer manages the play button — exclusively controlled by canplay to prevent premature enabling
Old localStorage cache keys v17–v28 cleaned up on each load to prevent stale library data
HUD leaderboard and online panels merged into a single unified dropdown — fixes WordPress admin bar rendering only one child node per parent
TOP 5 PLAYERS streak showing 0 for logged-out users fixed — get_live_leaderboard handler moved outside the is_user_logged_in() gate (leaderboard is public data)
TOTAL PLAYERS count now only includes players who have scored above 0
Rank shows a LOG IN link for guests instead of #N/A — both server-rendered and AJAX-updated versions handled
Login link in HUD bar given explicit inline styles to prevent WordPress admin bar CSS breaking flex alignment
best_streak column migration added to feeder_ensure_table() — ALTER TABLE adds it automatically on sites where the table predates v7.2.7
All five modular files (engine.js, game-logic.php, hud-bar.php, game-ui.php, footer-ui.php, feedheardle-main.php) fully commented throughout
crossorigin="anonymous" restored on audio element — fixes silent CORS failures on some browsers
Final attempt now plays the complete 30-second clip rather than stopping at 16s
Skip no longer flashes 0 seconds — display holds the current value during the rewind animation
Seconds display rolls up incrementally to the next duration on skip (80ms per step)
player.volume = 1 forced before every play() call to eliminate browser fade-in
crossorigin="anonymous" restored on audio element — fixes silent CORS failures on some browsers
v7.3.1 — Database Reliability Fix
Root cause of score/leaderboard not saving identified: add_action hooks in a template file never fire during admin-ajax.php requests as WordPress doesn't load the game template in that context
Reverted to inline POST handler pattern from test.php — AJAX requests now post back to window.location.href (the game page itself) guaranteeing WordPress and the database table are always available
All three fetch calls (saveScore, fetchLiveLeaderboard, fetchOnlineUsers) updated to post to window.location.href with correct Content-Type header
Hi-score protection retained — server compares incoming value against existing record and keeps the higher of the two
Removed redundant add_action/init hook registration that was never reliably reached
v7.3.0 — Leaderboard Overhaul
Both HUD dropdowns now show score (🔢) and streak (🔥) per player in a unified row layout
TOP 5 PLAYERS query updated to include best_streak alongside high_score
X ONLINE PLAYERS heading dynamically reflects singular/plural player count
Online users panel joins leaderboard table to display each user's score and streak
Dynamic AJAX refresh renders both panels in the new format every 30 seconds
lb-stats CSS layout added for consistent score/streak column alignment
v7.2.9 — Live Presence & Score Integrity
AJAX handlers now registered on init hook — fixes leaderboard and score saving on all WordPress configurations
feeder_ensure_table() added — auto-creates leaderboard table with correct schema on first load
Hi-score save bug fixed — server now compares incoming score against existing record and keeps the higher value
saveScore() syncs server-confirmed hi-score back to client, correcting any session discrepancies
Online users dropdown added to HUD — shows names of all currently active WordPress users
New get_online_users AJAX endpoint returns display names of online users
Online users list refreshes every 30 seconds alongside leaderboard
Stale session pruning applied consistently across all online tracking calls
nonce check added to get_live_leaderboard for consistency and security
v7.2.8 — Stability & Completeness
stopPlayback() now sets isPlaying = false immediately, closing the 400ms race window that left the bar stuck
onplaying guard extended to !isPlaying — prevents browser rebuffer events restarting the countdown after a stop
performance.now() countdown polling increased to 100ms for sub-second accuracy
Acoustic tracks from single releases no longer incorrectly blocked by the compilation gate
Duplicate const albums declaration removed — was silently crashing the library fetch and preventing cache writes
Come Back Around from The Best Of now correctly excluded in all cases
Single releases (- Single suffix) added to compilation gate via regex
Picture of Perfect Youth added to protected albums whitelist
Skip on final step (10pts) now marks it red before calling finish()
Escape key clears input and closes suggestions dropdown
Input field clears on focus for faster re-entry
Mobile layout refined — consistent 16px body padding, max-width: 100% on all containers
Title font scaled back on mobile to clamp(2.2rem, 13vw, 3.2rem) to prevent overflow
Version number moved from page title to footer, with auto-appended deploy date
Page title updated to "Feedheardle — Guess the Feeder Song"
Input placeholder updated to match title slogan
Patch notes modal added — clickable version number in footer reveals full history
v7.2.7 — Precision & Polish
Modularised codebase into feeder-parts (game-logic, hud-bar, game-ui, footer-ui, engine.js)
HUD bar extended with BEST streak, RANK, online player count and total players
Big seconds indicator — large central number displays current clip duration
Live countdown ticks to 0 using performance.now() to eliminate timer drift
Rewind animation on play button progress bar after clip ends
AJAX persistence switched to admin-ajax.php — fixes high score amnesia on refresh
Autocomplete suggestions with album art, bold match highlighting and keyboard navigation
Confetti on correct answer with album art and full track reveal
Score, hi-score, streak and best streak synced to WordPress database
Skip or guess during playback correctly stops audio immediately
Final step (10pts) now correctly turns red on failed guess
Track deduplication: live and acoustic versions always preserved
Come Back Around multi-album exception (Comfort in Sound + Picture of Perfect Youth)
Compilation gate: The Best Of and The Singles filtered, unique-only tracks allowed through
Single releases (- Single suffix) excluded unless track is genuinely unique
Remixes, remasters, radio edits, instrumentals and single versions excluded
Clear-on-focus for guess input; Escape key clears and closes suggestions
Mobile responsive layout with adjusted tap targets and hidden HUD bar
Box model fix — box-sizing: border-box enforced for uniform 58px button height
Footer version number with auto-appended deploy date, clickable for patch notes
Page title updated to "Feedheardle — Guess the Feeder Song"
v7.2.6 — The Modular Shift
Decoupled monolithic code into /feeder-parts/ modules: engine.js, game-logic.php, game-ui.php
filemtime versioning added to auto-bust CSS/JS caches on deploy
Admin HUD v2 rebuilt with throbbing green status dot and gold labels for personal bests
v7.2.5 — The Golden Era
Alignment perfected across logo, presents text and game board — established as the "Golden" standard
Timeline moved directly under title container to reduce vertical scrolling
Score bubbles redesigned — point values (100, 80, 60...) displayed inside each pip via CSS ::before
v6.0 – 7.2.4 — Visual Identity
Glassmorphism UI — semi-transparent cards with backdrop-filter: blur(15px)
ITC Avant Garde Std Bold integrated to match Feeder's official branding
Pronunciation guide "(feed - hur - dul)" added with skewed CSS styling
canvas-confetti integrated for correct guess celebration
Album art reveal transition on round end
v4.0 – 5.0 — The Social Layer
WordPress MySQL leaderboard table (feeder_leaderboard) replacing browser localStorage
Admin HUD alpha — Score, High Score and Streak visible in the top bar
Live presence counter via WordPress transients showing X ONLINE
wp_nonce security added to all database writes
v1.0 – 3.0 — The Prototype
Initial commit — HTML5 audio player with iTunes Search API via JSONP for 30-second Feeder previews