diff --git a/webui/static/style.css b/webui/static/style.css
index 8c253041..b252989c 100644
--- a/webui/static/style.css
+++ b/webui/static/style.css
@@ -13272,7 +13272,9 @@ body.helper-mode-active #dashboard-activity-feed:hover {
background-image: url('data:image/svg+xml;charset=utf-8,');
}
-/* ListenBrainz Sync tab sub-tabs (For You / My Playlists / Collaborative) */
+/* ListenBrainz Sync tab sub-tabs (For You / My Playlists / Collaborative).
+ * Neutral dark surface; orange used only as a subtle accent on the
+ * active state — matches the rest of the app's tone. */
.listenbrainz-sub-tabs {
display: inline-flex;
gap: 6px;
@@ -13280,9 +13282,9 @@ body.helper-mode-active #dashboard-activity-feed:hover {
}
.listenbrainz-sub-tab-btn {
- background: rgba(255, 255, 255, 0.05);
- color: rgba(255, 255, 255, 0.7);
- border: 1px solid rgba(255, 255, 255, 0.1);
+ background: rgba(255, 255, 255, 0.04);
+ color: rgba(255, 255, 255, 0.65);
+ border: 1px solid rgba(255, 255, 255, 0.08);
padding: 6px 12px;
border-radius: 6px;
font-size: 12px;
@@ -13291,24 +13293,15 @@ body.helper-mode-active #dashboard-activity-feed:hover {
}
.listenbrainz-sub-tab-btn:hover {
- background: rgba(235, 116, 59, 0.15);
+ background: rgba(255, 255, 255, 0.07);
color: #fff;
- border-color: rgba(235, 116, 59, 0.4);
}
.listenbrainz-sub-tab-btn.active {
- background: rgba(235, 116, 59, 0.25);
+ background: rgba(255, 255, 255, 0.08);
color: #fff;
- border-color: rgba(235, 116, 59, 0.6);
-}
-
-.refresh-button.listenbrainz {
- background: rgba(235, 116, 59, 0.15);
- border: 1px solid rgba(235, 116, 59, 0.4);
- color: #fff;
-}
-.refresh-button.listenbrainz:hover {
- background: rgba(235, 116, 59, 0.3);
+ border-color: rgba(235, 116, 59, 0.45);
+ box-shadow: 0 0 0 1px rgba(235, 116, 59, 0.15) inset;
}
.itunes-icon {
@@ -17542,7 +17535,8 @@ body.helper-mode-active #dashboard-activity-feed:hover {
.youtube-playlist-card,
.tidal-playlist-card,
.deezer-playlist-card,
-.spotify-public-card {
+.spotify-public-card,
+.listenbrainz-playlist-card {
background: rgba(18, 18, 22, 0.9);
backdrop-filter: blur(12px);
border-radius: 16px;
@@ -17563,7 +17557,8 @@ body.helper-mode-active #dashboard-activity-feed:hover {
.youtube-playlist-card::before,
.tidal-playlist-card::before,
.deezer-playlist-card::before,
-.spotify-public-card::before {
+.spotify-public-card::before,
+.listenbrainz-playlist-card::before {
content: '';
position: absolute;
top: 0;
@@ -17578,23 +17573,27 @@ body.helper-mode-active #dashboard-activity-feed:hover {
.tidal-playlist-card::before { background: linear-gradient(90deg, transparent, rgba(255, 102, 0, 0.4), transparent); }
.deezer-playlist-card::before { background: linear-gradient(90deg, transparent, rgba(162, 56, 255, 0.4), transparent); }
.spotify-public-card::before { background: linear-gradient(90deg, transparent, rgba(29, 185, 84, 0.4), transparent); }
+.listenbrainz-playlist-card::before { background: linear-gradient(90deg, transparent, rgba(235, 116, 59, 0.4), transparent); }
/* Hover — brand glow */
.youtube-playlist-card:hover { border-color: rgba(255, 0, 0, 0.15); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 0 16px rgba(255, 0, 0, 0.06); transform: translateY(-2px); }
.tidal-playlist-card:hover { border-color: rgba(255, 102, 0, 0.15); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 0 16px rgba(255, 102, 0, 0.06); transform: translateY(-2px); }
.deezer-playlist-card:hover { border-color: rgba(162, 56, 255, 0.15); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 0 16px rgba(162, 56, 255, 0.06); transform: translateY(-2px); }
.spotify-public-card:hover { border-color: rgba(29, 185, 84, 0.15); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 0 16px rgba(29, 185, 84, 0.06); transform: translateY(-2px); }
+.listenbrainz-playlist-card:hover { border-color: rgba(235, 116, 59, 0.15); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 0 16px rgba(235, 116, 59, 0.06); transform: translateY(-2px); }
.youtube-playlist-card:hover::before { left: 10%; right: 10%; background: linear-gradient(90deg, transparent, rgba(255, 0, 0, 0.7), transparent); }
.tidal-playlist-card:hover::before { left: 10%; right: 10%; background: linear-gradient(90deg, transparent, rgba(255, 102, 0, 0.7), transparent); }
.deezer-playlist-card:hover::before { left: 10%; right: 10%; background: linear-gradient(90deg, transparent, rgba(162, 56, 255, 0.7), transparent); }
.spotify-public-card:hover::before { left: 10%; right: 10%; background: linear-gradient(90deg, transparent, rgba(29, 185, 84, 0.7), transparent); }
+.listenbrainz-playlist-card:hover::before { left: 10%; right: 10%; background: linear-gradient(90deg, transparent, rgba(235, 116, 59, 0.7), transparent); }
/* Source icons */
.youtube-playlist-card .playlist-card-icon,
.tidal-playlist-card .playlist-card-icon,
.deezer-playlist-card .playlist-card-icon,
-.spotify-public-card .playlist-card-icon {
+.spotify-public-card .playlist-card-icon,
+.listenbrainz-playlist-card .playlist-card-icon {
width: 40px;
height: 40px;
border-radius: 10px;
diff --git a/webui/static/sync-listenbrainz.js b/webui/static/sync-listenbrainz.js
index d43ad46d..bf440422 100644
--- a/webui/static/sync-listenbrainz.js
+++ b/webui/static/sync-listenbrainz.js
@@ -87,10 +87,20 @@ function renderListenBrainzSyncPlaylists() {
}
container.innerHTML = playlists.map(p => {
- const mbid = p.playlist_mbid || p.id;
- const title = p.title || p.name || 'ListenBrainz Playlist';
- const creator = p.creator || 'ListenBrainz';
- const count = p.track_count || 0;
+ // The Discover-page endpoints wrap each entry in JSPF shape:
+ // { playlist: { identifier: 'https://.../', title, creator,
+ // annotation: {track_count}, track: [...] } }
+ // Pull out the inner playlist object + extract the mbid from the URL.
+ const inner = p.playlist || p;
+ const mbid = (inner.identifier || '').split('/').pop() || inner.id || '';
+ const title = inner.title || inner.name || 'ListenBrainz Playlist';
+ const creator = inner.creator || 'ListenBrainz';
+ let count = 0;
+ if (inner.annotation && inner.annotation.track_count) {
+ count = inner.annotation.track_count;
+ } else if (Array.isArray(inner.track) && inner.track.length > 0) {
+ count = inner.track.length;
+ }
// Reuse listenbrainzPlaylistStates so the modal state survives
// tab switches (matches Discover-page behavior).
const state = (typeof listenbrainzPlaylistStates !== 'undefined'