You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SoulSync/webui/index.html

2831 lines
182 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SoulSync - Music Sync & Manager</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<div class="main-container">
<!-- Sidebar - Always Visible -->
<div class="sidebar">
<!-- Header Section -->
<div class="sidebar-header">
<h1 class="app-name">SoulSync</h1>
<p class="app-subtitle">Music Sync & Manager</p>
</div>
<!-- Navigation Section -->
<nav class="sidebar-nav">
<button class="nav-button active" data-page="dashboard">
<span class="nav-icon">📊</span>
<span class="nav-text">Dashboard</span>
</button>
<button class="nav-button" data-page="sync">
<span class="nav-icon">🔄</span>
<span class="nav-text">Sync</span>
</button>
<button class="nav-button" data-page="downloads">
<span class="nav-icon">📥</span>
<span class="nav-text">Search</span>
</button>
<button class="nav-button" data-page="discover">
<span class="nav-icon">🎧</span>
<span class="nav-text">Discover</span>
</button>
<button class="nav-button" data-page="artists">
<span class="nav-icon">🎵</span>
<span class="nav-text">Artists</span>
</button>
<button class="nav-button" data-page="library">
<span class="nav-icon">📚</span>
<span class="nav-text">Library</span>
</button>
<button class="nav-button" data-page="settings">
<span class="nav-icon">⚙️</span>
<span class="nav-text">Settings</span>
</button>
</nav>
<!-- Spacer -->
<div class="sidebar-spacer"></div>
<!-- Media Player Section -->
<div class="media-player" id="media-player">
<!-- Loading Animation -->
<div class="loading-animation hidden" id="loading-animation">
<div class="loading-bar">
<div class="loading-progress"></div>
</div>
<div class="loading-text">0%</div>
</div>
<!-- Header (always visible) -->
<div class="media-header">
<div class="media-info">
<div class="track-title" id="track-title">No track</div>
<div class="artist-name" id="artist-name">Unknown Artist</div>
</div>
<button class="play-button" id="play-button" disabled></button>
</div>
<!-- Expanded Content (hidden initially) -->
<div class="media-expanded hidden" id="media-expanded">
<div class="album-name" id="album-name">Unknown Album</div>
<!-- Progress Bar and Time Display -->
<div class="progress-section">
<div class="time-display">
<span class="current-time" id="current-time">0:00</span>
<span class="time-separator">/</span>
<span class="total-time" id="total-time">0:00</span>
</div>
<div class="progress-bar-container">
<div class="progress-track">
<div class="progress-fill" id="progress-fill"></div>
</div>
<input type="range" class="progress-bar" id="progress-bar" min="0" max="100" value="0" step="0.1">
</div>
</div>
<div class="media-controls">
<div class="volume-control">
<span class="volume-icon">🔊</span>
<input type="range" class="volume-slider" id="volume-slider" min="0" max="100" value="70">
</div>
<button class="stop-button" id="stop-button" disabled></button>
</div>
</div>
<!-- No Track Message -->
<div class="no-track-message" id="no-track-message">
Start playing music to see controls
</div>
</div>
<!-- Crypto Donation Section -->
<div class="crypto-donation">
<div class="donation-header">
<span class="donation-title">Support Development</span>
<button class="toggle-button" id="donation-toggle">Show</button>
</div>
<div class="donation-addresses hidden" id="donation-addresses">
<div class="donation-item" onclick="openKofi()">
<span class="donation-name">Ko-fi</span>
<span class="donation-link">Click to open</span>
</div>
<div class="donation-item" onclick="copyAddress('3JVWrRSkozAQSmw5DXYVxYKsM9bndPTqdS', 'Bitcoin')">
<span class="donation-name">Bitcoin</span>
<span class="donation-address">3JVWrR...dPTqdS</span>
</div>
<div class="donation-item" onclick="copyAddress('0x343fC48c2cd1C6332b0df9a58F86e6520a026AC5', 'Ethereum')">
<span class="donation-name">Ethereum</span>
<span class="donation-address">0x343f...026AC5</span>
</div>
</div>
</div>
<!-- Version Section -->
<div class="version-section">
<button class="version-button" onclick="showVersionInfo()">v1.0</button>
</div>
<!-- Status Section -->
<div class="status-section">
<h4 class="status-title">Service Status</h4>
<div class="status-indicator" id="spotify-indicator">
<span class="status-dot disconnected"></span>
<span class="status-name">Spotify</span>
</div>
<div class="status-indicator" id="media-server-indicator">
<span class="status-dot disconnected"></span>
<span class="status-name" id="media-server-name">Plex</span>
</div>
<div class="status-indicator" id="soulseek-indicator">
<span class="status-dot disconnected"></span>
<span class="status-name">Soulseek</span>
</div>
</div>
</div>
<!-- Main Content Area -->
<div class="main-content">
<!-- Dashboard Page -->
<div class="page active" id="dashboard-page">
<div class="dashboard-container">
<div class="dashboard-header">
<div class="header-text">
<h2 class="header-title">System Dashboard</h2>
<p class="header-subtitle">Monitor your music system health and manage operations</p>
</div>
<div class="header-spacer"></div>
<div class="header-actions">
<button class="header-button watchlist-button" id="watchlist-button">👁️ Watchlist (0)</button>
<button class="header-button wishlist-button" id="wishlist-button">🎵 Wishlist (0)</button>
</div>
</div>
<div class="dashboard-section">
<h3 class="section-title">Service Status</h3>
<div class="service-status-grid">
<div class="service-card" id="spotify-service-card">
<div class="service-card-header">
<span class="service-card-title">Spotify</span>
<span class="service-card-indicator disconnected" id="spotify-status-indicator"></span>
</div>
<p class="service-card-status-text" id="spotify-status-text">Disconnected</p>
<p class="service-card-response-time" id="spotify-response-time">Response: --</p>
<div class="service-card-footer">
<button class="service-card-button" onclick="testDashboardConnection('spotify')">Test Connection</button>
</div>
</div>
<div class="service-card" id="media-server-service-card">
<div class="service-card-header">
<span class="service-card-title" id="media-server-service-name">Server</span>
<span class="service-card-indicator disconnected" id="media-server-status-indicator"></span>
</div>
<p class="service-card-status-text" id="media-server-status-text">Disconnected</p>
<p class="service-card-response-time" id="media-server-response-time">Response: --</p>
<div class="service-card-footer">
<button class="service-card-button" onclick="testDashboardConnection('server')">Test Connection</button>
</div>
</div>
<div class="service-card" id="soulseek-service-card">
<div class="service-card-header">
<span class="service-card-title">Soulseek</span>
<span class="service-card-indicator disconnected" id="soulseek-status-indicator"></span>
</div>
<p class="service-card-status-text" id="soulseek-status-text">Disconnected</p>
<p class="service-card-response-time" id="soulseek-response-time">Response: --</p>
<div class="service-card-footer">
<button class="service-card-button" onclick="testDashboardConnection('soulseek')">Test Connection</button>
</div>
</div>
</div>
</div>
<div class="dashboard-section">
<h3 class="section-title">System Statistics</h3>
<div class="stats-grid-dashboard">
<div class="stat-card-dashboard" id="active-downloads-card">
<p class="stat-card-title">Active Downloads</p>
<p class="stat-card-value">0</p>
<p class="stat-card-subtitle">Currently downloading</p>
</div>
<div class="stat-card-dashboard" id="finished-downloads-card">
<p class="stat-card-title">Finished Downloads</p>
<p class="stat-card-value">0</p>
<p class="stat-card-subtitle">Completed this session</p>
</div>
<div class="stat-card-dashboard" id="download-speed-card">
<p class="stat-card-title">Download Speed</p>
<p class="stat-card-value">0 KB/s</p>
<p class="stat-card-subtitle">Combined speed</p>
</div>
<div class="stat-card-dashboard" id="active-syncs-card">
<p class="stat-card-title">Active Syncs</p>
<p class="stat-card-value">0</p>
<p class="stat-card-subtitle">Playlists syncing</p>
</div>
<div class="stat-card-dashboard" id="uptime-card">
<p class="stat-card-title">System Uptime</p>
<p class="stat-card-value">0m</p>
<p class="stat-card-subtitle">Application runtime</p>
</div>
<div class="stat-card-dashboard" id="memory-card">
<p class="stat-card-title">Memory Usage</p>
<p class="stat-card-value">--</p>
<p class="stat-card-subtitle">Current usage</p>
</div>
</div>
</div>
<div class="dashboard-section">
<h3 class="section-title">Tools & Operations</h3>
<div class="tools-grid">
<div class="tool-card" id="db-updater-card">
<div class="tool-card-header">
<h4 class="tool-card-title">Database Updater</h4>
<button class="tool-help-button" data-tool="db-updater" title="Learn more about this tool">?</button>
</div>
<p class="tool-card-info">Last Full Refresh: <span id="db-last-refresh">Never</span></p>
<div class="tool-card-stats">
<div class="stat-item">
<span class="stat-item-label">Artists:</span>
<span class="stat-item-value" id="db-stat-artists">0</span>
</div>
<div class="stat-item">
<span class="stat-item-label">Albums:</span>
<span class="stat-item-value" id="db-stat-albums">0</span>
</div>
<div class="stat-item">
<span class="stat-item-label">Tracks:</span>
<span class="stat-item-value" id="db-stat-tracks">0</span>
</div>
<div class="stat-item">
<span class="stat-item-label">Size:</span>
<span class="stat-item-value" id="db-stat-size">0.0 MB</span>
</div>
</div>
<div class="tool-card-controls">
<select id="db-refresh-type">
<option value="incremental">Incremental Update</option>
<option value="full">Full Refresh</option>
</select>
<button id="db-update-button">Update Database</button>
</div>
<div class="tool-card-progress-section">
<p class="progress-phase-label" id="db-phase-label">Idle</p>
<div class="progress-bar-container">
<div class="progress-bar-fill" id="db-progress-bar" style="width: 0%;"></div>
</div>
<p class="progress-details-label" id="db-progress-label">0 / 0 artists (0.0%)</p>
</div>
</div>
<div class="tool-card" id="metadata-updater-card">
<div class="tool-card-header">
<h4 class="tool-card-title">Metadata Updater</h4>
<button class="tool-help-button" data-tool="metadata-updater" title="Learn more about this tool">?</button>
</div>
<p class="metadata-updater-description tool-card-info">Updates artist photos, genres, and album art from Spotify.</p>
<div class="tool-card-controls">
<select id="metadata-refresh-interval">
<option value="180">6 months</option>
<option value="90">3 months</option>
<option value="30" selected>1 month</option>
<option value="14">2 weeks</option>
<option value="7">1 week</option>
<option value="0">Full refresh</option>
</select>
<button id="metadata-update-button">Begin Update</button>
</div>
<div class="tool-card-progress-section">
<p class="progress-phase-label" id="metadata-phase-label">Current Artist: Not running</p>
<div class="progress-bar-container">
<div class="progress-bar-fill" id="metadata-progress-bar" style="width: 0%;"></div>
</div>
<p class="progress-details-label" id="metadata-progress-label">0 / 0 artists (0.0%)</p>
</div>
</div>
<div class="tool-card" id="quality-scanner-card">
<div class="tool-card-header">
<h4 class="tool-card-title">Quality Scanner</h4>
<button class="tool-help-button" data-tool="quality-scanner" title="Learn more about this tool">?</button>
</div>
<p class="tool-card-info">Scan library for tracks below quality preferences</p>
<div class="tool-card-stats">
<div class="stat-item">
<span class="stat-item-label">Processed:</span>
<span class="stat-item-value" id="quality-stat-processed">0</span>
</div>
<div class="stat-item">
<span class="stat-item-label">Quality Met:</span>
<span class="stat-item-value" id="quality-stat-met">0</span>
</div>
<div class="stat-item">
<span class="stat-item-label">Low Quality:</span>
<span class="stat-item-value" id="quality-stat-low">0</span>
</div>
<div class="stat-item">
<span class="stat-item-label">Matched:</span>
<span class="stat-item-value" id="quality-stat-matched">0</span>
</div>
</div>
<div class="tool-card-controls">
<select id="quality-scan-scope">
<option value="watchlist">Watchlist Artists Only</option>
<option value="all">All Library Tracks</option>
</select>
<button id="quality-scan-button">Scan Library</button>
</div>
<div class="tool-card-progress-section">
<p class="progress-phase-label" id="quality-phase-label">Ready to scan</p>
<div class="progress-bar-container">
<div class="progress-bar-fill" id="quality-progress-bar" style="width: 0%;"></div>
</div>
<p class="progress-details-label" id="quality-progress-label">0 / 0 tracks scanned (0.0%)</p>
</div>
</div>
<div class="tool-card" id="duplicate-cleaner-card">
<div class="tool-card-header">
<h4 class="tool-card-title">Duplicate Cleaner</h4>
<button class="tool-help-button" data-tool="duplicate-cleaner" title="Learn more about this tool">?</button>
</div>
<p class="tool-card-info">Detect and remove duplicate tracks in Transfer folder</p>
<div class="tool-card-stats">
<div class="stat-item">
<span class="stat-item-label">Files Scanned:</span>
<span class="stat-item-value" id="duplicate-stat-scanned">0</span>
</div>
<div class="stat-item">
<span class="stat-item-label">Duplicates Found:</span>
<span class="stat-item-value" id="duplicate-stat-found">0</span>
</div>
<div class="stat-item">
<span class="stat-item-label">Deleted:</span>
<span class="stat-item-value" id="duplicate-stat-deleted">0</span>
</div>
<div class="stat-item">
<span class="stat-item-label">Space Freed:</span>
<span class="stat-item-value" id="duplicate-stat-space">0 MB</span>
</div>
</div>
<div class="tool-card-controls">
<button id="duplicate-clean-button">Clean Duplicates</button>
</div>
<div class="tool-card-progress-section">
<p class="progress-phase-label" id="duplicate-phase-label">Ready to scan</p>
<div class="progress-bar-container">
<div class="progress-bar-fill" id="duplicate-progress-bar" style="width: 0%;"></div>
</div>
<p class="progress-details-label" id="duplicate-progress-label">0 files scanned (0.0%)</p>
</div>
</div>
<div class="tool-card" id="media-scan-card" style="display: none;">
<div class="tool-card-header">
<h4 class="tool-card-title">Media Server Scan</h4>
<button class="tool-help-button" data-tool="media-scan" title="Learn more about this tool">?</button>
</div>
<p class="tool-card-info">Manually trigger Plex media library scan for music</p>
<div class="tool-card-stats">
<div class="stat-item">
<span class="stat-item-label">Last Scan:</span>
<span class="stat-item-value" id="media-scan-last-time">Never</span>
</div>
<div class="stat-item">
<span class="stat-item-label">Status:</span>
<span class="stat-item-value" id="media-scan-status">Idle</span>
</div>
</div>
<div class="tool-card-controls">
<button id="media-scan-button" class="media-scan-btn">
<span class="scan-icon">📡</span>
<span class="scan-text">Scan Library</span>
</button>
</div>
<div class="tool-card-progress-section">
<p class="progress-phase-label" id="media-scan-phase-label">Ready to scan</p>
<div class="progress-bar-container">
<div class="progress-bar-fill" id="media-scan-progress-bar" style="width: 0%;"></div>
</div>
<p class="progress-details-label" id="media-scan-progress-label">Waiting for scan request</p>
</div>
</div>
</div>
</div>
<div class="dashboard-section">
<h3 class="section-title">Recent Activity</h3>
<div class="activity-feed-container" id="dashboard-activity-feed">
<div class="activity-item">
<span class="activity-icon">📊</span>
<div class="activity-text-content">
<p class="activity-title">System Started</p>
<p class="activity-subtitle">Dashboard initialized successfully</p>
</div>
<p class="activity-time">Now</p>
</div>
</div>
</div>
</div>
</div>
<!-- Main container for the Sync page -->
<div class="page" id="sync-page">
<!-- Header -->
<div class="sync-header">
<h2 class="sync-title">Playlist Sync</h2>
<p class="sync-subtitle">Synchronize your Spotify, Tidal, and YouTube playlists with your media server</p>
</div>
<!-- Main two-column content area -->
<div class="sync-content-area">
<!-- Left Panel: Tabbed Playlist Section -->
<div class="sync-main-panel">
<div class="sync-tabs">
<button class="sync-tab-button active" data-tab="spotify">
<span class="tab-icon spotify-icon"></span> Spotify
</button>
<button class="sync-tab-button" data-tab="tidal">
<span class="tab-icon tidal-icon"></span> Tidal
</button>
<button class="sync-tab-button" data-tab="youtube">
<span class="tab-icon youtube-icon"></span> YouTube
</button>
<button class="sync-tab-button" data-tab="beatport">
<span class="tab-icon beatport-icon"></span> Beatport
</button>
</div>
<!-- Spotify Tab Content -->
<div class="sync-tab-content active" id="spotify-tab-content">
<div class="playlist-header">
<h3>Your Spotify Playlists</h3>
<button class="refresh-button" id="spotify-refresh-btn">🔄 Refresh</button>
</div>
<div class="playlist-scroll-container" id="spotify-playlist-container">
<div class="playlist-placeholder">Click 'Refresh' to load your Spotify playlists.</div>
</div>
</div>
<!-- Tidal Tab Content -->
<div class="sync-tab-content" id="tidal-tab-content">
<div class="playlist-header">
<h3>Your Tidal Playlists</h3>
<button class="refresh-button tidal" id="tidal-refresh-btn">🔄 Refresh</button>
</div>
<div class="playlist-scroll-container" id="tidal-playlist-container">
<div class="playlist-placeholder">Click 'Refresh' to load your Tidal playlists.</div>
</div>
</div>
<!-- YouTube Tab Content -->
<div class="sync-tab-content" id="youtube-tab-content">
<div class="youtube-input-section">
<input type="text" id="youtube-url-input" placeholder="Paste YouTube Music Playlist URL...">
<button id="youtube-parse-btn">Parse Playlist</button>
</div>
<div class="playlist-scroll-container" id="youtube-playlist-container">
<div class="playlist-placeholder">Parsed YouTube playlists will appear here.</div>
</div>
</div>
<!-- Beatport Tab Content -->
<div class="sync-tab-content" id="beatport-tab-content">
<!-- Beatport Nested Tabs -->
<div class="beatport-tabs">
<button class="beatport-tab-button active" data-beatport-tab="rebuild">
<span class="tab-icon rebuild-icon"></span> Browse
</button>
<button class="beatport-tab-button" data-beatport-tab="browse">
<span class="tab-icon browse-icon"></span> Browse Charts
</button>
<button class="beatport-tab-button" data-beatport-tab="playlists">
<span class="tab-icon playlist-icon"></span> My Playlists
</button>
</div>
<!-- Browse Charts Tab Content -->
<div class="beatport-tab-content" id="beatport-browse-content">
<div class="beatport-navigation">
<!-- New Homepage Main View -->
<div class="beatport-main-view active" id="beatport-main-view">
<div class="beatport-hero">
<div class="beatport-hero-bg"></div>
<div class="beatport-hero-content">
<h2>Browse Beatport Charts</h2>
<p>Explore top electronic music charts and discover new tracks</p>
<div class="beatport-stats">
<span class="stat-item">39 Genres</span>
<span class="stat-divider"></span>
<span class="stat-item">Top 100</span>
<span class="stat-divider"></span>
<span class="stat-item">Daily Updates</span>
</div>
</div>
</div>
<!-- Genre Explorer Section -->
<div class="homepage-genre-section">
<h3 class="section-title">🎵 Genre Explorer</h3>
<div class="genre-chart-types-grid">
<div class="genre-chart-type-card" data-action="show-genres">
<div class="chart-type-icon">🎵</div>
<div class="chart-type-info">
<h3>Browse All Genres</h3>
<p>House, Techno, Trance, and 36 more genres</p>
<span class="track-count">39 Genres</span>
</div>
</div>
</div>
</div>
<!-- Main Charts Section -->
<div class="homepage-main-charts-section">
<h3 class="section-title">📊 Main Charts</h3>
<div class="genre-chart-types-grid">
<div class="genre-chart-type-card" data-chart-type="top-10" data-chart-endpoint="/api/beatport/top-100">
<div class="chart-type-icon">🔥</div>
<div class="chart-type-info">
<h3>Beatport Top 10</h3>
<p>Current hottest tracks</p>
<span class="track-count">10 tracks</span>
</div>
</div>
<div class="genre-chart-type-card" data-chart-type="top-100" data-chart-endpoint="/api/beatport/top-100">
<div class="chart-type-icon">💯</div>
<div class="chart-type-info">
<h3>Beatport Top 100</h3>
<p>Complete chart rankings</p>
<span class="track-count">100 tracks</span>
</div>
</div>
</div>
</div>
<!-- Releases Section -->
<div class="homepage-releases-section">
<h3 class="section-title">🎵 Releases</h3>
<div class="genre-chart-types-grid">
<div class="genre-chart-type-card" data-chart-type="releases-top-10" data-chart-endpoint="/api/beatport/homepage/top-10-releases">
<div class="chart-type-icon">🆕</div>
<div class="chart-type-info">
<h3>Top 10 Releases</h3>
<p>Newest releases trending</p>
<span class="track-count">10 releases</span>
</div>
</div>
<div class="genre-chart-type-card" data-chart-type="releases-top-100" data-chart-endpoint="/api/beatport/top-100-releases">
<div class="chart-type-icon">📊</div>
<div class="chart-type-info">
<h3>Top 100 Releases</h3>
<p>All trending releases</p>
<span class="track-count">100 releases</span>
</div>
</div>
<div class="genre-chart-type-card" data-chart-type="latest-releases" data-chart-endpoint="/api/beatport/homepage/new-releases">
<div class="chart-type-icon">🕒</div>
<div class="chart-type-info">
<h3>Latest Releases</h3>
<p>Recently published</p>
<span class="track-count">50 releases</span>
</div>
</div>
</div>
</div>
<!-- Hype Section -->
<div class="homepage-hype-section">
<h3 class="section-title">🔥 Hype</h3>
<div class="genre-chart-types-grid">
<div class="genre-chart-type-card" data-chart-type="hype-top-10" data-chart-endpoint="/api/beatport/hype-top-100">
<div class="chart-type-icon">🚀</div>
<div class="chart-type-info">
<h3>Hype Top 10</h3>
<p>Hottest trending tracks</p>
<span class="track-count">10 tracks</span>
</div>
</div>
<div class="genre-chart-type-card" data-chart-type="hype-top-100" data-chart-endpoint="/api/beatport/hype-top-100">
<div class="chart-type-icon">🔥</div>
<div class="chart-type-info">
<h3>Hype Top 100</h3>
<p>Complete hype chart rankings</p>
<span class="track-count">100 tracks</span>
</div>
</div>
<div class="genre-chart-type-card" data-chart-type="hype-picks" data-chart-endpoint="/api/beatport/homepage/hype-picks">
<div class="chart-type-icon"></div>
<div class="chart-type-info">
<h3>Hype Picks</h3>
<p>Editor selected hype tracks</p>
<span class="track-count">50 tracks</span>
</div>
</div>
</div>
</div>
<!-- DJ Charts Section -->
<div class="homepage-dj-charts-section">
<h3 class="section-title">🎧 DJ Charts Collection</h3>
<p class="section-description">DJ curated chart collections</p>
<div class="charts-loading-inline" id="dj-charts-loading-inline">
<div class="loading-spinner-small"></div>
<p>Loading DJ chart collections...</p>
</div>
<div class="dj-charts-grid" id="dj-charts-grid">
<!-- Charts will be populated here -->
</div>
</div>
<!-- Featured Charts Section -->
<div class="homepage-featured-charts-section">
<h3 class="section-title">⭐ Featured Charts Collection</h3>
<p class="section-description">Editor curated chart collections</p>
<div class="charts-loading-inline" id="featured-charts-loading-inline">
<div class="loading-spinner-small"></div>
<p>Loading featured chart collections...</p>
</div>
<div class="featured-charts-grid" id="featured-charts-grid">
<!-- Charts will be populated here -->
</div>
</div>
</div>
<!-- Genre Explorer Sub-View -->
<div class="beatport-sub-view" id="beatport-genres-view">
<div class="beatport-breadcrumb">
<button class="breadcrumb-back">← Back to Categories</button>
<span class="breadcrumb-path">Browse Charts > Genre Explorer</span>
</div>
<div class="beatport-genre-grid">
<div class="beatport-genre-item" data-genre-slug="house" data-genre-id="5">
<div class="genre-icon">🏠</div>
<h3>House</h3>
<span class="genre-track-count">Top 100</span>
</div>
<div class="beatport-genre-item" data-genre-slug="tech-house" data-genre-id="11">
<div class="genre-icon">🔧</div>
<h3>Tech House</h3>
<span class="genre-track-count">Top 100</span>
</div>
<div class="beatport-genre-item" data-genre-slug="techno" data-genre-id="6">
<div class="genre-icon"></div>
<h3>Techno</h3>
<span class="genre-track-count">Top 100</span>
</div>
<div class="beatport-genre-item" data-genre-slug="deep-house" data-genre-id="12">
<div class="genre-icon">🌊</div>
<h3>Deep House</h3>
<span class="genre-track-count">Top 100</span>
</div>
<div class="beatport-genre-item" data-genre-slug="trance" data-genre-id="7">
<div class="genre-icon">🌀</div>
<h3>Trance</h3>
<span class="genre-track-count">Top 100</span>
</div>
<div class="beatport-genre-item" data-genre-slug="drum-and-bass" data-genre-id="1">
<div class="genre-icon">🥁</div>
<h3>Drum & Bass</h3>
<span class="genre-track-count">Top 100</span>
</div>
<div class="beatport-genre-item" data-genre-slug="dubstep" data-genre-id="18">
<div class="genre-icon">🎵</div>
<h3>Dubstep</h3>
<span class="genre-track-count">Top 100</span>
</div>
<div class="beatport-genre-item" data-genre-slug="progressive-house" data-genre-id="15">
<div class="genre-icon">📈</div>
<h3>Progressive House</h3>
<span class="genre-track-count">Top 100</span>
</div>
<div class="beatport-genre-item" data-genre-slug="melodic-house-and-techno" data-genre-id="90">
<div class="genre-icon">🎼</div>
<h3>Melodic House & Techno</h3>
<span class="genre-track-count">Top 100</span>
</div>
<div class="beatport-genre-item" data-genre-slug="afro-house" data-genre-id="89">
<div class="genre-icon">🌍</div>
<h3>Afro House</h3>
<span class="genre-track-count">Top 100</span>
</div>
<div class="beatport-genre-item" data-genre-slug="minimal" data-genre-id="14">
<div class="genre-icon"></div>
<h3>Minimal</h3>
<span class="genre-track-count">Top 100</span>
</div>
<div class="beatport-genre-item" data-genre-slug="nu-disco" data-genre-id="50">
<div class="genre-icon"></div>
<h3>Nu Disco</h3>
<span class="genre-track-count">Top 100</span>
</div>
</div>
</div>
<!-- Genre Detail Sub-View -->
<div class="beatport-sub-view" id="beatport-genre-detail-view">
<div class="beatport-breadcrumb">
<button class="breadcrumb-back" id="genre-detail-back">← Back to Genre Explorer</button>
<span class="breadcrumb-path" id="genre-detail-breadcrumb">Browse Charts > Genre Explorer > Loading...</span>
</div>
<div class="genre-detail-header">
<div class="genre-detail-info">
<h2 id="genre-detail-title">Loading Genre...</h2>
<p id="genre-detail-description">Explore all chart types for this genre</p>
</div>
</div>
<!-- Main Chart Types Section -->
<div class="genre-main-charts-section">
<h3 class="section-title">📊 Main Charts</h3>
<div class="genre-chart-types-grid">
<div class="genre-chart-type-card" data-chart-type="top-10">
<div class="chart-type-icon">🔥</div>
<div class="chart-type-info">
<h3 id="genre-top-10-title">Top 10</h3>
<p>Current hottest tracks</p>
<span class="track-count">10 tracks</span>
</div>
</div>
<div class="genre-chart-type-card" data-chart-type="top-100">
<div class="chart-type-icon">💯</div>
<div class="chart-type-info">
<h3 id="genre-top-100-title">Top 100</h3>
<p>Complete chart rankings</p>
<span class="track-count">100 tracks</span>
</div>
</div>
</div>
</div>
<!-- Releases Section -->
<div class="genre-releases-section">
<h3 class="section-title">🎵 Releases</h3>
<div class="genre-chart-types-grid">
<div class="genre-chart-type-card" data-chart-type="releases-top-10">
<div class="chart-type-icon">🆕</div>
<div class="chart-type-info">
<h3 id="genre-releases-top-10-title">Top 10 Releases</h3>
<p>Newest releases trending</p>
<span class="track-count">10 releases</span>
</div>
</div>
<div class="genre-chart-type-card" data-chart-type="releases-top-100">
<div class="chart-type-icon">📊</div>
<div class="chart-type-info">
<h3 id="genre-releases-top-100-title">Top 100 Releases</h3>
<p>All trending releases</p>
<span class="track-count">100 releases</span>
</div>
</div>
<div class="genre-chart-type-card" data-chart-type="latest-releases">
<div class="chart-type-icon">🕒</div>
<div class="chart-type-info">
<h3 id="genre-latest-releases-title">Latest Releases</h3>
<p>Recently published</p>
<span class="track-count">50 releases</span>
</div>
</div>
</div>
</div>
<!-- Editorial Section -->
<div class="genre-editorial-section">
<h3 class="section-title">⭐ Editorial</h3>
<div class="genre-chart-types-grid">
<div class="genre-chart-type-card" data-chart-type="staff-picks">
<div class="chart-type-icon"></div>
<div class="chart-type-info">
<h3 id="genre-staff-picks-title">Staff Picks</h3>
<p>Editor curated selection</p>
<span class="track-count">50 tracks</span>
</div>
</div>
</div>
</div>
<!-- Hype Section -->
<div class="genre-hype-section">
<h3 class="section-title">🔥 Hype</h3>
<div class="genre-chart-types-grid">
<div class="genre-chart-type-card" data-chart-type="hype-top-10">
<div class="chart-type-icon">🚀</div>
<div class="chart-type-info">
<h3 id="genre-hype-top-10-title">Hype Top 10</h3>
<p>Hottest trending tracks</p>
<span class="track-count">10 tracks</span>
</div>
</div>
<div class="genre-chart-type-card" data-chart-type="hype-top-100">
<div class="chart-type-icon">🔥</div>
<div class="chart-type-info">
<h3 id="genre-hype-top-100-title">Hype Top 100</h3>
<p>Complete hype chart rankings</p>
<span class="track-count">100 tracks</span>
</div>
</div>
<div class="genre-chart-type-card" data-chart-type="hype-picks">
<div class="chart-type-icon"></div>
<div class="chart-type-info">
<h3 id="genre-hype-picks-title">Hype Picks</h3>
<p>Editor selected hype tracks</p>
<span class="track-count">50 tracks</span>
</div>
</div>
</div>
</div>
<!-- New Charts Section (Always Visible) -->
<div class="genre-new-charts-section">
<h3 class="section-title">📈 New Charts Collection</h3>
<p class="section-description">Artist and DJ curated chart collections</p>
<!-- Always Visible Charts List -->
<div class="new-charts-content" id="new-charts-content">
<div class="charts-loading-inline" id="charts-loading-inline">
<div class="loading-spinner-small"></div>
<p>Loading chart collections...</p>
</div>
<div class="new-charts-grid" id="new-charts-grid">
<!-- Charts will be populated here -->
</div>
</div>
</div>
</div>
<!-- Genre Charts List Sub-View -->
<div class="beatport-sub-view" id="beatport-genre-charts-list-view">
<div class="beatport-breadcrumb">
<button class="breadcrumb-back" id="genre-charts-list-back">← Back to Genre Charts</button>
<span class="breadcrumb-path" id="genre-charts-list-breadcrumb">Browse Charts > Genre Explorer > Genre Charts > New Charts</span>
</div>
<div class="genre-charts-list-header">
<div class="genre-charts-list-info">
<h2 id="genre-charts-list-title">Loading Charts...</h2>
<p id="genre-charts-list-description">Browse all available chart collections for this genre</p>
</div>
</div>
<div class="genre-charts-list-container">
<div class="charts-loading-placeholder" id="charts-loading-placeholder">
<div class="loading-spinner"></div>
<p>🔍 Loading chart collections...</p>
</div>
<div class="genre-charts-grid" id="genre-charts-grid">
<!-- Charts will be populated dynamically -->
</div>
</div>
</div>
</div>
</div>
<!-- My Playlists Tab Content -->
<div class="beatport-tab-content" id="beatport-playlists-content">
<div class="playlist-header">
<h3>My Beatport Playlists</h3>
<button class="refresh-button beatport" id="beatport-clear-btn">🗑️ Clear</button>
</div>
<div class="playlist-scroll-container" id="beatport-playlist-container">
<div class="playlist-placeholder">Your created Beatport playlists will appear here.</div>
</div>
</div>
<!-- Rebuild Tab Content -->
<div class="beatport-tab-content active" id="beatport-rebuild-content">
<div class="beatport-rebuild-slider-container">
<div class="beatport-rebuild-slider" id="beatport-rebuild-slider">
<div class="beatport-rebuild-slider-track" id="beatport-rebuild-slider-track">
<!-- Loading placeholder -->
<div class="beatport-rebuild-loading">
<div class="beatport-rebuild-loading-content">
<h2>🎯 Loading Fresh Beatport Tracks...</h2>
<p>Fetching the latest music from Beatport</p>
</div>
</div>
</div>
<!-- Slider Navigation -->
<div class="beatport-rebuild-slider-nav">
<button class="beatport-rebuild-nav-btn beatport-rebuild-prev-btn" id="beatport-rebuild-prev-btn"></button>
<button class="beatport-rebuild-nav-btn beatport-rebuild-next-btn" id="beatport-rebuild-next-btn"></button>
</div>
<!-- Slider Indicators -->
<div class="beatport-rebuild-slider-indicators">
<!-- Indicators will be dynamically generated -->
</div>
</div>
</div>
<!-- Navigation Buttons Section -->
<div class="beatport-nav-buttons-section">
<div class="beatport-nav-buttons-container">
<button class="beatport-nav-button" id="browse-by-genre-btn">
<span class="beatport-nav-icon genre-icon"></span>
<span class="beatport-nav-text">Browse by Genre</span>
</button>
<button class="beatport-nav-button" id="beatport-top100-btn">
<span class="beatport-nav-icon top100-icon"></span>
<span class="beatport-nav-text">Beatport Top 100</span>
</button>
<button class="beatport-nav-button" id="hype-top100-btn">
<span class="beatport-nav-icon hype-icon"></span>
<span class="beatport-nav-text">Hype Top 100</span>
</button>
</div>
</div>
<!-- Top 10 Lists Section -->
<div class="beatport-top10-section">
<div class="beatport-top10-header">
<h2 class="beatport-top10-title">🏆 Top 10 Lists</h2>
<p class="beatport-top10-subtitle">Current trending tracks from Beatport charts</p>
</div>
<div class="beatport-top10-container">
<!-- Beatport Top 10 List -->
<div class="beatport-top10-list" id="beatport-top10-list">
<div class="beatport-top10-list-header">
<h3 class="beatport-top10-list-title">🎵 Beatport Top 10</h3>
<p class="beatport-top10-list-subtitle">Most popular tracks on Beatport</p>
</div>
<div class="beatport-top10-tracks" id="beatport-top10-tracks">
<!-- Loading placeholder -->
<div class="beatport-top10-loading">
<div class="beatport-top10-loading-content">
<h4>🎵 Loading Beatport Top 10...</h4>
<p>Fetching trending tracks</p>
</div>
</div>
</div>
</div>
<!-- Hype Top 10 List -->
<div class="beatport-hype10-list" id="beatport-hype10-list">
<div class="beatport-hype10-list-header">
<h3 class="beatport-hype10-list-title">🔥 Hype Top 10</h3>
<p class="beatport-hype10-list-subtitle">Editor's hottest trending picks</p>
</div>
<div class="beatport-hype10-tracks" id="beatport-hype10-tracks">
<!-- Loading placeholder -->
<div class="beatport-hype10-loading">
<div class="beatport-hype10-loading-content">
<h4>🔥 Loading Hype Top 10...</h4>
<p>Fetching editor's picks</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Top 10 Releases Section -->
<div class="beatport-releases-top10-section">
<div class="beatport-releases-top10-header">
<h2 class="beatport-releases-top10-title">💿 Top 10 Releases</h2>
<p class="beatport-releases-top10-subtitle">Most popular albums and EPs on Beatport</p>
</div>
<div class="beatport-releases-top10-container">
<div class="beatport-releases-top10-list" id="beatport-releases-top10-list">
<!-- Loading placeholder -->
<div class="beatport-releases-top10-loading">
<div class="beatport-releases-top10-loading-content">
<h4>💿 Loading Top 10 Releases...</h4>
<p>Fetching trending albums and EPs</p>
</div>
</div>
</div>
</div>
</div>
<!-- New Releases Grid Slideshow Section -->
<div class="beatport-releases-section">
<div class="beatport-releases-header">
<h2 class="beatport-releases-title">🆕 New Releases</h2>
<p class="beatport-releases-subtitle">Latest albums and EPs from Beatport</p>
</div>
<div class="beatport-releases-slider-container">
<div class="beatport-releases-slider" id="beatport-releases-slider">
<div class="beatport-releases-slider-track" id="beatport-releases-slider-track">
<!-- Loading placeholder -->
<div class="beatport-releases-loading">
<div class="beatport-releases-loading-content">
<h3>📀 Loading New Releases...</h3>
<p>Fetching the latest albums and EPs</p>
</div>
</div>
</div>
<!-- Slider Navigation -->
<div class="beatport-releases-slider-nav">
<button class="beatport-releases-nav-btn beatport-releases-prev-btn" id="beatport-releases-prev-btn"></button>
<button class="beatport-releases-nav-btn beatport-releases-next-btn" id="beatport-releases-next-btn"></button>
</div>
<!-- Slider Indicators -->
<div class="beatport-releases-slider-indicators" id="beatport-releases-slider-indicators">
<!-- Indicators will be dynamically generated -->
</div>
</div>
</div>
</div>
<!-- Hype Picks Grid Slideshow Section -->
<div class="beatport-hype-picks-section">
<div class="beatport-hype-picks-header">
<h2 class="beatport-hype-picks-title">🔥 Hype Picks</h2>
<p class="beatport-hype-picks-subtitle">Editor selected trending tracks from Beatport</p>
</div>
<div class="beatport-hype-picks-slider-container">
<div class="beatport-hype-picks-slider" id="beatport-hype-picks-slider">
<div class="beatport-hype-picks-slider-track" id="beatport-hype-picks-slider-track">
<!-- Loading placeholder -->
<div class="beatport-hype-picks-loading">
<div class="beatport-hype-picks-loading-content">
<h3>🔥 Loading Hype Picks...</h3>
<p>Fetching the hottest trending tracks</p>
</div>
</div>
</div>
<!-- Slider Navigation -->
<div class="beatport-hype-picks-slider-nav">
<button class="beatport-hype-picks-nav-btn beatport-hype-picks-prev-btn" id="beatport-hype-picks-prev-btn"></button>
<button class="beatport-hype-picks-nav-btn beatport-hype-picks-next-btn" id="beatport-hype-picks-next-btn"></button>
</div>
<!-- Slider Indicators -->
<div class="beatport-hype-picks-slider-indicators" id="beatport-hype-picks-slider-indicators">
<!-- Indicators will be dynamically generated -->
</div>
</div>
</div>
</div>
<!-- Featured Charts Grid Slideshow Section -->
<div class="beatport-charts-section">
<div class="beatport-charts-header">
<h2 class="beatport-charts-title">🔥 Featured Charts</h2>
<p class="beatport-charts-subtitle">Top chart collections from Beatport creators</p>
</div>
<div class="beatport-charts-slider-container">
<div class="beatport-charts-slider" id="beatport-charts-slider">
<div class="beatport-charts-slider-track" id="beatport-charts-slider-track">
<!-- Loading placeholder -->
<div class="beatport-charts-loading">
<div class="beatport-charts-loading-content">
<h3>📊 Loading Featured Charts...</h3>
<p>Fetching top chart collections</p>
</div>
</div>
</div>
<!-- Slider Navigation -->
<div class="beatport-charts-slider-nav">
<button class="beatport-charts-nav-btn beatport-charts-prev-btn" id="beatport-charts-prev-btn"></button>
<button class="beatport-charts-nav-btn beatport-charts-next-btn" id="beatport-charts-next-btn"></button>
</div>
<!-- Slider Indicators -->
<div class="beatport-charts-slider-indicators" id="beatport-charts-slider-indicators">
<!-- Indicators will be dynamically generated -->
</div>
</div>
</div>
</div>
<!-- DJ Charts Carousel Section -->
<div class="beatport-dj-section">
<div class="beatport-dj-header">
<h2 class="beatport-dj-title">🎧 DJ Charts</h2>
<p class="beatport-dj-subtitle">Curated charts from top DJs and artists</p>
</div>
<div class="beatport-dj-slider-container">
<div class="beatport-dj-slider" id="beatport-dj-slider">
<div class="beatport-dj-slider-track" id="beatport-dj-slider-track">
<!-- Loading placeholder -->
<div class="beatport-dj-loading">
<div class="beatport-dj-loading-content">
<h3>🎧 Loading DJ Charts...</h3>
<p>Fetching curated DJ selections</p>
</div>
</div>
</div>
<!-- Slider Navigation -->
<div class="beatport-dj-slider-nav">
<button class="beatport-dj-nav-btn beatport-dj-prev-btn" id="beatport-dj-prev-btn"></button>
<button class="beatport-dj-nav-btn beatport-dj-next-btn" id="beatport-dj-next-btn"></button>
</div>
<!-- Slider Indicators -->
<div class="beatport-dj-slider-indicators" id="beatport-dj-slider-indicators">
<!-- Indicators will be dynamically generated -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Right Panel: Sidebar with Options & Logging -->
<div class="sync-sidebar">
<div class="sidebar-section">
<h4>Sync Actions</h4>
<div id="selection-info">Select playlists to sync</div>
<button id="start-sync-btn" class="neo-button" disabled>Start Sync</button>
</div>
<div class="sidebar-section progress-section">
<h4>Sync Progress</h4>
<div class="progress-bar-container">
<div class="progress-bar-fill" id="sync-progress-bar" style="width: 0%;"></div>
</div>
<div id="sync-progress-text">Ready to sync...</div>
<textarea id="sync-log-area" readonly>Waiting for sync to start...</textarea>
</div>
</div>
</div>
</div>
<!-- Downloads Page -->
<div class="page" id="downloads-page">
<!--
This top-level container replicates the QSplitter from downloads.py,
creating the two-panel layout for the page.
-->
<div class="downloads-content">
<!-- ======================================================= -->
<!-- == LEFT PANEL: Search, Filters, and Results == -->
<!-- ======================================================= -->
<div class="downloads-main-panel">
<!-- Header: Replicates create_elegant_header() -->
<div class="downloads-header">
<h2 class="downloads-title">🎵 Music Downloads</h2>
<p class="downloads-subtitle">Search, discover, and download high-quality music</p>
</div>
<!-- Search Bar: Replicates create_elegant_search_bar() -->
<div class="search-bar-container">
<input type="text" id="downloads-search-input" placeholder="Search for music... (e.g., 'Virtual Mage', 'Queen Bohemian Rhapsody')">
<button id="downloads-cancel-btn" class="hidden">✕ Cancel</button>
<button id="downloads-search-btn">🔍 Search</button>
</div>
<div id="filters-container" class="filters-container hidden">
<div class="filter-toggle-header">
<button id="filter-toggle-btn" class="filter-toggle-btn">⏷ Filters</button>
</div>
<div id="filter-content" class="filter-content hidden">
<!-- Filter by Type -->
<div class="filter-group">
<label class="filter-label">Type:</label>
<button class="filter-btn active" data-filter-type="type" data-value="all">All</button>
<button class="filter-btn" data-filter-type="type" data-value="album">Albums</button>
<button class="filter-btn" data-filter-type="type" data-value="track">Singles</button>
</div>
<!-- Filter by Format -->
<div class="filter-group">
<label class="filter-label">Format:</label>
<button class="filter-btn active" data-filter-type="format" data-value="all">All</button>
<button class="filter-btn" data-filter-type="format" data-value="flac">FLAC</button>
<button class="filter-btn" data-filter-type="format" data-value="mp3">MP3</button>
<!-- Added missing format buttons -->
<button class="filter-btn" data-filter-type="format" data-value="ogg">OGG</button>
<button class="filter-btn" data-filter-type="format" data-value="aac">AAC</button>
<button class="filter-btn" data-filter-type="format" data-value="wma">WMA</button>
</div>
<!-- Sort Controls -->
<div class="filter-group">
<label class="filter-label">Sort by:</label>
<button id="sort-order-btn" class="filter-btn sort-order-btn" data-order="desc"></button>
<!-- Added all sort options from the GUI -->
<button class="filter-btn active" data-filter-type="sort" data-value="relevance">Relevance</button>
<button class="filter-btn" data-filter-type="sort" data-value="quality_score">Quality</button>
<button class="filter-btn" data-filter-type="sort" data-value="size">Size</button>
<button class="filter-btn" data-filter-type="sort" data-value="title">Name</button>
<button class="filter-btn" data-filter-type="sort" data-value="username">Uploader</button>
<button class="filter-btn" data-filter-type="sort" data-value="bitrate">Bitrate</button>
<button class="filter-btn" data-filter-type="sort" data-value="duration">Duration</button>
<button class="filter-btn" data-filter-type="sort" data-value="availability">Available</button>
<button class="filter-btn" data-filter-type="sort" data-value="upload_speed">Speed</button>
</div>
</div>
</div>
<!-- Search Status Bar -->
<div class="search-status-container">
<div class="spinner-animation hidden"></div>
<p id="search-status-text">Ready to search • Enter artist, song, or album name</p>
<div class="dots-animation hidden"></div>
</div>
<!-- Search Results Area: Replicates the QScrollArea -->
<div class="search-results-container">
<div class="search-results-header">
<h3>Search Results</h3>
</div>
<div class="search-results-scroll-area" id="search-results-area">
<!--
The placeholder search results have been removed.
This area will now be populated by JavaScript based on API responses.
-->
<div class="search-results-placeholder">
<p>Your search results will appear here.</p>
</div>
</div>
</div>
</div>
<!-- ======================================================= -->
<!-- == RIGHT PANEL: Controls and Download Queue == -->
<!-- ======================================================= -->
<div class="downloads-side-panel">
<!-- Controls Panel: Replicates create_collapsible_controls_panel() -->
<div class="controls-panel">
<h3 class="controls-panel__header">Download Manager</h3>
<div class="controls-panel__stats">
<p id="active-downloads-label">• Active Downloads: 0</p>
<p id="finished-downloads-label">• Finished Downloads: 0</p>
</div>
<div class="controls-panel__actions">
<button class="controls-panel__clear-btn">🗑️ Clear Completed</button>
</div>
</div>
<!-- Download Queue: Replicates TabbedDownloadManager -->
<div class="download-manager">
<div class="download-manager__tabs">
<button class="tab-btn active" data-tab="active-queue">Download Queue (0)</button>
<button class="tab-btn" data-tab="finished-queue">Finished (0)</button>
</div>
<div class="download-manager__content">
<!-- Active Queue -->
<div class="download-queue active" id="active-queue">
<div class="download-queue__empty-message">No active downloads.</div>
</div>
<!-- Finished Queue -->
<div class="download-queue" id="finished-queue">
<div class="download-queue__empty-message">No finished downloads.</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Artists Page -->
<div class="page" id="artists-page">
<!-- Initial Search State -->
<div class="artists-search-state" id="artists-search-state">
<div class="artists-search-container">
<div class="artists-welcome-section">
<h2 class="artists-welcome-title">🎵 Discover Artists</h2>
<p class="artists-welcome-subtitle">Search for your favorite artists and explore their complete discography</p>
</div>
<div class="artists-search-input-container">
<input type="text"
id="artists-search-input"
class="artists-search-input"
placeholder="Search for an artist...">
<div class="artists-search-icon">🔍</div>
</div>
<div class="artists-search-status" id="artists-search-status">
Start typing to search for artists
</div>
</div>
</div>
<!-- Search Results State -->
<div class="artists-results-state hidden" id="artists-results-state">
<div class="artists-results-header">
<button class="artists-back-button" id="artists-back-button">
<span class="back-icon"></span>
<span>Back to Search</span>
</button>
<div class="artists-search-header">
<input type="text"
id="artists-header-search-input"
class="artists-header-search-input"
placeholder="Search for an artist...">
</div>
</div>
<div class="artists-results-content">
<div class="artists-results-title">Search Results</div>
<div class="artists-cards-container" id="artists-cards-container">
<!-- Artist cards will be dynamically populated here -->
</div>
</div>
</div>
<!-- Artist Detail State -->
<div class="artist-detail-state hidden" id="artist-detail-state">
<div class="artist-detail-header">
<div class="artist-detail-header-left">
<button class="artist-detail-back-button" id="artist-detail-back-button">
<span class="back-icon"></span>
<span>Back to Results</span>
</button>
<div class="artist-detail-info">
<div class="artist-detail-image" id="search-artist-detail-image"></div>
<div class="artist-detail-text">
<h2 class="artist-detail-name" id="search-artist-detail-name">Artist Name</h2>
<p class="artist-detail-genres" id="search-artist-detail-genres">Genres</p>
</div>
</div>
</div>
<button class="artist-detail-watchlist-btn" id="artist-detail-watchlist-btn">
<span class="watchlist-icon">👁️</span>
<span class="watchlist-text">Add to Watchlist</span>
</button>
</div>
<div class="artist-detail-content">
<div class="artist-detail-tabs">
<button class="artist-tab active" data-tab="albums" id="albums-tab">
<span class="tab-icon">💿</span>
<span>Albums</span>
</button>
<button class="artist-tab" data-tab="singles" id="singles-tab">
<span class="tab-icon">🎵</span>
<span>Singles & EPs</span>
</button>
</div>
<div class="artist-detail-discography">
<div class="tab-content active" id="albums-content">
<div class="album-cards-container" id="album-cards-container">
<!-- Album cards will be populated here -->
</div>
</div>
<div class="tab-content" id="singles-content">
<div class="singles-cards-container" id="singles-cards-container">
<!-- Singles cards will be populated here -->
</div>
</div>
</div>
<!-- Similar Artists Section -->
<div class="similar-artists-section" id="similar-artists-section">
<div class="similar-artists-header">
<h3 class="similar-artists-title">Similar Artists</h3>
<p class="similar-artists-subtitle">Discover artists with a similar sound</p>
</div>
<!-- Loading State -->
<div class="similar-artists-loading hidden" id="similar-artists-loading">
<div class="loading-spinner-small"></div>
<span>Finding similar artists...</span>
</div>
<!-- Error State -->
<div class="similar-artists-error hidden" id="similar-artists-error">
<span class="error-icon">⚠️</span>
<span class="error-text">Unable to load similar artists</span>
</div>
<!-- Similar Artists Bubbles Container -->
<div class="similar-artists-bubbles-container" id="similar-artists-bubbles-container">
<!-- Artist bubble cards will be populated here -->
</div>
</div>
</div>
</div>
</div>
<!-- Library Page -->
<div class="page" id="library-page">
<div class="library-container">
<!-- Header -->
<div class="library-header">
<div class="library-header-content">
<h2 class="library-title">📚 Music Library</h2>
<p class="library-subtitle">Browse your complete music collection</p>
</div>
<div class="library-stats" id="library-stats">
<span class="library-stat">
<span class="stat-number" id="library-artist-count">0</span>
<span class="stat-label">Artists</span>
</span>
</div>
</div>
<!-- Search and Filters -->
<div class="library-controls">
<div class="library-search-container">
<input type="text"
id="library-search-input"
class="library-search-input"
placeholder="Search artists...">
<div class="library-search-icon">🔍</div>
</div>
<!-- Alphabet Selector -->
<div class="alphabet-selector" id="alphabet-selector">
<div class="alphabet-selector-inner">
<button class="alphabet-btn active" data-letter="all">All</button>
<button class="alphabet-btn" data-letter="a">A</button>
<button class="alphabet-btn" data-letter="b">B</button>
<button class="alphabet-btn" data-letter="c">C</button>
<button class="alphabet-btn" data-letter="d">D</button>
<button class="alphabet-btn" data-letter="e">E</button>
<button class="alphabet-btn" data-letter="f">F</button>
<button class="alphabet-btn" data-letter="g">G</button>
<button class="alphabet-btn" data-letter="h">H</button>
<button class="alphabet-btn" data-letter="i">I</button>
<button class="alphabet-btn" data-letter="j">J</button>
<button class="alphabet-btn" data-letter="k">K</button>
<button class="alphabet-btn" data-letter="l">L</button>
<button class="alphabet-btn" data-letter="m">M</button>
<button class="alphabet-btn" data-letter="n">N</button>
<button class="alphabet-btn" data-letter="o">O</button>
<button class="alphabet-btn" data-letter="p">P</button>
<button class="alphabet-btn" data-letter="q">Q</button>
<button class="alphabet-btn" data-letter="r">R</button>
<button class="alphabet-btn" data-letter="s">S</button>
<button class="alphabet-btn" data-letter="t">T</button>
<button class="alphabet-btn" data-letter="u">U</button>
<button class="alphabet-btn" data-letter="v">V</button>
<button class="alphabet-btn" data-letter="w">W</button>
<button class="alphabet-btn" data-letter="x">X</button>
<button class="alphabet-btn" data-letter="y">Y</button>
<button class="alphabet-btn" data-letter="z">Z</button>
<button class="alphabet-btn" data-letter="#">#</button>
</div>
</div>
</div>
<!-- Content Area -->
<div class="library-content">
<!-- Loading State -->
<div class="library-loading hidden" id="library-loading">
<div class="loading-spinner"></div>
<div class="loading-text">Loading artists...</div>
</div>
<!-- Artist Grid -->
<div class="library-artists-grid" id="library-artists-grid">
<!-- Artist cards will be populated here -->
</div>
<!-- Empty State -->
<div class="library-empty hidden" id="library-empty">
<div class="empty-icon">🎵</div>
<div class="empty-title">No artists found</div>
<div class="empty-subtitle">Try adjusting your search or filters</div>
</div>
<!-- Pagination -->
<div class="library-pagination hidden" id="library-pagination">
<button class="pagination-btn" id="prev-page-btn" disabled>
<span>← Previous</span>
</button>
<div class="pagination-info">
<span id="page-info">Page 1 of 1</span>
</div>
<button class="pagination-btn" id="next-page-btn" disabled>
<span>Next →</span>
</button>
</div>
</div>
</div>
</div>
<!-- Artist Detail Page -->
<div class="page" id="artist-detail-page">
<div class="page-header">
<button class="back-btn" id="artist-detail-back-btn">
<span>← Back to Library</span>
</button>
<button class="library-artist-watchlist-btn" id="library-artist-watchlist-btn">
<span class="watchlist-icon">👁️</span>
<span class="watchlist-text">Add to Watchlist</span>
</button>
</div>
<!-- Artist Hero Section -->
<div class="artist-hero-section" id="artist-hero-section">
<div class="artist-hero-content">
<div class="artist-image-container">
<img class="artist-image" id="artist-detail-image" src="" alt="Artist Image" />
<div class="artist-image-fallback" id="artist-detail-image-fallback">🎵</div>
</div>
<div class="artist-info">
<h1 class="artist-name" id="artist-detail-name">Artist Name</h1>
<div class="artist-genres-container" id="artist-genres"></div>
<div class="collection-overview">
<div class="collection-category">
<div class="category-header">
<span class="category-label">Albums</span>
<span class="category-stats" id="albums-stats">0 owned, 0 missing</span>
</div>
<div class="completion-section">
<div class="completion-bar">
<div class="completion-fill" id="albums-completion-fill" style="width: 0%"></div>
</div>
<span class="completion-text" id="albums-completion-text">0%</span>
</div>
</div>
<div class="collection-category">
<div class="category-header">
<span class="category-label">EPs</span>
<span class="category-stats" id="eps-stats">0 owned, 0 missing</span>
</div>
<div class="completion-section">
<div class="completion-bar">
<div class="completion-fill" id="eps-completion-fill" style="width: 0%"></div>
</div>
<span class="completion-text" id="eps-completion-text">0%</span>
</div>
</div>
<div class="collection-category">
<div class="category-header">
<span class="category-label">Singles</span>
<span class="category-stats" id="singles-stats">0 owned, 0 missing</span>
</div>
<div class="completion-section">
<div class="completion-bar">
<div class="completion-fill" id="singles-completion-fill" style="width: 0%"></div>
</div>
<span class="completion-text" id="singles-completion-text">0%</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="artist-detail-content">
<!-- Loading State -->
<div class="artist-detail-loading hidden" id="artist-detail-loading">
<div class="loading-spinner"></div>
<p>Loading artist discography...</p>
</div>
<!-- Error State -->
<div class="artist-detail-error hidden" id="artist-detail-error">
<div class="error-icon">⚠️</div>
<h3>Failed to load artist details</h3>
<p id="artist-detail-error-message">An error occurred while loading the artist's discography.</p>
<button class="retry-btn" id="artist-detail-retry-btn">Retry</button>
</div>
<!-- Main Content -->
<div class="artist-detail-main" id="artist-detail-main">
<!-- Discography Sections -->
<div class="discography-sections">
<!-- Albums Section -->
<div class="discography-section" id="albums-section">
<div class="section-header">
<h3>Albums</h3>
<div class="section-stats">
<span id="albums-owned-count">0 owned</span>
<span id="albums-missing-count">0 missing</span>
</div>
</div>
<div class="releases-grid" id="albums-grid">
<!-- Album cards will be populated here -->
</div>
</div>
<!-- EPs Section -->
<div class="discography-section" id="eps-section">
<div class="section-header">
<h3>EPs</h3>
<div class="section-stats">
<span id="eps-owned-count">0 owned</span>
<span id="eps-missing-count">0 missing</span>
</div>
</div>
<div class="releases-grid" id="eps-grid">
<!-- EP cards will be populated here -->
</div>
</div>
<!-- Singles Section -->
<div class="discography-section" id="singles-section">
<div class="section-header">
<h3>Singles</h3>
<div class="section-stats">
<span id="singles-owned-count">0 owned</span>
<span id="singles-missing-count">0 missing</span>
</div>
</div>
<div class="releases-grid" id="singles-grid">
<!-- Single cards will be populated here -->
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Discover Page -->
<div class="page" id="discover-page">
<div class="discover-container">
<!-- Hero Section -->
<div class="discover-hero">
<div class="discover-hero-background" id="discover-hero-bg"></div>
<div class="discover-hero-overlay"></div>
<!-- Navigation Arrows -->
<button class="discover-hero-nav discover-hero-nav-prev" onclick="navigateDiscoverHero(-1)" aria-label="Previous artist">
<span></span>
</button>
<button class="discover-hero-nav discover-hero-nav-next" onclick="navigateDiscoverHero(1)" aria-label="Next artist">
<span></span>
</button>
<div class="discover-hero-content">
<div class="discover-hero-info">
<div class="discover-hero-label">FEATURED ARTIST</div>
<h1 class="discover-hero-title" id="discover-hero-title">Loading...</h1>
<p class="discover-hero-subtitle" id="discover-hero-subtitle">Discover new music tailored to your taste</p>
<div class="discover-hero-meta" id="discover-hero-meta">
<!-- Popularity and genres will be populated here -->
</div>
<div class="discover-hero-actions">
<button class="discover-hero-button secondary" id="discover-hero-discography" onclick="viewDiscoverHeroDiscography()">
<span class="button-icon">📀</span>
<span class="button-text">View Discography</span>
</button>
<button class="discover-hero-button primary watchlist-toggle-btn" id="discover-hero-add" onclick="toggleDiscoverHeroWatchlist(event)">
<span class="watchlist-icon">👁️</span>
<span class="watchlist-text">Add to Watchlist</span>
</button>
</div>
</div>
<div class="discover-hero-image" id="discover-hero-image">
<div class="hero-image-placeholder">🎧</div>
</div>
</div>
<!-- Slideshow Indicators -->
<div class="discover-hero-indicators" id="discover-hero-indicators"></div>
</div>
<!-- Recent Releases Section -->
<div class="discover-section">
<div class="discover-section-header">
<h2 class="discover-section-title">Recent Releases</h2>
<p class="discover-section-subtitle">New music from artists you follow</p>
</div>
<div class="discover-carousel" id="recent-releases-carousel">
<!-- Content will be populated dynamically -->
<div class="discover-loading">
<div class="loading-spinner"></div>
<p>Loading recent releases...</p>
</div>
</div>
</div>
<!-- Seasonal Albums Section (Auto-shows based on current season) -->
<div class="discover-section" id="seasonal-albums-section" style="display: none;">
<div class="discover-section-header">
<h2 class="discover-section-title" id="seasonal-albums-title">Seasonal</h2>
<p class="discover-section-subtitle" id="seasonal-albums-subtitle">Seasonal music</p>
</div>
<div class="discover-carousel" id="seasonal-albums-carousel">
<!-- Content will be populated dynamically -->
</div>
</div>
<!-- Seasonal Playlist Section (Auto-shows based on current season) -->
<div class="discover-section" id="seasonal-playlist-section" style="display: none;">
<div class="discover-section-header">
<div>
<h2 class="discover-section-title" id="seasonal-playlist-title">Seasonal Mix</h2>
<p class="discover-section-subtitle" id="seasonal-playlist-subtitle">Curated seasonal playlist</p>
</div>
<div class="discover-section-actions">
<button class="action-button secondary" onclick="openDownloadModalForDiscoverPlaylist('seasonal_playlist', 'Seasonal Mix')" title="Download missing tracks">
<span class="button-icon"></span>
<span class="button-text">Download</span>
</button>
<button class="action-button primary" id="seasonal-playlist-sync-btn" onclick="startDiscoverPlaylistSync('seasonal_playlist', 'Seasonal Mix')" title="Sync to media server">
<span class="button-icon"></span>
<span class="button-text">Sync</span>
</button>
</div>
</div>
<!-- Sync Status Display -->
<div class="discover-sync-status" id="seasonal-playlist-sync-status" style="display: none;">
<div class="sync-status-content">
<div class="sync-status-label">
<span class="sync-icon"></span>
<span>Syncing to media server...</span>
</div>
<div class="sync-status-stats">
<span class="sync-stat"><span id="seasonal-playlist-sync-completed">0</span></span>
<span class="sync-stat"><span id="seasonal-playlist-sync-pending">0</span></span>
<span class="sync-stat"><span id="seasonal-playlist-sync-failed">0</span></span>
<span class="sync-stat">(<span id="seasonal-playlist-sync-percentage">0</span>%)</span>
</div>
</div>
</div>
<div class="discover-playlist-container compact" id="seasonal-playlist">
<!-- Content will be populated dynamically -->
</div>
</div>
<!-- Recently Added Section -->
<div class="discover-section" style="display: none;">
<div class="discover-section-header">
<h2 class="discover-section-title">🆕 Recently Added</h2>
<p class="discover-section-subtitle">Latest additions to your library</p>
</div>
<div class="discover-playlist-container compact" id="personalized-recently-added">
<!-- Content will be populated dynamically -->
</div>
</div>
<!-- Daily Mixes Section -->
<div class="discover-section" style="display: none;">
<div class="discover-section-header">
<h2 class="discover-section-title">🎵 Daily Mixes</h2>
<p class="discover-section-subtitle">Personalized mixes based on your taste</p>
</div>
<div class="discover-more-playlists-grid" id="daily-mixes-grid">
<!-- Content will be populated dynamically -->
</div>
</div>
<!-- Fresh Tape Section -->
<div class="discover-section">
<div class="discover-section-header">
<div>
<h2 class="discover-section-title">Fresh Tape</h2>
<p class="discover-section-subtitle">New drops from recent releases</p>
</div>
<div class="discover-section-actions">
<button class="action-button secondary" onclick="openDownloadModalForDiscoverPlaylist('release_radar', 'Fresh Tape')" title="Download missing tracks">
<span class="button-icon"></span>
<span class="button-text">Download</span>
</button>
<button class="action-button primary" id="release-radar-sync-btn" onclick="startDiscoverPlaylistSync('release_radar', 'Fresh Tape')" title="Sync to media server">
<span class="button-icon"></span>
<span class="button-text">Sync</span>
</button>
</div>
</div>
<!-- Sync Status Display -->
<div class="discover-sync-status" id="release-radar-sync-status" style="display: none;">
<div class="sync-status-content">
<div class="sync-status-label">
<span class="sync-icon"></span>
<span>Syncing to media server...</span>
</div>
<div class="sync-status-stats">
<span class="sync-stat"><span id="release-radar-sync-total">0</span></span>
<span class="sync-separator">/</span>
<span class="sync-stat"><span id="release-radar-sync-matched">0</span></span>
<span class="sync-separator">/</span>
<span class="sync-stat"><span id="release-radar-sync-failed">0</span></span>
<span class="sync-stat">(<span id="release-radar-sync-percentage">0</span>%)</span>
</div>
</div>
</div>
<div class="discover-playlist-container compact" id="release-radar-playlist">
<!-- Content will be populated dynamically -->
<div class="discover-loading">
<div class="loading-spinner"></div>
<p>Loading fresh tape...</p>
</div>
</div>
</div>
<!-- The Archives Section -->
<div class="discover-section">
<div class="discover-section-header">
<div>
<h2 class="discover-section-title">The Archives</h2>
<p class="discover-section-subtitle">Curated from your collection</p>
</div>
<div class="discover-section-actions">
<button class="action-button secondary" onclick="openDownloadModalForDiscoverPlaylist('discovery_weekly', 'The Archives')" title="Download missing tracks">
<span class="button-icon"></span>
<span class="button-text">Download</span>
</button>
<button class="action-button primary" id="discovery-weekly-sync-btn" onclick="startDiscoverPlaylistSync('discovery_weekly', 'The Archives')" title="Sync to media server">
<span class="button-icon"></span>
<span class="button-text">Sync</span>
</button>
</div>
</div>
<!-- Sync Status Display -->
<div class="discover-sync-status" id="discovery-weekly-sync-status" style="display: none;">
<div class="sync-status-content">
<div class="sync-status-label">
<span class="sync-icon"></span>
<span>Syncing to media server...</span>
</div>
<div class="sync-status-stats">
<span class="sync-stat"><span id="discovery-weekly-sync-total">0</span></span>
<span class="sync-separator">/</span>
<span class="sync-stat"><span id="discovery-weekly-sync-matched">0</span></span>
<span class="sync-separator">/</span>
<span class="sync-stat"><span id="discovery-weekly-sync-failed">0</span></span>
<span class="sync-stat">(<span id="discovery-weekly-sync-percentage">0</span>%)</span>
</div>
</div>
</div>
<div class="discover-playlist-container compact" id="discovery-weekly-playlist">
<!-- Content will be populated dynamically -->
<div class="discover-loading">
<div class="loading-spinner"></div>
<p>Loading the archives...</p>
</div>
</div>
</div>
<!-- Popular Picks Section -->
<div class="discover-section" style="display: none;">
<div class="discover-section-header">
<div>
<h2 class="discover-section-title">🔥 Popular Picks</h2>
<p class="discover-section-subtitle">Trending tracks from new discoveries</p>
</div>
<div class="discover-section-actions">
<button class="action-button secondary" onclick="openDownloadModalForDiscoverPlaylist('popular_picks', 'Popular Picks')" title="Download missing tracks">
<span class="button-icon"></span>
<span class="button-text">Download</span>
</button>
<button class="action-button primary" id="popular-picks-sync-btn" onclick="startDiscoverPlaylistSync('popular_picks', 'Popular Picks')" title="Sync to media server">
<span class="button-icon"></span>
<span class="button-text">Sync</span>
</button>
</div>
</div>
<!-- Sync Status Display -->
<div class="discover-sync-status" id="popular-picks-sync-status" style="display: none;">
<div class="sync-status-content">
<div class="sync-status-label">
<span class="sync-icon"></span>
<span>Syncing to media server...</span>
</div>
<div class="sync-status-stats">
<span class="sync-stat"><span id="popular-picks-sync-completed">0</span></span>
<span class="sync-stat"><span id="popular-picks-sync-pending">0</span></span>
<span class="sync-stat"><span id="popular-picks-sync-failed">0</span></span>
<span class="sync-stat">(<span id="popular-picks-sync-percentage">0</span>%)</span>
</div>
</div>
</div>
<div class="discover-playlist-container compact" id="personalized-popular-picks">
<!-- Content will be populated dynamically -->
</div>
</div>
<!-- Hidden Gems Section -->
<div class="discover-section" style="display: none;">
<div class="discover-section-header">
<div>
<h2 class="discover-section-title">🌟 Hidden Gems</h2>
<p class="discover-section-subtitle">Underground discoveries waiting for you</p>
</div>
<div class="discover-section-actions">
<button class="action-button secondary" onclick="openDownloadModalForDiscoverPlaylist('hidden_gems', 'Hidden Gems')" title="Download missing tracks">
<span class="button-icon"></span>
<span class="button-text">Download</span>
</button>
<button class="action-button primary" id="hidden-gems-sync-btn" onclick="startDiscoverPlaylistSync('hidden_gems', 'Hidden Gems')" title="Sync to media server">
<span class="button-icon"></span>
<span class="button-text">Sync</span>
</button>
</div>
</div>
<!-- Sync Status Display -->
<div class="discover-sync-status" id="hidden-gems-sync-status" style="display: none;">
<div class="sync-status-content">
<div class="sync-status-label">
<span class="sync-icon"></span>
<span>Syncing to media server...</span>
</div>
<div class="sync-status-stats">
<span class="sync-stat"><span id="hidden-gems-sync-completed">0</span></span>
<span class="sync-stat"><span id="hidden-gems-sync-pending">0</span></span>
<span class="sync-stat"><span id="hidden-gems-sync-failed">0</span></span>
<span class="sync-stat">(<span id="hidden-gems-sync-percentage">0</span>%)</span>
</div>
</div>
</div>
<div class="discover-playlist-container compact" id="personalized-hidden-gems">
<!-- Content will be populated dynamically -->
</div>
</div>
<!-- Your Top 50 Section -->
<div class="discover-section" style="display: none;">
<div class="discover-section-header">
<h2 class="discover-section-title">🏆 Your Top 50</h2>
<p class="discover-section-subtitle">All-time favorites from your library</p>
</div>
<div class="discover-playlist-container compact" id="personalized-top-tracks">
<!-- Content will be populated dynamically -->
</div>
</div>
<!-- Forgotten Favorites Section -->
<div class="discover-section" style="display: none;">
<div class="discover-section-header">
<h2 class="discover-section-title">💎 Forgotten Favorites</h2>
<p class="discover-section-subtitle">Rediscover tracks you used to love</p>
</div>
<div class="discover-playlist-container compact" id="personalized-forgotten-favorites">
<!-- Content will be populated dynamically -->
</div>
</div>
<!-- Discovery Shuffle Section -->
<div class="discover-section" style="display: none;">
<div class="discover-section-header">
<div>
<h2 class="discover-section-title">🔀 Discovery Shuffle</h2>
<p class="discover-section-subtitle">Random tracks from your discovery pool - different every time</p>
</div>
<div class="discover-section-actions">
<button class="action-button secondary" onclick="openDownloadModalForDiscoverPlaylist('discovery_shuffle', 'Discovery Shuffle')" title="Download missing tracks">
<span class="button-icon"></span>
<span class="button-text">Download</span>
</button>
<button class="action-button primary" id="discovery-shuffle-sync-btn" onclick="startDiscoverPlaylistSync('discovery_shuffle', 'Discovery Shuffle')" title="Sync to media server">
<span class="button-icon"></span>
<span class="button-text">Sync</span>
</button>
</div>
</div>
<!-- Sync Status Display -->
<div class="discover-sync-status" id="discovery-shuffle-sync-status" style="display: none;">
<div class="sync-status-content">
<div class="sync-status-label">
<span class="sync-icon"></span>
<span>Syncing to media server...</span>
</div>
<div class="sync-status-stats">
<span class="sync-stat"><span id="discovery-shuffle-sync-completed">0</span></span>
<span class="sync-stat"><span id="discovery-shuffle-sync-pending">0</span></span>
<span class="sync-stat"><span id="discovery-shuffle-sync-failed">0</span></span>
<span class="sync-stat">(<span id="discovery-shuffle-sync-percentage">0</span>%)</span>
</div>
</div>
</div>
<div class="discover-playlist-container compact" id="personalized-discovery-shuffle">
<!-- Content will be populated dynamically -->
</div>
</div>
<!-- Familiar Favorites Section -->
<div class="discover-section" style="display: none;">
<div class="discover-section-header">
<div>
<h2 class="discover-section-title">❤️ Familiar Favorites</h2>
<p class="discover-section-subtitle">Your reliable go-to tracks</p>
</div>
<div class="discover-section-actions">
<button class="action-button secondary" onclick="openDownloadModalForDiscoverPlaylist('familiar_favorites', 'Familiar Favorites')" title="Download missing tracks">
<span class="button-icon"></span>
<span class="button-text">Download</span>
</button>
<button class="action-button primary" id="familiar-favorites-sync-btn" onclick="startDiscoverPlaylistSync('familiar_favorites', 'Familiar Favorites')" title="Sync to media server">
<span class="button-icon"></span>
<span class="button-text">Sync</span>
</button>
</div>
</div>
<!-- Sync Status Display -->
<div class="discover-sync-status" id="familiar-favorites-sync-status" style="display: none;">
<div class="sync-status-content">
<div class="sync-status-label">
<span class="sync-icon"></span>
<span>Syncing to media server...</span>
</div>
<div class="sync-status-stats">
<span class="sync-stat"><span id="familiar-favorites-sync-completed">0</span></span>
<span class="sync-stat"><span id="familiar-favorites-sync-pending">0</span></span>
<span class="sync-stat"><span id="familiar-favorites-sync-failed">0</span></span>
<span class="sync-stat">(<span id="familiar-favorites-sync-percentage">0</span>%)</span>
</div>
</div>
</div>
<div class="discover-playlist-container compact" id="personalized-familiar-favorites">
<!-- Content will be populated dynamically -->
</div>
</div>
<!-- Build a Playlist Section -->
<div class="discover-section">
<div class="discover-section-header">
<h2 class="discover-section-title">🎨 Build a Playlist</h2>
<p class="discover-section-subtitle">Create a custom playlist from your favorite artists</p>
</div>
<div class="build-playlist-container">
<!-- Artist Search -->
<div class="build-playlist-search-section">
<input
type="text"
id="build-playlist-search"
placeholder="Search for artists (1-5 artists)..."
oninput="searchBuildPlaylistArtists()"
/>
<div id="build-playlist-search-results" class="build-playlist-search-results"></div>
</div>
<!-- Selected Artists -->
<div class="build-playlist-selected-section">
<h3>Selected Artists:</h3>
<div id="build-playlist-selected-artists" class="build-playlist-selected-artists">
<div class="build-playlist-no-selection">No artists selected. Search and select 1-5 artists.</div>
</div>
</div>
<!-- Generate Button -->
<div class="build-playlist-actions">
<button
id="build-playlist-generate-btn"
class="build-playlist-generate-btn"
onclick="generateBuildPlaylist()"
disabled
style="opacity: 0.5;"
>
Generate Playlist (50 tracks)
</button>
<div id="build-playlist-loading" class="build-playlist-loading" style="display: none;">
<div class="loading-spinner"></div>
<p>Building your playlist...</p>
</div>
</div>
<!-- Generated Playlist Results -->
<div id="build-playlist-results-wrapper" style="display: none;">
<!-- Playlist Header with Actions -->
<div class="discover-section-header" style="margin-top: 20px;">
<div>
<h3 id="build-playlist-results-title" style="margin: 0; color: #fff; font-size: 18px;">Generated Playlist</h3>
<p id="build-playlist-results-subtitle" style="margin: 4px 0 0 0; color: #999; font-size: 13px;"></p>
</div>
<div class="discover-section-actions">
<button class="action-button secondary" onclick="openDownloadModalForBuildPlaylist()" title="Download missing tracks">
<span class="button-icon"></span>
<span class="button-text">Download</span>
</button>
<button class="action-button primary" id="build-playlist-sync-btn" onclick="startDiscoverPlaylistSync('build_playlist', 'Custom Playlist')" title="Sync to media server">
<span class="button-icon"></span>
<span class="button-text">Sync</span>
</button>
</div>
</div>
<!-- Sync Status Display -->
<div class="discover-sync-status" id="build-playlist-sync-status" style="display: none;">
<div class="sync-status-content">
<div class="sync-status-label">
<span class="sync-icon"></span>
<span>Syncing to media server...</span>
</div>
<div class="sync-status-stats">
<span class="sync-stat"><span id="build-playlist-sync-completed">0</span></span>
<span class="sync-stat"><span id="build-playlist-sync-pending">0</span></span>
<span class="sync-stat"><span id="build-playlist-sync-failed">0</span></span>
<span class="sync-stat">(<span id="build-playlist-sync-percentage">0</span>%)</span>
</div>
</div>
</div>
<!-- Metadata Display -->
<div id="build-playlist-metadata-display"></div>
<!-- Track List -->
<div id="build-playlist-results" class="discover-playlist-container compact">
<!-- Generated playlist will appear here -->
</div>
</div>
</div>
</div>
<!-- ListenBrainz Playlists (Tabbed) -->
<div class="discover-section">
<div class="discover-section-header">
<div>
<h2 class="discover-section-title">🧠 ListenBrainz Playlists</h2>
<p class="discover-section-subtitle">Playlists from ListenBrainz</p>
</div>
<div class="discover-section-actions">
<button class="action-button primary" id="listenbrainz-refresh-btn" onclick="refreshListenBrainzPlaylists()" title="Refresh playlists from ListenBrainz">
<span class="button-icon">🔄</span>
<span class="button-text">Refresh</span>
</button>
</div>
</div>
<!-- ListenBrainz Tabs -->
<div class="listenbrainz-tabs" id="listenbrainz-tabs">
<div class="discover-loading"><div class="loading-spinner"></div><p>Loading playlists...</p></div>
</div>
<!-- ListenBrainz Tab Content -->
<div class="listenbrainz-tab-content" id="listenbrainz-tab-content">
<!-- Content will be populated dynamically -->
</div>
</div>
<!-- Time Machine (Tabbed by Decade) -->
<div class="discover-section">
<div class="discover-section-header">
<h2 class="discover-section-title">⏰ Time Machine</h2>
<p class="discover-section-subtitle">Explore music from different decades</p>
</div>
<!-- Decade Tabs (will be populated dynamically) -->
<div class="decade-tabs" id="decade-tabs">
<div class="discover-loading"><div class="loading-spinner"></div><p>Loading decades...</p></div>
</div>
<!-- Decade Tab Contents (will be populated dynamically) -->
<div id="decade-tab-contents"></div>
</div>
<!-- Browse by Genre (Tabbed by Genre) -->
<div class="discover-section">
<div class="discover-section-header">
<h2 class="discover-section-title">🎵 Browse by Genre</h2>
<p class="discover-section-subtitle">Discover music by your favorite genres</p>
</div>
<!-- Genre Tabs (will be populated dynamically) -->
<div class="genre-tabs" id="genre-tabs">
<div class="discover-loading"><div class="loading-spinner"></div><p>Loading genres...</p></div>
</div>
<!-- Genre Tab Contents (will be populated dynamically) -->
<div id="genre-tab-contents"></div>
</div>
</div>
</div>
<!-- Settings Page -->
<div class="page" id="settings-page">
<div class="page-header">
<h2>Settings</h2>
<button class="save-button" onclick="document.getElementById('save-settings').click()">💾 Save Settings</button>
</div>
<div class="settings-content">
<!-- Two Column Layout -->
<div class="settings-columns">
<!-- Left Column - API Configuration -->
<div class="settings-left-column">
<!-- API Configuration -->
<div class="settings-group">
<h3>API Configuration</h3>
<!-- Spotify Settings -->
<div class="api-service-frame">
<h4 class="service-title spotify-title">Spotify</h4>
<div class="form-group">
<label>Client ID:</label>
<input type="text" id="spotify-client-id" placeholder="Spotify Client ID">
</div>
<div class="form-group">
<label>Client Secret:</label>
<input type="password" id="spotify-client-secret" placeholder="Spotify Client Secret">
</div>
<div class="form-group">
<label>Redirect URI:</label>
<input type="text" id="spotify-redirect-uri" placeholder="http://127.0.0.1:8888/callback">
</div>
<div class="callback-info">
<div class="callback-label">Current Redirect URI:</div>
<div class="callback-url" id="spotify-callback-display">http://127.0.0.1:8888/callback</div>
<div class="callback-help">Add this URL to your Spotify app's 'Redirect URIs' in the Spotify Developer Dashboard</div>
</div>
<div class="form-actions">
<button class="auth-button" onclick="authenticateSpotify()">🔐 Authenticate</button>
</div>
</div>
<!-- Tidal Settings -->
<div class="api-service-frame">
<h4 class="service-title tidal-title">Tidal</h4>
<div class="form-group">
<label>Client ID:</label>
<input type="text" id="tidal-client-id" placeholder="Tidal Client ID">
</div>
<div class="form-group">
<label>Client Secret:</label>
<input type="password" id="tidal-client-secret" placeholder="Tidal Client Secret">
</div>
<div class="form-group">
<label>Redirect URI:</label>
<input type="text" id="tidal-redirect-uri" placeholder="http://127.0.0.1:8889/tidal/callback">
</div>
<div class="callback-info">
<div class="callback-label">Current Redirect URI:</div>
<div class="callback-url" id="tidal-callback-display">http://127.0.0.1:8889/tidal/callback</div>
<div class="callback-help">Add this URL to your Tidal app configuration</div>
</div>
<div class="form-actions">
<button class="auth-button" onclick="authenticateTidal()">🔐 Authenticate</button>
</div>
</div>
<!-- Soulseek Settings -->
<div class="api-service-frame">
<h4 class="service-title soulseek-title">Soulseek</h4>
<div class="form-group">
<label>slskd URL:</label>
<div class="path-input-group">
<input type="url" id="soulseek-url" placeholder="http://localhost:5030">
<button class="detect-button" onclick="autoDetectSlskd()">Auto-detect</button>
</div>
</div>
<div class="form-group">
<label>API Key:</label>
<input type="password" id="soulseek-api-key" placeholder="Slskd API Key">
</div>
</div>
<!-- ListenBrainz Settings -->
<div class="api-service-frame">
<h4 class="service-title listenbrainz-title">ListenBrainz</h4>
<div class="form-group">
<label>User Token:</label>
<input type="password" id="listenbrainz-token" placeholder="ListenBrainz User Token">
</div>
<div class="callback-info">
<div class="callback-help">Get your token from <a href="https://listenbrainz.org/profile/" target="_blank" style="color: #eb743b;">ListenBrainz Settings</a></div>
</div>
</div>
<!-- Test Connection Buttons -->
<div class="api-test-buttons">
<button class="test-button" onclick="testConnection('spotify')">Test Spotify</button>
<button class="test-button" onclick="testConnection('tidal')">Test Tidal</button>
<button class="test-button" onclick="testConnection('soulseek')">Test Soulseek</button>
<button class="test-button" onclick="testConnection('listenbrainz')">Test ListenBrainz</button>
</div>
</div>
<!-- Server Connections -->
<div class="settings-group">
<h3>Server Connections</h3>
<!-- Server Toggle Buttons -->
<div class="server-toggle-container">
<button class="server-toggle-btn active" id="plex-toggle" onclick="toggleServer('plex')">
<img src="https://www.plex.tv/wp-content/themes/plex/assets/img/plex-logo.svg" alt="Plex" class="server-logo">
</button>
<button class="server-toggle-btn" id="jellyfin-toggle" onclick="toggleServer('jellyfin')">
<img src="https://jellyfin.org/images/logo.svg" alt="Jellyfin" class="server-logo">
</button>
<button class="server-toggle-btn" id="navidrome-toggle" onclick="toggleServer('navidrome')">
<img src="https://tweakers.net/ext/i/2007323764.png" alt="Navidrome" class="server-logo">
Navidrome
</button>
</div>
<!-- Plex Settings -->
<div class="server-config-container" id="plex-container">
<div class="form-group">
<label>Plex Server URL:</label>
<input type="url" id="plex-url" placeholder="http://localhost:32400">
</div>
<div class="form-group">
<label>Plex Token:</label>
<input type="password" id="plex-token" placeholder="X-Plex-Token">
</div>
<div class="form-group" id="plex-library-selector-container" style="display: none;">
<label>Music Library:</label>
<select id="plex-music-library" onchange="selectPlexLibrary()">
<option value="">Loading...</option>
</select>
<small style="color: #999; font-size: 0.9em; display: block; margin-top: 5px;">
Select which music library to use (doesn't affect config file)
</small>
</div>
<div class="form-actions">
<button class="detect-button" onclick="autoDetectPlex()">Auto-detect</button>
<button class="test-button" onclick="testConnection('plex')">Test</button>
</div>
</div>
<!-- Jellyfin Settings -->
<div class="server-config-container hidden" id="jellyfin-container">
<div class="form-group">
<label>Jellyfin Server URL:</label>
<input type="url" id="jellyfin-url" placeholder="http://localhost:8096">
</div>
<div class="form-group">
<label>API Key:</label>
<input type="password" id="jellyfin-api-key" placeholder="Jellyfin API Key">
</div>
<div class="form-actions">
<button class="detect-button" onclick="autoDetectJellyfin()">Auto-detect</button>
<button class="test-button" onclick="testConnection('jellyfin')">Test</button>
</div>
</div>
<!-- Navidrome Settings -->
<div class="server-config-container hidden" id="navidrome-container">
<div class="form-group">
<label>Navidrome Server URL:</label>
<input type="url" id="navidrome-url" placeholder="http://localhost:4533">
</div>
<div class="form-group">
<label>Username:</label>
<input type="text" id="navidrome-username" placeholder="Username">
</div>
<div class="form-group">
<label>Password:</label>
<input type="password" id="navidrome-password" placeholder="Password">
</div>
<div class="form-actions">
<button class="detect-button" onclick="autoDetectNavidrome()">Auto-detect</button>
<button class="test-button" onclick="testConnection('navidrome')">Test</button>
</div>
</div>
<!-- Server Test Button -->
<div class="server-test-section">
<button class="test-button server-test-btn" onclick="testConnection('server')">Test Server</button>
</div>
</div>
</div>
<!-- Right Column - Download Settings, Database, Metadata, Logging -->
<div class="settings-right-column">
<!-- Download Settings -->
<div class="settings-group">
<h3>Download Settings</h3>
<div class="form-group">
<label>Slskd Download Dir:</label>
<div class="path-input-group">
<input type="text" id="download-path" placeholder="./downloads">
<button class="browse-button" onclick="browsePath('download')">Browse</button>
</div>
</div>
<div class="form-group">
<label>Matched Transfer Dir (Plex Music Dir?):</label>
<div class="path-input-group">
<input type="text" id="transfer-path" placeholder="./Transfer">
<button class="browse-button" onclick="browsePath('transfer')">Browse</button>
</div>
</div>
</div>
<!-- Quality Profile Settings -->
<div class="settings-group">
<h3>🎵 Quality Profile</h3>
<!-- Presets -->
<div class="quality-presets">
<label>Quick Presets:</label>
<div class="preset-buttons">
<button class="preset-button" onclick="applyQualityPreset('audiophile')" title="FLAC only, strict size constraints">
🎧 Audiophile
</button>
<button class="preset-button active" onclick="applyQualityPreset('balanced')" title="FLAC preferred, MP3 fallback">
⚖️ Balanced
</button>
<button class="preset-button" onclick="applyQualityPreset('space_saver')" title="MP3 preferred, smaller sizes">
💾 Space Saver
</button>
</div>
</div>
<!-- FLAC Quality -->
<div class="quality-tier">
<div class="quality-tier-header">
<label class="checkbox-label">
<input type="checkbox" id="quality-flac-enabled" checked onchange="toggleQuality('flac')">
<span class="quality-tier-name">FLAC (Lossless)</span>
</label>
<span class="quality-tier-priority" id="priority-flac">Priority: 1</span>
</div>
<div class="quality-tier-sliders" id="sliders-flac">
<div class="slider-group">
<label>File Size Range:</label>
<div class="dual-slider-container">
<input type="range" class="range-slider range-slider-min" id="flac-min" min="0" max="200" value="0" step="5" oninput="updateQualityRange('flac')">
<input type="range" class="range-slider range-slider-max" id="flac-max" min="0" max="200" value="150" step="5" oninput="updateQualityRange('flac')">
<div class="range-slider-track"></div>
</div>
<div class="slider-values">
<span id="flac-min-value">0 MB</span>
<span>-</span>
<span id="flac-max-value">150 MB</span>
</div>
</div>
</div>
</div>
<!-- MP3 320 Quality -->
<div class="quality-tier">
<div class="quality-tier-header">
<label class="checkbox-label">
<input type="checkbox" id="quality-mp3_320-enabled" checked onchange="toggleQuality('mp3_320')">
<span class="quality-tier-name">MP3 320 kbps</span>
</label>
<span class="quality-tier-priority" id="priority-mp3_320">Priority: 2</span>
</div>
<div class="quality-tier-sliders" id="sliders-mp3_320">
<div class="slider-group">
<label>File Size Range:</label>
<div class="dual-slider-container">
<input type="range" class="range-slider range-slider-min" id="mp3_320-min" min="0" max="50" value="0" step="1" oninput="updateQualityRange('mp3_320')">
<input type="range" class="range-slider range-slider-max" id="mp3_320-max" min="0" max="50" value="20" step="1" oninput="updateQualityRange('mp3_320')">
<div class="range-slider-track"></div>
</div>
<div class="slider-values">
<span id="mp3_320-min-value">0 MB</span>
<span>-</span>
<span id="mp3_320-max-value">20 MB</span>
</div>
</div>
</div>
</div>
<!-- MP3 256 Quality -->
<div class="quality-tier">
<div class="quality-tier-header">
<label class="checkbox-label">
<input type="checkbox" id="quality-mp3_256-enabled" checked onchange="toggleQuality('mp3_256')">
<span class="quality-tier-name">MP3 256 kbps</span>
</label>
<span class="quality-tier-priority" id="priority-mp3_256">Priority: 3</span>
</div>
<div class="quality-tier-sliders" id="sliders-mp3_256">
<div class="slider-group">
<label>File Size Range:</label>
<div class="dual-slider-container">
<input type="range" class="range-slider range-slider-min" id="mp3_256-min" min="0" max="40" value="0" step="1" oninput="updateQualityRange('mp3_256')">
<input type="range" class="range-slider range-slider-max" id="mp3_256-max" min="0" max="40" value="15" step="1" oninput="updateQualityRange('mp3_256')">
<div class="range-slider-track"></div>
</div>
<div class="slider-values">
<span id="mp3_256-min-value">0 MB</span>
<span>-</span>
<span id="mp3_256-max-value">15 MB</span>
</div>
</div>
</div>
</div>
<!-- MP3 192 Quality -->
<div class="quality-tier">
<div class="quality-tier-header">
<label class="checkbox-label">
<input type="checkbox" id="quality-mp3_192-enabled" onchange="toggleQuality('mp3_192')">
<span class="quality-tier-name">MP3 192 kbps</span>
</label>
<span class="quality-tier-priority" id="priority-mp3_192">Priority: 4</span>
</div>
<div class="quality-tier-sliders disabled" id="sliders-mp3_192">
<div class="slider-group">
<label>File Size Range:</label>
<div class="dual-slider-container">
<input type="range" class="range-slider range-slider-min" id="mp3_192-min" min="0" max="30" value="0" step="1" oninput="updateQualityRange('mp3_192')">
<input type="range" class="range-slider range-slider-max" id="mp3_192-max" min="0" max="30" value="12" step="1" oninput="updateQualityRange('mp3_192')">
<div class="range-slider-track"></div>
</div>
<div class="slider-values">
<span id="mp3_192-min-value">0 MB</span>
<span>-</span>
<span id="mp3_192-max-value">12 MB</span>
</div>
</div>
</div>
</div>
<!-- Fallback Option -->
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="quality-fallback-enabled" checked>
Allow fallback to any quality if preferred qualities unavailable
</label>
</div>
<div class="help-text">
<strong>How it works:</strong> Downloads try each enabled quality in priority order (1 = highest).
File size constraints filter out outliers - MAX limits catch fake files (500MB "FLACs"), MIN limits (optional) can enforce minimum quality.
Set MIN to 0 to accept all file sizes (recommended for most users).
</div>
</div>
</div>
<!-- Third Column - Database, Metadata, Playlist Sync, Logging -->
<div class="settings-third-column">
<!-- Database Settings -->
<div class="settings-group">
<h3>Database Settings</h3>
<div class="form-group">
<label>Concurrent Workers:</label>
<select id="max-workers">
<option value="3">3</option>
<option value="4">4</option>
<option value="5" selected>5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
</select>
</div>
<div class="help-text">Number of parallel threads for database updates. Higher values = faster updates but more server load.</div>
</div>
<!-- Metadata Enhancement Settings -->
<div class="settings-group">
<h3>🎵 Metadata Enhancement</h3>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="metadata-enabled" checked>
Enable metadata enhancement with Spotify data
</label>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="embed-album-art" checked>
Embed high-quality album art from Spotify
</label>
</div>
<div class="form-group">
<label>Supported Formats:</label>
<div class="supported-formats">MP3, FLAC, MP4/M4A, OGG</div>
</div>
</div>
<!-- Playlist Sync Settings -->
<div class="settings-group">
<h3>Playlist Sync Settings</h3>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="create-backup" checked>
Create playlist backups before sync
</label>
</div>
</div>
<!-- Logging Information (Read-only) -->
<div class="settings-group">
<h3>Logging Information</h3>
<div class="form-group">
<label>Log Level:</label>
<div class="readonly-field" id="log-level-display">DEBUG</div>
</div>
<div class="form-group">
<label>Log Path:</label>
<div class="readonly-field" id="log-path-display">logs/app.log</div>
</div>
</div>
</div>
</div>
<!-- Save Button -->
<div class="settings-actions">
<button class="save-button" id="save-settings">💾 Save Settings</button>
</div>
</div>
</div>
</div>
</div>
<!-- Loading Overlay -->
<div class="loading-overlay hidden" id="loading-overlay">
<div class="loading-spinner"></div>
<div class="loading-message">Processing...</div>
</div>
<!-- Toast Notifications -->
<div class="toast-container" id="toast-container"></div>
<!-- Hidden HTML5 Audio Player for Streaming -->
<audio id="audio-player" style="display: none;"></audio>
<!-- Matched Download Modal -->
<div class="modal-overlay hidden" id="matching-modal-overlay">
<div class="matching-modal" id="matching-modal">
<div class="matching-modal-header">
<h2 id="matching-modal-title">Match Download to Spotify</h2>
<button class="matching-modal-close" onclick="closeMatchingModal()"></button>
</div>
<div class="matching-modal-content">
<!-- Artist Selection Stage -->
<div id="artist-selection-stage" class="selection-stage">
<div class="stage-header">
<h3 id="artist-stage-title">Step 1: Select the correct Artist</h3>
<p class="stage-subtitle">Choose the artist that best matches your download</p>
</div>
<div class="suggestions-section">
<h4 class="suggestions-title">Top Suggestions</h4>
<div class="suggestions-container" id="artist-suggestions">
<!-- Artist suggestion cards will be populated here -->
</div>
</div>
<div class="manual-search-section">
<h4 class="suggestions-title">Or, Search Manually</h4>
<input type="text" id="artist-search-input" class="search-input" placeholder="Search for an artist...">
<div class="suggestions-container" id="artist-manual-results">
<!-- Manual search results will be populated here -->
</div>
</div>
</div>
<!-- Album Selection Stage (for album downloads) -->
<div id="album-selection-stage" class="selection-stage hidden">
<div class="stage-header">
<h3 id="album-stage-title">Step 2: Select the correct Album</h3>
<p class="stage-subtitle">Choose the album that best matches your download for <span id="selected-artist-name"></span></p>
</div>
<div class="suggestions-section">
<h4 class="suggestions-title">Top Suggestions</h4>
<div class="suggestions-container" id="album-suggestions">
<!-- Album suggestion cards will be populated here -->
</div>
</div>
<div class="manual-search-section">
<h4 class="suggestions-title">Or, Search Manually</h4>
<input type="text" id="album-search-input" class="search-input" placeholder="Search for an album...">
<div class="suggestions-container" id="album-manual-results">
<!-- Manual search results will be populated here -->
</div>
</div>
</div>
</div>
<div class="matching-modal-actions">
<button id="skip-matching-btn" class="modal-button modal-button--secondary">Skip Matching</button>
<button id="cancel-match-btn" class="modal-button modal-button--cancel">Cancel</button>
<button id="confirm-match-btn" class="modal-button modal-button--primary" disabled>Confirm Selection</button>
</div>
</div>
</div>
<!-- Version Info Modal -->
<div class="version-modal-overlay hidden" id="version-modal-overlay" onclick="closeVersionModal()">
<div class="version-modal" onclick="event.stopPropagation()">
<!-- Header -->
<div class="version-modal-header">
<h2 class="version-modal-title">What's New in SoulSync</h2>
<div class="version-modal-subtitle">Version 1.0 - Complete WebUI Rebuild</div>
</div>
<!-- Content Area with Scroll -->
<div class="version-modal-content">
<div class="version-content-container" id="version-content-container">
<!-- Content will be populated by JavaScript -->
</div>
</div>
<!-- Footer -->
<div class="version-modal-footer">
<button class="version-modal-close" onclick="closeVersionModal()">Close</button>
</div>
</div>
</div>
<!-- Add to Wishlist Modal -->
<div class="modal-overlay hidden" id="add-to-wishlist-modal-overlay">
<div class="add-to-wishlist-modal" id="add-to-wishlist-modal">
<div class="add-to-wishlist-modal-header">
<div class="add-to-wishlist-modal-hero" id="add-to-wishlist-modal-hero">
<!-- Hero content will be dynamically populated -->
</div>
<div class="add-to-wishlist-modal-header-actions">
<span class="add-to-wishlist-modal-close" onclick="closeAddToWishlistModal()">&times;</span>
</div>
</div>
<div class="add-to-wishlist-modal-content">
<div class="add-to-wishlist-modal-body">
<div class="wishlist-track-list-container">
<div class="wishlist-track-list-header">
<h3>Tracks to Add to Wishlist</h3>
<p class="wishlist-track-list-subtitle">All tracks from this release will be added to your wishlist</p>
</div>
<div class="wishlist-track-list" id="wishlist-track-list">
<!-- Track list will be dynamically populated -->
</div>
</div>
</div>
<div class="add-to-wishlist-modal-footer">
<div class="wishlist-modal-actions">
<button class="wishlist-modal-btn wishlist-modal-btn-secondary" onclick="closeAddToWishlistModal()">
Close
</button>
<button class="wishlist-modal-btn wishlist-modal-btn-primary" id="confirm-add-to-wishlist-btn">
Add to Wishlist
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Genre Browser Modal -->
<div class="genre-browser-modal-overlay" id="genre-browser-modal">
<div class="genre-browser-modal-container">
<div class="genre-browser-modal-header">
<h2 class="genre-browser-modal-title">🎵 Browse by Genre</h2>
<button class="genre-browser-modal-close" id="genre-browser-modal-close">
<span class="genre-browser-close-icon">×</span>
</button>
</div>
<div class="genre-browser-modal-content">
<div class="genre-browser-search-section">
<div class="genre-browser-search-container">
<input type="text" class="genre-browser-search-input" placeholder="Search genres..." id="genre-browser-search">
<span class="genre-browser-search-icon">🔍</span>
</div>
</div>
<div class="genre-browser-genres-section">
<div class="genre-browser-genres-grid" id="genre-browser-genres-grid">
<!-- Loading placeholder -->
<div class="genre-browser-loading-container">
<div class="genre-browser-loading-spinner"></div>
<p class="genre-browser-loading-text">🔍 Discovering current Beatport genres...</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Tool Help Modal -->
<div class="tool-help-modal" id="tool-help-modal">
<div class="tool-help-modal-content">
<div class="tool-help-modal-header">
<h3 id="tool-help-modal-title">Tool Information</h3>
<button class="tool-help-modal-close">&times;</button>
</div>
<div class="tool-help-modal-body" id="tool-help-modal-body">
<!-- Content will be dynamically inserted -->
</div>
</div>
</div>
<!-- Right Sidebar Download Indicator (Global - outside all containers) -->
<div class="discover-download-sidebar" id="discover-download-sidebar">
<div class="discover-download-sidebar-header">
<span class="discover-download-sidebar-icon">🎵</span>
<span class="discover-download-sidebar-title">Downloads</span>
<span class="discover-download-sidebar-count" id="discover-download-count">0</span>
</div>
<div class="discover-download-bubbles" id="discover-download-bubbles">
<!-- Download bubbles will be added here dynamically -->
</div>
</div>
<script src="{{ url_for('static', filename='script.js') }}"></script>
</body>
</html>