VITREOUS
YOUR MUSIC DESERVES BETTER THAN A BASIC EMBED
Want to know more about Vitreous or learn about its use, use these 2 below to navigate to the areas you need:
About vitreous
Find out about Vitreous Music Player and its Library, Track and Artist management functions. Learn why this could be beneficial.
Knowledgebase
Get help in regards to the use of all functions of this plugin; its backend, its addition to pages and frontend use.
Find out how development of Vitreous is going:
| 2026 BUILD COUNTS | |
| JANUARY | Template builds from v0.1.0 to v2.4.6 |
| FEBRUARY | WordPress plugin build from v3.0.0 to v4.0.12 |
| MARCH | 64 builds from v4.0.13 to v4.3.10 |
| APRIL | 46 builds from v4.4.0 to v6.5.3 |
| MAY | 95 builds from v6.5.4 to v11.1.8 |
MAY 2026 BUILDS
TUESDAY THE 26TH OF MAY
- Removed: Dead CSS from
vitreous-player.css. Six dead blocks removed: orphaned property declarations with no selector (remnant of a deleted rule);#vamp-color-palette-sectionand#vamp-color-palette-light-sectionrules targeting elements that no longer exist in the player template;#vamp-embed-code-inputrule for a removed embed code panel;#fullscreen-artist-profilerule targeting a non-existent ID (element usesfullscreen-artist-profile-extras);.fullscreen-meta-sectionrule for a class not present in the template or JS;#vamp-crossfadehide rules targeting removed UI controls. 52 lines removed, zero functional change.
- Text: Full en-GB visible text pass across all frontend and admin files (excluding changelog). All em dashes in user-facing strings replaced with hyphens: format badge notices, import mode descriptions, download source hint, orphan purge notice, DO sidebar title, artist/library meta separator.
- Text: American English corrected in the main player frontend: “color” changed to “colour” in Disco Mode warning; “Audio Normalization (Auto-Leveling)” changed to “Audio Normalisation (Auto-Levelling)”; “Audio Visualizer” changed to “Audio Visualiser” in label and aria-label; Version placeholder em dash changed to hyphen.
- Removed:
migrations/migrate-to-v4.php– migration class never referenced anywhere in the plugin. Dead file. - Removed:
admin/admin-page.php– old modal and GUI editor page, never included or rendered anywhere. All IDs it defined were unhandled. Dead file. - Removed:
ajax_delete_library()handler and itswp_ajaxregistration – library deletion is handled via a nonce-protected GET link inlibraries-list.php. Never called from JS. - Removed:
handle_import_tracks()handler and itsadmin_postregistration – import was converted to AJAX at v11.1.2. The old form POST route was never reachable. - Removed:
ajax_link_track_artist()handler and itswp_ajaxregistration – replaced byvitreous_link_unlinked_track. Never called from anywhere. - Removed:
player_scalefromset_default_options()and fromsettings-page.phpPOST save and read – the setting was saved but never read or applied anywhere in the plugin or JS. - Removed:
vtReloadTracksdead call from import handler inadmin.js– function never defined anywhere. - Removed: Misplaced
Theme togglecomment from top ofadmin.js– sat above format indicator code, not theme toggle code. - Removed: Duplicate separator comment line in
admin.js. - Removed:
getAnimationSpeedLabel()fromvitreous-player.js– defined but never called anywhere. - Removed: Empty
else {}block invitreous-player.jsat thevitreousSettingscheck – did nothing.
MONDAY THE 25TH OF MAY
- New: Track edit area – tracks with no audio file now show a red warning badge: “No audio file – this track will not be displayed on the frontend.” Matches the style of the existing audio format support notices. Badge updates dynamically when the audio URL field is cleared.
- Fixed: Frontend player – tracks with an empty
srcfield are now excluded from the track list rendered to the frontend. They are never passed to the player JS. - Fixed: Metrics — all ranking and count queries now exclude tracks with an empty
src: Most Played, Most Liked, Artist Rankings, Genre/Mood/Tempo rankings, and per-library track counts in the metrics chart. Site Stats Card total track count, most played and most liked featured panels also exclude audio-less tracks.
- Fixed: Import Tracks – file input and radio buttons now match Vitreous admin theme. Native file input hidden and replaced with a styled label trigger showing a folder icon and selected filename. Radio buttons use custom
appearance: nonestyling with gold border and filled state on selection. Filename display resets to “No file chosen” after a successful import.
- Fixed: Import button was unresponsive. Root cause: the import IIFE was placed inside the Display Options sidebar IIFE which guards all its code behind
if (!doSidebar) return. On the library-edit page where#vt-do-sidebardoes not exist, the entire block was skipped before the import handler ran. Fixed by wrapping the DO code inif (doSidebar) { ... }instead of using early return, allowing the import IIFE to execute unconditionally on all admin pages.
- New: Import Tracks – three import modes added: Add New Only (previous behaviour), Overwrite Matching (replaces all fields on exact title match), Merge Matching (fills only empty fields on exact title match). Title matching is case-insensitive using
LOWER()on both sides. - New: Import Tracks – close match review step. When an incoming track title is similar but not identical to an existing track (≥80% Levenshtein similarity), the import pauses and presents a per-track decision panel showing the incoming title alongside the matched existing title and similarity percentage. User chooses per track: Add as New, Overwrite Existing, Merge into Existing, or Skip. Exact matches and new tracks are processed automatically per the selected mode. Only close matches require user input.
- Changed: Import is now AJAX-based rather than a full page POST/redirect. Results are shown inline without a page reload.
WEDNESDAY THE 20TH OF MAY
- Fixed: Colour options removed from Display Options typography areas for accent-driven elements.
astat_nameandastat_track_likeson Artist Stats Card, andsstat_feat_countandsstat_feat_badgeon Site Stats Card all usevar(--accent)— their colour is controlled by the panel-level Accent picker only. Colour picker rows removed from their typography accordions in the DO sidebar, colour property skipped during frontend inline style generation, and colour column keys removed from$allowed_keysso they are never saved.
- Fixed: Artist Stats Card — missing Display Options controls added: Stat Icons (Play & Heart) icon size slider; Most Liked Track Badge full typography area (font family, size, colour, weight, letter spacing). Both apply correctly to the rendered widget via inline styles.
- Fixed: Site Stats Card — missing Display Options controls added: Count Icons size slider; Featured Count Badge full typography area; Featured Panel Label full typography area. All apply correctly to the rendered widget via inline styles.
- New: DB migration adds missing columns to
vitreous_display_options:astat_stat_icon_font_size,astat_track_likes_*(9 cols),sstat_count_icon_font_size,sstat_feat_count_*(9 cols),sstat_feat_badge_*(9 cols). All new keys added to$allowed_keysinajax_save_display_options.
- Fixed: Display Options accent and theme not persisting for Artist Stats, Track Player, and Site Stats tabs. Three state management breaks identified and corrected: (1) trigger button in
libraries-list.phpwas missingdata-astat-*,data-tplayer-*,data-sstat-*attributes — accent and theme were never read from the DB at page load; (2)vtDoPopulateFromTriggerinadmin.jsonly populatedlist,card,alist— new sections never populated on sidebar open; (3) save handler write-back only updatedlist,card,alistdata attributes — new section values lost on next open without a page reload.
- Fixed: Display Options not persisting for Artist Stats, Track Player, and Site Stats tabs. All
astat_*,tplayer_*, andsstat_*column keys were missing from the$allowed_keyswhitelist inajax_save_display_options. POST data for these fields was being silently stripped before the database write. All 106 new keys added to the whitelist.
- Fixed: Track Player card now has a fixed width via
--vtp-max-width: 480pxCSS variable and centres within its container usingdisplay: flex; justify-content: centeron the root — mirroring the main player pattern. - Fixed: Track Player volume slider now slides in and out with 10-second auto-hide. Player bar wrapped in
.vt-list-item-playersovtListInitinvitreous-list.jsdiscovers and wires up all controls via the existing standalone item path. - Fixed: Track Player responsive breakpoint added — at
max-width: 520pxthe card width falls back to100%to fill narrow screens gracefully.
- Fixed: Track Player shortcode was reading
file_source_url(the download source) as the audio elementsrc. Corrected to read thesrccolumn, which holds the direct audio URL used by all other player contexts.
- Major: Three new frontend widgets added — Artist Stats Card, Single Track Minified Player, and Site-Wide Stats Card. All available as Elementor widgets, Gutenberg blocks, and shortcodes. All support Display Options styling. DB migration adds 106 new columns to
vitreous_display_options(astat_*,tplayer_*,sstat_*). - New: Display Options sidebar updated to two-row tab layout (six tabs, three per row) to accommodate the three new widget tabs. Tabs: Track List, Artist Card, Artist List, Artist Stats, Track Player, Site Stats.
- New: Metrics page — Most Played Artists and Most Liked Artists ranking panels added. Top Genres, Top Moods, Top Tempos attribute ranking sections added. Per-library bar chart now shows average plays per track. Artist filter dropdown added to the time-series chart for per-artist play overlay.
- New: Library Edit — unlinked track count badge in the Tracks header. Artist Profiles — Unlinked Tracks section in Column C with inline Link button.
- Summary of patch versions leading to this release: v10.1.7 (artist chart line), v10.1.8 (DB migration), v10.1.9 (DO tab layout + new panels), v10.1.10 (admin.js extension), v10.1.11 (Artist Stats widget), v10.1.12 (Track Player widget), v10.1.13 (Site Stats widget).
- New: Site-Wide Stats Card widget — displays aggregate totals (total plays, likes, tracks, artists, libraries) in a count grid, plus three featured panels: Most Played Track, Most Liked Track, and Most Active Library — each with album art, gradient overlay, title, artist/meta, and count badge. Available as Elementor widget, Gutenberg block, and shortcode
[ vitreous_site_stats ]. Supports Display Options viasstat_*columns.
- New: Single Track Minified Player widget — displays a single track with album art thumbnail, title, and artist in a meta row above a horizontal minified player (play button, progress bar, volume control). Track selected from all available tracks across all libraries. Available as Elementor widget, Gutenberg block, and shortcode
[ vitreous_track_player id="#" ]. Reuses.vt-list-*player classes so the existingvitreous-list.jshandles all audio controls automatically. Supports Display Options viatplayer_*columns.
- New: Artist Stats Card widget — displays artist image, name, social icons, total plays, total likes (aggregated from all linked tracks), and most liked track with album art, gradient overlay, and like count badge. Available as Elementor widget, Gutenberg block, and shortcode
[ vitreous_artist_stats id="#" ]. Styled to match Artist Card. Supports Display Options viaastat_*columns.
- New:
admin.js—previewsobject extended withastat,tplayer,sstatpreview panel references. - New:
vtDoUpdatePreview—previewMapextended with typography element mappings for all three new sections. Social icon size preview extended to includeastat. - New:
vtDoLoadFirstTrack— populates all new preview element text nodes with first track data on sidebar open. - New:
vtDoLoadTypography— skip list extended to ignoreastat_*,tplayer_*,sstat_*accent and theme keys during load.
- New: Display Options sidebar tab bar updated to two-row layout —
flex-wrap: wrapwithflex: 0 0 33.333%, three tabs per row. Font size reduced to 11px to accommodate longer labels. Three new tabs added: Artist Stats, Track Player, Site Stats. - New: Three new live preview panels added to the DO sidebar: Artist Stats preview (image, name, social icon, stat blocks, most liked track), Track Player preview (meta row with art/title/artist, horizontal player bar), Site Stats preview (count blocks, featured track panel).
- New: Three new DO section panels added (
astat,tplayer,sstat) — full typography, colour, glass mode controls. Artist Stats includes social icon size control.
- DB: Migration added to
maybe_upgrade_schemafor v11.0.0 widget Display Options columns —astat_*(Artist Stats Card: 48 columns),tplayer_*(Track Player: 20 columns),sstat_*(Site Stats Card: 38 columns). All added viaALTER TABLEwith existence check. No frontend changes.
- New: Metrics chart — third line added showing artist plays over time in purple (
rgba(167,139,250,0.85)), rendered as a dashed line to distinguish from the solid Plays and Likes lines. Only appears when an artist is selected. - New: Artist filter dropdown added to the chart legend. Selecting an artist re-fetches the chart and overlays their play activity. Defaults to “All Artists” (no third line). Only appears when at least one artist has play data.
- New: Chart tooltip gains a third “Artist” row showing artist plays for the hovered bucket. Hidden when no artist is selected.
- Fixed: Metrics page critical error — PHP parse error: unexpected
endifon line 880. The<?php if ($play_log_exists): ?>wrapper around the chart script block was lost when the new ranking sections were inserted. The orphanedendifcaused a fatal parse error before any page output. Wrapper restored.
- Debug: Temporary error reporting added to metrics-page.php to surface the exact PHP fault in the browser. To be removed once fault is identified.
- Fixed: Metrics page critical error.
$wpdb->prepare()was being called with a partial SQL fragment inside string concatenation passed toget_results(). Replaced with safeintval()interpolation —$filter_libraryis already sanitised withintval()at input, making direct interpolation safe.
- Fixed: Metrics page critical error. Artist ranking queries were constructing invalid SQL by appending
AND t.library_id = %ddirectly after aJOINclause with no precedingWHEREkeyword. AddedWHERE 1=1before the conditional filter clause in both Most Played Artists and Most Liked Artists queries. Library filter variable extracted to$lib_where_artiststo avoid calling$wpdb->prepare()inside string concatenation twice.
- Fixed: Metrics page critical error.
HAVING total_plays > 0andHAVING total_likes > 0in the Most Played Artists and Most Liked Artists queries used column aliases in theHAVINGclause, which is not supported by MariaDB. Replaced with full aggregate expressions:HAVING SUM(t.global_play_count) > 0andHAVING SUM(t.global_favourite_count) > 0.
- Fixed: Metrics page critical error on load. MySQL reserved word
atwas used as a table alias in the Most Played Artists, Most Liked Artists, Unlinked Tracks (AJAX), and Library Edit unlinked count queries. All new query aliases renamed tovat.
- New: Metrics — Most Played Artists and Most Liked Artists ranking panels added below the existing track rankings. Both follow the same panel pattern as Most Played and Most Liked tracks. Requires tracks to be linked to artist profiles to populate.
- New: Metrics — Track Attribute Rankings section added: Top Genres, Top Moods, and Top Tempos, each showing a ranked scrollable list with inline bar chart and play count. All filtered by the existing library filter.
- New: Metrics — Per-Library bar chart now shows average plays per track alongside total plays and likes.
- New: Library Edit — Unlinked track count badge added to the Tracks section header. Only appears when one or more tracks in the library have no linked artist profile. Shown in red to distinguish from informational badges.
- New: Artist Profiles — Unlinked Tracks section added to Column C. When an artist is selected, all tracks across all libraries with no artist link are listed below the Linked Tracks panel. Each unlinked track has an inline Link button to assign it to the selected artist immediately without leaving the page.
TUESDAY THE 19TH OF MAY
- Fixed: Display Options sidebar button was non-functional — clicking it produced no response. Root cause:
vtDoUpdatePreview,vtDoLoadFirstTrack,vtDoSetText, andvtDoLoadTypographyfunction definitions were missing fromadmin.js. AReferenceErroronvtDoUpdatePreviewhalted execution insidevtDoPopulateFromTriggerbeforevtDoOpenwas ever reached. All four functions restored from v8.3.1.
- Fixed: Editor overlay added to
.glass-playervia CSS::afterpseudo-element, scoped tobody.elementor-editor-active. Displays “Ready for Live Page” in gold over the glassmorphic card when a library is selected in the Elementor editor. No effect on the frontend. - Removed: Alignment controls removed from Elementor widget and Gutenberg block. Queued for future work.
- Fixed: Player width setting now works correctly.
.glass-playerwas hardcoded to400pxinside@media (min-width: 521px), overriding--player-max-widthentirely. Replaced withvar(--player-max-width, 420px). All width defaults (CSS, JS, PHP, template) corrected from400px/500pxto420pxto match the settings slider minimum. - Fixed:
.player-wrapperno longer usesmin-height: 100vhoralign-items: centerin standard page view — the player now sits naturally in the page flow rather than being vertically centred in the viewport. Fullscreen mode retains full centring via explicit rules on:fullscreenand.fullscreen-override. - New: Player alignment control added. Shortcode supports
align="left|center|right"(default: center). Elementor widget has a new alignment picker (left/centre/right) in the widget panel. Gutenberg block has a new alignment select in the inspector sidebar. All three apply avt-align-*class to.player-wrapper. Users can use widget/block padding and margin to fine-tune placement.
SUNDAY THE 17TH OF MAY
- Fixed: Animation Speed dropdown showed no selected option on load. The reset path was setting
animationSpeed: 1.0(float) while the select option hasvalue="1"(string). Changed toanimationSpeed: 1throughout. Change handler updated to store the value as a string rather than parsing it back to a float viaparseFloat, eliminating the type mismatch.
- Fixed — Rope, Pulse Rings, DNA/Helix: All three styles were using a full-spectrum frequency average which produced low values on bass-heavy and DnB tracks, causing minimal reactivity. All three now sample the first 20 frequency bins (sub-bass and kick range, ~20–200Hz) instead. Rope amplitude, Pulse Rings spawn threshold, and DNA/Helix strand amplitude all now respond correctly to bass-driven and low-BPM tracks.
- Fixed — Pulse Rings: Spawn threshold raised from 0.15 to 0.30 to reduce excess ring density. Spawn guard gap increased from r>12 to r>30 to space rings further apart. Alpha decay slowed from 0.93 to 0.97 so rings remain visible across more of the canvas width. Growth rate increased from 2.5 to 3.5 so rings reach the far edge before fading completely.
- Fixed — Pulse Rings: Spawn threshold lowered from 0.55 to 0.15 so rings appear at normal playing volumes. Starting radius changed from 2 to 0 so rings are visible immediately at the left edge.
- Fixed — Particle Drift: Upward float fixed — velocity now decays toward zero at low signal using a damping factor rather than drifting constantly. Spawn position uses full canvas height (random y between 2 and h-2) instead of always spawning at centre. Blur added to each dot. Each particle has a randomly assigned fade target between 60%–100% of canvas width so particles disappear at varied positions.
- New: Waveform container edge fade added via CSS
mask-image— 12px soft fade on left and right edges, 4px on top and bottom. Affects all canvas layers simultaneously including the static waveform, live visualiser, progress overlay, and playhead.
- New: Five additional live visualiser styles — Circles (repeating portrait-mirrored circles across canvas width), Rope (sine wave driven by audio amplitude), Pulse Rings (concentric arcs expanding from left edge on transients), Particle Drift (dots drifting right with vertical oscillation, fading to transparent), DNA / Helix (two offset sine waves with scrolling rungs). All selectable from the Visualiser Style dropdown in Visual settings.
- Renamed: “Circular” visualiser style renamed to “Circles”.
- Improved: Oscilloscope line spacing increased — samples every 8th point instead of every point, giving the waveform more breathing room.
- Fixed: Static waveform seed changed from a fixed value of
42to the track DB ID. Each track now generates a unique stable decorative waveform that is consistent across page loads. - New: Three additional live visualiser styles added — Oscilloscope (raw time-domain signal as a continuous line), Filled Wave (frequency data as a filled gradient area), and Circular (frequency bars radiating from a centre point). Selectable via a new Visualiser Style dropdown in the player Visual settings tab. Style persists to localStorage.
- Fixed: Keyboard Shortcuts button and sidebar are now hidden on touch-primary mobile and tablet devices on init, using the existing
vtIsMobileDevice()check. Keyboard shortcuts are not applicable on touch devices.
- Fixed: Landscape fullscreen overlay was incorrectly firing on desktop browsers in widescreen because
window.innerWidth > window.innerHeightis always true on a landscape monitor. AddedvtIsMobileDevice()check —navigator.maxTouchPoints > 0combined with(pointer: coarse)media query — so the overlay only activates on touch-primary mobile devices. Desktop browsers are unaffected.
- Fixed: Artist Profiles three-column layout now uses
1fr 1fr 1fr— equal thirds — instead of a fixed-width approach that left Column A dominating. All three columns share the available width equally. - Improved: Linked Tracks items in Column C now have left and right padding (14px) giving the art thumbnail and library pill breathing room.
- Fixed: Three-column layout on Artist Profiles was still collapsing because the
.vt-track-editor-layout--three-colmodifier rule was declared before the base.vt-track-editor-layoutrule in the stylesheet, causing the base two-columngrid-template-columnsto win the cascade. Modifier moved to after the base rule so it correctly overrides it.
- Fixed: Three-column layout on Artist Profiles was still collapsing because
calc(100% - 700px)for Column A produced a near-zero or negative value when the WordPress admin container width was reduced by the sidebar. Replaced withminmax(160px, 1fr)so Column A flexes within available space without going negative, while Columns B (400px) and C (300px) remain fixed.
- Fixed: Artist Profiles three-column layout was collapsing Column C into a full-width row below Columns A and B at desktop widths due to an uninstructed 1100px breakpoint. Removed. Three columns now remain side by side at all desktop widths. Mobile stack at 700px is retained.
- Improved: Artist Profiles page now uses a three-column layout. Linked Tracks moves from the bottom of Column B (editor form) into a dedicated Column C (300px fixed, scrollable) sitting alongside the artist list and editor. A loading indicator shows while tracks are fetched.
- Responsive: At 1100px and below, Column C drops to a full-width row below Columns A and B (max-height 300px). At 700px and below all three columns stack vertically.
- New DB table:
vitreous_artist_tracks— stores direct artist-to-track links (artist_id, track_id). Replaces fragile text-matching between the track Artist field and the artist profile Name field. Migration guard added tomaybe_upgrade_schema()for existing installs. - Backend — Track Edit: Artist field replaced with a searchable combo input backed by a datalist of all existing artist profiles. Selecting a profile sets a hidden
linked_artist_idfield. A “New” button reveals an inline create form (Name, Year Started, Bio, Image) that saves via the existingvitreous_save_artisthandler, then automatically selects the newly created profile. A clear button removes the link. - Backend — Artist Profiles: Column B now shows a “Linked Tracks” section listing all tracks linked to the selected artist, with art thumbnail, title, and library name.
- Backend — Save flow:
ajax_save_track()acceptslinked_artist_id. If set, the linked profile name is synced into the cachedartistcolumn automatically. The artist-track link is written tovitreous_artist_tracks.ajax_load_track()JOINs the linkage table and returnslinkedArtistIdso the combo shows the correct profile on load. - Frontend — Player: Artist profile matching in the fullscreen sidebar now uses
linkedArtistId(ID lookup) as the primary method, falling back to text match for tracks without a link. This eliminates case-sensitivity and whitespace fragility. - New AJAX handlers:
vitreous_link_track_artist(write/clear a link),vitreous_get_artist_tracks(fetch all tracks linked to an artist).
- Fixed: Added 16px spacing between the copyright line and the Ko-fi button in the About sidebar.
- New: Ko-fi support button added to the About sidebar of the main player, below the copyright line. Gold coloured (
#c4a75d) to match the plugin aesthetic.
- Fixed: Metrics page layout corrected — time-series chart and per-library breakdown now appear above the Full Rankings, under an “Activity Over Time” section label. Rankings appear below under “Full Rankings”.
- Fixed: Most Played and Most Liked ranking lists are now scrollable fixed-height panels (
max-height: 520px; overflow-y: auto) so they do not flood the page with large track libraries. Custom scrollbar styled to match the plugin gold palette. - Improved: Bar chart replaced with a smooth curved line chart. Two lines (plays gold, likes red) drawn using cubic bezier curves. Subtle filled area beneath each line. Data point circles on each bucket. Y-axis gridlines and X-axis labels retained.
- New: Hover tooltip added — HTML
divabsolutely positioned over the chart container (z-index: 100), showing the bucket label, play count, and like count onmouseenterof invisible hit-area rects. Edge-aware positioning: right-edge overflow anchors tooltip to the left of the point; left-edge check ensures tooltip never clips at the left boundary.
- New: Dedicated Metrics admin page (
vitreous-metrics) added to the WordPress sidebar. Contains the full extended Most Played and Most Liked rankings (no cap, all tracks with at least one play or like), filterable by library via a dropdown. Each panel shows a track count badge in the header. Time-series chart (Hourly/Daily/Monthly/Custom) and per-library breakdown sit below the rankings. - Fixed: Metrics chart and library breakdown removed from the Overview page where they did not belong. Overview now contains only the stats bar, quick actions, top 10 Most Played, top 10 Most Liked, and the Ko-fi support panel.
- New: Metrics quick action card added to the Overview page linking to the new Metrics page.
- New DB tables:
vitreous_play_logandvitreous_like_logadded. Each play event inserts a row intovitreous_play_log(track_id, library_id, played_at). Each like or unlike event inserts a row intovitreous_like_log(track_id, library_id, action, liked_at). Existing running totals andlast_played_atbehaviour are completely unchanged. - New AJAX handler:
ajax_get_metrics()— admin-only, nonce-protected. Accepts range (hourly/daily/monthly/custom) and optional date_from/date_to. Returns grouped play and like totals as JSON plus per-library running totals. Custom ranges over 90 days auto-switch to monthly grouping. Max range capped at 365 days server-side. - Overview page — Metrics section: Four-tab chart panel (Hourly 24h, Daily 30d, Monthly 12m, Custom) with SVG bar chart showing plays (gold) and likes (red) per time bucket. Custom tab shows native date inputs with 365-day max validation. Per-library horizontal bar breakdown below the chart, drawn from all-time running totals. Historical data note displayed — time-series data records from v9.0.0 onwards only.
- Fixed: Scenario B-2 — when a user pressed the fullscreen button in landscape, rotated to portrait, and the overlay dismissed, the player showed with the accent gradient but not in true fullscreen (website chrome visible around it). Native fullscreen was never entered in Scenario B. A
vtScenarioBPendingflag now tracks this state. When the resize listener detects a portrait rotation while the flag is set, it callsrequestFullscreen()to properly enter native fullscreen, then clears the flag. The flag is also cleared on Exit Fullscreen button press (Scenario B-1).
- New: Landscape fullscreen overlay added. When the player is in fullscreen and the device rotates to landscape, a blocking overlay appears with a rotate-back prompt and an Exit Fullscreen button. Rotating back to portrait automatically dismisses the overlay. When the fullscreen button is pressed while already in landscape, the overlay appears instead of entering fullscreen. The native fullscreen state is only exited if the user explicitly presses Exit Fullscreen.
- New: BPM sort filter now has two directions — BPM ↑ (slow to fast) and BPM ↓ (fast to slow). Group order in the playlist panel reverses accordingly. Both directions are reflected in play order via
buildPlayOrder(). - New: BPM badge colours now use a continuous rainbow gradient derived from the actual BPM value. 70 BPM and under renders blue (hue 220). 71–200 BPM interpolates across the full rainbow (blue → cyan → green → yellow → orange → red). Over 200 BPM renders purple (hue 270). Colour is applied inline via
applyBpmBadgeStyle()— the three static CSS classes (bpm-slow,bpm-medium,bpm-fast) are removed.
- Fixed: Track play order (Next/Prev buttons, swipe, keyboard arrows, auto-advance on end) previously followed DB insertion order regardless of the active sort filter. A
playOrderarray is now maintained — an ordered list of track indices matching the active sort mode — rebuilt on init and whenever the sort filter changes. Next and Prev navigate throughplayOrder, so play order always matches what the user sees in the track list. - Fixed: Shuffle now picks randomly from
playOrderrather than the raw track count, correctly acting as an override to the sort order rather than ignoring it.
FRIDAY THE 15TH OF MAY
- Fixed: Audio visualiser bars had a hardcoded cyan/teal bottom gradient stop (
rgba(0,210,255,0.3)) regardless of the track accent colour. The bottom stop now derives fromcurrentThemeHex— parsed to RGB, reduced to 25% brightness, at 0.4 opacity — giving a dark shade of the accent colour instead.
- Fixed: Browse Libraries and Artist Profiles quick-action cards on the Overview page were showing empty icon boxes.
fa-list-musicandfa-user-musicare Font Awesome Pro icons not available in the free CDN. Replaced withfa-layer-groupandfa-userrespectively.
- New: Overview page now shows Most Played and Most Liked track rankings — top 10 each, side by side. Each entry shows position number, album art thumbnail, track title, artist, library name (as a pill label), and the play or like count. Tracks with zero plays or likes are excluded. Empty state shown if no data exists yet.
- CSS: New ranking panel styles added to
admin.css. Rankings collapse to a single column below 900px.
- New: Overview page added as the Vitreous plugin landing page. Shows live counts for libraries, tracks, and artist profiles. Quick-action cards link directly to Add a Library, Browse Libraries, Artist Profiles, Settings, and Changelog. Includes a Ko-fi support button at the bottom.
- Structure: Top-level Vitreous menu item now opens the Overview page. Libraries list moved to its own submenu entry (
vitreous-library-list). All internal back-links and delete redirects updated accordingly. No DB changes.
THURSDAY THE 14TH OF MAY
- Fixed: After saving a track, the sidebar item in Column A did not update its art thumbnail, artist meta line, or duration — requiring a full page refresh to see the correct data. Both
wp_send_json_successcalls inajax_save_track()now returnart,artist, andtotal_timealongsidetrack_idandtitle, matching what the JS sidebar update handler expects.
- Rebuild: Library Edit and Artist Profiles backend layout rebuilt to match the Standalone Tracklist Builder. Column A (track/artist list) now fills the majority of the screen width; Column B (edit form) is a fixed 400px panel on the right. Grid changed from
240px 1frtocalc(100% - 400px) 400pxinadmin.css. - Rebuild: Track sidebar items in Column A now display a number badge, art thumbnail, title, artist meta line, and duration. DB query in
library-edit.phpupdated to includeartist,art, andtotal_time. New CSS classes added:.vt-track-sidebar-num,.vt-track-sidebar-art,.vt-track-sidebar-info,.vt-track-sidebar-meta,.vt-track-sidebar-duration. - Rebuild: Artist sidebar items in Column A now display the artist image thumbnail and name. DB query in
artist-profile-page.phpupdated to includeimage_url. - Rebuild: Track edit form in Column B (
track-row.php) converted fromform-tabletwo-column layout to single-column builder form with labelled sections and paired field rows. All fieldnameattributes,data-indexvalues, and JS hook classes preserved unchanged. - Rebuild: Artist edit form in Column B (
artist-profile-page.php) converted to builder form sections — Artist Image, Artist Details, Social Media. All element IDs preserved unchanged. - Fix: Dynamic track and artist item creation in
admin.jsupdated to match new enriched sidebar HTML.vtSortSidebarnow renumbers.vt-track-sidebar-numbadges after every sort and delete. - Fix: Two
.closest('.vt-track-fields')calls in the WP Media Library audio picker updated to.closest('.vt-tab-panel')to remain functional after removal of.vt-track-fieldswrapper. - CSS: Responsive collapse breakpoint for
.vt-track-editor-layoutmoved from 900px to 700px to preserve the two-panel layout at typical admin widths.
WEDNESDAY THE 13TH OF MAY
- Redesign: All backend page headers (
.vitreous-page-head) redesigned to match the Tracklist Builder top bar — sticky, dark glass background with gold gradient, backdrop blur, border and shadow. Applied across all admin pages viaadmin.css. - Redesign: Changelog page header updated to match the new page header style.
- Redesign: Vitreous logo updated to white SVG (
vitreous-logo-white.svg) across all admin pages — correct for dark header backgrounds. - Redesign: Library name in
library-edit.phprestyled as a prominent inline editable heading — large uppercase text with underline input replacing the standard form row. - Layout: Audio File URL and Album Art URL fields moved to a full-width section above the two-column track edit grid in
track-row.php.
- Fixed: Sidebar bleeding on mobile — `.vamp-sidebar`, `.vamp-sidebar-right` and `#dna-recon-sidebar` width and hidden position constraints now applied at 768px covering all phones and tablets, including the Honor 90 on Vivaldi and Opera GX.
- Fixed: Fullscreen track/artist sidebar (`#fullscreen-metadata-sidebar .vamp-sidebar-content`) could not be scrolled by touch on mobile. Touch scrolling restored within the 768px breakpoint.
TUESDAY THE 12TH OF MAY
- Layout: Desktop and mobile player layouts are now fully separated via
@media— no shared sizing rules between the two. - Desktop (
min-width: 521px):transform: scale()removed. All internal elements sized to 80% of previous coded values matching the previous scale(0.8) visual. Player width400px. Player Scale setting removed from backend. - Mobile (
max-width: 520px): Player fills viewport width. All internal elements useclamp()for fluid sizing. Both sidebars constrained tocalc(100vw - 40px). Player wrapper padding reduced to8px.
- Fixed:
vtUpdateFormatIndicatorexposed globally viawindow.vtUpdateFormatIndicatorso it is accessible from the WordPress Media Library integration block outside the main IIFE.
- Fixed: Auto-fill of track title and duration when selecting audio from WP Media Library. JS was traversing to
.track-rowwhich does not exist — corrected to.vt-track-fields. Removed reference to non-existent.track-title-displayclass. - Fixed: Duration fallback path now correctly handles tracks over 60 minutes, outputting
H:MM:SSformat instead ofMMM:SS. - Fixed: Main player current time counter now shows
H:MM:SSfor tracks over 60 minutes. SharedvtFormatTime()function used across all three time display points. - Fixed: Minified player (Track List, Artist Card, Artist List) current time counter now shows
H:MM:SSfor tracks over 60 minutes via updatedvtListFormatTime(). - New: Duration field in track edit now has a
?help button opening a modal listing accepted duration formats (M:SS, MM:SS, H:MM:SS, HH:MM:SS).
SATURDAY THE 9TH OF MAY
- Fixed: Artist List search and pagination typography not applying on frontend. Both elements moved inside
.vt-artist-list-rootso they are children of the ID-scoped root element, matching the existing typography scoping pattern used by all other Artist List elements.
- DB: 18 new columns on
vitreous_display_options—alist_search_*andalist_pagination_*(9 typography properties each). Added safely viaSHOW COLUMNSguard inmaybe_upgrade_schema(). - New: Artist List Display Options now includes Search Input and Pagination typography areas, matching the Track List accordion.
- Fixed: Track List and Artist List search and pagination now consistently themed. CSS variables and
data-thememoved from the inner root element to the outer wrapper in both shortcodes, so search and pagination correctly inherit glassmorphic styling and accent colours from Display Options.
- Fixed: Artist List search and pagination now correctly inherit theme CSS variables.
data-themeand inline CSS vars moved from.vt-artist-list-rootto.vt-artist-list-wrapperso all child elements including search and pagination receive them. - Fixed: Artist List search and pagination CSS rewritten to mirror the Track List accordion pattern exactly — same sizing, same variable usage, same hover/active states.
TUESDAY THE 5TH OF MAY
- New: Artist List — fuzzy search input filters artists by name in real time. Pagination at 10 artists per page with Previous/Next and page number controls.
- Fixed: Elementor Artist List widget — Show All toggle now correctly reveals a multi-select artist picker when toggled off. Selected artist IDs are passed to the shortcode as
id="1,2,3". - Fixed: Gutenberg Artist List block — Show All toggle now reveals per-artist toggle controls. Selected artists stored as
artistIdsattribute and passed to the shortcode.vitreousArtistsnow localised to the artist list block script.
- Fixed: Last Modified column now displays the raw stored date and time (DD/MM/YYYY HH:MM) with no time-ago calculation. Removes timezone offset issues that varied by server and user location.
- Fixed: Last Modified time-ago was offset by the server timezone. Now uses WordPress’s configured GMT offset for date display and
current_time('timestamp')for time-ago comparison — correct for any server location worldwide.
- Fixed: Last Modified on the library list was showing the creation date instead of the actual modification date. The
updated_atcolumn onvitreous_librarieswas missingON UPDATE CURRENT_TIMESTAMPon existing installs due to a dbDelta limitation. Fixed via aSHOW COLUMNSguard inmaybe_upgrade_schema()that runs a targetedALTER TABLE MODIFY COLUMNon affected installs only.
- Fixed: Library list query filter removed — phantom entries can no longer be created since the pre-insert was removed in v8.1.4. Any existing phantom entries are visible and deleteable via the standard Delete button.
- Fixed: Add New Library — blank page after saving.
wp_redirectwas failing silently as headers were already sent. Replaced with JavaScript redirect. - Fixed: Library list now hides phantom (empty-titled) libraries from the list query.
- Fixed: Last Modified column now shows UK date/time (DD/MM/YYYY HH:MM) with time-ago below in muted text.
- Fixed: Vitreous Artist List Gutenberg block error —
SelectControlwas missing from component destructuring. - Fixed: About sidebar version was hardcoded at v4.4.0. Now reads dynamically from
vitreousSettings.pluginVersion.
SUNDAY THE 3RD OF MAY
- Fixed: Year sort now sorts by full release date, not just year. Tracks within the same year are ordered by their complete parsed date, then A-Z by title as a tiebreaker.
- New:
vtParseReleaseDate()— full date parser supporting ISO, DD/MM/YYYY, DD-MM-YYYY, ordinal long form (30th April 2026), plain long form (30 April 2026), named month US order (April 30, 2026), month and year only (April 2026), and year only. US numeric MM/DD/YYYY is intentionally excluded. UK regional DD/MM assumed for ambiguous numeric formats. - New: Release Date field in track edit now has a help button () that opens a modal listing all accepted date formats. Modal closes via X button, Close button, overlay click, or Escape key.
- Fixed: Recently Played tab was inheriting admin backend styles, showing a gold border and gold text instead of matching the player frontend theme. Tab now uses
var(--player-accent)— identical to the TRACKS tab — so it responds to per-track colour changes and global player colour settings. Inactive tab renders at 0.4 opacity; active tab at full opacity.
SATURDAY THE 2ND OF MAY
- New: Recently Played tab added to the Media Recon sidebar to the right of TRACKS. Shows the 10 most recently played unique tracks for the current library, ordered by most recent play time. Deduplicated via
GROUP BY id— each track appears once at its most recent play time. - New: Clicking a Recently Played track row selects it in the main player.
- New: 300-second auto-refresh poll fires while the Recently Played tab is open. Poll is cleared when switching back to TRACKS or closing the Media Recon sidebar.
- New:
vitreous_get_recently_playedAJAX endpoint — acceptslibrary_id, returns 10 deduplicated recently played tracks.
- DB: Two new columns on
vitreous_display_options—card_social_icon_font_sizeandalist_social_icon_font_size. Added safely viaSHOW COLUMNSguard inmaybe_upgrade_schema(). - New: Social Media Icons accordion area added to the end of the Typography section in Artist Card and Artist List Display Options panels. Contains a single icon size slider (8–48px) with a synced text input.
- New: Live preview shows a sample Instagram icon in the Artist Card and Artist List preview sections. Icon size updates in real time as the slider is adjusted.
- New: Saved icon size applied to all social link elements on the frontend via inline style.
- Fixed: Media Recon like count spacing not applying on mobile —
.track-favorite-btnnow usesdisplay: flex; align-items: centerso themargin-lefton the count span works correctly in both desktop and mobile contexts.
- Fixed: Media Recon like count spacing —
margin-leftincreased from 3px to 8px to give clear separation between the heart icon and the count number.
- Fixed: Tracklist utility row — global like count moved to between the heart button and the download icon. Order is now: heart | like count | download | play count.
- Fixed: Artist Card and Artist List random track players were not incrementing global play counts. The track DB
idwas selected in the query but never rendered onto the.vt-list-item-playerdiv asdata-track-id, so the play count AJAX call had no track ID to send. Attribute added.
- Fixed: Heart icon state not syncing between main player and tracklist widget on toggle. Added shared
window.vtUpdateAllHeartState(trackDbId, trackIdx, isFavourited)function updating Media Recon heart button, fullscreen heart button, and tracklist heart button simultaneously. Addeddata-track-indexto Media Recon heart button so it can be found by the shared function.
- Fixed: Like count not syncing between main player and tracklist widget on toggle. A shared
window.vtUpdateAllLikeCounts(trackDbId, trackIdx, count)function is now defined by the main player and called by both the main player and tracklist widget on every toggle and poll response — updating Media Recon, fullscreen sidebar, and tracklist utility row simultaneously. Fallback handles tracklist-only pages where the main player is absent.
- Fixed: Main player regression —
trackswas used instead of the correcttrackDatavariable in both thetoggleFavoritehandler and the 60-second poll, causing aReferenceErrorthat prevented the player from initialising.
- Fixed: Media Recon and fullscreen sidebar like count not updating on toggle — the
tracksarray was not updated beforeupdatePlaylistUIrebuilt the DOM, causing the AJAX response to target a replaced element. Count now updates thetracksarray first so subsequent UI rebuilds render the correct value. - Fixed: Redundant heart icon removed from the tracklist utility row global likes span — the like button already has its own heart icon.
- New:
vitreous_get_track_countsAJAX endpoint returning global like and play counts for multiple track IDs in a single request. - New: 60-second poll in both the main player and tracklist widget refreshing global like counts from the server. All visible count displays update in sync.
- DB: New
global_favourite_countcolumn onvitreous_tracks. 18 new typography columns onvitreous_display_optionsfor Global Likes and Global Plays text areas. Both added safely viaSHOW COLUMNSguards inmaybe_upgrade_schema(). - New: Global like count — clicking the heart/favourite toggle increments or decrements the global like count via AJAX. Decrement floors at 0. Count updates immediately on the page without reload.
- New: Media Recon — global like count displayed to the right of the heart icon per track row.
- New: Fullscreen sidebar — global like count displayed below the Favourite button label.
- New: Accordion track list utility row — global like count (heart icon + number) shown to the left of the global play count. Updates immediately on toggle.
- New: Display Options — Global Likes and Global Plays are now separate typography areas in the Track List section.
- Fixed: Artist Card and Artist List Elementor widgets now have a Display Options Library dropdown. The selected library ID is passed to the shortcode so Display Options are correctly applied on the frontend.
- Fixed: Artist Card and Artist List Gutenberg blocks now have a Display Options Library selector in the block inspector. The selected library ID is stored as a block attribute, passed to the render callback, and included in the shortcode call.
vitreousLibrariesnow localised to both artist block scripts.
- Fixed: Live preview now updates in real time on every control change — colour pickers, hex inputs, sliders, text inputs, selects, and glass mode toggle all call the preview update immediately. Select elements now correctly use the
changeevent. This was missing from the initial build. - Updated: Font Size control replaced with a slider (8–72px) synced with a text input. Dragging the slider updates the text input. Typing in the text input updates the slider. Value saved and applied as px.
- Fixed: All admin CSS and JS enqueue version strings updated to match the plugin version — previously left at old values causing WordPress to serve cached files and preventing updated styles from loading.
- New: Font Family control replaced with searchable font picker matching Stratum’s implementation — fuzzy search across System Fonts and Google Fonts, selected font rendered in its own typeface, Google Fonts injected dynamically on selection.
- Fixed: Display Options sidebar inputs and selects were unstyled due to WordPress core overriding plugin CSS. Scoped
!importantoverrides added to#vt-do-sidebarmatching Stratum’s pattern, correctly theming all text inputs, selects, and colour pickers.
- Fixed: Display Options sidebar moved to the correct location — Libraries list page, one trigger button per library row in the actions column alongside Edit and Delete. Sidebar shell rendered once after the page wrap, hidden by default. Follows the Stratum pattern exactly: trigger button carries saved accent/theme values as data attributes, sidebar is populated immediately from those on click, typography loaded via AJAX, saved values written back to trigger button data attributes on save so reopening the same row shows correct values without a fresh fetch.
- Fixed: Display Options button and sidebar completely removed from library edit page.
FRIDAY THE 1ST OF MAY
- DB: New
vitreous_display_optionstable — one row per library,library_idas unique key. 180 scalar columns covering accent colour, glass mode toggle, and 9 typography properties for 19 named text areas across Track List, Artist Card, and Artist List widgets. - New: Display Options button on the library edit page opens a right sidebar with Live Preview, tabbed sections for Track List, Artist Card, and Artist List, each with Colours and Typography sub-sections.
- New: Live Preview shows the first real track from the library. Updating any control updates the preview immediately.
- New: Accent colour picker and hex input synced per section. Glass Mode toggle switches between Light and Dark glassmorphic backgrounds.
- New: Typography controls per named text area — font family, size, colour, weight, style, text transform, text decoration, letter spacing, line height. No alignment.
- New: All three shortcodes read saved Display Options for the library and apply
data-theme, inline CSS variable overrides, and scoped typography styles on the root element. - New: Dark glass mode added to all three widget CSS files —
rgba(0,0,0,0.X)values matching light mode opacity.
- Fixed: Minified players in the accordion track list, artist card, and artist list tracklists were not incrementing the global play count when a track was played. Global play count is now incremented via
vitreous_increment_playAJAX on each play press — matching the main player pattern.vitreousListSettingslocalised to provideajaxUrlto the list script.
- Fixed: Page load performance — audio context and compressor chain now created only on first play press, never on page init. Removed
vtListApplyNormalisationwhich was fetching every audio file on page load. - Updated: Minified player compressor chain now matches main player values — threshold -24dB, knee 30, ratio 12, attack 3ms, release 250ms. Single shared
vtListAudioCtxcontext reused across all minified players. All chain variables prefixedvtListto avoid conflicts with the main player. - Updated: Default volume on all minified players set to 60%.
- New: Fuzzy search input above the accordion track list — filters by title and artist in real time. Resets to page 1 on each keystroke.
- New: Pagination below the accordion track list — fixed 10 tracks per page. Open rows close and playing audio stops on page change. Pagination updates against the filtered set when search is active.
APRIL 2026 BUILDS
TUESDAY THE 28TH OF APRIL
- Fixed: Accordion track list now orders all tracks A-Z by title on the frontend. Previously tracks were ordered by the backend drag order, meaning newly added tracks always appeared at the bottom. Backend drag order in the library editor is unaffected.
MONDAY THE 27TH OF APRIL
- Fixed: Favourite heart icon now switches between outline (
far fa-heart) and solid filled (fas fa-heart) when toggled. Solid state is also restored correctly on page load for previously favourited tracks.
- Fixed: Accordion track list utility row — download icon now renders correctly using the full source type map mirroring
FILE_SOURCESfrom the player. Font Awesome icons render as<i>elements, favicon-based services render as<img>via Google’s favicon service — matching the Media Recon and fullscreen sidebar behaviour exactly.
- Updated: Accordion track list — Download link removed from the track detail area.
- New: Accordion track list — new row added below the track details showing a Favourite heart button and the global play count for that track.
- New: Favourite state is saved to browser local storage and restored on page load.
SUNDAY THE 26TH OF APRIL
- Fixed: Artist Card right column — added
min-width: 0,overflow: hidden, andbox-sizing: border-boxso content respects the grid column boundary at all viewport sizes. Bio text now usesoverflow-wrap: break-wordto prevent long words overflowing. - Fixed: Artist Accordion List body content — added
min-width: 0andoverflow: hiddento the body content flex column so it respects the grid track boundary. Bio word-wrap fixed. Responsive breakpoint widened from600pxto700pxso the two-column grid switches to single column earlier on tablet widths where the fixed 200px image column was causing overflow.
- Fixed: Volume slider in artist card and artist list tracklists reverted to inline flex behaviour — removed absolute positioning overrides. The track item enforces the row boundary via
overflow: hidden. The slider expands inline pushing the track title right, which compresses and clips with ellipsis at the boundary. No other container elements are affected.
- Fixed: Volume slider in artist card and artist list tracklists was causing overflow — pushing track titles, duration text, and artist images outside the container boundary. Replaced the
max-widthtransition withopacityandvisibilitytransitions on the absolutely positioned slider overlay. The slider now fades in and out at a fixed width anchored to the right edge of the row without affecting any other layout elements. - Fixed: Artist tracklist was showing the first 5 alphabetical tracks rather than a random selection. Query now picks 5 random unique titles then sorts them alphabetically for display. Duplicate tracks across libraries are deduplicated by title via
GROUP BY.
- Fixed: Volume slider in artist card and artist list tracklists was expanding inline and pushing track titles, duration, and parent container elements out of bounds. The volume slider wrap is now
position: absoluteanchored to the right edge of the track row. The row usesposition: relative; overflow: hiddento contain the slider within the row boundary. Track title clips with ellipsis when the slider is visible. - Fixed: Artist tracklist was showing duplicate tracks when the same track exists in multiple libraries. Added
GROUP BY titleto deduplicate before selecting. - Fixed: Artist tracklist was showing the first 5 alphabetical tracks rather than a random selection. Now selects 5 random unique tracks then sorts them A-Z for display. Each page load shows a different set.
- New: Artist tracklist added to both Artist Card and Artist Accordion List. Shows up to 5 tracks alphabetically matching the artist name, each with the full minified player (play/pause, progress bar, volume slide-in). Suppressed if no matching tracks found. Play button and progress fill use the correct accent colour from the parent root context via scoped CSS — no
!important. - Updated: Play count display format changed to “You: X plays” and “Global: Y plays” in both Media Recon sidebar and Fullscreen Track Details sidebar.
- Updated: Fullscreen Track Details sidebar now shows both local and global play counts using dedicated fullscreen-scoped CSS — does not inherit Media Recon styling.
SATURDAY THE 25TH OF APRIL
- New: Artist Accordion List — new
[ vitreous_artist_list ]shortcode, Gutenberg block, and Elementor widget. Lists all artist profiles as a glassmorphic accordion. Each collapsed row shows the artist name and social link icons. Expanding a row reveals the 16:9 artist image, bio, year started, and members. Social icons are the only interactive elements and stop accordion toggle propagation. Multi-open — multiple rows can be expanded simultaneously.
- New: Artist Card — new
[ vitreous_artist_card id="1" ]shortcode, Gutenberg block, and Elementor widget. Renders a two-column glassmorphic card for any artist profile. Left column shows the artist image at 16:9 ratio, artist name, and social link icons. Right column shows bio and year started. Social icons are the only interactive elements — each opens in a new tab. Cards with no data for a field suppress that element entirely.
- Fixed: Replaced
!importanton accordion track list image fill rules with.vt-list-root-scoped selectors (.vt-list-root .vt-list-art imgand.vt-list-root .vt-list-body-art img). The increased specificity overrides WordPress and theme global image styles without requiring!important.
- Fixed: Album art images in both the collapsed row thumbnail and expanded body not filling their square containers. WordPress and theme stylesheets apply
max-width: 100%andheight: autoglobally to images which was overriding the fill rules. Added!importantto all critical image fill properties on both.vt-list-art imgand.vt-list-body-art imgto enforce correct fill behaviour regardless of external stylesheet interference.
- Fixed: Removed
loading="lazy"from both album art image elements in the accordion track list. Lazy loading deferred image dimension establishment causing images to not fill their containers correctly and contributing to page load issues on WordPress. All Vitreous image output is eager-loaded.
- Fixed: Collapsed row album art thumbnail was flush to the top of its container and not filling the square. The fixed
height: 48pxon.vt-list-artwas being overridden by the flex parent causing the container to collapse, leaving the absolutely positioned image anchored totop: 0with no height to fill. Replaced withaspect-ratio: 1 / 1matching the main player pattern — the square is now enforced independently of the flex context.
- Fixed: Album art in both the collapsed row thumbnail and the expanded body was not correctly filling its 1:1 square container for landscape or portrait source images. Both containers now use
position: relativewith the image set toposition: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; object-position: center— matching the main Vitreous player pattern exactly. The expanded body art additionally usesaspect-ratio: 1 / 1withalign-self: startreplacing the previous fixed height, eliminating the empty space below the image when the field grid is taller than the art container.
- Fixed: Volume slider in the accordion track list replaced the popup pattern with an inline slide-in on the same row as the player controls. The slider slides in horizontally from beside the volume icon using a CSS
max-widthtransition. Hovering the volume icon or clicking it reveals the slider for 10 seconds. Any adjustment to the slider resets the timer to 5 seconds from the last interaction. The slider auto-hides after the timer expires. Hovering or clicking the icon again re-shows it for another 10 seconds.
- Fixed: Volume slider popup in the accordion track list was clipped at the top edge of the row. Root cause was
overflow: hiddenon.vt-list-itemwhich prevented the absolutely positioned slider from escaping the item boundary. Removedoverflow: hiddenfrom the item and redistributed border-radius clipping to the row (full radius when collapsed, top corners only when open) and the expanded body (bottom corners only), preserving the glassmorphic corner rounding without clipping the volume popup.
- New: Accordion Track List — new
[ vitreous_list id="1" ]shortcode, Gutenberg block, and Elementor widget. Renders a glassmorphic accordion list for any library. Each collapsed row shows the 1:1 album art thumbnail, track title, artist name, and a minified player. Multi-open — multiple rows can be expanded simultaneously. - New: Minified player — each row has its own independent audio element with a progress bar (seekable), play/pause button, and volume control. Volume icon acts as mute/unmute on click and reveals a slider on hover. Playback is restricted to one track at a time across all rows — pressing play on a new row stops the current one.
- New: Volume normalisation — each minified player applies a Web Audio API gain/compressor chain to normalise playback level. If the audio source is on an external CDN without CORS headers, the normalisation falls back gracefully and the track plays without adjustment.
- New: Expanded accordion body — all non-empty track fields are displayed in a responsive grid alongside a larger 1:1 album art image. Empty fields and the internal colour value are suppressed. Inspiration and Credits render full-width. Download link rendered if a file source URL is present.
- DB: Two new columns added to
vitreous_tracksviamaybe_upgrade_schema()withSHOW COLUMNSexistence checks —global_play_count INT(11) DEFAULT 0andlast_played_at DATETIME DEFAULT NULL. Both are added safely on first admin load for existing installs. Fresh installs receive the columns via the existingCREATE TABLEdefinition. - New: Global play count — every time a track is played on the frontend, a fire-and-forget
fetchPOST incrementsglobal_play_countand setslast_played_atserver-side. The handler is registered as bothwp_ajax_*andwp_ajax_nopriv_*to support all visitors regardless of login state. No nonce required — mirrors the existing localStorage play count behaviour exactly. - New: Media Recon play count display updated to show two lines per track — “X plays (you)” from localStorage and “Y plays (all)” from the server-side global count. The in-memory
globalPlayCountvalue is updated immediately on each play so the Media Recon reflects the increment without a page reload. - Note:
last_played_atis stored but not yet displayed. It will be used for a “Recently Played” tab in a future build.
- Fixed: Audio format warning moved from save callback to a real-time indicator displayed directly below the Audio File URL field and media library button. The indicator updates immediately as the URL is typed or pasted, and when a file is selected via the media library picker. A green badge confirms good browser support (MP3, etc.), an amber badge warns of reduced support (OGG, OPUS, FLAC, WAV, M4A, AAC), and a red badge flags poor support (AIFF). Existing tracks display the correct badge on page load.
- Fixed: Removed format warning from the track save response — it was in the wrong place and never displayed correctly.
FRIDAY THE 24TH OF APRIL
- New: Track Import — replaces the disabled CSV import placeholder. Accepts a Vitreous
.jsonexport file containing an array of track objects. Thetitlefield is required; all others are optional. Tracks are appended to the library without removing existing ones. A result notice confirms how many tracks were imported and how many entries were skipped. Uses the WordPressadmin-post.phpform pattern for reliable file upload handling. - New: Track Export — exports all tracks in the current library as a
.jsonfile. The exported file uses the same field names as the import schema and round-trips cleanly into any Vitreous library. Uses the WordPressadmin-post.phpform pattern for reliable file download handling — no JavaScript required. - New: Format warning on track save. If the Audio File URL uses a format with reduced browser support (OGG, OPUS, FLAC, WAV, M4A, AAC, AIFF), a warning is displayed in the save status bar alongside the confirmation, persisting for six seconds.
- New: Format warning on JSON import. If any imported track’s
srcURL uses a reduced-support format, the import result notice includes a format notice listing the affected formats.
- Fixed: Copy button in the Share sidebar was non-functional. The
copyToClipboard()function was called but never defined, causing a silent ReferenceError on every click attempt. The function is now implemented usingnavigator.clipboard.writeText()on HTTPS contexts, with adocument.execCommand('copy')fallback for non-secure or older browser environments. On success, a “Link copied!” confirmation fades in below the input for two seconds. On failure, an instruction to use Ctrl+C is shown instead. - Fixed: Right-click context menu did not offer a copy option when manually highlighting the share link. Clicking the share link input field now automatically selects all text, ensuring both right-click copy and Ctrl+C work without requiring manual drag-selection.
- Fixed: Share link now encodes the track’s stable database ID (
track.id) rather than its current array index. Previously,?track=used the sorted array position which could change as tracks were added or reordered, causing shared links to land on the wrong track. The parameter now always resolves to the correct track regardless of library changes. - Fixed: Share links are now consumed on page load. A new deep-link handler reads the
?track=URL parameter, finds the matching track by database ID, and sets it as the initial track before the player loads. If a&t=timestamp parameter is also present, the player seeks to that position once the audio is ready. Deep-link resolution takes priority over the Remember Track setting. - Fixed: Frontend play order — each track in
trackDatais now stamped with its pre-sort injection index (_injectionIdx) before the year-descending sort is applied. This ensures positional operations (track selection, navigation) and identity operations (play counts, favourites, share ID) remain consistent regardless of how many tracks are added to the library or in what order.
SUNDAY THE 19TH OF APRIL
- Versioning correction: This release corrects a versioning error introduced at v4.6.0. Under ARV, any DB change (new table, new column, migration, or rebuild) constitutes a Major version bump as all DB changes carry plugin-breaking potential. The Artist Profiles feature shipped at v4.6.0 introduced a new
vitreous_artistsDB table and migrated existing data — this was always a Major change and should have been v5.0.0 at the time. Versions v4.6.0 through v4.6.10 are therefore misnumbered. This was an AI assistant classification error, not an ARV rule change. All versioning from v5.0.0 forward follows the correct rule strictly. - Fixed: Animation Speed dropdown showed a blank selection on load. The Normal option had
value="1.0"but JavaScript sets.value = 1(float-to-string converts1.0to"1"), so no option matched and the dropdown appeared empty. Option value corrected to"1". JS default corrected to match. Normal option relabelled Normal (Default) for clarity.
- Fixed: Animation Speed control replaced. The range slider visually rendered at the leftmost (Slow) position regardless of the actual value due to layout constraints inside the settings sidebar. Replaced with a three-option dropdown — Slow (0.5), Normal (1.0), Fast (2.0) — matching the three bands already used by
getAnimationSpeedLabel(). Default remains Normal (1.0). Event listener updated frominputtochange.
- Fixed: Changelog card gap not rendering. Cards sit directly inside
#vt-cl-entries— the.vitreous-changelog-listwrapper class and itsgaprule were never applied. Fixed by applyingdisplay:flex; flex-direction:column; gap:32px; margin-top:24pxdirectly to#vt-cl-entries.
- Fixed: Admin background colour corrected from
#1a1a2eto#0f172aacross all Vitreous admin pages, matching Criterium and Stratum. Both--vt-bgand--vt-admin-bgtokens updated.--vt-surfaceupdated fromrgba(20,24,48,0.95)torgba(20,30,50,0.95)to match. - Updated: Changelog page redesigned to match Criterium layout. Outer wrapper changed to WordPress standard
wrapclass for full-width rendering — the previousmax-width:860pxconstraint has been removed. Page head replaced with logo + title pattern matching Criterium. All changelog card heads now include a version-row with a colour-coded type badge (Patch/Minor/Major) and a date aligned to the right, matching Criterium exactly. New CSS rules added for.vitreous-changelog-wrap,.vitreous-changelog-head,.vitreous-changelog-logo,.vitreous-changelog-title,.vitreous-changelog-version-row,.vitreous-changelog-type, and.vitreous-changelog-date.
- Fixed: Frontend player regression persisting from v4.6.5 and v4.6.6. The
nonewaveform handler was inserted with three closing braces before it (}}}) instead of two (}}), closingdrawWave()prematurely and leaving theelse if(none)block outside the function entirely. Corrected to}}else if(style==='none'){...}}— the minimal for-loop and if-block close with two braces, the none handler follows inside the function, then one final brace closesdrawWave().
- Fixed: Frontend player regression introduced in v4.6.5. The
nonewaveform handler was inserted afterdrawWave()‘s closing brace rather than inside it, producing a syntax error that broke the entire player JS. The extra closing brace has been removed and thenonehandler correctly placed as the finalelse ifbranch insidedrawWave().
- Added: Waveform Style now includes a None option across all three surfaces — the in-player Settings dropdown, the global Waveform Style setting in the admin, and the per-track override in the track editor. When None is selected,
drawWave()clears bothwaveform-canvas-bgandwaveform-canvas-fgwithout drawing anything. The visualiser layer (waveform-canvas-vis) and progress mask continue to operate normally.
- Fixed: Waveform style options (Bars, Line Wave, Mirrored Bars, Minimal) now update in real time when selected from the in-player Settings sidebar, including during playback. The guard in
drawWave()that prevented it from running while the visualiser was active has been removed. That guard existed to prevent both functions drawing to the same canvas — sincedrawVisualizer()now draws to the dedicatedwaveform-canvas-vislayer (v4.6.3), the conflict no longer exists anddrawWave()can always run freely.
- Fixed: Waveform layer system restored to correct four-layer architecture. A dedicated
waveform-canvas-viscanvas (z-index 2) has been added betweenwaveform-canvas-bg(z-index 1) andwaveform-canvas-fg(z-index 3).drawVisualizer()now draws tovisinstead offg, meaning the live frequency visualiser and the static waveform are fully independent layers. Bothvisandfgare revealed by the playhead clip-path ontimeupdateand reset to fully hidden on track load.visis cleared on stop/pause.waveform-canvas-fgz-index corrected from 2 to 3. Global accent colour applies tovis,fg, andwave-progress-mask.bgremains fixed transparent light grey.
SATURDAY THE 18TH OF APRIL
- Fixed: Play counts now keyed by database track ID instead of array index position. Previously, adding or reordering tracks caused index positions to shift, assigning existing play counts to different tracks. New tracks inherited counts from whichever track previously occupied their index. Play counts are now stored as
{trackDbId: count}in localStorage — the DB ID is stable regardless of sort order, additions, or deletions. Existing localStorage data keyed by index becomes orphaned and ignored; counts start fresh from zero for all tracks after this update.
- Fixed: Mobile layout and Player Max Width restored. The outer
player-wrapperdiv was incorrectly removed fromplayer-template.phpin v4.3.5 under the assumption it was a duplicate. It was not — the JS usesgetElementById('dynamic-bg')to target the outer wrapper specifically for background, border-radius, and viewport-width context. Without it, mobile layout was broken and all CSS variable-based settings (scale, max-width) failed to cascade correctly. Reinstated exactly as it existed in v4.3.4.
- Major: Artist Profile (singular) replaced with Artist Profiles — supports any number of artist profiles. New dedicated database table
vitreous_artistswith individual columns for all profile fields and 15 social platform URLs. - Added: Artist Profiles admin page — two-panel layout identical to Library Edit. Left panel: scrollable alphabetical artist list. Right panel: full artist editing form (image, name, members, bio, year started, 15 social URLs). Save, load, and delete all via AJAX. Auto-alphabetises on save. Unsaved changes protection with Save Now / Discard modal.
- Added: AJAX handlers —
vitreous_save_artist,vitreous_load_artist,vitreous_delete_artist. - Migration: On first load after update, any existing single artist profile stored as WordPress options is automatically migrated to the new
vitreous_artiststable. Legacy options are deleted after migration. No data is lost. - Updated: Frontend player —
vitreousSettings.artistProfile(single object) replaced withvitreousSettings.artistProfiles(array). Profile matching logic updated to find the correct profile from the array by exact artist name match. Multiple tracks by different artists on the same page each show their own profile.
WEDNESDAY THE 15TH OF APRIL
- Fixed: Save Track button moved out of the scrolling editor area into a persistent full-width footer bar that spans the full width of both the track list and track edit panels. The button is now always visible without needing to scroll. The footer appears when a track is loaded or a new track is created, and hides when the editor resets to the placeholder state.
- Fixed: Library Details — title input and Save Title button now sit on one row. The containing element was constrained to 240px by the
vitreous-field--smclass, causing the button to wrap below. - Fixed: Track sidebar and track editor area now use
calc(100vh - 320px)instead of a fixed 640px height, scaling responsively to the actual viewport. - Added: Gold scrollbars on the track sidebar and track editor area via
::-webkit-scrollbar. Firefox receives partial theming viascrollbar-color. Scrollbar thumb is gold at 35% opacity, brightening on hover. - Reordered: Track Info fields reorganised by likely input priority. Left column: Title, Artist, Album, Mix Version, Genre, Tempo, Production Method, Theme Colour. Right column: Audio File URL, Album Art URL, File Source, Duration, Release Date, Copyright Year, License, Key Signature, Mood, Inspiration, Credits.
- Rebuilt: Library Edit page — replaced the accordion track row layout with a two-panel architecture. Left panel: scrollable alphabetical track list. Right panel: single track editing area loaded on demand. Only one set of form fields exists in the DOM at any time, resolving performance degradation with 10+ track libraries.
- Added: Per-track AJAX save — each track saves individually to the database via AJAX. The previous bulk delete-then-reinsert approach is retired. New tracks are inserted on first save; existing tracks update in place using their database ID.
- Added: AJAX handlers —
vitreous_save_track,vitreous_load_track,vitreous_delete_track— covering insert, update, load for editing, and hard delete. - Added: Auto-alphabetisation — the track sidebar list sorts A-Z automatically whenever a track is saved or its title is updated. No manual ordering needed.
- Added: Unsaved changes protection — dirty flag system matching the Criterium pattern. If a track has unsaved changes when the user clicks away to another track, a modal fires with Save Now or Discard options.
- Disabled: CSV Import — panel is present but marked unavailable. The import schema does not cover all 26 track fields and will be reworked before re-enabling.
SUNDAY THE 12TH OF APRIL
- Fixed: Icon size mismatch on Artist Profile social media list and Settings share platform tiles. FontAwesome icons were inheriting small font sizes from their parent containers (10px and 11px respectively) while the Bluesky SimpleIcons image was rendering at its explicit pixel size. Fixed by adding explicit
font-size:16pxto FA icons on the Artist Profile page andfont-size:20pxon the Settings tile icons, matching the Bluesky image dimensions in both locations.
- Fixed: Preview audio button in the track editor was still rendering green. Should have been changed to gold ghost style alongside all other track row buttons in v4.4.2.
- Fixed: Bluesky icon definitively resolved for Artist Profile and Settings share platforms. Replaced
fa-brands fa-bluesky(FontAwesome dependency) with a SimpleIcons CDN image (cdn.simpleicons.org/bluesky/c4a75d) — an SVG served directly as an<img>tag, gold-coloured to match the admin theme. No FontAwesome required. A newsimpleiconicon type has been added to both admin pages’ icon rendering logic, mirroring the existingfaviconpattern.
- Fixed: Bluesky icon still missing from admin pages (Artist Profile, Settings share platforms) after v4.4.2. Root cause:
elementor-font-awesomeis registered by Elementor on all admin pages but not on frontend pages — which is why the frontend player showed Bluesky correctly while the admin did not. This handle was in the skip list, causing the CDN fallback to never fire in the admin. Removed from the skip list. Only four genuine FA Free handles remain:font-awesome,font-awesome-5-all,font-awesome-official,fontawesome.
- Fixed: Bluesky icon missing from Artist Profile socials and Settings share platforms. Root cause: three Elementor icon handles were incorrectly added to the FontAwesome skip list during the v4.4.0 rebuild. Because Elementor registers those handles on every admin page, Vitreous was bailing out before loading its own FA 6.6.0 from CDN. The skip list has been restored to the original five handles from v4.3.4.
- Fixed: Track row media buttons (Select audio, Select image, Select from Media Library, Copy Audio URL, Add Track Below) were rendering with WordPress default white styling. All now use the admin gold ghost button style matching the rest of the backend.
- Fixed: About section in Changelog page was showing version 4.3.10 — updated to current.
- Removed: Dead
.vt-cl-btnand.vt-cl-page-labelCSS from the Changelog page inline style block — these classes were replaced in v4.4.0 and the rules were never removed.
- Added: Light/dark theme toggle — crescent moon button (☾) in the page header on all admin pages except Changelog. Defaults to dark. Preference persisted to
localStorageasvitreous-admin-theme, matching the Criterium pattern exactly. - Added: Light theme CSS —
body.vitreous-admin-page.vitreous-lighttoken block overrides all surface, background, text, input, and danger tokens for the light variant. Light-mode overrides added for changelog item text, diagnostics result text colours, modal background, and track card backgrounds. - Removed: Admin Appearance settings section — background colour picker, custom colour picker, and glass intensity selector all removed from Settings. The admin background is now fixed to
#1a1a2e(dark) or#f0f0f0(light) controlled by the toggle. Glass intensity hardcoded to bold defaults inadmin.css :root. - Removed:
inject_admin_appearance_css()PHP method and itsadmin_headhook — no longer needed now that all CSS variables are static inadmin.css. - Removed:
vitreous_admin_bg_preset,vitreous_admin_bg_custom, andvitreous_admin_glass_intensityWordPress options — save and load logic both removed fromsettings-page.php.
- Major: Full admin backend rebuild — architecture brought in line with Criterium plugin. All admin pages now use custom
vitreous-*component classes instead of WordPress native classes (.wp-list-table,.button,.notice,.form-tableetc.), eliminating all CSS specificity conflicts with WordPress core styles. - Added:
admin_body_classfilter — injectsbody.vitreous-admin-pageon all Vitreous admin screens. Background override CSS now scoped to this class (Criterium/Stratum pattern), preventing any bleed to other admin pages. - Added: Full custom component set —
vitreous-btn(primary, ghost, danger, sm),vitreous-table,vitreous-notice(success, error, warning),vitreous-label,vitreous-field,vitreous-field-hint,vitreous-panel,vitreous-section,vitreous-page-head,vitreous-toolbar,vitreous-actions,vitreous-empty,vitreous-tabs,vitreous-modal,vitreous-diag-resultvariants,vitreous-changelog-card. - Fixed: Font rendering — every component class now carries an explicit
font-family: var(--vt-font-head)orvar(--vt-font-body)declaration. Font inheritance no longer relies on the cascade, so WordPress core styles cannot override it. - Updated: Admin accent colour changed from cyan
#00d2ffto gold#c4a75dthroughout the admin backend, matching Criterium and Stratum design language. Player frontend accent remains cyan. - Updated: Admin CSS rebuilt from 682 lines to 1,078 lines — matching Criterium’s full component coverage.
- Updated: Font tokens renamed to
--vt-font-head(Geologica 600) and--vt-font-body(Asap) — consistent with planned Criterium/Stratum font migration. - Updated:
inject_admin_appearance_cssnow outputs only dynamic CSS variables (background, glass intensity). Background scoping moved toadmin.cssunderbody.vitreous-admin-page. - Restored:
wp_enqueue_style('vitreous-admin-fonts')with correctnullversion parameter — Elementor loads Asap and Geologica globally in this installation, so the fonts are available. - Fixed: Glassmorphic confirm dialogs — all
window.confirm()calls replaced with thevitreous-confirm-deletemodal system (matching Criterium). Library delete links and orphan purge button both use the new modal. - Fixed: CSV import messages updated from
notice notice-*WP classes tovitreous-noticeclasses. - Fixed: Track number badges no longer display a
#prefix — numbers only, matching the gold badge design. - Rebuilt:
libraries-list.php,library-edit.php,settings-page.php,artist-profile-page.php,database-viewer.php,changelog-page.php— all HTML updated to use new component classes throughout.
Share it, so others know...
- Share on Bluesky (Opens in new window) Bluesky
- Share on Mastodon (Opens in new window) Mastodon
- Email a link to a friend (Opens in new window) Email
- Print (Opens in new window) Print
- More
- Share on X (Opens in new window) X
- Share on WhatsApp (Opens in new window) WhatsApp
- Share on Reddit (Opens in new window) Reddit
- Share on Pinterest (Opens in new window) Pinterest
- Share on Threads (Opens in new window) Threads
- Share on Tumblr (Opens in new window) Tumblr
- Share on Facebook (Opens in new window) Facebook
- Share on Telegram (Opens in new window) Telegram
- Share on Nextdoor (Opens in new window) Nextdoor
- Share on LinkedIn (Opens in new window) LinkedIn
- Share on X (Opens in new window) X
