Files
NovaSonic/index.html
T
HoneyandClaude Opus 4.8 93ee958434 feat: artist-page scroll/search memory (android) + move APK button to bottom (web)
- Android: the artist page's main list and the "Alle anzeigen" album overlay
  (grid scroll + search query) are hoisted into the Artist/Explore ViewModels,
  so drilling into an album/artist and back keeps position + query. Covers the
  library artist and Deezer (Explore) artist screens.
- Web: the "Android App" download section now sits at the very bottom of
  Settings, below the Navidrome-Server (account) section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 07:42:24 +02:00

1214 lines
79 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<meta name="theme-color" content="#07070f">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="NovaSonic">
<link rel="manifest" href="manifest.json">
<link rel="icon" href="icon.svg" type="image/svg+xml">
<link rel="icon" href="icon-192.png" type="image/png" sizes="192x192">
<link rel="apple-touch-icon" href="icon.svg">
<title>NovaSonic</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@300;400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css">
<script>window.NS_SERVER_URL='';window.NS_BACKEND_URL='';</script>
<script src="config.js" onerror="0"></script>
<script type="module" src="/src/main.js"></script>
</head>
<body>
<script>(function(){try{if(localStorage.getItem('ns_cfg'))document.documentElement.classList.add('ns-authed');}catch(e){}})()</script>
<!-- ─── SETUP ─── -->
<div id="setup-screen">
<div class="setup-card">
<div class="setup-logo">
<div class="logo-icon">♫</div>
<h1>Nova<em>Sonic</em></h1>
</div>
<div class="setup-pane active" id="pane-navidrome">
<div class="field"><label>Server URL</label><input id="srv-url" type="url" placeholder="https://music.example.com"></div>
<div class="field"><label>Benutzername</label><input id="srv-user" type="text" placeholder="admin"></div>
<div class="field"><label>Passwort</label><input id="srv-pass" type="password" placeholder="••••••••"></div>
</div>
<button class="btn-primary" id="btn-connect" onclick="doConnect()">Verbinden</button>
<div class="setup-error" id="setup-error"></div>
</div>
</div>
<!-- ─── APP ─── -->
<div id="app">
<div class="app-body">
<!-- Sidebar -->
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<div class="sidebar-logo">
<img src="icon.svg" width="30" height="30" style="border-radius:8px;flex-shrink:0">
<span>Nova<em>Sonic</em></span>
</div>
</div>
<nav>
<div class="nav-section">
<div class="nav-section-title">Bibliothek</div>
<div class="nav-item active" onclick="navigate('home')" data-page="home">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>Home
</div>
<div class="nav-item" onclick="navigate('artists')" data-page="artists">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>Künstler
</div>
<div class="nav-item" onclick="navigate('albums')" data-page="albums">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>Alben
</div>
<div class="nav-item" onclick="navigate('playlists')" data-page="playlists">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>Playlists
</div>
<div class="nav-item" onclick="navigate('starred')" data-page="starred">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>Favoriten
</div>
</div>
<div class="nav-section">
<div class="nav-section-title">Entdecken</div>
<div class="nav-item" onclick="navigate('discover')" data-page="discover">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polygon points="10 8 16 12 10 16 10 8"/></svg>Global Suche
</div>
<div class="nav-item" onclick="navigate('new-releases')" data-page="new-releases">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>Neue Releases
</div>
<div class="nav-item" onclick="navigate('recommendations')" data-page="recommendations">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>Für dich
</div>
<div class="nav-item" onclick="navigate('random')" data-page="random">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/></svg>Zufällig
</div>
</div>
<div class="nav-section" id="nav-abs-section" style="display:none">
<div class="nav-section-title">Hörbücher</div>
<div class="nav-item" onclick="navigate('audiobooks')" data-page="audiobooks">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>Bibliothek
</div>
</div>
</nav>
</aside>
<div class="mobile-overlay" id="mobile-overlay" onclick="closeSidebar()"></div>
<!-- MAIN -->
<main class="main" id="main-content">
<!-- Mobile header -->
<div id="mobile-header" style="position:sticky;top:0;background:var(--bg);z-index:10;border-bottom:1px solid var(--border)">
<div style="display:flex;align-items:center;gap:8px;padding:10px 12px">
<div class="header-search-wrap">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
<input id="header-search-input" type="text" placeholder="Suchen…" oninput="onHeaderSearch(this.value)" autocomplete="off">
<button id="header-search-clear" onclick="closeHeaderSearch()" style="display:none;background:none;border:none;color:var(--text3);cursor:pointer;font-size:15px;padding:0;line-height:1;flex-shrink:0">✕</button>
</div>
<div style="display:flex;align-items:center;gap:2px;flex-shrink:0">
<button class="hbtn notif-bell-btn" onclick="toggleNotifPanel()" title="Benachrichtigungen" style="padding:8px;color:var(--text2)">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
<span class="notif-badge" style="display:none">0</span>
</button>
<button class="hbtn" onclick="openSettings()" title="Einstellungen" style="padding:8px;color:var(--text2)">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
</button>
</div>
</div>
<!-- Results panel: spans the full main-content width (anchored to the header, which already
sits right of the sidebar) so it never covers the sidebar and leaves no dead scroll strip -->
<div id="header-search-overlay" style="display:none">
<div id="header-search-results"></div>
</div>
</div>
<!-- HOME -->
<div class="page active" id="page-home">
<div id="home-greeting" class="home-greeting"></div>
<div id="home-hero" class="home-hero"></div>
<div class="section-header" style="margin-top:20px"><span class="section-title">Genres</span><span class="section-more" id="home-genres-more" onclick="toggleAllGenres()" style="display:none">Alle anzeigen</span></div>
<div id="home-genres" class="genre-grid"></div>
<div class="section-header" style="margin-top:20px"><span class="section-title">Neueste Alben</span><span class="section-more" onclick="navigate('albums')">Mehr</span></div>
<div class="scroll-row" id="home-newest"></div>
<div class="section-header"><span class="section-title">Zuletzt gespielt</span></div>
<div class="scroll-row" id="home-recent"></div>
<div class="section-header"><span class="section-title">Zufällig</span><span class="section-more" onclick="navigate('random')">Mehr</span></div>
<div class="scroll-row" id="home-random"></div>
<div class="section-header"><span class="section-title">Häufig gespielt</span></div>
<div class="scroll-row" id="home-frequent"></div>
</div>
<!-- ARTISTS -->
<div class="page" id="page-artists">
<div class="page-header"><div class="page-title">Künstler</div></div>
<div id="artists-grid" class="grid grid-4"></div>
</div>
<!-- ARTIST DETAIL -->
<div class="page" id="page-artist-detail">
<button class="back-btn" id="artist-back-btn"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>Alle Künstler</button>
<div class="artist-hero" id="artist-detail-hero"><div class="artist-hero-bg" id="artist-hero-bg"></div><div class="artist-hero-overlay"><div class="artist-hero-pfp-wrap" id="artist-hero-pfp-wrap"><span class="artist-hero-pfp-initial" id="artist-hero-pfp-initial"></span></div><div class="artist-hero-info"><div class="artist-hero-name" id="artist-detail-name"></div><div class="artist-hero-fans" id="artist-detail-fans"></div></div></div></div>
<div id="artist-action-bar" class="artist-action-bar"></div>
<div id="artist-bio-section"></div>
<div id="artist-similar-section"></div>
<div id="artist-topsongs-section"></div>
<div id="artist-albums-section"></div>
</div>
<!-- ARTIST ALL SONGS -->
<div class="page" id="page-artist-all-songs">
<button class="back-btn" id="artist-songs-back-btn"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>Zurück</button>
<div class="page-header" style="margin-top:8px"><div class="page-title" id="artist-songs-title">Alle Songs</div></div>
<div id="artist-songs-list"></div>
</div>
<!-- DEEZER ALBUM DETAIL -->
<div class="page" id="page-deezer-album-detail">
<button class="back-btn" id="deezer-album-back-btn"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>Zurück</button>
<div class="album-header">
<div class="album-cover" id="deezer-album-cover-wrap"><div class="no-art">💿</div></div>
<div class="album-meta">
<div class="album-type">Deezer</div>
<div class="album-name" id="deezer-album-detail-name">—</div>
<div class="album-artist-name" id="deezer-album-detail-artist"></div>
<div class="album-stats" id="deezer-album-detail-stats"></div>
<div class="album-actions">
<button class="btn-outline" id="deezer-album-dl-btn"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>Album laden</button>
</div>
</div>
</div>
<div id="deezer-album-songs"></div>
</div>
<!-- PARTIAL ALBUM DETAIL (incomplete album: downloaded + missing tracks) -->
<div class="page" id="page-partial-album-detail">
<button class="back-btn" id="partial-album-back-btn"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>Zurück</button>
<div class="album-header">
<div class="album-cover" id="partial-album-cover-wrap"><div class="no-art">💿</div></div>
<div class="album-meta">
<div class="album-type">Unvollständig</div>
<div class="album-name" id="partial-album-detail-name">—</div>
<div class="album-artist-name" id="partial-album-detail-artist"></div>
<div class="album-stats" id="partial-album-detail-stats"></div>
<div class="album-actions">
<button class="btn-play-all" id="partial-album-play-btn"><svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>Abspielen</button>
<button class="btn-outline" id="partial-album-dl-btn"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>Fehlende laden</button>
</div>
</div>
</div>
<div id="partial-album-downloaded"></div>
<div id="partial-album-missing"></div>
</div>
<!-- ALBUMS -->
<div class="page" id="page-albums">
<div class="page-header"><div class="page-title">Alben</div></div>
<div id="albums-sort-chips" class="sort-chips">
<button class="sort-chip active" data-sort="alphabeticalByName" onclick="loadAlbums('alphabeticalByName')">A–Z</button>
<button class="sort-chip" data-sort="newest" onclick="loadAlbums('newest')">Neueste</button>
<button class="sort-chip" data-sort="recent" onclick="loadAlbums('recent')">Zuletzt gespielt</button>
<button class="sort-chip" data-sort="frequent" onclick="loadAlbums('frequent')">Meistgespielt</button>
</div>
<div id="albums-grid" class="grid grid-4"></div>
</div>
<!-- ALBUM DETAIL -->
<div class="page" id="page-album-detail">
<button class="back-btn" id="album-back-btn"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>Zurück</button>
<div class="album-header">
<div class="album-cover" id="album-cover-wrap"><div class="no-art">💿</div></div>
<div class="album-meta">
<div class="album-type">Album</div>
<div class="album-name" id="album-detail-name">—</div>
<div class="album-artist-name" id="album-detail-artist"></div>
<div class="album-stats" id="album-detail-stats"></div>
<div class="album-actions">
<button class="btn-play-all" id="btn-play-album"><svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>Abspielen</button>
<button class="btn-outline" id="btn-dl-album"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>Download</button>
</div>
</div>
</div>
<div class="song-list" id="album-songs"></div>
</div>
<!-- GENRE DETAIL -->
<div class="page" id="page-genre-detail">
<button class="back-btn" id="genre-back-btn"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>Zurück</button>
<div class="album-header">
<div class="album-cover" id="genre-cover-wrap" style="display:flex;align-items:center;justify-content:center;font-size:40px">🎵</div>
<div class="album-meta">
<div class="album-type">Genre</div>
<div class="album-name" id="genre-detail-name">—</div>
<div class="album-stats" id="genre-detail-stats"></div>
<div class="album-actions">
<button class="btn-play-all" id="btn-play-genre"><svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>Shuffle</button>
</div>
</div>
</div>
<div class="song-list" id="genre-songs"></div>
</div>
<!-- STARRED -->
<div class="page" id="page-starred">
<div class="page-header"><div class="page-title">Favoriten ⭐</div></div>
<div id="starred-sort-chips" class="sort-chips">
<button class="sort-chip active" data-sort="newest" onclick="loadStarred('newest')">Neueste</button>
<button class="sort-chip" data-sort="oldest" onclick="loadStarred('oldest')">Älteste</button>
<button class="sort-chip" data-sort="az" onclick="loadStarred('az')">A–Z</button>
<button class="sort-chip" data-sort="artist" onclick="loadStarred('artist')">Künstler</button>
<button class="sort-chip" data-sort="plays" onclick="loadStarred('plays')">Meistgespielt</button>
</div>
<div class="list-search-wrap">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input id="starred-search" class="list-search" type="text" placeholder="In Favoriten suchen…" oninput="filterStarred(this.value)">
</div>
<div id="starred-songs" class="song-list"></div>
</div>
<!-- PLAYLISTS -->
<div class="page" id="page-playlists">
<div class="page-header">
<div class="page-title">Playlists 🎶</div>
<button class="btn-outline" style="font-size:12px;padding:8px 14px" onclick="createPlaylistPrompt()">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Neue Playlist
</button>
</div>
<div id="playlists-grid" class="grid grid-4"></div>
</div>
<!-- PLAYLIST DETAIL -->
<div class="page" id="page-playlist-detail">
<button class="back-btn" id="playlist-back-btn" onclick="navigate('playlists')">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>Alle Playlists
</button>
<div class="album-header">
<div class="album-cover" id="playlist-cover"><div class="no-art">🎶</div></div>
<div class="album-meta">
<div class="album-type">Playlist</div>
<div class="album-name" id="playlist-detail-name">—</div>
<div class="album-stats" id="playlist-detail-stats"></div>
<div class="playlist-detail-desc" id="playlist-detail-desc"></div>
<div class="album-actions">
<button class="btn-play-all" id="btn-play-playlist"><svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>Abspielen</button>
<button class="btn-outline" id="btn-shuffle-playlist"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/></svg>Shuffle</button>
<button class="btn-outline" id="btn-edit-playlist"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>Bearbeiten</button>
<button class="btn-outline" id="btn-reorder-playlist"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>Neu anordnen</button>
</div>
</div>
</div>
<div class="list-search-wrap">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input id="playlist-search" class="list-search" type="text" placeholder="In Playlist suchen…" oninput="filterPlaylist(this.value)">
</div>
<div class="pl-reorder-bar" id="pl-reorder-bar" style="display:none">
<span>Reihenfolge ändern</span>
<div style="display:flex;gap:8px">
<button class="edit-pl-btn-cancel" onclick="plReorderCancel()">Abbrechen</button>
<button class="edit-pl-btn-save" onclick="plReorderSave()">Speichern</button>
</div>
</div>
<div class="song-list" id="playlist-songs"></div>
</div>
<!-- RANDOM -->
<div class="page" id="page-random">
<div class="page-header">
<div class="page-title">Zufällig <em>♪</em></div>
<button class="btn-outline" onclick="loadRandom()" style="font-size:12px;padding:8px 14px"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/></svg>Neu mischen</button>
</div>
<div id="random-songs" class="song-list"></div>
</div>
<!-- LOCAL SEARCH -->
<div class="page" id="page-search">
<div class="page-header"><div class="page-title">Suche</div></div>
<div id="search-results"></div>
</div>
<!-- DISCOVER (Global) — Deezer search + link importer unified in ONE field -->
<div class="page" id="page-discover">
<div class="page-header">
<div class="page-title"><span class="blue">Global</span> Suche</div>
<span class="badge badge-deezer" style="font-size:11px;padding:4px 10px">Deezer</span>
</div>
<div class="search-wrap" style="padding:0 0 12px">
<div style="display:flex;gap:8px">
<div class="search-box" style="background:var(--surface);border-color:var(--border2);flex:1">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
<div id="importer-badge" style="display:none;font-size:10px;font-weight:700;padding:2px 7px;border-radius:10px;background:var(--surface2);color:var(--text3);white-space:nowrap;flex-shrink:0">URL</div>
<input id="global-search-input" type="text" placeholder="Künstler, Titel, Album — oder Link zum Importieren einfügen…" oninput="onGlobalInput(this.value)" onkeydown="if(event.key==='Enter'){event.preventDefault();tryImporterResolve()}" style="font-size:15px">
</div>
<button id="importer-btn" class="btn-outline" style="display:none;padding:0 16px;font-size:13px;font-weight:700;white-space:nowrap;flex-shrink:0" onclick="resolveImporterLink()">Importieren</button>
</div>
</div>
<!-- Link importer — auto-detects Spotify / SoundCloud / YouTube; shown only when a link is in the field -->
<div id="importer-area" style="display:none">
<div id="importer-hint" style="background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:14px;font-size:12px;color:var(--text2);line-height:1.8;margin-bottom:8px">
<div style="display:flex;gap:16px;flex-wrap:wrap">
<div style="display:flex;align-items:center;gap:6px"><span style="color:#1DB954;font-weight:700">Spotify</span> — Track, Album oder Playlist</div>
<div style="display:flex;align-items:center;gap:6px"><span style="color:#ff5500;font-weight:700">SoundCloud</span> — Track oder Playlist</div>
<div style="display:flex;align-items:center;gap:6px"><span style="color:#FF0000;font-weight:700">YouTube</span> — Video oder Playlist</div>
</div>
<div style="margin-top:6px;color:var(--text3);font-size:11px">Link einfügen → Metadaten werden geladen → via yt-dlp in die Navidrome Library herunterladen.</div>
</div>
<!-- hidden inputs kept for compat with spotify.js / soundcloud.js resolvers -->
<input id="importer-link-input" type="hidden">
<input id="spotify-link-input" type="hidden">
<input id="sc-link-input" type="hidden">
<!-- SPOTIFY RESULTS -->
<div id="spotify-preview" style="display:none;margin-bottom:8px">
<div id="spotify-preview-inner"></div>
<div id="spotify-enrich-status" style="display:none"></div>
<div id="spotify-tracks-section" style="display:none">
<div class="section-header" style="margin-top:8px">
<span class="section-title" id="spotify-tracks-title">Tracks</span>
</div>
<div id="spotify-tracks-list" class="song-list"></div>
</div>
</div>
<!-- SOUNDCLOUD RESULTS -->
<div id="sc-preview" style="display:none;margin-bottom:8px">
<div id="sc-preview-inner"></div>
<div id="sc-tracks-section" style="display:none">
<div class="section-header" style="margin-top:8px">
<span class="section-title" id="sc-tracks-title">Tracks</span>
</div>
<div id="sc-tracks-list" class="song-list"></div>
</div>
</div>
<!-- YOUTUBE RESULTS -->
<div id="yt-preview" style="display:none;margin-bottom:8px">
<div id="yt-preview-inner"></div>
<div id="yt-tracks-section" style="display:none">
<div class="section-header" style="margin-top:8px">
<span class="section-title" id="yt-tracks-title">Tracks</span>
</div>
<div id="yt-tracks-list" class="song-list"></div>
</div>
</div>
</div>
<div id="global-search-results">
<div class="empty-state"><div class="icon">🔍</div><p>Gib einen Suchbegriff ein — oder füge einen Spotify-/SoundCloud-/YouTube-Link ein zum Importieren</p></div>
</div>
</div>
<!-- NEW RELEASES -->
<div class="page" id="page-new-releases">
<div class="page-header">
<div class="page-title">Neue <em>Releases</em></div>
<span class="badge badge-deezer" style="font-size:11px;padding:4px 10px">Deezer Charts</span>
</div>
<div class="section-header" style="margin-top:0"><span class="section-title">Top Alben weltweit</span></div>
<div id="nr-albums" class="grid grid-4"></div>
<div class="section-header"><span class="section-title">Top Songs</span></div>
<div id="nr-songs" class="song-list"></div>
</div>
<!-- RECOMMENDATIONS -->
<div class="page" id="page-recommendations">
<div class="page-header">
<div class="page-title">Für <em>dich</em></div>
</div>
<div id="reco-content">
<div class="empty-state"><div class="icon">🎵</div><p>Spiele zuerst Musik in deiner Bibliothek,<br>dann zeigen wir dir ähnliche Künstler und Tracks</p></div>
</div>
</div>
<!-- AUDIOBOOKS -->
<div class="page" id="page-audiobooks">
<div class="page-header">
<div class="page-title">Hörbücher <em>📚</em></div>
</div>
<div class="search-wrap" style="padding:0 0 16px">
<div class="search-box" style="background:var(--surface);border-color:var(--border2)">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
<input id="abs-search-input" type="text" placeholder="Titel oder Autor suchen…" oninput="absOnSearch(this.value)">
</div>
</div>
<div id="abs-books-grid" class="abs-books-grid"></div>
</div>
<!-- AUDIOBOOK DETAIL -->
<div class="page" id="page-abs-book-detail">
<button class="back-btn" onclick="navigate('audiobooks')">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>Hörbücher
</button>
<div id="abs-book-detail-content"></div>
</div>
</main>
</div>
<!-- QUEUE PANEL -->
<div class="queue-panel" id="queue-panel">
<div class="queue-title">Warteschlange</div>
<div class="queue-list" id="queue-list"></div>
</div>
<!-- PLAYER -->
<div class="player">
<div class="player-drag-handle"></div>
<div class="player-track">
<div class="player-art" id="player-art" style="cursor:pointer" title="Jetzt läuft öffnen"><div class="no-art">♪</div></div>
<div class="player-info-wrap">
<div class="player-info">
<div class="player-title" id="player-title">Kein Titel</div>
<div class="player-artist">
<span id="player-album-name" onclick="playerBarGoAlbum()" style="cursor:pointer" title="Zum Album"></span>
</div>
<div class="player-artist" id="player-artist">
<span id="player-artist-name">—</span>
</div>
<div class="player-status-row">
<span class="status-badge badge-shuffle" id="badge-shuffle">🔀 Shuffle</span>
<span class="status-badge badge-repeat" id="badge-repeat">🔁 Repeat</span>
</div>
</div>
<button id="btn-star-current" onclick="starCurrent()" title="Favorit" style="background:none;border:none;cursor:pointer;padding:4px;flex-shrink:0;display:flex;align-items:center;color:var(--text3)">
<svg id="star-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="transition:fill .2s,stroke .2s"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
</button>
</div>
</div>
<div class="player-controls">
<div class="ctrl-buttons">
<button class="ctrl-btn" id="btn-shuffle" onclick="toggleShuffle()" title="Shuffle">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/></svg>
</button>
<button class="ctrl-btn" onclick="prevSong()">
<svg width="17" height="17" viewBox="0 0 24 24" fill="currentColor"><polygon points="19 20 9 12 19 4 19 20"/><line x1="5" y1="19" x2="5" y2="5" stroke="currentColor" stroke-width="2"/></svg>
</button>
<button class="play-pause-btn" id="btn-play-pause" onclick="togglePlay()">
<svg id="play-icon" width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>
</button>
<button class="ctrl-btn" onclick="nextSong()">
<svg width="17" height="17" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 4 15 12 5 20 5 4"/><line x1="19" y1="5" x2="19" y2="19" stroke="currentColor" stroke-width="2"/></svg>
</button>
<button class="ctrl-btn" id="btn-repeat" onclick="toggleRepeat()" title="Wiederholen">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg>
</button>
</div>
<div class="progress-bar-wrap">
<span class="progress-time" id="time-cur">0:00</span>
<div class="progress-bar" id="progress-bar"><div class="progress-fill" id="progress-fill"></div></div>
<span class="progress-time right" id="time-total">0:00</span>
</div>
</div>
<div class="player-right">
<button class="icon-btn" onclick="downloadCurrent()" title="Herunterladen">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
</button>
<button class="icon-btn" onclick="toggleQueue()" title="Warteschlange">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
</button>
<button class="icon-btn" id="btn-radio-mode" onclick="toggleRadioMode()" title="Radio-Modus: endloser Shuffle">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="2"/><path d="M4.93 4.93a10 10 0 0 0 0 14.14"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M7.76 7.76a6 6 0 0 0 0 8.49"/><path d="M16.24 7.76a6 6 0 0 1 0 8.49"/></svg>
</button>
<div class="volume-wrap">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color:var(--text3)"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/></svg>
<input type="range" class="volume-slider volume-slider-sync" id="volume-slider" min="0" max="100" value="50" oninput="setVolume(this.value)">
</div>
</div>
</div>
</div>
<!-- ABS MINI BAR (overlays the music player bar when an audiobook is active) -->
<div id="abs-mini-bar" class="abs-mini-bar">
<div class="abs-mini-prog-strip"><div id="abs-mini-prog-fill" class="abs-mini-prog-fill"></div></div>
<div id="abs-mini-cover" class="abs-mini-cover" onclick="absOpenPlayer()">📚</div>
<div class="abs-mini-info" onclick="absOpenPlayer()">
<div id="abs-mini-title" class="abs-mini-title">—</div>
<div id="abs-mini-chapter" class="abs-mini-chapter"></div>
</div>
<button class="abs-mini-play" id="abs-mini-play" onclick="absTogglePlay()">
<svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>
</button>
<button class="abs-mini-open" onclick="absOpenPlayer()" title="Öffnen">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="18 15 12 9 6 15"/></svg>
</button>
</div>
<!-- PREVIEW BAR (Deezer 30s) -->
<div class="preview-bar" id="preview-bar">
<div class="player-art" id="preview-art" style="width:42px;height:42px;border-radius:6px"><div class="no-art" style="font-size:16px">♪</div></div>
<div class="preview-info">
<div class="preview-title" id="preview-title">—<span class="preview-badge">30s Preview</span></div>
<div class="preview-sub" id="preview-sub">Deezer</div>
</div>
<div class="preview-prog"><div class="preview-fill" id="preview-fill"></div></div>
<button class="preview-close" onclick="stopPreview()">✕</button>
</div>
<!-- DOWNLOAD MODAL -->
<div class="modal-overlay" id="download-modal">
<div class="modal">
<h2>Auf Server herunterladen</h2>
<p class="modal-sub">Der NovaSonic Backend lädt die Musik via yt-dlp herunter und speichert sie direkt in deinem Navidrome-Musikordner.</p>
<div class="modal-track-info" id="dl-modal-info"></div>
<div class="modal-opts" id="dl-modal-opts">
<div class="modal-opt selected" data-type="track" onclick="selectDlType(this,'track')">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polygon points="10 8 16 12 10 16 10 8"/></svg>
<div><div class="opt-label">Einzelner Track</div><div class="opt-sub">Nur diesen Titel herunterladen</div></div>
</div>
<div class="modal-opt" data-type="album" onclick="selectDlType(this,'album')">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>
<div><div class="opt-label">Ganzes Album</div><div class="opt-sub" id="dl-album-sub">Album herunterladen</div></div>
</div>
<div class="modal-opt" data-type="artist" onclick="selectDlType(this,'artist')">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg>
<div><div class="opt-label">Ganzer Künstler</div><div class="opt-sub">Alle Top-Alben des Künstlers</div></div>
</div>
</div>
<div class="modal-disclaimer">
ℹ️ Bitte lade nur Musik herunter, die du besitzt oder für die du eine Lizenz hast. Dieses Tool ist für Backup-Zwecke und eigene Inhalte gedacht.
</div>
<div class="modal-btns">
<button class="modal-btns btn-cancel" style="flex:1;padding:12px;border-radius:9px;font-family:var(--font);font-size:14px;font-weight:600;cursor:pointer;border:none;background:var(--surface2);color:var(--text2)" onclick="closeDlModal()">Abbrechen</button>
<button class="modal-btns btn-download" style="flex:1;padding:12px;border-radius:9px;font-family:var(--font);font-size:14px;font-weight:600;cursor:pointer;border:none;background:linear-gradient(135deg,var(--blue),#2d6ad4);color:#fff" id="btn-do-download" onclick="executeDownload()">Herunterladen</button>
</div>
</div>
</div>
<!-- SETTINGS MODAL -->
<div class="modal-overlay" id="settings-modal">
<div class="modal" style="padding:0;display:flex;flex-direction:column;max-height:85vh;overflow:hidden;width:min(480px,calc(100vw - 32px))">
<!-- Sticky header -->
<div style="display:flex;align-items:center;justify-content:space-between;padding:20px 24px 16px;border-bottom:1px solid var(--border);flex-shrink:0">
<div style="display:flex;align-items:center;gap:12px">
<div style="width:36px;height:36px;border-radius:10px;background:linear-gradient(135deg,var(--accent),var(--accent-dark));display:flex;align-items:center;justify-content:center;font-size:17px;box-shadow:0 4px 12px var(--accent-glow)">⚙</div>
<div>
<div style="font-size:17px;font-weight:800;letter-spacing:-.3px">Einstellungen</div>
<div style="font-size:11px;color:var(--text2);margin-top:1px">NovaSonic</div>
</div>
</div>
<button onclick="closeSettings()" style="background:var(--surface2);border:none;color:var(--text2);width:32px;height:32px;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:15px;flex-shrink:0;transition:background .15s" onmouseover="this.style.background='var(--surface)'" onmouseout="this.style.background='var(--surface2)'">✕</button>
</div>
<!-- Scrollable body -->
<div style="flex:1;overflow-y:auto;padding:18px 24px 8px">
<div class="settings-section">
<h3 style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
<span style="width:24px;height:24px;border-radius:6px;background:var(--surface2);display:inline-flex;align-items:center;justify-content:center;font-size:12px">🎨</span>
Theme
</h3>
<div id="theme-picker" class="theme-picker"></div>
<div class="edit-pl-toggle-row" style="margin-top:14px">
<span>Einfarbiger Player-Hintergrund</span>
<div id="s-cover-color-bg" class="toggle" onclick="this.classList.toggle('on')"></div>
</div>
</div>
<div class="settings-section">
<h3 style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
<span style="width:24px;height:24px;border-radius:6px;background:var(--surface2);display:inline-flex;align-items:center;justify-content:center;font-size:12px">📊</span>
Bibliothek
</h3>
<div class="edit-pl-toggle-row">
<span>Abspielhäufigkeit anzeigen</span>
<div id="s-show-playcount" class="toggle" onclick="this.classList.toggle('on')"></div>
</div>
<div class="edit-pl-toggle-row" style="margin-top:12px">
<span>Romaji anzeigen</span>
<div id="s-show-romaji" class="toggle" onclick="this.classList.toggle('on')"></div>
</div>
<div class="edit-pl-toggle-row" style="margin-top:12px">
<span>Scrobble senden nach</span>
<select id="s-scrobble-mode" style="background:var(--surface2);color:var(--text);border:1px solid var(--border);border-radius:8px;padding:6px 10px;font-family:var(--font);font-size:13px;cursor:pointer">
<option value="15s">15 Sekunden</option>
<option value="30s">30 Sekunden</option>
<option value="1/3">1/3 der Song-Dauer</option>
<option value="2/3">2/3 der Song-Dauer</option>
<option value="end">Song-Ende</option>
</select>
</div>
<div style="display:flex;align-items:center;justify-content:space-between;margin-top:14px">
<div style="font-size:13px;font-weight:600">Romaji Korrekturen</div>
<button onclick="openRomajiOverridesModal()" class="btn-outline" style="padding:7px 14px;font-size:13px;font-weight:600;flex-shrink:0">Liste öffnen</button>
</div>
</div>
<div class="settings-section">
<h3 style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
<span style="width:24px;height:24px;border-radius:6px;background:var(--green-dim);display:inline-flex;align-items:center;justify-content:center;font-size:12px">📚</span>
Audiobookshelf
</h3>
<div class="field">
<label>Server URL</label>
<input id="abs-s-url" type="url" placeholder="https://books.example.com">
</div>
<div class="field">
<label>API Key</label>
<input id="abs-s-apikey" type="password" placeholder="Aus ABS: Profil → API Token">
<div class="hint">Einstellungen → Profil → API Token in Audiobookshelf</div>
</div>
<div id="abs-lib-picker" style="display:none" class="field">
<label>Bibliothek</label>
<select id="abs-lib-select" onchange="absSetLibrary(this.value)" style="width:100%;padding:10px 12px;background:var(--bg2);border:1px solid var(--border2);border-radius:var(--radius-sm);color:var(--text);font-family:var(--font);font-size:14px;outline:none"></select>
</div>
<div class="settings-row" style="margin-top:8px;border-radius:9px">
<div>
<div style="font-size:13px;font-weight:500">Audiobookshelf Status</div>
<div class="hint" id="abs-s-status">Nicht verbunden</div>
</div>
<div style="display:flex;align-items:center;gap:8px">
<div class="status-dot" id="abs-s-dot" style="display:none"></div>
<button class="btn-outline" id="abs-s-connect-btn" style="padding:6px 12px;font-size:12px;font-weight:600" onclick="absToggleConnection()">Verbinden</button>
</div>
</div>
</div>
<div class="settings-section">
<h3 style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
<span style="width:24px;height:24px;border-radius:6px;background:var(--accent-dim);display:inline-flex;align-items:center;justify-content:center;font-size:12px">🔑</span>
Discover APIs
</h3>
<div class="field">
<label>Last.fm API Key</label>
<input id="s-lastfm" type="text" placeholder="Für Künstler-Infos & Empfehlungen">
<div class="hint">Kostenlos unter last.fm/api/account/create</div>
</div>
<div class="field">
<label>NovaSonic Backend URL</label>
<input id="s-backend" type="url" placeholder="http://192.168.x.x:3700">
<div class="hint">Für Download-to-Server via yt-dlp</div>
</div>
<div class="settings-row" style="margin-top:8px;border-radius:9px">
<div>
<div style="font-size:13px;font-weight:500">Backend Status</div>
<div class="hint" id="backend-status-text">Nicht verbunden</div>
</div>
<div style="display:flex;align-items:center;gap:8px">
<div class="status-dot" id="backend-status-dot"></div>
<button class="btn-outline" style="padding:6px 12px;font-size:12px" onclick="checkBackend()">Testen</button>
</div>
</div>
</div>
<div class="settings-section">
<h3 style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
<span style="width:24px;height:24px;border-radius:6px;background:var(--blue-dim);display:inline-flex;align-items:center;justify-content:center;font-size:12px">🌐</span>
Navidrome Server
</h3>
<div class="field"><label>Server URL</label><input id="s-url" type="url" placeholder="https://music.example.com"></div>
<div class="field"><label>Benutzername</label><input id="s-user" type="text" placeholder="admin"></div>
<div class="field"><label>Passwort</label><input id="s-pass" type="password" placeholder="(unverändert lassen)"></div>
</div>
<div class="settings-section" id="s-apk-section" style="display:none">
<h3 style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
<span style="width:24px;height:24px;border-radius:6px;background:var(--surface2);display:inline-flex;align-items:center;justify-content:center;font-size:12px">🤖</span>
Android App
</h3>
<div style="font-size:12px;color:var(--text2);margin-bottom:10px;line-height:1.6">Installiere die NovaSonic Android-App direkt aufs Handy. <span id="s-apk-meta" style="color:var(--text3)"></span></div>
<a id="s-apk-btn" href="#" download style="display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border-radius:10px;background:linear-gradient(135deg,var(--accent),var(--accent-dark));color:#fff;font-weight:700;font-size:13px;text-decoration:none;box-shadow:0 4px 12px var(--accent-glow)">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
APK herunterladen
</a>
<div style="font-size:11px;color:var(--text3);margin-top:8px">Danach im Handy „Installation aus unbekannten Quellen" für den Browser erlauben.</div>
</div>
</div>
<!-- Sticky footer -->
<div style="display:flex;flex-direction:column;gap:8px;padding:12px 24px 16px;border-top:1px solid var(--border);flex-shrink:0;background:var(--surface);border-radius:0 0 18px 18px">
<div style="display:flex;gap:8px">
<button style="flex:1;padding:12px;border-radius:9px;font-family:var(--font);font-size:14px;font-weight:600;cursor:pointer;border:none;background:var(--surface2);color:var(--text2)" onclick="closeSettings()">Abbrechen</button>
<button style="flex:1;padding:12px;border-radius:9px;font-family:var(--font);font-size:14px;font-weight:600;cursor:pointer;border:none;background:linear-gradient(135deg,var(--accent),var(--accent-dark));color:#000" onclick="saveSettings()">Speichern</button>
</div>
<button style="width:100%;padding:10px;border-radius:9px;font-family:var(--font);font-size:13px;font-weight:600;cursor:pointer;background:none;border:1px solid var(--border);color:var(--text2);transition:background .15s" onmouseover="this.style.background='var(--surface2)'" onmouseout="this.style.background='none'" onclick="closeSettings(); openStats()">📊 Meine Statistiken</button>
<button style="width:100%;padding:10px;border-radius:9px;font-family:var(--font);font-size:13px;font-weight:600;cursor:pointer;background:none;border:1px solid var(--border);color:var(--text2);transition:background .15s" onmouseover="this.style.background='var(--surface2)'" onmouseout="this.style.background='none'" onclick="closeSettings(); openCompare()">🎧 Musik-Match</button>
<button style="width:100%;padding:10px;border-radius:9px;font-family:var(--font);font-size:13px;font-weight:600;cursor:pointer;background:none;border:1px solid rgba(224,85,85,0.3);color:var(--danger);transition:background .15s" onmouseover="this.style.background='rgba(224,85,85,0.1)'" onmouseout="this.style.background='none'" onclick="confirmDisconnect()">Abmelden</button>
</div>
</div>
</div>
<!-- ROMAJI OVERRIDES MODAL -->
<div class="modal-overlay" id="romaji-overrides-modal">
<div class="modal" style="padding:0;display:flex;flex-direction:column;max-height:80vh;width:min(460px,calc(100vw - 32px))">
<div style="display:flex;align-items:center;justify-content:space-between;padding:18px 20px 14px;border-bottom:1px solid var(--border);flex-shrink:0">
<div style="font-size:16px;font-weight:700">Romaji Korrekturen</div>
<button onclick="closeRomajiOverridesModal()" style="background:var(--surface2);border:none;color:var(--text2);width:30px;height:30px;border-radius:50%;cursor:pointer;font-size:15px;display:flex;align-items:center;justify-content:center">✕</button>
</div>
<div style="flex:1;overflow-y:auto;overflow-x:hidden;padding:14px 20px">
<div class="hint" style="margin-bottom:12px">Kanji → korrektes Romaji<br>Wird sofort in der Anzeige, bei Downloads und direkt auf bestehende Songs in der Bibliothek (Sort-Tags + Dateiname) angewendet.</div>
<div id="romaji-overrides-list" style="display:flex;flex-direction:column;gap:5px;margin-bottom:14px"></div>
<div style="display:flex;gap:6px;align-items:center;min-width:0">
<input id="ro-kanji" placeholder="米津玄師" style="flex:1;min-width:0;padding:8px 10px;background:var(--bg2);border:1px solid var(--border2);border-radius:8px;color:var(--text);font-family:var(--font);font-size:13px;outline:none" onkeydown="if(event.key==='Enter')addRomajiOverrideUI()">
<span style="color:var(--text2);flex-shrink:0">→</span>
<input id="ro-romaji" placeholder="Yonezu Kenshi" style="flex:1.2;min-width:0;padding:8px 10px;background:var(--bg2);border:1px solid var(--border2);border-radius:8px;color:var(--text);font-family:var(--font);font-size:13px;outline:none" onkeydown="if(event.key==='Enter')addRomajiOverrideUI()">
<button onclick="addRomajiOverrideUI()" style="flex-shrink:0;padding:8px 12px;border-radius:8px;border:none;background:linear-gradient(135deg,var(--accent),var(--accent-dark));color:#000;font-family:var(--font);font-size:14px;font-weight:700;cursor:pointer">+</button>
</div>
</div>
</div>
</div>
<!-- JOB PANEL -->
<div class="jobs-panel" id="jobs-panel"></div>
<div class="toast-container" id="toast-container"></div>
<audio id="audio-element" preload="auto" playsinline crossorigin="anonymous"></audio>
<audio id="audio-element-b" preload="auto" playsinline crossorigin="anonymous"></audio>
<audio id="preview-audio"></audio>
<audio id="abs-audio"></audio>
<!-- AUDIOBOOKSHELF PLAYER OVERLAY -->
<div id="abs-player" class="abs-player-overlay">
<!-- Header -->
<div class="abs-player-header">
<button class="abs-hbtn" onclick="absClosePlayer()">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></svg>
</button>
<span class="abs-player-label">Hörbuch</span>
<div style="width:36px"></div>
</div>
<!-- Cover -->
<div class="abs-cover-area">
<div class="abs-cover-wrap">
<img id="abs-cover" src="" alt="" class="abs-cover-img" style="display:none">
<div id="abs-cover-placeholder" class="abs-cover-ph">📚</div>
</div>
</div>
<!-- Info -->
<div class="abs-player-info">
<div id="abs-title" class="abs-player-title">—</div>
<div id="abs-author" class="abs-player-author"></div>
<div id="abs-chapter-name" class="abs-player-chapter"></div>
</div>
<!-- Progress bar -->
<div class="abs-progress-area">
<div class="abs-prog-bar" id="abs-prog-bar"
onmousedown="absProgDown(event)" onmousemove="absProgMove(event)" onmouseup="absProgUp(event)"
ontouchstart="absProgDown(event)" ontouchmove="absProgMove(event)" ontouchend="absProgUp(event)">
<div class="abs-prog-track">
<div class="abs-prog-fill" id="abs-prog-fill"></div>
<div class="abs-prog-thumb" id="abs-prog-thumb"></div>
</div>
</div>
<div class="abs-prog-times">
<span id="abs-time-cur">0:00</span>
<span id="abs-time-rem">-0:00</span>
</div>
</div>
<!-- Main controls -->
<div class="abs-controls">
<button class="abs-ctrl-btn" onclick="absPrevChapter()" title="Voriges Kapitel">
<svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor"><polygon points="19 20 9 12 19 4 19 20"/><line x1="5" y1="19" x2="5" y2="5" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/></svg>
</button>
<button class="abs-ctrl-btn abs-skip-btn" onclick="absSkipSecs(-10)" title="-10s">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
<path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10"/>
<polyline points="15 9 12 6 9 9"/>
<path d="M12 6v4"/>
</svg>
<span class="abs-skip-label">10</span>
</button>
<button class="abs-play-pause" id="abs-playpause-btn" onclick="absTogglePlay()">
<svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>
</button>
<button class="abs-ctrl-btn abs-skip-btn" onclick="absSkipSecs(30)" title="+30s">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
<path d="M12 22C17.523 22 22 17.523 22 12S17.523 2 12 2 2 6.477 2 12"/>
<polyline points="9 9 12 6 15 9"/>
<path d="M12 6v4"/>
</svg>
<span class="abs-skip-label">30</span>
</button>
<button class="abs-ctrl-btn" onclick="absNextChapter()" title="Nächstes Kapitel">
<svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 4 15 12 5 20 5 4"/><line x1="19" y1="5" x2="19" y2="19" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/></svg>
</button>
</div>
<!-- Extra controls -->
<div class="abs-extra-controls">
<!-- Speed -->
<div class="abs-picker-wrap">
<button class="abs-extra-btn" id="abs-speed-btn" onclick="absToggleSpeedPicker()">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
<span id="abs-speed-val">1×</span>
</button>
<div id="abs-speed-picker" class="abs-picker">
<button data-speed="0.75" onclick="absSetSpeed(0.75)">0.75×</button>
<button data-speed="1" onclick="absSetSpeed(1)">1×</button>
<button data-speed="1.25" onclick="absSetSpeed(1.25)">1.25×</button>
<button data-speed="1.5" onclick="absSetSpeed(1.5)">1.5×</button>
<button data-speed="1.75" onclick="absSetSpeed(1.75)">1.75×</button>
<button data-speed="2" onclick="absSetSpeed(2)">2×</button>
</div>
</div>
<!-- Sleep timer -->
<div class="abs-picker-wrap">
<button class="abs-extra-btn" id="abs-sleep-btn" onclick="absToggleSleepPicker()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
</button>
<div id="abs-sleep-picker" class="abs-picker abs-picker-right">
<button onclick="absSleepIn(0)">Aus</button>
<button onclick="absSleepIn(5)">5 Min</button>
<button onclick="absSleepIn(10)">10 Min</button>
<button onclick="absSleepIn(15)">15 Min</button>
<button onclick="absSleepIn(30)">30 Min</button>
<button onclick="absSleepIn(45)">45 Min</button>
<button onclick="absSleepIn(60)">60 Min</button>
<div class="abs-sleep-custom-row">
<span class="abs-sleep-custom-label">Eigene Zeit</span>
<div class="abs-sleep-custom-controls">
<input id="abs-sleep-custom-input" type="number" min="1" max="999" placeholder="Min" onkeydown="if(event.key==='Enter'){var v=parseInt(this.value);if(v>0)absSleepIn(v);}">
<button class="abs-sleep-custom-ok" onclick="var v=parseInt(document.getElementById('abs-sleep-custom-input').value);if(v>0)absSleepIn(v);">OK</button>
</div>
</div>
</div>
</div>
<!-- Chapter list toggle -->
<button class="abs-extra-btn" onclick="absToggleChapters()">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
Kapitel
</button>
<!-- Chapter track mode -->
<button class="abs-extra-btn" id="abs-chtrack-btn" onclick="absToggleChapterTrack()" title="Kapitel-Track: Fortschritt nur im aktuellen Kapitel anzeigen">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12"/><line x1="12" y1="12" x2="15" y2="15"/><line x1="3" y1="12" x2="6" y2="12" stroke-width="2.5"/></svg>
Kap.Track
</button>
</div>
<!-- Volume -->
<div class="abs-volume-row">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color:var(--text3);flex-shrink:0"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/></svg>
<input type="range" class="abs-vol-slider volume-slider-sync" min="0" max="100" value="50" oninput="setVolume(this.value)">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color:var(--text3);flex-shrink:0"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/></svg>
</div>
<!-- Chapter list -->
<div id="abs-chapter-list" class="abs-chapter-list"></div>
</div>
<!-- CONTEXT MENU -->
<div class="ctx-menu" id="ctx-menu" style="display:none"></div>
<!-- ADD TO PLAYLIST MODAL -->
<div class="pl-modal" id="pl-modal">
<div class="inner">
<h3 id="pl-modal-title">Zu Playlist hinzufügen</h3>
<div class="pl-list" id="pl-list"></div>
<div class="pl-new-row">
<input class="pl-input" id="pl-new-name" placeholder="Neue Playlist erstellen…" type="text">
<div class="pl-btns">
<button style="background:var(--surface2);color:var(--text2)" onclick="closePlModal()">Abbrechen</button>
<button style="background:linear-gradient(135deg,var(--accent),var(--accent-dark));color:#000" onclick="createAndAddPlaylist()">Erstellen & Hinzufügen</button>
</div>
</div>
</div>
</div>
<!-- EDIT PLAYLIST MODAL -->
<div class="edit-pl-overlay" id="edit-pl-overlay" onclick="if(event.target===this)closeEditPlModal()">
<div class="edit-pl-box">
<div class="edit-pl-header">
<span>Playlist bearbeiten</span>
<button class="edit-pl-close" onclick="closeEditPlModal()">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
</div>
<div class="edit-pl-body">
<div class="edit-pl-cover-wrap">
<div class="edit-pl-cover" id="edit-pl-cover"><div class="no-art">🎶</div></div>
<div class="edit-pl-cover-actions">
<button class="edit-pl-cover-btn" onclick="document.getElementById('edit-pl-file').click()" title="Bild hochladen">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
</button>
</div>
<input type="file" id="edit-pl-file" accept="image/*" style="display:none" onchange="editPlCoverSelected(this)">
</div>
<div class="edit-pl-fields">
<label class="edit-pl-label">Name <span style="color:var(--accent)">*</span></label>
<input class="edit-pl-input" id="edit-pl-name" type="text" placeholder="Playlist-Name">
<label class="edit-pl-label">Beschreibung</label>
<textarea class="edit-pl-input edit-pl-textarea" id="edit-pl-desc" placeholder="Optionale Beschreibung…" rows="3"></textarea>
<div class="edit-pl-toggle-row">
<span>Öffentlich</span>
<div class="toggle" id="edit-pl-public-toggle" onclick="this.classList.toggle('on')"></div>
</div>
</div>
</div>
<div class="edit-pl-footer">
<button class="edit-pl-btn-delete" onclick="deletePlaylist()">Löschen</button>
<div style="display:flex;gap:10px">
<button class="edit-pl-btn-cancel" onclick="closeEditPlModal()">Abbrechen</button>
<button class="edit-pl-btn-save" onclick="saveEditPlaylist()">Speichern</button>
</div>
</div>
</div>
</div>
<!-- CONFIRM DIALOG -->
<div class="edit-pl-overlay" id="confirm-overlay" onclick="if(event.target===this)_confirmCancel()">
<div class="confirm-box">
<div class="confirm-title" id="confirm-title"></div>
<div class="confirm-msg" id="confirm-msg"></div>
<div class="confirm-footer">
<button class="edit-pl-btn-cancel" onclick="_confirmCancel()">Abbrechen</button>
<button class="edit-pl-btn-delete" id="confirm-ok-btn" onclick="_confirmOk()">Bestätigen</button>
</div>
</div>
</div>
<!-- EVENTS MODAL -->
<div class="modal-overlay" id="events-modal" onclick="if(event.target===this)closeEventsModal()">
<div class="modal events-modal">
<div class="events-modal-header">
<div id="events-modal-title" class="events-modal-title"></div>
<button class="events-modal-close" onclick="closeEventsModal()">✕</button>
</div>
<div id="events-modal-list" class="events-modal-list"></div>
</div>
</div>
<!-- SONG INFO MODAL -->
<div class="info-modal" id="info-modal">
<div class="inner">
<div class="info-header">
<div class="info-cover" id="info-cover"><div class="no-art" style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:32px">🎵</div></div>
<div style="flex:1;min-width:0"><div class="info-top-title" id="info-top-title">—</div><div class="info-top-sub" id="info-top-sub">—</div></div>
<button class="info-edit-toggle" id="info-edit-toggle" onclick="toggleInfoEdit()" title="Bearbeiten">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
</button>
</div>
<!-- VIEW MODE -->
<div id="info-view-mode">
<div class="info-rows" id="info-rows"></div>
<button class="info-close" onclick="closeInfoModal()">Schließen</button>
</div>
<!-- EDIT MODE -->
<div id="info-edit-mode" style="display:none">
<div class="info-edit-art-row">
<div class="info-edit-art-wrap">
<div class="info-cover info-edit-art-preview" id="info-edit-art-preview"></div>
<button class="info-edit-art-btn" onclick="document.getElementById('info-art-file').click()" title="Bild hochladen">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
Upload
</button>
<input type="file" id="info-art-file" accept="image/*" style="display:none" onchange="onInfoArtFile(this)">
</div>
<button class="btn-outline blue" style="font-size:11px;padding:6px 10px;height:fit-content" onclick="autofillMusicBrainz()">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right:4px"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
MusicBrainz
</button>
<button class="btn-outline blue" style="font-size:11px;padding:6px 10px;height:fit-content" onclick="autofillDeezer()">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right:4px"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
Deezer
</button>
</div>
<div class="info-edit-fields">
<label class="info-edit-label">Titel<input class="info-edit-input" id="ie-title" type="text" placeholder="Titel"></label>
<label class="info-edit-label">Künstler<span class="info-edit-hint">Mehrere mit <code>;</code> oder <code>,</code> trennen — wird in einzelne Künstler aufgeteilt</span><input class="info-edit-input" id="ie-artist" type="text" placeholder="Künstler"></label>
<label class="info-edit-label">Album-Künstler<span class="info-edit-hint">Mehrere mit <code>;</code> oder <code>,</code> trennen — bleibt als ein Album-Credit zusammen</span><input class="info-edit-input" id="ie-albumartist" type="text" placeholder="Album-Künstler"></label>
<label class="info-edit-label">Album<input class="info-edit-input" id="ie-album" type="text" placeholder="Album"></label>
<label class="info-edit-label">Genre<input class="info-edit-input" id="ie-genre" type="text" placeholder="Genre"></label>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">
<label class="info-edit-label">Jahr<input class="info-edit-input" id="ie-year" type="number" placeholder="2024" min="1900" max="2099"></label>
<label class="info-edit-label">Track #<input class="info-edit-input" id="ie-track" type="number" placeholder="1" min="1"></label>
<label class="info-edit-label">Disc #<input class="info-edit-input" id="ie-disc" type="number" placeholder="1" min="1"></label>
<label class="info-edit-label">Tracks ges.<input class="info-edit-input" id="ie-totaltracks" type="number" placeholder="12" min="1"></label>
</div>
</div>
<details class="ie-sort-details">
<summary>Sort-Tags (Japanisch / Englisch)</summary>
<div class="info-edit-fields" style="margin-top:8px">
<label class="info-edit-label">Titel-Sort<input class="info-edit-input" id="ie-titlesort" type="text" placeholder="Romaji / Englisch"></label>
<label class="info-edit-label">Künstler-Sort<input class="info-edit-input" id="ie-artistsort" type="text" placeholder="Romaji / Englisch"></label>
<label class="info-edit-label">Album-Künstler-Sort<input class="info-edit-input" id="ie-albumartistsort" type="text" placeholder="Romaji / Englisch"></label>
<label class="info-edit-label">Album-Sort<input class="info-edit-input" id="ie-albumsort" type="text" placeholder="Romaji / Englisch"></label>
</div>
</details>
<div id="info-edit-status" style="font-size:12px;color:var(--text3);padding:0 20px 8px;min-height:18px"></div>
<div style="display:flex;gap:8px;padding:0 20px 20px">
<button class="info-close" style="flex:1;margin:0" onclick="toggleInfoEdit()">Abbrechen</button>
<button class="info-close" style="flex:1;margin:0;background:var(--accent);color:#fff" onclick="saveMetadata()">Speichern</button>
</div>
<div style="padding:0 20px 20px">
<button class="info-close" style="width:100%;margin:0;background:none;border:1px solid #c0392b;color:#c0392b;display:flex;align-items:center;justify-content:center;gap:6px" onclick="deleteSong()">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M9 6V4h6v2"/></svg>
Song löschen
</button>
</div>
</div>
</div>
</div>
<!-- NOW PLAYING OVERLAY -->
<div class="np-overlay" id="np-overlay">
<div class="np-bg" id="np-bg-a"></div>
<div class="np-bg" id="np-bg-b" style="opacity:0"></div>
<div class="np-inner">
<div class="np-topbar">
<button class="np-close" onclick="closeNowPlaying()" title="Schließen">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></svg>
</button>
<div class="np-tabs">
<button class="np-tab active" id="np-tab-player" onclick="switchNpTab('player')">Player</button>
<button class="np-tab" id="np-tab-lyrics" onclick="switchNpTab('lyrics')">Lyrics</button>
<button class="np-tab" id="np-tab-queue" onclick="switchNpTab('queue')">Queue</button>
</div>
<button class="np-menu-btn" onclick="openNpMenu()" title="Optionen">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="5" r="1.5" fill="currentColor"/><circle cx="12" cy="12" r="1.5" fill="currentColor"/><circle cx="12" cy="19" r="1.5" fill="currentColor"/></svg>
</button>
</div>
<div id="np-player-view">
<div class="np-cover" id="np-cover">
<div class="no-art">♪</div>
</div>
<div class="np-info">
<div class="np-text">
<div class="np-title-row">
<div class="np-title" id="np-title">Kein Titel</div>
</div>
<div class="np-artist">
<span id="np-album-name" onclick="npGoAlbum()" style="cursor:pointer;opacity:.8">—</span>
</div>
<div class="np-artist" id="np-artist">
<span id="np-artist-name">—</span>
</div>
</div>
<button class="np-star" id="np-star-btn" onclick="npToggleStar()">
<svg id="np-star-icon" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="rgba(255,255,255,.5)" stroke-width="2" style="transition:fill .2s,stroke .2s"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
</button>
</div>
<div class="np-progress">
<div class="np-bar" id="np-bar" onclick="npSeek(event)">
<div class="np-bar-fill" id="np-fill"></div>
</div>
<div class="np-times">
<span id="np-cur">0:00</span>
<span id="np-tot">0:00</span>
</div>
</div>
<div class="np-controls">
<button class="np-ctrl" id="np-shuffle-btn" onclick="toggleShuffle()" title="Shuffle">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/></svg>
</button>
<button class="np-ctrl" onclick="prevSong()">
<svg width="30" height="30" viewBox="0 0 24 24" fill="currentColor"><polygon points="19 20 9 12 19 4 19 20"/><line x1="5" y1="19" x2="5" y2="5" stroke="currentColor" stroke-width="2"/></svg>
</button>
<button class="np-play" id="np-play-btn" onclick="togglePlay()">
<svg id="np-play-icon" width="26" height="26" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>
</button>
<button class="np-ctrl" onclick="nextSong()">
<svg width="30" height="30" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 4 15 12 5 20 5 4"/><line x1="19" y1="5" x2="19" y2="19" stroke="currentColor" stroke-width="2"/></svg>
</button>
<button class="np-ctrl" id="np-repeat-btn" onclick="toggleRepeat()" title="Wiederholen">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg>
</button>
</div>
<div class="np-extras">
<button class="np-icon-btn" onclick="downloadCurrent()" title="Download">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
</button>
<div class="np-vol">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color:rgba(255,255,255,.45)"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/></svg>
<input type="range" class="np-vol-slider volume-slider-sync" id="np-vol-slider" min="0" max="100" value="50" oninput="setVolume(this.value)">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color:rgba(255,255,255,.45)"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/></svg>
</div>
<button class="np-icon-btn" id="np-radio-btn" onclick="toggleRadioMode()" title="Radio-Modus: endloser Shuffle">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="2"/><path d="M4.93 4.93a10 10 0 0 0 0 14.14"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M7.76 7.76a6 6 0 0 0 0 8.49"/><path d="M16.24 7.76a6 6 0 0 1 0 8.49"/></svg>
</button>
</div>
</div><!-- /np-player-view -->
<div id="np-lyrics-view">
<div id="np-lyrics-content"></div>
</div>
<div id="np-queue-view">
<div id="np-queue-list"></div>
</div>
</div>
</div>
<!-- NP ACTION SHEET -->
<div class="np-sheet-overlay" id="np-sheet-overlay" onclick="closeNpMenu()"></div>
<div class="np-sheet" id="np-sheet">
<div class="np-sheet-handle"></div>
<div class="np-sheet-song" id="np-sheet-song"></div>
<div id="np-sheet-items"></div>
</div>
<nav class="bottom-nav" id="bottom-nav">
<div class="bottom-nav-inner">
<div class="bnav-tabs">
<button class="bnav-tab active" id="bnav-tab-library" onclick="switchNavMode('library')">Bibliothek</button>
<button class="bnav-tab" id="bnav-tab-discover" onclick="switchNavMode('discover')">Entdecken</button>
</div>
<div class="bnav-pages" id="bnav-library">
<button class="bnav-item active" onclick="navigate('home')" data-page="home">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
Home
</button>
<button class="bnav-item" onclick="navigate('artists')" data-page="artists">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
Künstler
</button>
<button class="bnav-item" onclick="navigate('albums')" data-page="albums">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>
Alben
</button>
<button class="bnav-item" onclick="navigate('playlists')" data-page="playlists">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
Playlists
</button>
<button class="bnav-item" onclick="navigate('starred')" data-page="starred">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
Favoriten
</button>
<button class="bnav-item" id="bnav-audiobooks" onclick="navigate('audiobooks')" data-page="audiobooks" style="display:none">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
Bücher
</button>
</div>
<div class="bnav-pages" id="bnav-discover" style="display:none">
<button class="bnav-item" onclick="navigate('discover')" data-page="discover">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
Suche
</button>
<button class="bnav-item" onclick="navigate('new-releases')" data-page="new-releases">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>
Releases
</button>
<button class="bnav-item" onclick="navigate('recommendations')" data-page="recommendations">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>
Für dich
</button>
<button class="bnav-item" onclick="navigate('random')" data-page="random">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/></svg>
Zufällig
</button>
</div>
</div>
</nav>
<!-- NOTIFICATION PANEL -->
<div id="notif-overlay" class="notif-overlay" onclick="toggleNotifPanel()"></div>
<div id="notif-panel" class="notif-panel">
<div class="notif-panel-hdr">
<span class="notif-panel-title">Benachrichtigungen</span>
<button class="notif-clear-btn" onclick="clearNotifs()">Alle löschen</button>
</div>
<div id="notif-list" class="notif-list"></div>
</div>
</body>
</html>