From 6bdd6f3a592834c6ccde70c8396136938a9f84e1 Mon Sep 17 00:00:00 2001 From: Psychotoxical Date: Wed, 25 Mar 2026 21:30:13 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20v1.17.0=20=E2=80=94=20Media=20Keys,=203?= =?UTF-8?q?=20New=20Themes,=20Perf=20Fixes,=20Contrast=20Audit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 29 + CLAUDE.md | 37 +- README.md | 5 +- package.json | 2 +- packages/aur/PKGBUILD | 2 +- src-tauri/Cargo.lock | 656 +++- src-tauri/Cargo.toml | 1 + src-tauri/Entitlements.plist | 11 + src-tauri/Info.plist | 11 + src-tauri/src/lib.rs | 118 +- src-tauri/tauri.conf.json | 6 +- src/components/NowPlayingDropdown.tsx | 2 +- src/components/ThemePicker.tsx | 37 +- src/i18n.ts | 40 +- src/pages/Favorites.tsx | 22 +- src/pages/RandomMix.tsx | 42 +- src/store/playerStore.ts | 37 +- src/store/themeStore.ts | 2 +- src/styles/components.css | 23 + src/styles/layout.css | 1 + src/styles/theme.css | 5077 +++++++++++++++++++------ 21 files changed, 4929 insertions(+), 1232 deletions(-) create mode 100644 src-tauri/Entitlements.plist create mode 100644 src-tauri/Info.plist diff --git a/CHANGELOG.md b/CHANGELOG.md index 52829818..1bddd799 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,35 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.17.0] - 2026-03-25 + +### Added + +- **Media Keys & OS Media Controls** *(experimental)*: Initial integration via [souvlaki](https://github.com/Sinono3/souvlaki) — MPRIS2 on Linux, Now Playing on macOS, SMTC on Windows. Track metadata (title, artist, album, cover art) and playback state are pushed to the OS media overlay in real time. On Linux, init is skipped gracefully if no D-Bus session is present. This feature is still under active development and observation — behaviour may vary across desktop environments and OS versions. +- **Random Mix — Artist Blacklist**: Artist names are now included in the keyword blacklist filter. Clickable artist chips in the tracklist let you add an artist to the blacklist with one click — same UX as the existing genre chips. +- **Favorites — Remove Song**: Each song row in Favorites now has an inline X button to remove the track from favorites instantly (optimistic UI, server unstar happens in the background). +- **3 New Themes**: + - *Games*: **Horde** — Durotar blood-red earth, iron-plate sidebar, forge-fire gold glow on track name. + - *Games*: **Alliance** — Stormwind deep navy, cathedral stone columns, paladin holy-light glow, gold sidebar trim and nav accent. + - *Operating Systems*: **W11** — Windows 11 Fluent Design dark mode. Mica-style sidebar, clean neutral palette, taskbar-inspired player bar. No gradients — faithful to the minimal Fluent aesthetic. + +### Changed + +- **Theme renames**: Cobalt Media → **WinMedPlayer**, Onyx Cinema → **P-DVD**, Navy Jukebox → **MuMa Jukebox**. +- **NowPlayingDropdown**: Username / player name row now uses `--text-secondary` for improved readability across all themes. + +### Fixed + +- **Performance — App-wide interaction lag**: Removed `[data-theme='X'] * { font-family: ... !important }` universal selectors from several themes (DOS, Unix, and others). The browser places universal selectors in the "universal bucket" and checks them against every DOM node on every style recalculation — measurably sluggish with 500–1000+ elements even when the affected theme is not active. `font-family` is now set on the theme root block (inherits to children) with a targeted `button, input, textarea, select` override for elements that don't inherit font. +- **Performance — Scroll jank**: Removed `repeating-linear-gradient` / `repeating-radial-gradient` from `.app-shell` in DOS, Unix, GW1, Morpheus, Aqua Quartz, and others. WebKitGTK with `WEBKIT_DISABLE_COMPOSITING_MODE=1` (always set by the AUR wrapper) has no GPU compositing — fine-pitch repeating patterns on the full-viewport background re-rasterize every scroll frame. Patterns are now applied only to `.sidebar` and `.player-bar`, which never scroll. +- **Contrast — 29 themes**: Audited all themes against WCAG AA. Fixed `--text-muted` and `--text-secondary` values in 29 themes that had insufficient contrast ratios (< 3.5:1). Affects Catppuccin (all four variants), Gruvbox (all six), Nord variants, GW1, Heisenberg, Ice and Fire, Spider-Tech, Morpheus, Hill Valley 85, Dune, and others. + +### Removed + +- **Theme**: Azerothian Gold removed from the Games group. + +--- + ## [1.16.0] - 2026-03-24 ### Added diff --git a/CLAUDE.md b/CLAUDE.md index dec5eb7a..c6d683b1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -50,7 +50,7 @@ There are no test scripts. TypeScript compilation (`tsc`) is part of the build. | `src/store/authStore.ts` | Multi-server support via `ServerProfile[]` + `activeServerId`. `getBaseUrl()` / `getActiveServer()` used by subsonic.ts. Also stores Last.fm session key, username, scrobbling toggle. Persisted via **`localStorage`** (synchronous — do not change to async storage). | | `src/store/playerStore.ts` | Playback state, queue, scrobbling at 50% via Last.fm, server queue sync (debounced 1.5s). On `playTrack`: calls `reportNowPlaying` (Navidrome) + `lastfmUpdateNowPlaying` (Last.fm) independently. Persists `currentTrack`, `queue`, `queueIndex`, `currentTime` for cold-start resume. | | `src-tauri/src/audio.rs` | Rust audio engine: `audio_play`, `audio_pause`, `audio_resume`, `audio_stop`, `audio_seek`, `audio_set_volume` commands. Emits `audio:playing`, `audio:progress` (100ms), `audio:ended`, `audio:error` events. `MASTER_HEADROOM` (-1 dB) prevents inter-sample clipping at full volume. | -| `src/store/themeStore.ts` | Theme selection (62 themes across 8 groups), applied as `data-theme` on `` | +| `src/store/themeStore.ts` | Theme selection (60 themes across 8 groups), applied as `data-theme` on `` | | `src/store/lyricsStore.ts` | Sidebar tab state (`activeTab: 'queue' \| 'lyrics'`). `showLyrics()` / `showQueue()` / `setTab()`. Not persisted. | | `src/components/LyricsPane.tsx` | Lyrics pane rendered inside QueuePanel when `activeTab === 'lyrics'`. Fetches from LRCLIB, parses LRC, auto-scrolls active line. Only subscribes to `currentTime` when synced lyrics are present. | | `src/api/lrclib.ts` | Fetches lyrics from `https://lrclib.net/api/get`. Returns `{ syncedLyrics, plainLyrics }`. `parseLrc()` parses LRC timestamps into sorted `LrcLine[]`. | @@ -113,7 +113,7 @@ Use `getActiveServer()` to get the current server, `getBaseUrl()` to get its URL Add a function to `src/api/subsonic.ts` using the `api()` helper. The helper automatically injects auth params and unwraps `subsonic-response`. ### Themes -62 themes across 8 groups, selectable in Settings via `ThemePicker`. `themeStore` persists the choice and sets `data-theme` on ``. All component CSS uses semantic tokens (`--accent`, `--text-primary`, etc.) — only the player button gradient and a few decorative elements reference `--ctp-*` palette vars directly, so every theme must define the full `--ctp-*` set. +60 themes across 8 groups, selectable in Settings via `ThemePicker`. `themeStore` persists the choice and sets `data-theme` on ``. All component CSS uses semantic tokens (`--accent`, `--text-primary`, etc.) — only the player button gradient and a few decorative elements reference `--ctp-*` palette vars directly, so every theme must define the full `--ctp-*` set. `--volume-accent` overrides the volume slider colour independently of `--accent` (used by WnAmp for orange volume, yellow accent elsewhere). @@ -125,41 +125,44 @@ Add a function to `src/api/subsonic.ts` using the `api()` helper. The helper | `vintage-tube-radio` | Psysonic Themes | warm brown, VFD orange | Orange `#FF6F00` | | `neon-drift` | Psysonic Themes | midnight blue, electric cyan glow | Cyan `#00f2ff` | | `wnamp` | Mediaplayer | cool gray-blue dark, LCD glow, Courier New | Yellow `#d4cc46`, volume `#de9b35` | -| `navy-jukebox` | Mediaplayer | silver/blue light | Blue `#0070a0` | -| `cobalt-media` | Mediaplayer | cobalt blue dark | Lime `#45ff00` | -| `onyx-cinema` | Mediaplayer | near-black cinematic | Cyan `#00aaff` | +| `muma-jukebox` | Mediaplayer | silver/blue light | Blue `#0070a0` | +| `winmedplayer` | Mediaplayer | cobalt blue dark | Lime `#45ff00` | +| `p-dvd` | Mediaplayer | near-black cinematic | Cyan `#00aaff` | | `spotless` | Mediaplayer | flat dark, Spotify-inspired | Green `#1ED760` | | `dzr0` | Mediaplayer | flat light, Deezer-inspired | Purple `#A238FF` | | `cupertino-beats` | Mediaplayer | Apple Music dark, glassmorphism | Red `#fa243c` | | `cupertino-light` | Operating Systems | macOS light, frosted glass | Apple Blue `#0071e3` | | `cupertino-dark` | Operating Systems | macOS Space Grey, frosted glass | Vibrant Blue `#007aff` | -| `aero-glass` | Operating Systems | Win7 Aero glass blue | Blue `#1878e8` | +| `aero-glass` | Operating Systems | Win7 Aero — ice-blue glass sidebar, near-black frosted taskbar player bar, Aero button gradients | Blue `#1878e8` | | `w98` | Operating Systems | Windows 98 teal desktop | Navy `#000080` | -| `luna-teal` | Operating Systems | WinXP Luna, green gel buttons | Green `#3c9d29` | -| `ascalon` | Games | Guild Wars 1 dark stone fantasy | Gold `#d4af37` | -| `azerothian-gold` | Games | World of Warcraft | Gold `#c19e67` | +| `luna-teal` | Operating Systems | WinXP Luna — warm tan bg, Luna blue task-pane sidebar, XP selection blue hover `#316AC5`, gel buttons | Green `#3c9d29` | +| `w11` | Operating Systems | Windows 11 Fluent Design dark — Mica sidebar, clean neutrals, no gradients | Windows Blue `#0078d4` | +| `gw1` | Games | Guild Wars 1 — aged Tyrian stone, ornate gold borders, Cinzel serif track name, Searing crimson danger | Gold `#c8960c` | | `grand-theft-audio` | Games | GTA night city | Green `#57b05a` | | `lambda-17` | Games | Half-Life orange alert | Amber `#ff9d00` | | `nightcity-2077` | Games | Cyberpunk 2077 | Neon Yellow `#FCEE0A` | | `tetrastack` | Games | Tetris 8-bit, grid background | Cyan `#00f0f0` | | `v-tactical` | Games | Battlefield | Burnt Orange `#ff8a00` | -| `b-runner` | Movies | Blade Runner 2049, amber neon | Amber `#ff9500` | +| `horde` | Games | WoW Horde — Durotar blood-red earth, forge-fire gold glow, iron-plate sidebar | Blood Red `#cc2200` | +| `alliance` | Games | WoW Alliance — Stormwind deep navy, cathedral stone, paladin holy-light glow, gold sidebar trim | Royal Blue `#3388cc` | | `blade` | Movies | deep black, blood-red | Red `#b30000` | -| `dune` | Movies | Arrakis desert stone, spice orange | Orange `#ff8c00` | -| `hill-valley-85` | Movies | Back to the Future, brushed metal | Orange `#ff9900` | +| `dune` | Movies | Arrakis — warm sand main vs cool sietch-blue `#0e0c1a` sidebar, spice cinnamon `#c8780a` accent, desert horizon gradient, sand-grain scrollbar | Spice `#c8780a` | +| `hill-valley-85` | Movies | BTTF — DeLorean time circuit: track name red `#ff2200` Courier New uppercase, artist amber, stainless-steel sidebar lines, fire+lightning radial gradients | Orange `#ff8c00` | | `imperial-sith` | Movies | Star Wars dark side | Red `#e60000` | -| `middle-earth` | Movies | warm parchment light (LOTR) | Gold `#d4af37` | -| `morpheus` | Movies | Matrix terminal | Phosphor Green `#00ff41` | +| `middle-earth` | Movies | LOTR — parchment bg, Bag End oak wood-grain sidebar, `ring-inscription-glow` 5s animation on track name, Sammath Naur player bar, seven-stop gold progress bar, Georgia serif | Gold `#d4a820` | +| `morpheus` | Movies | Matrix — CRT scanlines on app-shell, vertical code-column sidebar pattern, terminal buttons (monospace, no fill, green glow border-radius 0), 6px scrollbar | Phosphor Green `#00ff41` | | `order-of-the-phoenix` | Movies | Harry Potter | Ember Orange `#e63900` | | `pandora` | Movies | Avatar bioluminescent | Cyan `#00f2ff` | -| `spider-tech` | Movies | Spider-Man navy blue, hero red | Red `#E62429` | +| `spider-tech` | Movies | Spider-Man — CSS spider web (conic+radial) radiating from sidebar top-left, Into the Spider-Verse halftone dots on app-shell, track name red glow, artist in suit-blue `#4a88ff` | Red `#E62429` | | `stark-hud` | Movies | Iron Man HUD | Cyan `#00f2ff` | | `t-800` | Movies | Terminator, Skynet blue | Cyan `#00d4ff` | | `aqua-quartz` | Operating Systems | Mac OS X Aqua, skeuomorphic jelly buttons | Blue `#3876f7` | +| `dos` | Operating Systems | MS-DOS — ANSI blue `#0000AA` bg, Courier New everywhere, inverted grey selection, blinking block cursor on track name, 16px DOS scrollbar | Yellow `#FFFF55` | +| `unix` | Operating Systems | Unix Shell — pure black, Courier New, `$ ` prompt prefix + blinking `_` cursor on track name, artist in ANSI blue `#5588FF` (ls directory color), thin 6px scrollbar | Green `#22C55E` | | `w3-1` | Operating Systems | Windows 3.1, light silver/teal | Navy `#000080` | -| `ice-and-fire` | Series | Game of Thrones | Ice Blue `#70a1ff` | +| `ice-and-fire` | Series | Game of Thrones — temperature duality: volcanic warm main (`#100c08`) vs cold Castle Black sidebar (`#090c10`), `fire-flicker` 5s irregular animation on track name, dragon gold `#c8880a` artist, red-to-gold content header rule, forge fire glow on player bar | Blood Red `#c41e1e` | | `doh-matic` | Series | The Simpsons | Blue `#1F75FE` | -| `heisenberg` | Series | Breaking Bad | Crystal Blue `#3fe0ff` | +| `heisenberg` | Series | Breaking Bad — periodic table grid on app-shell, hazmat tape diagonal on sidebar, `crystal-pulse` 3s glow animation on track name, lab fluorescent blue top border on player bar | Crystal Blue `#35d4f8` | | `turtle-power` | Series | TMNT, turtle green, brick sidebar | Green `#33cc33` | | `insta` | Social Media | Instagram dark, pink gradient | Pink `#E1306C` | | `readit` | Social Media | Reddit dark, orange-red | OrangeRed `#FF4500` | diff --git a/README.md b/README.md index ed9a2fab..19eb1b7c 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Designed specifically for users hosting their own music via Navidrome or other S ## ✨ Features -- 🎨 **Gorgeous UI**: 47 deeply integrated themes across 7 groups — Open Source Classics (Catppuccin, Nord, Gruvbox), Operating Systems, Games, Movies, Series, Psysonic originals, and Psysonic Mediaplayer — with smooth glassmorphism effects and micro-animations. +- 🎨 **Gorgeous UI**: A large selection of beautiful, lean themes for every taste — Open Source Classics (Catppuccin, Nord, Gruvbox), Operating Systems, Games, Movies, Series, Psysonic originals, and Mediaplayer — with smooth glassmorphism effects and micro-animations. - ⚡ **Blazing Fast**: Built with Rust & Tauri — native audio engine (rodio), minimal RAM usage compared to typical Electron apps. - 🌍 **Internationalization (i18n)**: Fully translated into English, German, French, and Dutch. - 📻 **Live "Now Playing"**: See what other users on your server are currently listening to in real-time. @@ -55,7 +55,7 @@ Designed specifically for users hosting their own music via Navidrome or other S - [x] Multi-server support - [x] IndexedDB image caching - [x] Random Mix with keyword filter & Super Genre mix -- [x] 47 themes across 7 groups: Open Source Classics, Operating Systems, Games, Movies, Series, Psysonic originals, Psysonic Mediaplayer +- [x] Large theme library across 8 groups: Open Source Classics, Operating Systems, Games, Movies, Series, Social Media, Psysonic originals, Mediaplayer - [x] Internationalization (English, German, French, Dutch) - [x] AUR package (Arch / CachyOS) - [x] Configurable keybindings @@ -63,6 +63,7 @@ Designed specifically for users hosting their own music via Navidrome or other S ### 📋 Planned - [ ] General UI polish & visual refinement +- [ ] Accessibility (a11y) — keyboard navigation, screen reader support, ARIA labels - [ ] More languages --- diff --git a/package.json b/package.json index 6cf4671a..4a5cfa3b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "psysonic", - "version": "1.16.0", + "version": "1.17.0", "private": true, "scripts": { "dev": "vite", diff --git a/packages/aur/PKGBUILD b/packages/aur/PKGBUILD index 6810a0ae..31a5ccb3 100644 --- a/packages/aur/PKGBUILD +++ b/packages/aur/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Psychotoxic pkgname=psysonic -pkgver=1.16.0 +pkgver=1.17.0 pkgrel=1 pkgdesc="Desktop music player for Subsonic API-compatible servers (Navidrome, Gonic, etc.)" arch=('x86_64') diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index eac9309b..2d38fe83 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -75,13 +75,23 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "async-broadcast" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" +dependencies = [ + "event-listener 2.5.3", + "futures-core", +] + [[package]] name = "async-broadcast" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" dependencies = [ - "event-listener", + "event-listener 5.4.1", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -107,12 +117,44 @@ checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", - "fastrand", - "futures-lite", + "fastrand 2.3.0", + "futures-lite 2.6.1", "pin-project-lite", "slab", ] +[[package]] +name = "async-fs" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "blocking", + "futures-lite 1.13.0", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.28", + "slab", + "socket2 0.4.10", + "waker-fn", +] + [[package]] name = "async-io" version = "2.6.0" @@ -123,25 +165,51 @@ dependencies = [ "cfg-if", "concurrent-queue", "futures-io", - "futures-lite", + "futures-lite 2.6.1", "parking", - "polling", - "rustix", + "polling 3.11.0", + "rustix 1.1.4", "slab", "windows-sys 0.61.2", ] +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + [[package]] name = "async-lock" version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "event-listener", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] +[[package]] +name = "async-process" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +dependencies = [ + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", + "blocking", + "cfg-if", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.44", + "windows-sys 0.48.0", +] + [[package]] name = "async-process" version = "2.5.0" @@ -149,15 +217,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ "async-channel", - "async-io", - "async-lock", + "async-io 2.6.0", + "async-lock 3.4.2", "async-signal", "async-task", "blocking", "cfg-if", - "event-listener", - "futures-lite", - "rustix", + "event-listener 5.4.1", + "futures-lite 2.6.1", + "rustix 1.1.4", ] [[package]] @@ -177,13 +245,13 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" dependencies = [ - "async-io", - "async-lock", + "async-io 2.6.0", + "async-lock 3.4.2", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix", + "rustix 1.1.4", "signal-hook-registry", "slab", "windows-sys 0.61.2", @@ -295,6 +363,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "block-buffer" version = "0.10.4" @@ -322,7 +396,7 @@ dependencies = [ "async-channel", "async-task", "futures-io", - "futures-lite", + "futures-lite 2.6.1", "piper", ] @@ -524,6 +598,36 @@ dependencies = [ "libloading 0.8.9", ] +[[package]] +name = "cocoa" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation", + "core-foundation 0.9.4", + "core-graphics 0.22.3", + "foreign-types 0.3.2", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "libc", + "objc", +] + [[package]] name = "combine" version = "4.6.7" @@ -585,6 +689,19 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types 0.3.2", + "libc", +] + [[package]] name = "core-graphics" version = "0.25.0" @@ -593,11 +710,22 @@ checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ "bitflags 2.11.0", "core-foundation 0.10.1", - "core-graphics-types", + "core-graphics-types 0.2.0", "foreign-types 0.5.0", "libc", ] +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "libc", +] + [[package]] name = "core-graphics-types" version = "0.2.0" @@ -783,6 +911,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.20" @@ -827,6 +966,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + [[package]] name = "dispatch2" version = "0.3.1" @@ -998,6 +1143,23 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "event-listener" version = "5.4.1" @@ -1015,7 +1177,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener", + "event-listener 5.4.1", "pin-project-lite", ] @@ -1025,6 +1187,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -1046,7 +1217,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ - "memoffset", + "memoffset 0.9.1", "rustc_version", ] @@ -1171,13 +1342,28 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-lite" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ - "fastrand", + "fastrand 2.3.0", "futures-core", "futures-io", "parking", @@ -1347,7 +1533,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ - "rustix", + "rustix 1.1.4", "windows-link 0.2.1", ] @@ -1616,6 +1802,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hermit-abi" version = "0.5.2" @@ -1750,7 +1942,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.3", "system-configuration", "tokio", "tower-service", @@ -1951,6 +2143,26 @@ dependencies = [ "cfb", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "ipnet" version = "2.12.0" @@ -2188,6 +2400,18 @@ dependencies = [ "libc", ] +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -2242,6 +2466,15 @@ dependencies = [ "libc", ] +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "markup5ever" version = "0.14.1" @@ -2285,6 +2518,15 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.9.1" @@ -2434,6 +2676,18 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -2456,12 +2710,12 @@ version = "4.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21af20a1b50be5ac5861f74af1a863da53a11c38684d9818d82f1c42f7fdc6c2" dependencies = [ - "futures-lite", + "futures-lite 2.6.1", "log", "mac-notification-sys", "serde", "tauri-winrt-notification", - "zbus", + "zbus 5.14.0", ] [[package]] @@ -2512,6 +2766,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + [[package]] name = "objc2" version = "0.6.4" @@ -2966,7 +3229,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", - "fastrand", + "fastrand 2.3.0", "futures-io", ] @@ -3015,6 +3278,22 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + [[package]] name = "polling" version = "3.11.0" @@ -3023,12 +3302,18 @@ checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi", + "hermit-abi 0.5.2", "pin-project-lite", - "rustix", + "rustix 1.1.4", "windows-sys 0.61.2", ] +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + [[package]] name = "potential_utf" version = "0.1.4" @@ -3147,6 +3432,7 @@ dependencies = [ "rodio", "serde", "serde_json", + "souvlaki", "tauri", "tauri-build", "tauri-plugin-dialog", @@ -3530,6 +3816,33 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.37.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + [[package]] name = "rustix" version = "1.1.4" @@ -3539,7 +3852,7 @@ dependencies = [ "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] @@ -3884,6 +4197,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.9" @@ -3973,6 +4297,16 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.6.3" @@ -4031,12 +4365,37 @@ dependencies = [ "system-deps", ] +[[package]] +name = "souvlaki" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5855c8f31521af07d896b852eaa9eca974ddd3211fc2ae292e58dda8eb129bc8" +dependencies = [ + "base64 0.22.1", + "block", + "cocoa", + "core-graphics 0.22.3", + "dispatch", + "objc", + "pollster", + "thiserror 1.0.69", + "windows 0.44.0", + "zbus 3.15.2", + "zvariant 3.15.2", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "string_cache" version = "0.8.9" @@ -4315,7 +4674,7 @@ dependencies = [ "bitflags 2.11.0", "block2", "core-foundation 0.10.1", - "core-graphics", + "core-graphics 0.25.0", "crossbeam-channel", "dispatch2", "dlopen2", @@ -4737,10 +5096,10 @@ version = "3.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ - "fastrand", + "fastrand 2.3.0", "getrandom 0.4.2", "once_cell", - "rustix", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -4846,7 +5205,7 @@ dependencies = [ "libc", "mio", "pin-project-lite", - "socket2", + "socket2 0.6.3", "tokio-macros", "windows-sys 0.61.2", ] @@ -5122,7 +5481,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b70b87d15e91f553711b40df3048faf27a7a04e01e0ddc0cf9309f0af7c2ca" dependencies = [ - "memoffset", + "memoffset 0.9.1", "tempfile", "windows-sys 0.61.2", ] @@ -5279,6 +5638,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "walkdir" version = "2.5.0" @@ -5583,6 +5948,15 @@ dependencies = [ "windows-version", ] +[[package]] +name = "windows" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows" version = "0.54.0" @@ -5771,6 +6145,15 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -5822,6 +6205,21 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -5879,6 +6277,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -5897,6 +6301,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -5915,6 +6325,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -5945,6 +6361,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -5963,6 +6385,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -5981,6 +6409,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -5999,6 +6433,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -6206,7 +6646,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" dependencies = [ "gethostname", - "rustix", + "rustix 1.1.4", "x11rb-protocol", ] @@ -6216,6 +6656,16 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "xkeysym" version = "0.2.1" @@ -6245,29 +6695,70 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zbus" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6" +dependencies = [ + "async-broadcast 0.5.1", + "async-executor", + "async-fs", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-process 1.8.1", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "byteorder", + "derivative", + "enumflags2", + "event-listener 2.5.3", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "once_cell", + "ordered-stream", + "rand 0.8.5", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "winapi", + "xdg-home", + "zbus_macros 3.15.2", + "zbus_names 2.6.1", + "zvariant 3.15.2", +] + [[package]] name = "zbus" version = "5.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" dependencies = [ - "async-broadcast", + "async-broadcast 0.7.2", "async-executor", - "async-io", - "async-lock", - "async-process", + "async-io 2.6.0", + "async-lock 3.4.2", + "async-process 2.5.0", "async-recursion", "async-task", "async-trait", "blocking", "enumflags2", - "event-listener", + "event-listener 5.4.1", "futures-core", - "futures-lite", + "futures-lite 2.6.1", "hex", "libc", "ordered-stream", - "rustix", + "rustix 1.1.4", "serde", "serde_repr", "tracing", @@ -6275,9 +6766,23 @@ dependencies = [ "uuid", "windows-sys 0.61.2", "winnow 0.7.15", - "zbus_macros", - "zbus_names", - "zvariant", + "zbus_macros 5.14.0", + "zbus_names 4.3.1", + "zvariant 5.10.0", +] + +[[package]] +name = "zbus_macros" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", + "zvariant_utils 1.0.1", ] [[package]] @@ -6290,9 +6795,20 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.117", - "zbus_names", - "zvariant", - "zvariant_utils", + "zbus_names 4.3.1", + "zvariant 5.10.0", + "zvariant_utils 3.3.0", +] + +[[package]] +name = "zbus_names" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d" +dependencies = [ + "serde", + "static_assertions", + "zvariant 3.15.2", ] [[package]] @@ -6303,7 +6819,7 @@ checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" dependencies = [ "serde", "winnow 0.7.15", - "zvariant", + "zvariant 5.10.0", ] [[package]] @@ -6392,6 +6908,20 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +[[package]] +name = "zvariant" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db" +dependencies = [ + "byteorder", + "enumflags2", + "libc", + "serde", + "static_assertions", + "zvariant_derive 3.15.2", +] + [[package]] name = "zvariant" version = "5.10.0" @@ -6402,8 +6932,21 @@ dependencies = [ "enumflags2", "serde", "winnow 0.7.15", - "zvariant_derive", - "zvariant_utils", + "zvariant_derive 5.10.0", + "zvariant_utils 3.3.0", +] + +[[package]] +name = "zvariant_derive" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", + "zvariant_utils 1.0.1", ] [[package]] @@ -6416,7 +6959,18 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.117", - "zvariant_utils", + "zvariant_utils 3.3.0", +] + +[[package]] +name = "zvariant_utils" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b88e09b6..816fe856 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -36,3 +36,4 @@ md5 = "0.7" tokio = { version = "1", features = ["rt", "time"] } biquad = "0.4" tauri-plugin-window-state = "2.4.1" +souvlaki = { version = "0.8", default-features = false, features = ["use_zbus"] } diff --git a/src-tauri/Entitlements.plist b/src-tauri/Entitlements.plist new file mode 100644 index 00000000..c01bd2bc --- /dev/null +++ b/src-tauri/Entitlements.plist @@ -0,0 +1,11 @@ + + + + + + com.apple.security.device.audio-input + + + diff --git a/src-tauri/Info.plist b/src-tauri/Info.plist new file mode 100644 index 00000000..5bd183a1 --- /dev/null +++ b/src-tauri/Info.plist @@ -0,0 +1,11 @@ + + + + + + NSMicrophoneUsageDescription + Psysonic does not use the microphone. This prompt is triggered by the audio subsystem initializing output devices. + + diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index e2df5da4..57b74590 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -16,6 +16,10 @@ use tauri::{ /// Prevents on_shortcut() accumulating duplicate handlers across JS reloads (HMR / StrictMode). type ShortcutMap = Mutex>; +/// Shared handle to OS media controls (MPRIS2 on Linux, Now Playing on macOS, SMTC on Windows). +/// `None` if souvlaki failed to initialize (e.g. no D-Bus session on Linux). +type MprisControls = Mutex>; + #[tauri::command] fn greet(name: &str) -> String { format!("Hello, {}!", name) @@ -138,6 +142,52 @@ fn unregister_global_shortcut( app.global_shortcut().unregister(parsed).map_err(|e| e.to_string()) } +#[tauri::command] +fn mpris_set_metadata( + controls: tauri::State, + title: Option, + artist: Option, + album: Option, + cover_url: Option, + duration_secs: Option, +) -> Result<(), String> { + use souvlaki::MediaMetadata; + use std::time::Duration; + + let duration = duration_secs.map(|s| Duration::from_secs_f64(s)); + let mut guard = controls.lock().unwrap(); + let Some(ctrl) = guard.as_mut() else { return Ok(()); }; + ctrl.set_metadata(MediaMetadata { + title: title.as_deref(), + artist: artist.as_deref(), + album: album.as_deref(), + cover_url: cover_url.as_deref(), + duration, + }) + .map_err(|e| format!("MPRIS set_metadata failed: {e:?}")) +} + +#[tauri::command] +fn mpris_set_playback( + controls: tauri::State, + playing: bool, + position_secs: Option, +) -> Result<(), String> { + use souvlaki::{MediaPlayback, MediaPosition}; + use std::time::Duration; + + let progress = position_secs.map(|s| MediaPosition(Duration::from_secs_f64(s))); + let playback = if playing { + MediaPlayback::Playing { progress } + } else { + MediaPlayback::Paused { progress } + }; + let mut guard = controls.lock().unwrap(); + let Some(ctrl) = guard.as_mut() else { return Ok(()); }; + ctrl.set_playback(playback) + .map_err(|e| format!("MPRIS set_playback failed: {e:?}")) +} + pub fn run() { let (audio_engine, _audio_thread) = audio::create_engine(); @@ -201,26 +251,56 @@ pub fn run() { }) .build(app)?; - // Register media key global shortcuts (all platforms) + // ── MPRIS2 / OS media controls via souvlaki ────────────────── { - use tauri_plugin_global_shortcut::{GlobalShortcutExt, Shortcut, ShortcutState}; - let shortcuts = ["MediaPlayPause", "MediaNextTrack", "MediaPreviousTrack"]; - for shortcut_str in &shortcuts { - if let Ok(shortcut) = shortcut_str.parse::() { - let shortcut_clone = shortcut_str.to_string(); - let _ = app.global_shortcut().on_shortcut(shortcut, move |app, _shortcut, event| { - if event.state == ShortcutState::Pressed { - let event_name = match shortcut_clone.as_str() { - "MediaPlayPause" => "media:play-pause", - "MediaNextTrack" => "media:next", - "MediaPreviousTrack" => "media:prev", - _ => return, - }; - let _ = app.emit(event_name, ()); - } - }); + use souvlaki::{MediaControlEvent, MediaControls, PlatformConfig}; + + // On Linux, souvlaki requires a live D-Bus session. If the env var + // is absent or empty (headless, test, or stripped environment), + // skip init entirely — commands will no-op via the None branch. + #[cfg(target_os = "linux")] + let dbus_ok = std::env::var("DBUS_SESSION_BUS_ADDRESS") + .map(|v| !v.is_empty()) + .unwrap_or(false); + #[cfg(not(target_os = "linux"))] + let dbus_ok = true; + + if !dbus_ok { + eprintln!("[Psysonic] No D-Bus session — MPRIS media controls disabled"); + app.manage(MprisControls::new(None)); + } else { + + let config = PlatformConfig { + dbus_name: "psysonic", + display_name: "Psysonic", + hwnd: None, + }; + + let maybe_controls = match MediaControls::new(config) { + Ok(mut controls) => { + let app_handle = app.handle().clone(); + if let Err(e) = controls.attach(move |event: MediaControlEvent| { + let event_name = match event { + MediaControlEvent::Toggle => "media:play-pause", + MediaControlEvent::Play => "media:play-pause", + MediaControlEvent::Pause => "media:play-pause", + MediaControlEvent::Next => "media:next", + MediaControlEvent::Previous => "media:prev", + _ => return, + }; + let _ = app_handle.emit(event_name, ()); + }) { + eprintln!("[Psysonic] Failed to attach media controls: {e:?}"); + } + Some(controls) } - } + Err(e) => { + eprintln!("[Psysonic] Could not create media controls: {e:?}"); + None + } + }; + app.manage(MprisControls::new(maybe_controls)); + } // end dbus_ok } Ok(()) @@ -239,6 +319,8 @@ pub fn run() { exit_app, register_global_shortcut, unregister_global_shortcut, + mpris_set_metadata, + mpris_set_playback, audio::audio_play, audio::audio_pause, audio::audio_resume, diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 7f50f317..4ec4961b 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Psysonic", - "version": "1.16.0", + "version": "1.17.0", "identifier": "dev.psysonic.player", "build": { "beforeDevCommand": "npm run dev", @@ -55,6 +55,10 @@ "bundleMediaFramework": true } }, + "macOS": { + "entitlements": "Entitlements.plist", + "minimumSystemVersion": "10.15" + }, "windows": { "wix": { "upgradeCode": "e3b4c2a1-7f6d-4e8b-9c5a-2d1f0e3b8a7c" diff --git a/src/components/NowPlayingDropdown.tsx b/src/components/NowPlayingDropdown.tsx index 3c1f4c96..38dcb599 100644 --- a/src/components/NowPlayingDropdown.tsx +++ b/src/components/NowPlayingDropdown.tsx @@ -146,7 +146,7 @@ export default function NowPlayingDropdown() {
{stream.title}
{stream.artist}
-
+
{stream.username} ({stream.playerName || 'Web'}) {stream.minutesAgo > 0 && • {t('nowPlaying.minutesAgo', { n: stream.minutesAgo })}} diff --git a/src/components/ThemePicker.tsx b/src/components/ThemePicker.tsx index da4eda84..e0a659d1 100644 --- a/src/components/ThemePicker.tsx +++ b/src/components/ThemePicker.tsx @@ -13,25 +13,25 @@ const THEME_GROUPS: { group: string; themes: ThemeDef[] }[] = [ { group: 'Games', themes: [ - { id: 'ascalon', label: 'Ascalon', bg: '#1c1a17', card: '#0f0d0b', accent: '#d4af37' }, - { id: 'azerothian-gold', label: 'Azerothian Gold', bg: '#1a1a1a', card: '#0a0a0a', accent: '#c19e67' }, + { id: 'gw1', label: 'GW1', bg: '#0e0b08', card: '#1a1208', accent: '#c8960c' }, { id: 'grand-theft-audio', label: 'Grand Theft Audio', bg: '#141414', card: '#0a0a0a', accent: '#57b05a' }, { id: 'lambda-17', label: 'Lambda 17', bg: '#14171a', card: '#0a0b0c', accent: '#ff9d00' }, { id: 'nightcity-2077', label: 'NightCity 2077', bg: '#050505', card: '#000000', accent: '#FCEE0A' }, { id: 'tetrastack', label: 'TetraStack', bg: '#0a0a0a', card: '#151515', accent: '#00f0f0' }, { id: 'v-tactical', label: 'V-Tactical', bg: '#161c22', card: '#090c0e', accent: '#ff8a00' }, + { id: 'horde', label: 'Horde', bg: '#1a0500', card: '#2e0a02', accent: '#cc2200' }, + { id: 'alliance', label: 'Alliance', bg: '#06101e', card: '#0c1e34', accent: '#3388cc' }, ], }, { group: 'Movies', themes: [ - { id: 'b-runner', label: 'B-Runner', bg: '#141211', card: '#080707', accent: '#ff9500' }, { id: 'blade', label: 'Blade', bg: '#121212', card: '#050505', accent: '#b30000' }, - { id: 'dune', label: 'Dune', bg: '#1c1917', card: '#0c0a09', accent: '#ff8c00' }, - { id: 'hill-valley-85', label: 'Hill Valley 85', bg: '#1a1d23', card: '#0a0a0c', accent: '#ff9900' }, - { id: 'middle-earth', label: 'Middle Earth', bg: '#f4e4bc', card: '#2a1d15', accent: '#d4af37' }, - { id: 'morpheus', label: 'Morpheus', bg: '#0a0a0a', card: '#000000', accent: '#00ff41' }, - { id: 'spider-tech', label: 'Spider-Tech', bg: '#0F172A', card: '#050C1A', accent: '#E62429' }, + { id: 'dune', label: 'Dune', bg: '#1c1408', card: '#0e0c1a', accent: '#c8780a' }, + { id: 'hill-valley-85', label: 'Hill Valley 85', bg: '#0d0b18', card: '#141120', accent: '#ff8c00' }, + { id: 'middle-earth', label: 'Middle Earth', bg: '#f0e0b0', card: '#241a0e', accent: '#d4a820' }, + { id: 'morpheus', label: 'Morpheus', bg: '#050905', card: '#0a120a', accent: '#00ff41' }, + { id: 'spider-tech', label: 'Spider-Tech', bg: '#0e0c18', card: '#181428', accent: '#E62429' }, { id: 'stark-hud', label: 'Stark HUD', bg: '#0b0f15', card: '#05070a', accent: '#00f2ff' }, { id: 't-800', label: 'T-800', bg: '#1f242d', card: '#0a0c10', accent: '#00d4ff' }, ], @@ -61,10 +61,13 @@ const THEME_GROUPS: { group: string; themes: ThemeDef[] }[] = [ { id: 'aqua-quartz', label: 'Aqua Quartz', bg: '#f6f6f6', card: '#ffffff', accent: '#3876f7' }, { id: 'cupertino-dark', label: 'Cupertino Dark', bg: '#1e1e1f', card: '#2d2d2f', accent: '#007aff' }, { id: 'cupertino-light', label: 'Cupertino Light', bg: '#ffffff', card: '#f2f2f7', accent: '#0071e3' }, - { id: 'w3-1', label: 'W3.1', bg: '#008080', card: '#c0c0c0', accent: '#000080' }, - { id: 'aero-glass', label: 'W7', bg: '#cddbed', card: '#1d4268', accent: '#1878e8' }, - { id: 'w98', label: 'W98', bg: '#008080', card: '#c0c0c0', accent: '#000080' }, - { id: 'luna-teal', label: 'WXP', bg: '#ece9d8', card: '#0055e5', accent: '#3c9d29' }, + { id: 'dos', label: 'DOS', bg: '#0000AA', card: '#000080', accent: '#FFFF55' }, + { id: 'unix', label: 'Unix', bg: '#000000', card: '#111111', accent: '#22C55E' }, + { id: 'w3-1', label: 'W3.1', bg: '#c0c0c0', card: '#ffffff', accent: '#000080' }, + { id: 'aero-glass', label: 'W7', bg: '#b8cfe8', card: '#05080f', accent: '#1878e8' }, + { id: 'w98', label: 'W98', bg: '#008080', card: '#d4d0c8', accent: '#000080' }, + { id: 'luna-teal', label: 'WXP', bg: '#ece9d8', card: '#1248b8', accent: '#3c9d29' }, + { id: 'w11', label: 'W11', bg: '#202020', card: '#2c2c2c', accent: '#0078d4' }, ], }, { @@ -80,11 +83,11 @@ const THEME_GROUPS: { group: string; themes: ThemeDef[] }[] = [ { group: 'Mediaplayer', themes: [ - { id: 'cobalt-media', label: 'Cobalt Media', bg: '#3a62a5', card: '#000000', accent: '#45ff00' }, + { id: 'winmedplayer', label: 'WinMedPlayer', bg: '#3a62a5', card: '#000000', accent: '#45ff00' }, { id: 'cupertino-beats', label: 'Cupertino Beats', bg: '#1c1c1e', card: '#2c2c2e', accent: '#fa243c' }, { id: 'dzr0', label: 'DZR', bg: '#FFFFFF', card: '#F5F5F7', accent: '#A238FF' }, - { id: 'navy-jukebox', label: 'Navy Jukebox', bg: '#d4d8db', card: '#001358', accent: '#0070a0' }, - { id: 'onyx-cinema', label: 'Onyx Cinema', bg: '#141414', card: '#000000', accent: '#00aaff' }, + { id: 'muma-jukebox', label: 'MuMa Jukebox', bg: '#d4d8db', card: '#001358', accent: '#0070a0' }, + { id: 'p-dvd', label: 'P-DVD', bg: '#141414', card: '#000000', accent: '#00aaff' }, { id: 'spotless', label: 'Spotless', bg: '#121212', card: '#181818', accent: '#1ED760' }, { id: 'jayfin', label: 'Jayfin', bg: '#141414', card: '#1e1e1e', accent: '#AA5CC3' }, { id: 'wnamp', label: 'WnAmp', bg: '#2b2b3a', card: '#000000', accent: '#00ff00' }, @@ -93,9 +96,9 @@ const THEME_GROUPS: { group: string; themes: ThemeDef[] }[] = [ { group: 'Series', themes: [ - { id: 'ice-and-fire', label: 'A Theme of Ice and Fire', bg: '#121820', card: '#05070a', accent: '#70a1ff' }, + { id: 'ice-and-fire', label: 'A Theme of Ice and Fire', bg: '#100c08', card: '#090c10', accent: '#c41e1e' }, { id: 'doh-matic', label: "D'oh-matic", bg: '#FFFDF0', card: '#FFD90F', accent: '#1F75FE' }, - { id: 'heisenberg', label: 'Heisenberg', bg: '#1a1d1a', card: '#0a0c0a', accent: '#3fe0ff' }, + { id: 'heisenberg', label: 'Heisenberg', bg: '#0b0e12', card: '#141a22', accent: '#35d4f8' }, { id: 'turtle-power', label: 'Turtle Power', bg: '#1a1a1a', card: '#0a0a0a', accent: '#33cc33' }, ], }, diff --git a/src/i18n.ts b/src/i18n.ts index 6e0582b7..f3022ec0 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -148,6 +148,7 @@ const enTranslation = { albums: 'Albums', songs: 'Songs', enqueueAll: 'Add all to queue', + removeSong: 'Remove from favorites', }, randomAlbums: { title: 'Random Albums', @@ -168,17 +169,20 @@ const enTranslation = { play: 'Play', trackGenre: 'Genre', excludeAudiobooks: 'Exclude audiobooks & radio plays', - excludeAudiobooksDesc: 'Matches keywords against genre, title, and album — e.g. Hörbuch, Audiobook, Spoken Word, …', + excludeAudiobooksDesc: 'Matches keywords against genre, title, album, and artist — e.g. Hörbuch, Audiobook, Spoken Word, …', genreBlocked: 'Keyword blocked', genreAddedToBlacklist: 'Added to filter list', genreAlreadyBlocked: 'Already blocked', + artistBlocked: 'Artist blocked', + artistAddedToBlacklist: 'Artist added to filter list', + artistClickHint: 'Click to block this artist', blacklistToggle: 'Keyword Filter', genreMixTitle: 'Genre Mix', genreMixDesc: 'Select a genre to get a curated random mix', genreMixLoadMore: 'Load 10 more', genreMixNoGenres: 'No genres found on server.', filterPanelTitle: 'Filters', - genreClickHint: 'Click a genre tag to add it\nas a filter keyword.\nMatches genre, title & album.', + genreClickHint: 'Click a genre tag to add it\nas a filter keyword.\nMatches genre, title, album & artist.', }, playlists: { title: 'Playlists', @@ -341,7 +345,7 @@ const enTranslation = { changelog: 'Changelog', randomMixTitle: 'Random Mix', randomMixBlacklistTitle: 'Custom Filter Keywords', - randomMixBlacklistDesc: 'Songs are excluded when any keyword matches their genre, title, or album (active when the checkbox above is on).', + randomMixBlacklistDesc: 'Songs are excluded when any keyword matches their genre, title, album, or artist (active when the checkbox above is on).', randomMixBlacklistPlaceholder: 'Add keyword…', randomMixBlacklistAdd: 'Add', randomMixBlacklistEmpty: 'No custom keywords added yet.', @@ -691,6 +695,7 @@ const deTranslation = { albums: 'Alben', songs: 'Songs', enqueueAll: 'Alle in die Warteschlange', + removeSong: 'Aus Favoriten entfernen', }, randomAlbums: { title: 'Zufallsalben', @@ -711,17 +716,20 @@ const deTranslation = { play: 'Abspielen', trackGenre: 'Genre', excludeAudiobooks: 'Hörbücher & Hörspiele ausschließen', - excludeAudiobooksDesc: 'Prüft Keywords gegen Genre, Titel und Album — z. B. Hörbuch, Audiobook, Spoken Word, …', + excludeAudiobooksDesc: 'Prüft Keywords gegen Genre, Titel, Album und Künstler — z. B. Hörbuch, Audiobook, Spoken Word, …', genreBlocked: 'Keyword gesperrt', genreAddedToBlacklist: 'Zur Filterliste hinzugefügt', genreAlreadyBlocked: 'Bereits gesperrt', + artistBlocked: 'Künstler gesperrt', + artistAddedToBlacklist: 'Künstler zur Filterliste hinzugefügt', + artistClickHint: 'Klicken um diesen Künstler zu sperren', blacklistToggle: 'Keyword-Filter', genreMixTitle: 'Genre-Mix', genreMixDesc: 'Genre auswählen für einen passenden Zufallsmix', genreMixLoadMore: '10 weitere laden', genreMixNoGenres: 'Keine Genres auf dem Server gefunden.', filterPanelTitle: 'Filter', - genreClickHint: 'Genre-Tag anklicken,\num es als Filter-Keyword hinzuzufügen.\nPrüft Genre, Titel & Album.', + genreClickHint: 'Genre-Tag anklicken,\num es als Filter-Keyword hinzuzufügen.\nPrüft Genre, Titel, Album & Künstler.', }, playlists: { title: 'Playlists', @@ -884,7 +892,7 @@ const deTranslation = { changelog: 'Changelog', randomMixTitle: 'Zufallsmix', randomMixBlacklistTitle: 'Eigene Filter-Keywords', - randomMixBlacklistDesc: 'Songs werden ausgeschlossen, wenn ein Keyword auf Genre, Titel oder Album zutrifft (aktiv wenn die Checkbox oben an ist).', + randomMixBlacklistDesc: 'Songs werden ausgeschlossen, wenn ein Keyword auf Genre, Titel, Album oder Künstler zutrifft (aktiv wenn die Checkbox oben an ist).', randomMixBlacklistPlaceholder: 'Keyword hinzufügen…', randomMixBlacklistAdd: 'Hinzufügen', randomMixBlacklistEmpty: 'Noch keine eigenen Keywords hinzugefügt.', @@ -1234,6 +1242,7 @@ const frTranslation = { albums: 'Albums', songs: 'Morceaux', enqueueAll: 'Tout ajouter à la file', + removeSong: 'Retirer des favoris', }, randomAlbums: { title: 'Albums aléatoires', @@ -1254,17 +1263,20 @@ const frTranslation = { play: 'Lire', trackGenre: 'Genre', excludeAudiobooks: 'Exclure les livres audio et pièces radiophoniques', - excludeAudiobooksDesc: 'Correspond aux mots-clés dans le genre, le titre et l\'album — ex. Hörbuch, Audiobook, Spoken Word, …', + excludeAudiobooksDesc: 'Correspond aux mots-clés dans le genre, le titre, l\'album et l\'artiste — ex. Hörbuch, Audiobook, Spoken Word, …', genreBlocked: 'Mot-clé bloqué', genreAddedToBlacklist: 'Ajouté à la liste de filtres', genreAlreadyBlocked: 'Déjà bloqué', + artistBlocked: 'Artiste bloqué', + artistAddedToBlacklist: 'Artiste ajouté à la liste de filtres', + artistClickHint: 'Cliquer pour bloquer cet artiste', blacklistToggle: 'Filtre par mot-clé', genreMixTitle: 'Mix par genre', genreMixDesc: 'Sélectionnez un genre pour obtenir un mix aléatoire', genreMixLoadMore: 'Charger 10 de plus', genreMixNoGenres: 'Aucun genre trouvé sur le serveur.', filterPanelTitle: 'Filtres', - genreClickHint: 'Cliquez sur un tag de genre pour l\'ajouter\ncomme mot-clé de filtre.\nCorrespond au genre, titre et album.', + genreClickHint: 'Cliquez sur un tag de genre pour l\'ajouter\ncomme mot-clé de filtre.\nCorrespond au genre, titre, album et artiste.', }, playlists: { title: 'Listes de lecture', @@ -1427,7 +1439,7 @@ const frTranslation = { changelog: 'Journal des modifications', randomMixTitle: 'Mix aléatoire', randomMixBlacklistTitle: 'Mots-clés de filtre personnalisés', - randomMixBlacklistDesc: 'Les morceaux sont exclus si un mot-clé correspond à leur genre, titre ou album (actif quand la case ci-dessus est cochée).', + randomMixBlacklistDesc: 'Les morceaux sont exclus si un mot-clé correspond à leur genre, titre, album ou artiste (actif quand la case ci-dessus est cochée).', randomMixBlacklistPlaceholder: 'Ajouter un mot-clé…', randomMixBlacklistAdd: 'Ajouter', randomMixBlacklistEmpty: 'Aucun mot-clé personnalisé ajouté.', @@ -1777,6 +1789,7 @@ const nlTranslation = { albums: 'Albums', songs: 'Nummers', enqueueAll: 'Alles aan wachtrij toevoegen', + removeSong: 'Verwijderen uit favorieten', }, randomAlbums: { title: 'Willekeurige albums', @@ -1797,17 +1810,20 @@ const nlTranslation = { play: 'Afspelen', trackGenre: 'Genre', excludeAudiobooks: 'Luisterboeken en hoorspelen uitsluiten', - excludeAudiobooksDesc: 'Vergelijkt trefwoorden met genre, titel en album — bijv. Hörbuch, Audiobook, Spoken Word, …', + excludeAudiobooksDesc: 'Vergelijkt trefwoorden met genre, titel, album en artiest — bijv. Hörbuch, Audiobook, Spoken Word, …', genreBlocked: 'Trefwoord geblokkeerd', genreAddedToBlacklist: 'Aan filterlijst toegevoegd', genreAlreadyBlocked: 'Al geblokkeerd', + artistBlocked: 'Artiest geblokkeerd', + artistAddedToBlacklist: 'Artiest aan filterlijst toegevoegd', + artistClickHint: 'Klik om deze artiest te blokkeren', blacklistToggle: 'Trefwoordfilter', genreMixTitle: 'Genremix', genreMixDesc: 'Selecteer een genre voor een samengestelde willekeurige mix', genreMixLoadMore: '10 meer laden', genreMixNoGenres: 'Geen genres gevonden op server.', filterPanelTitle: 'Filters', - genreClickHint: 'Klik op een genre-tag om het\ntoe te voegen als filtertrefwoord.\nVergelijkt genre, titel & album.', + genreClickHint: 'Klik op een genre-tag om het\ntoe te voegen als filtertrefwoord.\nVergelijkt genre, titel, album & artiest.', }, playlists: { title: 'Afspeellijsten', @@ -1970,7 +1986,7 @@ const nlTranslation = { changelog: 'Wijzigingslog', randomMixTitle: 'Willekeurige mix', randomMixBlacklistTitle: 'Aangepaste filtertrefwoorden', - randomMixBlacklistDesc: 'Nummers worden uitgesloten als een trefwoord overeenkomt met hun genre, titel of album (actief wanneer het selectievakje hierboven is aangevinkt).', + randomMixBlacklistDesc: 'Nummers worden uitgesloten als een trefwoord overeenkomt met hun genre, titel, album of artiest (actief wanneer het selectievakje hierboven is aangevinkt).', randomMixBlacklistPlaceholder: 'Trefwoord toevoegen…', randomMixBlacklistAdd: 'Toevoegen', randomMixBlacklistEmpty: 'Nog geen aangepaste trefwoorden toegevoegd.', diff --git a/src/pages/Favorites.tsx b/src/pages/Favorites.tsx index 93cbb8a5..757d597d 100644 --- a/src/pages/Favorites.tsx +++ b/src/pages/Favorites.tsx @@ -3,9 +3,10 @@ import AlbumRow from '../components/AlbumRow'; import ArtistRow from '../components/ArtistRow'; import { getStarred, SubsonicAlbum, SubsonicArtist, SubsonicSong } from '../api/subsonic'; import { usePlayerStore } from '../store/playerStore'; -import { Play, ListPlus } from 'lucide-react'; +import { ListPlus, X } from 'lucide-react'; import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; +import { unstar } from '../api/subsonic'; export default function Favorites() { const { t } = useTranslation(); @@ -15,6 +16,11 @@ export default function Favorites() { const [loading, setLoading] = useState(true); const { playTrack, enqueue } = usePlayerStore(); + + function removeSong(id: string) { + unstar(id, 'song').catch(() => {}); + setSongs(prev => prev.filter(s => s.id !== id)); + } const openContextMenu = usePlayerStore(s => s.openContextMenu); const navigate = useNavigate(); @@ -77,11 +83,12 @@ export default function Favorites() {
-
+
#
{t('albumDetail.trackTitle')}
{t('albumDetail.trackArtist')}
{t('albumDetail.trackDuration')}
+
{songs.map((song, i) => { const track = { @@ -93,6 +100,7 @@ export default function Favorites() {
playTrack(song, songs)} onContextMenu={e => { e.preventDefault(); openContextMenu(e.clientX, e.clientY, track, 'song'); }} role="row" @@ -118,6 +126,16 @@ export default function Favorites() {
{Math.floor(song.duration / 60)}:{(song.duration % 60).toString().padStart(2, '0')}
+
+ +
); })} diff --git a/src/pages/RandomMix.tsx b/src/pages/RandomMix.tsx index 3bf0c1bd..8dec68f8 100644 --- a/src/pages/RandomMix.tsx +++ b/src/pages/RandomMix.tsx @@ -48,6 +48,7 @@ export default function RandomMix() { const [starredSongs, setStarredSongs] = useState>(new Set()); const { excludeAudiobooks, setExcludeAudiobooks, customGenreBlacklist, setCustomGenreBlacklist } = useAuthStore(); const [addedGenre, setAddedGenre] = useState(null); + const [addedArtist, setAddedArtist] = useState(null); // Blacklist panel state const [blacklistOpen, setBlacklistOpen] = useState(false); @@ -94,6 +95,7 @@ export default function RandomMix() { if (song.genre && checkText(song.genre)) return false; if (song.title && checkText(song.title)) return false; if (song.album && checkText(song.album)) return false; + if (song.artist && checkText(song.artist)) return false; return true; }); @@ -419,7 +421,45 @@ export default function RandomMix() {
- {song.artist} + {(() => { + const artist = song.artist; + if (!artist) return ; + const isBlocked = customGenreBlacklist.some(bg => artist.toLowerCase().includes(bg.toLowerCase())); + const justAdded = addedArtist === artist; + return ( + + ); + })()}
diff --git a/src/store/playerStore.ts b/src/store/playerStore.ts index 1e28a501..a03e2ed5 100644 --- a/src/store/playerStore.ts +++ b/src/store/playerStore.ts @@ -2,7 +2,7 @@ import { create } from 'zustand'; import { persist, createJSONStorage } from 'zustand/middleware'; import { invoke } from '@tauri-apps/api/core'; import { listen } from '@tauri-apps/api/event'; -import { buildStreamUrl, getPlayQueue, savePlayQueue, reportNowPlaying, scrobbleSong, SubsonicSong } from '../api/subsonic'; +import { buildStreamUrl, buildCoverArtUrl, getPlayQueue, savePlayQueue, reportNowPlaying, scrobbleSong, SubsonicSong } from '../api/subsonic'; import { lastfmScrobble, lastfmUpdateNowPlaying, lastfmLoveTrack, lastfmUnloveTrack, lastfmGetTrackLoved, lastfmGetAllLovedTracks } from '../api/lastfm'; import { useAuthStore } from './authStore'; @@ -335,8 +335,43 @@ export function initAudioListeners(): () => void { invoke('audio_set_gapless', { enabled: state.gaplessEnabled }).catch(() => {}); }); + // ── MPRIS / OS media controls sync ─────────────────────────────────────── + // Whenever the current track or playback state changes, push updates to the + // Rust souvlaki MediaControls so the OS media overlay stays accurate. + let prevTrackId: string | null = null; + let prevIsPlaying: boolean | null = null; + + const unsubMpris = usePlayerStore.subscribe((state) => { + const { currentTrack, isPlaying, currentTime } = state; + + // Update metadata when track changes + if (currentTrack && currentTrack.id !== prevTrackId) { + prevTrackId = currentTrack.id; + const coverUrl = currentTrack.coverArt + ? buildCoverArtUrl(currentTrack.coverArt, 512) + : undefined; + invoke('mpris_set_metadata', { + title: currentTrack.title, + artist: currentTrack.artist, + album: currentTrack.album, + coverUrl, + durationSecs: currentTrack.duration, + }).catch(() => {}); + } + + // Update playback state when it changes + if (isPlaying !== prevIsPlaying) { + prevIsPlaying = isPlaying; + invoke('mpris_set_playback', { + playing: isPlaying, + positionSecs: currentTime > 0 ? currentTime : null, + }).catch(() => {}); + } + }); + return () => { unsubAuth(); + unsubMpris(); pending.forEach(p => p.then(unlisten => unlisten())); }; } diff --git a/src/store/themeStore.ts b/src/store/themeStore.ts index c3b14aba..39de77e2 100644 --- a/src/store/themeStore.ts +++ b/src/store/themeStore.ts @@ -1,7 +1,7 @@ import { create } from 'zustand'; import { persist } from 'zustand/middleware'; -type Theme = 'mocha' | 'macchiato' | 'frappe' | 'latte' | 'nord' | 'nord-snowstorm' | 'nord-frost' | 'nord-aurora' | 'psychowave' | 'wnamp' | 'poison' | 'nucleo' | 'navy-jukebox' | 'cobalt-media' | 'onyx-cinema' | 'vintage-tube-radio' | 'neon-drift' | 'aero-glass' | 'luna-teal' | 'w98' | 'cupertino-light' | 'cupertino-dark' | 'gruvbox-dark-hard' | 'gruvbox-dark-medium' | 'gruvbox-dark-soft' | 'gruvbox-light-hard' | 'gruvbox-light-medium' | 'gruvbox-light-soft' | 'spotless' | 'dzr0' | 'cupertino-beats' | 'lambda-17' | 'azerothian-gold' | 'ascalon' | 'grand-theft-audio' | 'v-tactical' | 'nightcity-2077' | 'middle-earth' | 'morpheus' | 'stark-hud' | 'blade' | 'heisenberg' | 'ice-and-fire' | 'doh-matic' | 't-800' | 'b-runner' | 'dune' | 'tetrastack' | 'the-book' | 'readit' | 'insta' | 'hill-valley-85' | 'turtle-power' | 'w3-1' | 'aqua-quartz' | 'spider-tech' | 'jayfin'; +type Theme = 'mocha' | 'macchiato' | 'frappe' | 'latte' | 'nord' | 'nord-snowstorm' | 'nord-frost' | 'nord-aurora' | 'psychowave' | 'wnamp' | 'poison' | 'nucleo' | 'muma-jukebox' | 'winmedplayer' | 'p-dvd' | 'vintage-tube-radio' | 'neon-drift' | 'aero-glass' | 'luna-teal' | 'w98' | 'cupertino-light' | 'cupertino-dark' | 'gruvbox-dark-hard' | 'gruvbox-dark-medium' | 'gruvbox-dark-soft' | 'gruvbox-light-hard' | 'gruvbox-light-medium' | 'gruvbox-light-soft' | 'spotless' | 'dzr0' | 'cupertino-beats' | 'lambda-17' | 'gw1' | 'grand-theft-audio' | 'v-tactical' | 'nightcity-2077' | 'middle-earth' | 'morpheus' | 'stark-hud' | 'blade' | 'heisenberg' | 'ice-and-fire' | 'doh-matic' | 't-800' | 'dune' | 'tetrastack' | 'the-book' | 'readit' | 'insta' | 'hill-valley-85' | 'turtle-power' | 'w3-1' | 'aqua-quartz' | 'spider-tech' | 'dos' | 'unix' | 'jayfin' | 'horde' | 'alliance' | 'w11'; interface ThemeState { theme: Theme; diff --git a/src/styles/components.css b/src/styles/components.css index 0a721779..289b47aa 100644 --- a/src/styles/components.css +++ b/src/styles/components.css @@ -2556,6 +2556,29 @@ opacity: 1; } +.fav-remove-btn { + opacity: 0; + color: var(--text-muted); + background: none; + border: none; + padding: 4px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-sm); + transition: opacity 0.15s, color 0.15s; +} + +.fav-remove-btn:hover { + color: var(--ctp-red); +} + +.track-row:hover .fav-remove-btn, +.track-row.context-active .fav-remove-btn { + opacity: 1; +} + /* ─ Statistics Page ─ */ .stats-page { display: flex; diff --git a/src/styles/layout.css b/src/styles/layout.css index 8211c893..0f0675ee 100644 --- a/src/styles/layout.css +++ b/src/styles/layout.css @@ -332,6 +332,7 @@ overflow-y: auto; overflow-x: hidden; padding: var(--space-6); + contain: paint; } /* ─── Player Bar ─── */ diff --git a/src/styles/theme.css b/src/styles/theme.css index 3d07d06f..5a463928 100644 --- a/src/styles/theme.css +++ b/src/styles/theme.css @@ -48,7 +48,7 @@ --accent-glow: rgba(203, 166, 247, 0.3); --text-primary: var(--ctp-text); --text-secondary:var(--ctp-subtext1); - --text-muted: var(--ctp-overlay1); + --text-muted: var(--ctp-subtext0); --border: var(--ctp-surface1); --border-subtle: var(--ctp-surface0); --positive: var(--ctp-green); @@ -98,7 +98,7 @@ --accent-glow: rgba(198, 160, 246, 0.3); --text-primary: var(--ctp-text); --text-secondary:var(--ctp-subtext1); - --text-muted: var(--ctp-overlay1); + --text-muted: var(--ctp-subtext0); --border: var(--ctp-surface1); --border-subtle: var(--ctp-surface0); --positive: var(--ctp-green); @@ -148,7 +148,7 @@ --accent-glow: rgba(202, 158, 230, 0.3); --text-primary: var(--ctp-text); --text-secondary:var(--ctp-subtext1); - --text-muted: var(--ctp-overlay1); + --text-muted: var(--ctp-subtext0); --border: var(--ctp-surface1); --border-subtle: var(--ctp-surface0); --positive: var(--ctp-green); @@ -199,7 +199,7 @@ --accent-glow: rgba(136, 57, 239, 0.3); --text-primary: var(--ctp-text); --text-secondary:var(--ctp-subtext1); - --text-muted: var(--ctp-overlay1); + --text-muted: var(--ctp-subtext0); --border: var(--ctp-surface1); --border-subtle: var(--ctp-surface0); --positive: var(--ctp-green); @@ -253,7 +253,7 @@ --accent-glow: rgba(136, 192, 208, 0.3); --text-primary: #eceff4; --text-secondary:#e5e9f0; - --text-muted: #8894a4; + --text-muted: #a0aab8; --border: #434c5e; --border-subtle: #3b4252; --border-dropdown: #576070; @@ -418,7 +418,7 @@ --accent-glow: rgba(180, 142, 173, 0.3); --text-primary: #eceff4; --text-secondary:#e5e9f0; - --text-muted: #8894a4; + --text-muted: #a0aab8; --border: #434c5e; --border-subtle: #3b4252; --border-dropdown: #576070; @@ -474,7 +474,7 @@ --accent-glow: rgba(27, 214, 85, 0.35); --text-primary: #d0d0cc; --text-secondary:#a8a8a4; - --text-muted: #686866; + --text-muted: #909090; --border: #3a3a38; --border-subtle: #282826; --positive: #1bd655; @@ -549,7 +549,7 @@ --volume-accent: #de9b35; --text-primary: #c8c8d0; --text-secondary:#a0a0ac; - --text-muted: #6e6e88; + --text-muted: #a0a0bc; --border: #5a5a75; --border-subtle: #353545; --positive: #00cc66; @@ -1137,178 +1137,214 @@ color: var(--accent); } -/* ─── Azerothian Gold ─── */ -[data-theme='azerothian-gold'] { +/* ─── Guild Wars 1 — Tyria ─── */ +[data-theme='gw1'] { color-scheme: dark; - --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23c19e67%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); + --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23c8960c%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); - --ctp-crust: #0a0a0a; - --ctp-mantle: #121212; - --ctp-base: #1a1a1a; - --ctp-surface0: #25221e; - --ctp-surface1: #363028; - --ctp-surface2: #4d4538; - --ctp-overlay0: #6b6254; - --ctp-overlay1: #8c8170; - --ctp-overlay2: #a69884; - --ctp-text: #e6dbcc; - --ctp-subtext1: #c19e67; - --ctp-subtext0: #a68a56; - --ctp-mauve: #f5d45c; - --ctp-lavender: #ffe485; - --ctp-pink: #e74c3c; - --ctp-flamingo: #e74c3c; - --ctp-rosewater:#e6dbcc; - --ctp-green: #2ecc71; - --ctp-teal: #3498db; - --ctp-sky: #3498db; - --ctp-blue: #3498db; - --ctp-sapphire: #3498db; - --ctp-yellow: #f1c40f; - --ctp-peach: #c19e67; - --ctp-maroon: #e74c3c; - --ctp-red: #e74c3c; + /* Palette — aged Tyrian stone, ornate gold, Searing crimson */ + --ctp-crust: #060402; + --ctp-mantle: #0a0806; + --ctp-base: #0e0b08; + --ctp-surface0: #1a1208; + --ctp-surface1: #261b0c; + --ctp-surface2: #342510; + --ctp-overlay0: #5a4830; + --ctp-overlay1: #7a6448; + --ctp-overlay2: #9a8060; + --ctp-text: #f0e4c4; + --ctp-subtext1: #d4c49a; + --ctp-subtext0: #b0a07a; + --ctp-mauve: #c8960c; + --ctp-lavender: #e8b820; + --ctp-pink: #c0321a; + --ctp-flamingo: #d4780c; + --ctp-rosewater:#f0e4c4; + --ctp-green: #5a8030; + --ctp-teal: #3a6858; + --ctp-sky: #7aaccc; + --ctp-blue: #3a6898; + --ctp-sapphire: #3a6898; + --ctp-yellow: #e8c840; + --ctp-peach: #d4780c; + --ctp-maroon: #8b1515; + --ctp-red: #c0321a; - --bg-app: #1a1a1a; - --bg-sidebar: #121212; - --bg-card: #25221e; - --bg-hover: rgba(193, 158, 103, 0.1); - --bg-player: #0a0a0a; - --bg-glass: rgba(18, 18, 18, 0.85); - --accent: #c19e67; - --accent-dim: rgba(193, 158, 103, 0.15); - --accent-glow: rgba(193, 158, 103, 0.4); - --text-primary: #e6dbcc; - --text-secondary:#c19e67; - --text-muted: #8c8170; - --border: #4d4538; - --border-subtle: #363028; - --border-dropdown: #4d4538; - --shadow-dropdown: rgba(0, 0, 0, 0.7); - --positive: #2ecc71; - --warning: #f1c40f; - --danger: #e74c3c; + --bg-app: #0e0b08; + --bg-sidebar: #0a0806; + --bg-card: #1a1208; + --bg-hover: #261b0c; + --bg-player: #060402; + --bg-glass: rgba(14, 11, 8, 0.88); + --accent: #c8960c; + --accent-dim: rgba(200, 150, 12, 0.15); + --accent-glow: rgba(200, 150, 12, 0.35); + --text-primary: #f0e4c4; + --text-secondary:#9a8060; + --text-muted: #a08858; + --border: rgba(200, 150, 12, 0.28); + --border-subtle: rgba(200, 150, 12, 0.10); + --border-dropdown: rgba(200, 150, 12, 0.35); + --shadow-dropdown: rgba(0, 0, 0, 0.85); + --positive: #5a8030; + --warning: #d4780c; + --danger: #c0321a; --radius-sm: 2px; - --radius-md: 4px; - --radius-lg: 6px; + --radius-md: 3px; + --radius-lg: 4px; } -[data-theme='azerothian-gold'] .sidebar { - border-right: 2px solid var(--border); - background: linear-gradient(180deg, #161616 0%, #0d0d0d 100%); +/* App shell — solid dark stone base (grid moved to sidebar-only for perf) */ + +/* Sidebar — worn leather with faint horizontal stone lines */ +[data-theme='gw1'] .sidebar { + border-right: 1px solid rgba(200,150,12,0.35); + background: linear-gradient(180deg, #0c0906 0%, #080604 100%); + background-image: repeating-linear-gradient( + 0deg, + rgba(200,150,12,0.04) 0px, + transparent 1px, + transparent 48px, + rgba(200,150,12,0.04) 49px + ); } -[data-theme='azerothian-gold'] .player-bar { - border-top: 2px solid var(--border); - box-shadow: 0 -4px 10px rgba(0, 0, 0, 0.5); +/* Player bar — the GW1 skill bar: deepest black, gold top border */ +[data-theme='gw1'] .player-bar { + background: #060402; + border-top: 2px solid #c8960c; + box-shadow: 0 -6px 28px rgba(200,150,12,0.14), 0 -1px 0 rgba(0,0,0,0.9); } -[data-theme='azerothian-gold'] .nav-link.active { - background: linear-gradient(90deg, rgba(193, 158, 103, 0.15) 0%, transparent 100%); - color: var(--ctp-mauve) !important; - text-shadow: 0 0 8px rgba(245, 212, 92, 0.4); +/* Track name — Tyrian item-name gold glow, Cinzel serif */ +[data-theme='gw1'] .player-track-name { + color: #e8b820; + text-shadow: 0 0 10px rgba(232,184,32,0.55), 0 0 22px rgba(200,150,12,0.25); + font-family: 'Cinzel', 'Palatino Linotype', Georgia, serif; + letter-spacing: 0.03em; } -[data-theme='azerothian-gold'] .nav-link.active::before { - background-color: var(--ctp-mauve); - box-shadow: 0 0 10px var(--ctp-mauve); +/* Artist name — faded parchment, not competing with gold */ +[data-theme='gw1'] .player-artist-name { + color: #9a8060; } -[data-theme='azerothian-gold'] .player-track-name { - color: var(--ctp-mauve); - font-weight: 700; +/* Nav active — left gold bar like GW1 menu selection */ +[data-theme='gw1'] .nav-link.active { + background: linear-gradient(90deg, rgba(200,150,12,0.20) 0%, transparent 100%); + border-left: 3px solid #c8960c; + color: #e8b820; } -/* ─── Ascalon ─── */ -[data-theme='ascalon'] { - color-scheme: dark; - --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23a68d5d%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); - - --ctp-crust: #0f0d0b; - --ctp-mantle: #151310; - --ctp-base: #1c1a17; - --ctp-surface0: #2a2722; - --ctp-surface1: #38342d; - --ctp-surface2: #4a453c; - --ctp-overlay0: #6b6355; - --ctp-overlay1: #8a7f6d; - --ctp-overlay2: #a69882; - --ctp-text: #f0ead6; - --ctp-subtext1: #d4cbb3; - --ctp-subtext0: #b8af98; - --ctp-mauve: #d4af37; - --ctp-lavender: #e5c158; - --ctp-pink: #b22222; - --ctp-flamingo: #cd853f; - --ctp-rosewater:#f0ead6; - --ctp-green: #6b8e23; - --ctp-teal: #4d5d53; - --ctp-sky: #87ceeb; - --ctp-blue: #4682b4; - --ctp-sapphire: #4682b4; - --ctp-yellow: #ffcc00; - --ctp-peach: #cd853f; - --ctp-maroon: #800000; - --ctp-red: #b22222; - - --bg-app: #1c1a17; - --bg-sidebar: #151310; - --bg-card: #2a2722; - --bg-hover: #38342d; - --bg-player: #0f0d0b; - --bg-glass: rgba(28, 26, 23, 0.85); - --accent: #d4af37; - --accent-dim: rgba(212, 175, 55, 0.15); - --accent-glow: rgba(212, 175, 55, 0.3); - --text-primary: #f0ead6; - --text-secondary:#a69882; - --text-muted: #6b6355; - --border: #4a453c; - --border-subtle: #2a2722; - --border-dropdown: #4a453c; - --shadow-dropdown: rgba(0, 0, 0, 0.7); - --positive: #6b8e23; - --warning: #cd853f; - --danger: #b22222; - --radius-sm: 2px; - --radius-md: 4px; - --radius-lg: 6px; +[data-theme='gw1'] .nav-link:hover:not(.active) { + background: linear-gradient(90deg, rgba(200,150,12,0.09) 0%, transparent 100%); + border-left: 3px solid rgba(200,150,12,0.35); } -[data-theme='ascalon'] .sidebar { - border-right: 1px solid var(--border); - background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px); - background-size: 100% 4px; +/* Content header — ornate double gold rule */ +[data-theme='gw1'] .content-header { + border-bottom: 1px solid rgba(200,150,12,0.22); + position: relative; } -[data-theme='ascalon'] .player-bar { - border-top: 2px solid var(--accent); - box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.5); +[data-theme='gw1'] .content-header::after { + content: ''; + position: absolute; + bottom: -3px; + left: 0; + right: 0; + height: 1px; + background: linear-gradient(90deg, transparent 0%, rgba(200,150,12,0.7) 20%, rgba(232,184,32,0.9) 50%, rgba(200,150,12,0.7) 80%, transparent 100%); } -[data-theme='ascalon'] .player-track-name { - color: var(--accent); - text-shadow: 0 0 8px var(--accent-glow); - font-family: 'Cinzel', serif, system-ui; +/* Cards — dark leather panels with subtle gold frame */ +[data-theme='gw1'] .album-card, +[data-theme='gw1'] .artist-card { + box-shadow: inset 0 0 0 1px rgba(200,150,12,0.18); } -[data-theme='ascalon'] .nav-link.active { - background: linear-gradient(90deg, var(--accent-dim) 0%, transparent 100%); - border-left: 3px solid var(--accent); - color: var(--accent); +[data-theme='gw1'] .album-card:hover, +[data-theme='gw1'] .artist-card:hover { + box-shadow: inset 0 0 0 1px rgba(200,150,12,0.55), 0 4px 20px rgba(200,150,12,0.18); } -[data-theme='ascalon'] .player-btn-primary { - background: var(--accent); - color: var(--ctp-crust); - box-shadow: 0 0 15px var(--accent-glow); +/* Queue / track rows — gold left accent bar on hover */ +[data-theme='gw1'] .track-row:hover, +[data-theme='gw1'] .queue-item:hover { + box-shadow: inset 2px 0 0 #c8960c; + background: rgba(200,150,12,0.08); } -[data-theme='ascalon'] .player-btn-primary:hover { - transform: scale(1.05); - background: var(--ctp-lavender); +/* Primary play button — hammered gold like GW1 UI buttons */ +[data-theme='gw1'] .player-btn-primary { + background: linear-gradient(180deg, #e8b820 0%, #c8960c 50%, #a87808 100%); + color: #060402; + box-shadow: 0 0 14px rgba(200,150,12,0.45); + border: 1px solid #906606; } +[data-theme='gw1'] .player-btn-primary:hover { + background: linear-gradient(180deg, #f0c830 0%, #d8a818 50%, #b88818 100%); + box-shadow: 0 0 22px rgba(200,150,12,0.65); +} + +/* btn-primary (play album, etc.) */ +[data-theme='gw1'] .btn-primary { + background: linear-gradient(180deg, #e8b820 0%, #c8960c 50%, #a87808 100%); + color: #060402; + border: 1px solid #906606; +} + +[data-theme='gw1'] .btn-primary:hover { + background: linear-gradient(180deg, #f0c830 0%, #d8a818 50%, #b88818 100%); +} + +/* Hero play button — Cinzel font, gold, no flash on hover */ +[data-theme='gw1'] .hero-play-btn { + background: linear-gradient(180deg, #e8b820 0%, #c8960c 50%, #a87808 100%); + color: #060402; + border: 1px solid #906606; + box-shadow: 0 2px 14px rgba(200,150,12,0.45); + font-family: 'Cinzel', Georgia, serif; + letter-spacing: 0.05em; + transition: filter var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast); +} + +[data-theme='gw1'] .hero-play-btn:hover { + background: linear-gradient(180deg, #f0c830 0%, #d8a818 50%, #b88818 100%); + box-shadow: 0 4px 22px rgba(200,150,12,0.65); + transform: scale(1.02); +} + +/* Album card overlay play button */ +[data-theme='gw1'] .album-card-details-btn { + background: linear-gradient(180deg, #e8b820 0%, #c8960c 50%, #a87808 100%); + color: #060402; + border: 1px solid #906606; + box-shadow: 0 2px 10px rgba(200,150,12,0.5); +} + +/* Scrollbar — dark stone with gold thumb */ +[data-theme='gw1'] ::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +[data-theme='gw1'] ::-webkit-scrollbar-track { + background: #0a0806; + border-left: 1px solid rgba(200,150,12,0.08); +} + +[data-theme='gw1'] ::-webkit-scrollbar-thumb { + background: linear-gradient(180deg, #c8960c, #a87808); + border-radius: 3px; +} + +[data-theme='gw1'] ::-webkit-scrollbar-thumb:hover { + background: #e8b820; +} + + /* ─── Grand Theft Audio ─── */ [data-theme='grand-theft-audio'] { color-scheme: dark; @@ -1352,7 +1388,7 @@ --accent-glow: rgba(87, 176, 90, 0.4); --text-primary: #ffffff; --text-secondary:#999999; - --text-muted: #666666; + --text-muted: #888888; --border: #333333; --border-subtle: #1e1e1e; --border-dropdown: #333333; @@ -1521,7 +1557,7 @@ --accent-glow: rgba(252, 238, 10, 0.4); --text-primary: #f0f0f0; --text-secondary:#cccccc; - --text-muted: #666666; + --text-muted: #888888; --border: #FCEE0A; --border-subtle: #2a2a2a; --border-dropdown: #2a2a2a; @@ -1570,174 +1606,439 @@ clip-path: polygon(0% 0%, 100% 0%, 100% 70%, 90% 100%, 0% 100%); } -/* ─── Imperial Sith ─── */ -/* ─── Heisenberg ─── */ +/* ─── Heisenberg — Breaking Bad ─── */ +@keyframes crystal-pulse { + 0%, 100% { + text-shadow: + 0 0 6px rgba(78,223,47,0.60), + 0 0 18px rgba(78,223,47,0.32), + 0 0 40px rgba(78,223,47,0.14); + } + 50% { + text-shadow: + 0 0 10px rgba(78,223,47,0.80), + 0 0 28px rgba(78,223,47,0.48), + 0 0 60px rgba(78,223,47,0.22); + } +} + [data-theme='heisenberg'] { color-scheme: dark; - --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%233fe0ff%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); + --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%2335d4f8%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); - --ctp-crust: #0a0c0a; - --ctp-mantle: #121512; - --ctp-base: #1a1d1a; - --ctp-surface0: #242824; - --ctp-surface1: #2e332e; - --ctp-surface2: #383d38; - --ctp-overlay0: #5c635c; - --ctp-overlay1: #7f897f; - --ctp-overlay2: #a2b0a2; - --ctp-text: #e0e7e0; - --ctp-subtext1: #b0b8b0; - --ctp-subtext0: #8a928a; - --ctp-mauve: #3fe0ff; - --ctp-lavender: #87f0ff; - --ctp-pink: #ff79c6; - --ctp-flamingo: #ffb86c; - --ctp-rosewater:#f8f8f2; - --ctp-green: #47d08a; - --ctp-teal: #2bbbad; - --ctp-sky: #3fe0ff; - --ctp-blue: #3498db; - --ctp-sapphire: #2980b9; - --ctp-yellow: #f1c40f; - --ctp-peach: #e67e22; - --ctp-maroon: #c0392b; - --ctp-red: #ff4b2b; + /* Breaking Bad palette — crystal blue, BB logo green, hazmat yellow */ + --ctp-crust: #050709; + --ctp-mantle: #080b0e; + --ctp-base: #0b0e12; + --ctp-surface0: #141a22; + --ctp-surface1: #1e2830; + --ctp-surface2: #283440; + --ctp-overlay0: #3a4e60; + --ctp-overlay1: #5a7288; + --ctp-overlay2: #7a96a8; + --ctp-text: #e4f0f8; + --ctp-subtext1: #c0d8e8; + --ctp-subtext0: #8ab0c8; + --ctp-mauve: #35d4f8; + --ctp-lavender: #70e8ff; + --ctp-pink: #f05080; + --ctp-flamingo: #e84060; + --ctp-rosewater:#e4f0f8; + --ctp-green: #4edf2f; + --ctp-teal: #20c8b0; + --ctp-sky: #55ddff; + --ctp-blue: #35d4f8; + --ctp-sapphire: #1ab8e0; + --ctp-yellow: #f0c020; + --ctp-peach: #e88040; + --ctp-maroon: #a01820; + --ctp-red: #e03030; - --bg-app: #1a1d1a; - --bg-sidebar: #121512; - --bg-card: #242824; - --bg-hover: rgba(63, 224, 255, 0.1); - --bg-player: #0a0c0a; - --bg-glass: rgba(26, 29, 26, 0.85); - --accent: #3fe0ff; - --accent-dim: rgba(63, 224, 255, 0.15); - --accent-glow: rgba(63, 224, 255, 0.4); - --text-primary: #e0e7e0; - --text-secondary:#b0b8b0; - --text-muted: #5c635c; - --border: #383d38; - --border-subtle: #242824; - --border-dropdown: #383d38; - --shadow-dropdown: rgba(0, 0, 0, 0.8); - --positive: #47d08a; - --warning: #f1c40f; - --danger: #ff4b2b; + --bg-app: #0b0e12; + --bg-sidebar: #060a0e; + --bg-card: #141a22; + --bg-hover: #1e2830; + --bg-player: #060809; + --bg-glass: rgba(8, 11, 14, 0.92); + --accent: #35d4f8; + --accent-dim: rgba(53, 212, 248, 0.12); + --accent-glow: rgba(53, 212, 248, 0.35); + --text-primary: #e4f0f8; + --text-secondary:#7a96a8; + --text-muted: #7aaabe; + --border: rgba(53, 212, 248, 0.14); + --border-subtle: rgba(53, 212, 248, 0.06); + --border-dropdown: rgba(53, 212, 248, 0.25); + --shadow-dropdown: rgba(0, 0, 0, 0.92); + --positive: #4edf2f; + --warning: #f0c020; + --danger: #e03030; + --radius-sm: 2px; + --radius-md: 4px; + --radius-lg: 6px; } -[data-theme='heisenberg'] .player-track-name { - color: var(--accent); - text-shadow: 0 0 10px var(--accent-glow); - font-family: 'JetBrains Mono', 'Fira Code', monospace; +/* App shell — periodic table grid (BB opening credits) */ +[data-theme='heisenberg'] .app-shell { + background-image: + linear-gradient(rgba(53,212,248,0.04) 1px, transparent 1px), + linear-gradient(90deg, rgba(53,212,248,0.04) 1px, transparent 1px); + background-size: 60px 60px; } +/* Sidebar — darker lab space, hazmat tape diagonal (very subtle) */ [data-theme='heisenberg'] .sidebar { - border-right: 1px solid var(--accent-dim); -} - -[data-theme='heisenberg'] .nav-link.active { - background: linear-gradient(90deg, var(--accent-dim) 0%, transparent 100%); + background: #060a0e; + border-right: 1px solid rgba(53,212,248,0.14); + background-image: + repeating-linear-gradient( + 45deg, + transparent 0px, + transparent 20px, + rgba(240,192,32,0.028) 20px, + rgba(240,192,32,0.028) 22px + ); } +/* Player bar — lab fluorescent: crystal blue top glow */ [data-theme='heisenberg'] .player-bar { - border-top: 1px solid var(--accent-dim); - box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.5); + background: #060809; + border-top: 2px solid #35d4f8; + box-shadow: 0 -8px 32px rgba(53,212,248,0.14), 0 -1px 0 rgba(0,0,0,0.9); +} + +/* Track name — BB logo green glow (the Br/Ba element box color) */ +[data-theme='heisenberg'] .player-track-name { + color: #4edf2f; + animation: crystal-pulse 3s ease-in-out infinite; +} + +/* Artist name — hazmat suit yellow */ +[data-theme='heisenberg'] .player-artist-name { + color: #f0c020; +} + +/* Nav active — BB green left bar */ +[data-theme='heisenberg'] .nav-link.active { + background: linear-gradient(90deg, rgba(78,223,47,0.12) 0%, transparent 100%); + border-left: 3px solid #4edf2f; + color: #4edf2f; +} + +[data-theme='heisenberg'] .nav-link:hover:not(.active) { + background: linear-gradient(90deg, rgba(53,212,248,0.06) 0%, transparent 100%); + border-left: 3px solid rgba(53,212,248,0.28); +} + +/* Content header */ +[data-theme='heisenberg'] .content-header { + border-bottom: 1px solid rgba(53,212,248,0.10); +} + +/* Cards — blue crystal border on hover */ +[data-theme='heisenberg'] .album-card:hover, +[data-theme='heisenberg'] .artist-card:hover { + box-shadow: 0 0 0 1px rgba(53,212,248,0.50), 0 4px 20px rgba(53,212,248,0.14); +} + +/* Track / queue rows */ +[data-theme='heisenberg'] .track-row:hover, +[data-theme='heisenberg'] .queue-item:hover { + box-shadow: inset 2px 0 0 #35d4f8; + background: rgba(53,212,248,0.05); +} + +/* Primary play button — crystal blue gradient */ +[data-theme='heisenberg'] .player-btn-primary { + background: linear-gradient(180deg, #60e4ff 0%, #35d4f8 50%, #18b8e0 100%); + color: #060809; + box-shadow: 0 0 16px rgba(53,212,248,0.45); + border: 1px solid #14a8d0; +} + +[data-theme='heisenberg'] .player-btn-primary:hover { + background: linear-gradient(180deg, #7aecff 0%, #50deff 50%, #28caf0 100%); + box-shadow: 0 0 26px rgba(53,212,248,0.70); +} + +/* btn-primary */ +[data-theme='heisenberg'] .btn-primary { + background: linear-gradient(180deg, #60e4ff 0%, #35d4f8 50%, #18b8e0 100%); + color: #060809; + border: 1px solid #14a8d0; +} + +[data-theme='heisenberg'] .btn-primary:hover { + background: linear-gradient(180deg, #7aecff 0%, #50deff 50%, #28caf0 100%); +} + +/* Hero play button */ +[data-theme='heisenberg'] .hero-play-btn { + background: linear-gradient(180deg, #60e4ff 0%, #35d4f8 50%, #18b8e0 100%); + color: #060809; + border: 1px solid #14a8d0; + box-shadow: 0 2px 16px rgba(53,212,248,0.45); + transition: filter var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast); +} + +[data-theme='heisenberg'] .hero-play-btn:hover { + background: linear-gradient(180deg, #7aecff 0%, #50deff 50%, #28caf0 100%); + box-shadow: 0 4px 26px rgba(53,212,248,0.68); + transform: scale(1.02); +} + +/* Album card overlay button */ +[data-theme='heisenberg'] .album-card-details-btn { + background: linear-gradient(180deg, #60e4ff 0%, #35d4f8 50%, #18b8e0 100%); + color: #060809; + border: 1px solid #14a8d0; + box-shadow: 0 2px 12px rgba(53,212,248,0.40); +} + +/* Scrollbar — thin blue crystal */ +[data-theme='heisenberg'] ::-webkit-scrollbar { width: 5px; height: 5px; } + +[data-theme='heisenberg'] ::-webkit-scrollbar-track { + background: #080b0e; +} + +[data-theme='heisenberg'] ::-webkit-scrollbar-thumb { + background: rgba(53,212,248,0.35); + border-radius: 3px; +} + +[data-theme='heisenberg'] ::-webkit-scrollbar-thumb:hover { + background: #35d4f8; +} + +/* ─── A Theme of Ice and Fire — Game of Thrones ─── */ +/* Concept: FIRE (volcanic Dragonstone, main area) vs ICE (Castle Black, sidebar) */ +@keyframes fire-flicker { + 0% { text-shadow: 0 0 8px rgba(200,30,20,0.65), 0 0 20px rgba(200,60,10,0.30); } + 20% { text-shadow: 0 0 12px rgba(220,55,15,0.75), 0 0 28px rgba(210,40,10,0.38); } + 40% { text-shadow: 0 0 6px rgba(180,20,10,0.55), 0 0 14px rgba(190,30,10,0.22); } + 65% { text-shadow: 0 0 14px rgba(215,50,12,0.80), 0 0 32px rgba(200,70,15,0.40); } + 85% { text-shadow: 0 0 9px rgba(195,25,15,0.60), 0 0 22px rgba(200,40,10,0.28); } + 100% { text-shadow: 0 0 8px rgba(200,30,20,0.65), 0 0 20px rgba(200,60,10,0.30); } } -/* ─── A Theme of Ice and Fire ─── */ [data-theme='ice-and-fire'] { color-scheme: dark; - --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%2370a1ff%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); + --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23c41e1e%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); - --ctp-crust: #05070a; - --ctp-mantle: #0d1117; - --ctp-base: #121820; - --ctp-surface0: #1c2533; - --ctp-surface1: #2a374a; - --ctp-surface2: #384961; - --ctp-overlay0: #5c6a7e; - --ctp-overlay1: #7d8da3; - --ctp-overlay2: #a0b1c7; - --ctp-text: #f0f4f8; - --ctp-subtext1: #cbd5e0; - --ctp-subtext0: #a0aec0; - --ctp-mauve: #70a1ff; - --ctp-lavender: #a4b0be; - --ctp-pink: #ff4757; - --ctp-flamingo: #ff6b81; - --ctp-rosewater:#f0f4f8; - --ctp-green: #2ed573; - --ctp-teal: #1e90ff; - --ctp-sky: #70a1ff; - --ctp-blue: #1e90ff; - --ctp-sapphire: #1e90ff; - --ctp-yellow: #ffa502; - --ctp-peach: #ffa502; - --ctp-maroon: #c0392b; - --ctp-red: #ff4757; + /* Palette — Targaryen blood red, dragon gold, volcanic black, Wall ice */ + --ctp-crust: #060402; + --ctp-mantle: #0a0806; + --ctp-base: #100c08; + --ctp-surface0: #1c1410; + --ctp-surface1: #281c14; + --ctp-surface2: #38261c; + --ctp-overlay0: #5a3e2e; + --ctp-overlay1: #7a5840; + --ctp-overlay2: #9a7858; + --ctp-text: #ecdcc8; + --ctp-subtext1: #d0b898; + --ctp-subtext0: #a89070; + --ctp-mauve: #c41e1e; + --ctp-lavender: #e03030; + --ctp-pink: #e03030; + --ctp-flamingo: #c83010; + --ctp-rosewater:#ecdcc8; + --ctp-green: #5a8a3a; + --ctp-teal: #5090a0; /* Wall ice teal */ + --ctp-sky: #80b8d0; /* Northern sky */ + --ctp-blue: #3a6898; + --ctp-sapphire: #3a6898; + --ctp-yellow: #c8880a; /* Lannister / dragon gold */ + --ctp-peach: #c83010; + --ctp-maroon: #8b0808; + --ctp-red: #c41e1e; - --bg-app: #121820; - --bg-sidebar: #0d1117; - --bg-card: #1c2533; - --bg-hover: rgba(112, 161, 255, 0.1); - --bg-player: #05070a; - --bg-glass: rgba(13, 17, 23, 0.85); - --accent: #70a1ff; - --accent-dim: rgba(112, 161, 255, 0.15); - --accent-glow: rgba(112, 161, 255, 0.25); - --volume-accent: #ffa502; - --text-primary: #f0f4f8; - --text-secondary:#cbd5e0; - --text-muted: #5c6a7e; - --border: #2a374a; - --border-subtle: #1c2533; - --border-dropdown: #2a374a; - --shadow-dropdown: rgba(0, 0, 0, 0.8); - --positive: #2ed573; - --warning: #ffa502; - --danger: #ff4757; - --radius-sm: 1px; - --radius-md: 2px; - --radius-lg: 4px; + --bg-app: #100c08; /* volcanic black — warm dark */ + --bg-sidebar: #090c10; /* Castle Black — cold blue-grey stone */ + --bg-card: #1c1410; + --bg-hover: #281c14; + --bg-player: #060402; /* obsidian black */ + --bg-glass: rgba(10, 8, 6, 0.92); + --accent: #c41e1e; /* Targaryen blood red */ + --accent-dim: rgba(196, 30, 30, 0.14); + --accent-glow: rgba(196, 30, 30, 0.38); + --text-primary: #ecdcc8; /* warm stone parchment */ + --text-secondary:#9a7858; + --text-muted: #b08860; + --border: rgba(196, 30, 30, 0.20); + --border-subtle: rgba(196, 30, 30, 0.08); + --border-dropdown: rgba(196, 30, 30, 0.32); + --shadow-dropdown: rgba(0, 0, 0, 0.92); + --positive: #5a8a3a; + --warning: #c8880a; + --danger: #c41e1e; + --radius-sm: 2px; + --radius-md: 4px; + --radius-lg: 6px; } +/* App shell — scattered torch-light: warm pools of fire at corners */ [data-theme='ice-and-fire'] .app-shell { - background: radial-gradient(circle at top right, #1a2a3a, #121820); + background-image: + radial-gradient(ellipse at 15% 85%, rgba(200, 80, 10, 0.07) 0%, transparent 55%), + radial-gradient(ellipse at 85% 15%, rgba(180, 20, 10, 0.06) 0%, transparent 55%), + radial-gradient(ellipse at 85% 85%, rgba(200, 100, 15, 0.05) 0%, transparent 45%); } +/* Sidebar — THE NORTH: cold Castle Black stone, masonry pattern */ [data-theme='ice-and-fire'] .sidebar { - border-right: 1px solid #1c2533; - background: linear-gradient(to bottom, #0d1117, #05070a); + background: #090c10; + border-right: 1px solid rgba(196, 30, 30, 0.20); + background-image: + repeating-linear-gradient( + 0deg, + rgba(80, 110, 140, 0.04) 0px, transparent 1px, transparent 56px, + rgba(80, 110, 140, 0.04) 57px + ), + repeating-linear-gradient( + 90deg, + rgba(80, 110, 140, 0.025) 0px, transparent 1px, transparent 112px, + rgba(80, 110, 140, 0.025) 113px + ); } +/* Player bar — Dragonstone forge: fire glow rising from below */ [data-theme='ice-and-fire'] .player-bar { - border-top: 2px solid #ffa502; - box-shadow: 0 -4px 30px rgba(255, 165, 2, 0.1); - background: #05070a; -} - -[data-theme='ice-and-fire'] .nav-link.active { - background: linear-gradient(90deg, rgba(112, 161, 255, 0.15) 0%, transparent 100%); - color: #70a1ff; - font-weight: 600; - text-shadow: 0 0 10px rgba(112, 161, 255, 0.4); -} - -[data-theme='ice-and-fire'] .slider-track-fill { - background: linear-gradient(90deg, #70a1ff, #ffa502) !important; + background: #060402; + border-top: 2px solid #c41e1e; + background-image: + radial-gradient(ellipse at 50% 130%, rgba(200, 80, 15, 0.22) 0%, rgba(180, 20, 10, 0.12) 45%, transparent 70%); + box-shadow: 0 -8px 36px rgba(180, 20, 10, 0.22), 0 -1px 0 rgba(0,0,0,0.9); } +/* Track name — Targaryen red, fire flicker (irregular like real flame) */ [data-theme='ice-and-fire'] .player-track-name { - color: #f0f4f8; - text-shadow: 0 0 12px rgba(112, 161, 255, 0.6); + color: #d42020; + animation: fire-flicker 5s ease-in-out infinite; } -[data-theme='ice-and-fire'] .btn { - border: 1px solid var(--border); - text-transform: uppercase; - font-size: 0.75rem; - letter-spacing: 0.1em; +/* Artist name — Lannister/dragon gold */ +[data-theme='ice-and-fire'] .player-artist-name { + color: #c8880a; } +/* Nav active — blood red left bar */ +[data-theme='ice-and-fire'] .nav-link.active { + background: linear-gradient(90deg, rgba(196,30,30,0.18) 0%, transparent 100%); + border-left: 3px solid #c41e1e; + color: #d42020; +} + +[data-theme='ice-and-fire'] .nav-link:hover:not(.active) { + background: linear-gradient(90deg, rgba(196,30,30,0.08) 0%, transparent 100%); + border-left: 3px solid rgba(196,30,30,0.32); +} + +/* Content header — red-to-gold ornate rule: Fire and Blood / Hear Me Roar */ +[data-theme='ice-and-fire'] .content-header { + border-bottom: 1px solid rgba(196,30,30,0.16); + position: relative; +} + +[data-theme='ice-and-fire'] .content-header::after { + content: ''; + position: absolute; + bottom: -3px; + left: 0; right: 0; + height: 1px; + background: linear-gradient(90deg, + transparent 0%, + rgba(196,30,30,0.70) 25%, + rgba(200,136,10,0.90) 50%, + rgba(196,30,30,0.70) 75%, + transparent 100% + ); +} + +/* Cards — volcanic panel, fire-gold border on hover */ +[data-theme='ice-and-fire'] .album-card:hover, +[data-theme='ice-and-fire'] .artist-card:hover { + box-shadow: + 0 0 0 1px rgba(196,30,30,0.50), + 0 0 0 2px rgba(200,136,10,0.14), + 0 4px 24px rgba(180,20,10,0.18); +} + +/* Track / queue rows */ +[data-theme='ice-and-fire'] .track-row:hover, +[data-theme='ice-and-fire'] .queue-item:hover { + box-shadow: inset 2px 0 0 #c41e1e; + background: rgba(196,30,30,0.07); +} + +/* Primary play button — Targaryen red gradient */ +[data-theme='ice-and-fire'] .player-btn-primary { + background: linear-gradient(180deg, #e03030 0%, #c41e1e 50%, #9c1010 100%); + color: #ecdcc8; + box-shadow: 0 0 16px rgba(196,30,30,0.48); + border: 1px solid #880808; +} + +[data-theme='ice-and-fire'] .player-btn-primary:hover { + background: linear-gradient(180deg, #f04040 0%, #d42828 50%, #ac1818 100%); + box-shadow: 0 0 26px rgba(196,30,30,0.70); +} + +/* btn-primary */ +[data-theme='ice-and-fire'] .btn-primary { + background: linear-gradient(180deg, #e03030 0%, #c41e1e 50%, #9c1010 100%); + color: #ecdcc8; + border: 1px solid #880808; +} + +[data-theme='ice-and-fire'] .btn-primary:hover { + background: linear-gradient(180deg, #f04040 0%, #d42828 50%, #ac1818 100%); +} + +/* Hero play button */ +[data-theme='ice-and-fire'] .hero-play-btn { + background: linear-gradient(180deg, #e03030 0%, #c41e1e 50%, #9c1010 100%); + color: #ecdcc8; + border: 1px solid #880808; + box-shadow: 0 2px 16px rgba(196,30,30,0.48); + transition: filter var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast); +} + +[data-theme='ice-and-fire'] .hero-play-btn:hover { + background: linear-gradient(180deg, #f04040 0%, #d42828 50%, #ac1818 100%); + box-shadow: 0 4px 26px rgba(196,30,30,0.70); + transform: scale(1.02); +} + +/* Album card overlay button */ +[data-theme='ice-and-fire'] .album-card-details-btn { + background: linear-gradient(180deg, #e03030 0%, #c41e1e 50%, #9c1010 100%); + color: #ecdcc8; + border: 1px solid #880808; + box-shadow: 0 2px 12px rgba(196,30,30,0.45); +} + +/* Scrollbar — obsidian dark, blood-red thumb transitioning to gold */ +[data-theme='ice-and-fire'] ::-webkit-scrollbar { width: 5px; height: 5px; } + +[data-theme='ice-and-fire'] ::-webkit-scrollbar-track { + background: #090c10; +} + +[data-theme='ice-and-fire'] ::-webkit-scrollbar-thumb { + background: linear-gradient(180deg, #c41e1e, #883010); + border-radius: 3px; +} + +[data-theme='ice-and-fire'] ::-webkit-scrollbar-thumb:hover { + background: #c8880a; +} + +/* Connection indicators */ +[data-theme='ice-and-fire'] .connection-type, +[data-theme='ice-and-fire'] .connection-server { color: #9a7858; } + /* ─── D'oh-matic ─── */ [data-theme='doh-matic'] { color-scheme: light; @@ -1781,7 +2082,7 @@ --accent-glow: rgba(31, 117, 254, 0.3); --text-primary: #222222; --text-secondary:#444444; - --text-muted: #777777; + --text-muted: #555555; --border: #222222; --border-subtle: rgba(0, 0, 0, 0.1); --border-dropdown: #cccccc; @@ -1868,7 +2169,7 @@ --text-primary: #000000; --text-secondary:#000000; - --text-muted: #808080; + --text-muted: #000000; --border: #808080; --border-subtle: #d4d0c8; @@ -1886,11 +2187,12 @@ --radius-full: 0px; } -/* Teal Desktop */ +/* Teal Desktop (nur der äußere Shell-Rahmen) */ [data-theme='w98'] .app-shell { background-color: #008080; } + /* ── 3D Bevel: Raised ── */ [data-theme='w98'] .sidebar, [data-theme='w98'] .player-bar, @@ -2087,6 +2389,31 @@ [data-theme='w98'] .collapse-btn:hover { background: #000080 !important; color: #ffffff !important; } [data-theme='w98'] .album-row-nav .nav-btn:hover:not(.disabled) { background: #000080; color: #ffffff; } +/* Live-Dropdown: kein backdrop-blur (saugt teal durch), solider W98-Hintergrund */ +[data-theme='w98'] .glass { + background: #d4d0c8 !important; + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; + border: 1px solid #000000; + box-shadow: inset 1px 1px #ffffff, inset -1px -1px #808080, 2px 2px 4px rgba(0,0,0,0.3); + color: #000000; +} + +/* Stream-Einträge: --bg-hover ist navy → Override auf W98-Grau mit Bevel */ +[data-theme='w98'] .glass [style*="var(--bg-hover)"] { + background: #ece8e0 !important; + border: 1px solid #808080; + box-shadow: inset 1px 1px #ffffff, inset -1px -1px #808080; + border-radius: 0 !important; +} + +/* Inline-color-Overrides für Text in Stream-Einträgen */ +[data-theme='w98'] .glass [style*="var(--text-primary)"], +[data-theme='w98'] .glass [style*="var(--text-secondary)"], +[data-theme='w98'] .glass [style*="var(--text-muted)"] { + color: #000000 !important; +} + /* ─── Global Base Settings ─── */ :root { /* Typography */ @@ -2390,7 +2717,7 @@ --text-primary: #121216; --text-secondary:#4A4A5A; - --text-muted: #8E8E9F; + --text-muted: #6B6B7A; --border: #E2E2E9; --border-subtle: #F0F0F5; @@ -2726,7 +3053,7 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* ─── Musicmatch Jukebox — Y2K Metallic Silver / Blue Display ─── */ -[data-theme='navy-jukebox'] { +[data-theme='muma-jukebox'] { color-scheme: light; --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%234a4a4a%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); @@ -2772,7 +3099,7 @@ input[type="range"]:hover::-webkit-slider-thumb { --volume-accent: #ff6600; /* Musicmatch orange for volume */ --text-primary: #1a1a1a; --text-secondary:#4a4a4a; - --text-muted: #6a7074; + --text-muted: #909090; --border: #8a9094; --border-subtle: #c0c4c6; --positive: #008840; @@ -2782,24 +3109,24 @@ input[type="range"]:hover::-webkit-slider-thumb { /* ── Musicmatch: contrast fixes ── */ /* Active elements: navy text on cyan bg — high contrast, on-brand */ -[data-theme='navy-jukebox'] .queue-round-btn.active { +[data-theme='muma-jukebox'] .queue-round-btn.active { color: #001358; } /* Accent-coloured text on silver body needs to be darker */ -[data-theme='navy-jukebox'] { +[data-theme='muma-jukebox'] { --accent: #0070a0; /* darker cyan — readable as text on silver */ --accent-dim: rgba(0, 112, 160, 0.15); --accent-glow: rgba(0, 112, 160, 0.35); } /* Player bar keeps the bright cyan since it's on dark blue bg */ -[data-theme='navy-jukebox'] .player-bar { +[data-theme='muma-jukebox'] .player-bar { --accent: #00d0ff; } /* ── Musicmatch: metallic bevel buttons ── */ -[data-theme='navy-jukebox'] .btn { +[data-theme='muma-jukebox'] .btn { background: linear-gradient(180deg, #e4e8eb 0%, #c0c4c7 100%); color: #1a1a1a; box-shadow: @@ -2809,11 +3136,11 @@ input[type="range"]:hover::-webkit-slider-thumb { border-radius: 6px; } -[data-theme='navy-jukebox'] .btn:hover { +[data-theme='muma-jukebox'] .btn:hover { background: linear-gradient(180deg, #eceef0 0%, #cacdd0 100%); } -[data-theme='navy-jukebox'] .btn-primary { +[data-theme='muma-jukebox'] .btn-primary { background: linear-gradient(180deg, #40e0ff 0%, #00a8d8 100%); color: #001358; box-shadow: @@ -2823,25 +3150,25 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* ── Player bar: blue LCD display area ── */ -[data-theme='navy-jukebox'] .player-bar { +[data-theme='muma-jukebox'] .player-bar { background: #001358; border-top: 2px solid #8a9094; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08); } -[data-theme='navy-jukebox'] .player-track-name { +[data-theme='muma-jukebox'] .player-track-name { color: #ffffff; text-shadow: 0 0 8px rgba(0, 208, 255, 0.75), 0 0 2px rgba(0, 208, 255, 0.4); letter-spacing: 0.02em; } -[data-theme='navy-jukebox'] .player-track-artist { +[data-theme='muma-jukebox'] .player-track-artist { color: #00d0ff; opacity: 0.85; } -[data-theme='navy-jukebox'] .player-btn, -[data-theme='navy-jukebox'] .player-btn-primary { +[data-theme='muma-jukebox'] .player-btn, +[data-theme='muma-jukebox'] .player-btn-primary { background: linear-gradient(180deg, #1a2880 0%, #000e40 100%); color: #00d0ff; box-shadow: @@ -2851,22 +3178,22 @@ input[type="range"]:hover::-webkit-slider-thumb { border-radius: 50%; } -[data-theme='navy-jukebox'] .player-btn:hover, -[data-theme='navy-jukebox'] .player-btn-primary:hover { +[data-theme='muma-jukebox'] .player-btn:hover, +[data-theme='muma-jukebox'] .player-btn-primary:hover { background: linear-gradient(180deg, #2030a0 0%, #001060 100%); color: #40e8ff; } /* ── Sidebar: brushed-metal look ── */ -[data-theme='navy-jukebox'] .sidebar { +[data-theme='muma-jukebox'] .sidebar { background: linear-gradient(180deg, #c8ccce 0%, #b0b4b7 100%); border-right: 2px solid #8a9094; box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.4); } /* ── Cards / panels: inset bevel ── */ -[data-theme='navy-jukebox'] .glass, -[data-theme='navy-jukebox'] .card { +[data-theme='muma-jukebox'] .glass, +[data-theme='muma-jukebox'] .card { box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.8), inset -1px -1px 0 rgba(0, 0, 0, 0.15), @@ -2874,7 +3201,7 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* ─── WMP8 Classic — Windows Media Player 8 / XP Luna ─── */ -[data-theme='cobalt-media'] { +[data-theme='winmedplayer'] { color-scheme: dark; --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23c2d4f2%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); @@ -2930,26 +3257,26 @@ input[type="range"]:hover::-webkit-slider-thumb { /* ── WMP8: Luna-style gradients + skeuomorphic detail ── */ /* Sidebar: deep WMP task-pane blue */ -[data-theme='cobalt-media'] .sidebar { +[data-theme='winmedplayer'] .sidebar { background: linear-gradient(180deg, #244080 0%, #1a3060 60%, #0e2048 100%); border-right: 2px solid #0e2048; box-shadow: inset -1px 0 0 rgba(120, 160, 220, 0.2); } /* Main body: Luna blue */ -[data-theme='cobalt-media'] .app-shell { +[data-theme='winmedplayer'] .app-shell { background: linear-gradient(160deg, #4a72b8 0%, #3a62a5 40%, #2e5498 100%); } /* Player bar: black LCD display with green glow ambience */ -[data-theme='cobalt-media'] .player-bar { +[data-theme='winmedplayer'] .player-bar { background: #000000; border-top: 2px solid #1a3060; box-shadow: inset 0 1px 0 rgba(69, 255, 0, 0.06), 0 -2px 12px rgba(0, 0, 0, 0.6); } /* Track name: WMP green glow */ -[data-theme='cobalt-media'] .player-track-name { +[data-theme='winmedplayer'] .player-track-name { color: #45ff00; text-shadow: 0 0 8px rgba(69, 255, 0, 0.80), @@ -2958,15 +3285,15 @@ input[type="range"]:hover::-webkit-slider-thumb { letter-spacing: 0.03em; } -[data-theme='cobalt-media'] .player-track-artist { +[data-theme='winmedplayer'] .player-track-artist { color: #30dd00; opacity: 0.85; text-shadow: 0 0 4px rgba(69, 255, 0, 0.4); } /* Transport buttons: round, radial metallic gradient, drop shadow */ -[data-theme='cobalt-media'] .player-btn, -[data-theme='cobalt-media'] .player-btn-primary { +[data-theme='winmedplayer'] .player-btn, +[data-theme='winmedplayer'] .player-btn-primary { background: radial-gradient(circle at 38% 32%, #c8dcf8 0%, #8aacdc 40%, #4870b8 100%); color: #ffffff; border-radius: 50%; @@ -2978,8 +3305,8 @@ input[type="range"]:hover::-webkit-slider-thumb { border: 1px solid #2a5090; } -[data-theme='cobalt-media'] .player-btn:hover, -[data-theme='cobalt-media'] .player-btn-primary:hover { +[data-theme='winmedplayer'] .player-btn:hover, +[data-theme='winmedplayer'] .player-btn-primary:hover { background: radial-gradient(circle at 38% 32%, #d8ecff 0%, #a0c0ee 40%, #5888d0 100%); box-shadow: 0 4px 10px rgba(0, 0, 0, 0.55), @@ -2989,7 +3316,7 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* Regular buttons: Luna soft rounded pill */ -[data-theme='cobalt-media'] .btn { +[data-theme='winmedplayer'] .btn { background: linear-gradient(180deg, #b8d0f0 0%, #7898d8 55%, #5878c0 100%); color: #ffffff; border-radius: 12px; @@ -3000,11 +3327,11 @@ input[type="range"]:hover::-webkit-slider-thumb { border: 1px solid #3a60b0; } -[data-theme='cobalt-media'] .btn:hover { +[data-theme='winmedplayer'] .btn:hover { background: linear-gradient(180deg, #cce0ff 0%, #90aaee 55%, #6888d0 100%); } -[data-theme='cobalt-media'] .btn-primary { +[data-theme='winmedplayer'] .btn-primary { background: linear-gradient(180deg, #70ff40 0%, #38cc00 55%, #28aa00 100%); color: #003300; border: 1px solid #208800; @@ -3016,13 +3343,13 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* Active queue round buttons: green bg, dark text */ -[data-theme='cobalt-media'] .queue-round-btn.active { +[data-theme='winmedplayer'] .queue-round-btn.active { color: #003300; } /* Cards / glass panels: slightly elevated with border */ -[data-theme='cobalt-media'] .glass, -[data-theme='cobalt-media'] .card { +[data-theme='winmedplayer'] .glass, +[data-theme='winmedplayer'] .card { background: rgba(90, 128, 190, 0.55); border: 1px solid rgba(160, 190, 230, 0.5); box-shadow: @@ -3031,13 +3358,13 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* Content header: slightly darker Luna band */ -[data-theme='cobalt-media'] .content-header { +[data-theme='winmedplayer'] .content-header { background: linear-gradient(180deg, rgba(58, 98, 165, 0.55) 0%, rgba(58, 98, 165, 0.2) 100%); border-bottom: 1px solid #6888c2; } /* ─── PowerDVD Classic — Virtual HiFi Receiver / VFD Display ─── */ -[data-theme='onyx-cinema'] { +[data-theme='p-dvd'] { color-scheme: dark; --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23666666%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); @@ -3082,7 +3409,7 @@ input[type="range"]:hover::-webkit-slider-thumb { --accent-glow: rgba(0, 170, 255, 0.35); --text-primary: #b3b3b3; --text-secondary:#888888; - --text-muted: #555555; + --text-muted: #888888; --border: #2a2a2a; --border-subtle: #1c1c1c; --positive: #00cc66; @@ -3090,9 +3417,8 @@ input[type="range"]:hover::-webkit-slider-thumb { --danger: #cc2222; } -/* ── PowerDVD: Brushed aluminium chassis texture ── */ -[data-theme='onyx-cinema'] .app-shell, -[data-theme='onyx-cinema'] .sidebar { +/* ── PowerDVD: Brushed aluminium chassis texture (sidebar only for perf) ── */ +[data-theme='p-dvd'] .sidebar { background-image: repeating-linear-gradient( 90deg, rgba(255, 255, 255, 0.018) 0px, @@ -3103,14 +3429,14 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* Sidebar: darker than chassis, drive-bay feel */ -[data-theme='onyx-cinema'] .sidebar { +[data-theme='p-dvd'] .sidebar { background-color: #0a0a0a; border-right: 1px solid #1e1e1e; box-shadow: inset -2px 0 4px rgba(0, 0, 0, 0.6); } /* ── VFD Display (Player Bar) ── */ -[data-theme='onyx-cinema'] .player-bar { +[data-theme='p-dvd'] .player-bar { background: #000000; border-top: 2px solid #1a1a1a; box-shadow: @@ -3119,7 +3445,7 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* Track name: VFD blue glow — the key effect */ -[data-theme='onyx-cinema'] .player-track-name { +[data-theme='p-dvd'] .player-track-name { color: #00e5ff; text-shadow: 0 0 6px rgba(0, 229, 255, 0.90), @@ -3128,21 +3454,21 @@ input[type="range"]:hover::-webkit-slider-thumb { letter-spacing: 0.04em; } -[data-theme='onyx-cinema'] .player-track-artist { +[data-theme='p-dvd'] .player-track-artist { color: #00aaff; text-shadow: 0 0 6px rgba(0, 170, 255, 0.55); opacity: 1; } /* Time display: VFD blue, tabular */ -[data-theme='onyx-cinema'] .player-time { +[data-theme='p-dvd'] .player-time { color: #00aaff; text-shadow: 0 0 5px rgba(0, 170, 255, 0.60); } /* ── Chrome transport buttons: silver metallic ── */ -[data-theme='onyx-cinema'] .player-btn, -[data-theme='onyx-cinema'] .player-btn-primary { +[data-theme='p-dvd'] .player-btn, +[data-theme='p-dvd'] .player-btn-primary { background: linear-gradient(170deg, #e8e8e8 0%, #ffffff 30%, #c0c0c0 70%, #989898 100%); color: #1a1a1a; border: 1px solid #707070; @@ -3153,8 +3479,8 @@ input[type="range"]:hover::-webkit-slider-thumb { inset 0 -1px 0 rgba(0, 0, 0, 0.2); } -[data-theme='onyx-cinema'] .player-btn:hover, -[data-theme='onyx-cinema'] .player-btn-primary:hover { +[data-theme='p-dvd'] .player-btn:hover, +[data-theme='p-dvd'] .player-btn-primary:hover { background: linear-gradient(170deg, #f2f2f2 0%, #ffffff 30%, #d0d0d0 70%, #aaaaaa 100%); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.7), @@ -3164,18 +3490,18 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* ── Regular buttons: dark matte chassis style ── */ -[data-theme='onyx-cinema'] .btn { +[data-theme='p-dvd'] .btn { background: linear-gradient(180deg, #2a2a2a 0%, #1c1c1c 100%); color: #b3b3b3; border: 1px solid #383838; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 1px 3px rgba(0, 0, 0, 0.5); } -[data-theme='onyx-cinema'] .btn:hover { +[data-theme='p-dvd'] .btn:hover { background: linear-gradient(180deg, #333333 0%, #242424 100%); } -[data-theme='onyx-cinema'] .btn-primary { +[data-theme='p-dvd'] .btn-primary { background: linear-gradient(180deg, #00bbff 0%, #0088dd 100%); color: #000000; border: 1px solid #0060bb; @@ -3186,13 +3512,13 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* Active queue round buttons: dark text on VFD blue */ -[data-theme='onyx-cinema'] .queue-round-btn.active { +[data-theme='p-dvd'] .queue-round-btn.active { color: #000000; } /* Cards / glass panels: chassis inset */ -[data-theme='onyx-cinema'] .glass, -[data-theme='onyx-cinema'] .card { +[data-theme='p-dvd'] .glass, +[data-theme='p-dvd'] .card { background: rgba(28, 28, 28, 0.85); border: 1px solid #2a2a2a; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03), 0 2px 6px rgba(0, 0, 0, 0.4); @@ -3244,7 +3570,7 @@ input[type="range"]:hover::-webkit-slider-thumb { --accent-glow: rgba(255, 111, 0, 0.40); --text-primary: #FFECB3; --text-secondary:#BCAAA4; - --text-muted: #8D6E63; + --text-muted: #b09880; --border: #B08D57; /* tarnished brass */ --border-subtle: #4E342E; --positive: #558B2F; @@ -3381,25 +3707,25 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* ─── Windows 7 Aero — Aero Glass & Frutiger Aero ─── */ +/* ─── Windows 7 Aero Glass ─── */ [data-theme='aero-glass'] { color-scheme: light; --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%234c607a%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); /* ── Palette ── */ - --ctp-crust: #1d4268; /* Aero taskbar navy */ - --ctp-mantle: #e6f0fa; /* inner glass panel */ - --ctp-base: #cddbed; /* window glass blue-gray */ - --ctp-surface0: #d8e6f2; - --ctp-surface1: #e0ecf5; - --ctp-surface2: #e8f2f8; - --ctp-overlay0: #a9c4eb; - --ctp-overlay1: #8ab0de; - --ctp-overlay2: #6a9cd0; - --ctp-text: #1a1a1a; - --ctp-subtext1: #2e4260; - --ctp-subtext0: #4c607a; - /* Aero blue highlight palette */ - --ctp-mauve: #1878e8; /* Windows highlight blue */ + --ctp-crust: #05080f; + --ctp-mantle: #0d1a2e; + --ctp-base: #b8cfe8; + --ctp-surface0: #ccdaea; + --ctp-surface1: #d8e6f2; + --ctp-surface2: #e4f0f8; + --ctp-overlay0: #a0bcd8; + --ctp-overlay1: #7aa0c0; + --ctp-overlay2: #5a84a8; + --ctp-text: #0d1a2e; + --ctp-subtext1: #1e3250; + --ctp-subtext0: #3a5070; + --ctp-mauve: #1878e8; --ctp-lavender: #3399ff; --ctp-sky: #5bb3ff; --ctp-blue: #1d4268; @@ -3415,167 +3741,371 @@ input[type="range"]:hover::-webkit-slider-thumb { --ctp-red: #c42b1c; /* ── Semantic tokens ── */ - --bg-app: #cddbed; - --bg-sidebar: #e6f0fa; - --bg-card: #d8e6f2; - --bg-hover: #c0d8ef; - --bg-player: #1d4268; - --bg-glass: rgba(205, 219, 237, 0.70); - --accent: #1878e8; /* 4.0:1 on #cddbed ✓ */ - --accent-dim: rgba(24, 120, 232, 0.12); - --accent-glow: rgba(24, 120, 232, 0.35); - --text-primary: #1a1a1a; - --text-secondary:#2e4260; - --text-muted: #4c607a; - --border: #a9c4eb; - --border-subtle: #d0e3f5; + --bg-app: #b8cfe8; + --bg-sidebar: rgba(210, 228, 248, 0.55); + --bg-card: rgba(225, 238, 252, 0.65); + --bg-hover: rgba(24, 120, 232, 0.85); + --bg-player: #05080f; + --bg-glass: rgba(210, 228, 248, 0.82); + --accent: #1878e8; + --accent-dim: rgba(24, 120, 232, 0.14); + --accent-glow: rgba(24, 120, 232, 0.40); + --volume-accent: #1878e8; + --text-primary: #0d1a2e; + --text-secondary:#1e3250; + --text-muted: #7090b8; + --border: rgba(130, 175, 220, 0.65); + --border-subtle: rgba(160, 200, 240, 0.45); --positive: #107c10; --warning: #c87400; --danger: #c42b1c; + --radius-sm: 4px; + --radius-md: 6px; + --radius-lg: 8px; } -/* ── Aero: background — soft sky gradient ── */ +/* ── Background: W7 sky with depth ── */ [data-theme='aero-glass'] .app-shell { - background: linear-gradient(160deg, #daeaf8 0%, #cddbed 45%, #b8d0e8 100%); + background: linear-gradient(160deg, #c8e2f5 0%, #b5cfe4 45%, #9fc0db 100%); } -/* ── Sidebar: Aero glass panel with backdrop blur ── */ +/* ── Sidebar: Aero glass panel — frosted translucent ── */ [data-theme='aero-glass'] .sidebar { - background: rgba(230, 240, 250, 0.62); - backdrop-filter: blur(14px); - -webkit-backdrop-filter: blur(14px); - border-right: 1px solid rgba(169, 196, 235, 0.75); - box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.6); + background: rgba(210, 232, 252, 0.52); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-right: 1px solid rgba(150, 190, 230, 0.55); + box-shadow: + inset -1px 0 0 rgba(255,255,255,0.75), + inset 1px 0 0 rgba(255,255,255,0.25), + 2px 0 8px rgba(0,0,0,0.12); } -/* ── Player bar: Aero taskbar — deep glass navy ── */ +/* ── Player bar: authentic W7 taskbar — near-black glass ── */ [data-theme='aero-glass'] .player-bar { - background: rgba(29, 66, 104, 0.90); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - border-top: 1px solid rgba(100, 160, 220, 0.45); - box-shadow: inset 0 1px 0 rgba(120, 180, 255, 0.15), 0 -2px 12px rgba(0, 0, 0, 0.3); + background: linear-gradient(180deg, + rgba(12, 18, 32, 0.96) 0%, + rgba(6, 10, 20, 0.99) 100% + ); + backdrop-filter: blur(22px); + -webkit-backdrop-filter: blur(22px); + border-top: 1px solid rgba(80, 155, 235, 0.60); + box-shadow: + inset 0 1px 0 rgba(100, 180, 255, 0.28), + inset 0 2px 0 rgba(255,255,255,0.06), + 0 -2px 16px rgba(0,0,0,0.55); } -/* Track name: white on dark taskbar, subtle blue glow */ +/* Track info: white on near-black, blue glow */ [data-theme='aero-glass'] .player-track-name { color: #ffffff; - text-shadow: 0 0 8px rgba(51, 153, 255, 0.60), 0 1px 2px rgba(0, 0, 0, 0.4); + text-shadow: 0 0 12px rgba(80, 160, 255, 0.65), 0 1px 2px rgba(0,0,0,0.60); + font-weight: 600; } +[data-theme='aero-glass'] .player-track-artist { color: #88b8e0; opacity: 1; } +[data-theme='aero-glass'] .player-time { color: #88b8e0; } -[data-theme='aero-glass'] .player-track-artist { - color: #a9c8f0; - opacity: 1; -} - -[data-theme='aero-glass'] .player-time { - color: #a9c8f0; -} - -/* ── Transport buttons: glossy Aero pill ── */ +/* ── Transport buttons: Aero glass gel circles ── */ [data-theme='aero-glass'] .player-btn, [data-theme='aero-glass'] .player-btn-primary { background: linear-gradient(180deg, - rgba(255, 255, 255, 0.75) 0%, - rgba(200, 228, 255, 0.80) 48%, - rgba(90, 160, 230, 0.90) 50%, - rgba(40, 120, 200, 0.95) 100% + rgba(255,255,255,0.80) 0%, + rgba(195,228,255,0.82) 48%, + rgba(80,160,235,0.92) 50%, + rgba(30,110,205,0.96) 100% ); color: #ffffff; - border: 1px solid rgba(24, 80, 180, 0.55); + border: 1px solid rgba(20, 75, 180, 0.55); border-radius: 50%; box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.85), - 0 2px 6px rgba(0, 0, 0, 0.35), - 0 0 0 1px rgba(100, 160, 220, 0.3); + inset 0 1px 0 rgba(255,255,255,0.90), + 0 2px 6px rgba(0,0,0,0.40), + 0 0 0 1px rgba(80,150,230,0.25); } - [data-theme='aero-glass'] .player-btn:hover, [data-theme='aero-glass'] .player-btn-primary:hover { background: linear-gradient(180deg, - rgba(255, 255, 255, 0.85) 0%, - rgba(215, 238, 255, 0.88) 48%, - rgba(110, 175, 245, 0.93) 50%, - rgba(55, 135, 215, 0.98) 100% + rgba(255,255,255,0.92) 0%, + rgba(215,240,255,0.90) 48%, + rgba(105,178,248,0.95) 50%, + rgba(50,130,220,0.99) 100% ); box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.9), - 0 3px 8px rgba(0, 0, 0, 0.35), - 0 0 8px rgba(51, 153, 255, 0.40); + inset 0 1px 0 rgba(255,255,255,0.95), + 0 3px 10px rgba(0,0,0,0.40), + 0 0 12px rgba(51,153,255,0.45); } -/* ── Regular buttons: glossy Aero style ── */ -[data-theme='aero-glass'] .btn { +/* ── Regular buttons: Aero frosted glass ── */ +[data-theme='aero-glass'] .btn, +[data-theme='aero-glass'] .btn-surface, +[data-theme='aero-glass'] .btn-ghost { background: linear-gradient(180deg, - rgba(255, 255, 255, 0.82) 0%, - rgba(255, 255, 255, 0.82) 48%, - rgba(195, 220, 245, 0.92) 50%, - rgba(160, 200, 240, 0.95) 100% + rgba(255,255,255,0.85) 0%, + rgba(255,255,255,0.85) 48%, + rgba(190,220,248,0.90) 50%, + rgba(155,198,240,0.94) 100% ); - color: #1a1a1a; - border: 1px solid rgba(130, 175, 220, 0.70); + color: #0d1a2e; + border: 1px solid rgba(120, 170, 220, 0.65); box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.90), - 0 1px 3px rgba(0, 0, 0, 0.18); - border-radius: 4px; + inset 0 1px 0 rgba(255,255,255,0.95), + inset 0 1px 0 rgba(255,255,255,0.50), + 0 1px 3px rgba(0,0,0,0.18); + border-radius: 5px; } - -[data-theme='aero-glass'] .btn:hover { +[data-theme='aero-glass'] .btn:hover, +[data-theme='aero-glass'] .btn-surface:hover, +[data-theme='aero-glass'] .btn-ghost:hover { background: linear-gradient(180deg, - rgba(255, 255, 255, 0.92) 0%, - rgba(255, 255, 255, 0.92) 48%, - rgba(210, 232, 252, 0.95) 50%, - rgba(175, 212, 248, 0.98) 100% + rgba(255,255,255,0.96) 0%, + rgba(255,255,255,0.96) 48%, + rgba(210,235,255,0.95) 50%, + rgba(175,215,252,0.98) 100% ); + border-color: rgba(24, 120, 232, 0.70); box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.95), - 0 1px 4px rgba(0, 0, 0, 0.20), - 0 0 6px rgba(51, 153, 255, 0.25); + inset 0 1px 0 rgba(255,255,255,1), + 0 1px 4px rgba(0,0,0,0.20), + 0 0 8px rgba(24,120,232,0.22); } +/* ── Primary button: Aero blue gel ── */ [data-theme='aero-glass'] .btn-primary { background: linear-gradient(180deg, - rgba(110, 180, 255, 0.90) 0%, - rgba(80, 155, 240, 0.90) 48%, - rgba(24, 100, 200, 0.95) 50%, - rgba(15, 75, 170, 0.98) 100% + rgba(110,185,255,0.92) 0%, + rgba(70,155,245,0.92) 48%, + rgba(24,100,205,0.96) 50%, + rgba(12,72,175,0.99) 100% ); color: #ffffff; - border: 1px solid rgba(15, 60, 150, 0.70); + border: 1px solid rgba(12, 60, 155, 0.70); box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.55), - 0 1px 4px rgba(0, 0, 0, 0.3), - 0 0 8px rgba(51, 153, 255, 0.35); + inset 0 1px 0 rgba(255,255,255,0.58), + 0 1px 4px rgba(0,0,0,0.30), + 0 0 10px rgba(24,120,232,0.38); + border-radius: 5px; +} +[data-theme='aero-glass'] .btn-primary:hover { + background: linear-gradient(180deg, + rgba(140,200,255,0.95) 0%, + rgba(90,170,255,0.95) 48%, + rgba(40,120,225,0.98) 50%, + rgba(24,95,195,1) 100% + ); + box-shadow: + inset 0 1px 0 rgba(255,255,255,0.65), + 0 1px 5px rgba(0,0,0,0.30), + 0 0 14px rgba(24,120,232,0.50); } -/* Active queue buttons: white text on blue */ +/* ── Hero / album-card buttons: frosted glass ── */ +[data-theme='aero-glass'] .hero-play-btn, +[data-theme='aero-glass'] .album-card-details-btn { + background: linear-gradient(180deg, + rgba(255,255,255,0.82) 0%, + rgba(190,220,248,0.88) 48%, + rgba(140,190,235,0.92) 50%, + rgba(100,160,220,0.95) 100% + ); + color: #0d1a2e; + border: 1px solid rgba(100,160,220,0.60); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.90), 0 1px 3px rgba(0,0,0,0.20); +} +[data-theme='aero-glass'] .hero-play-btn:hover, +[data-theme='aero-glass'] .album-card-details-btn:hover { + background: linear-gradient(180deg, + rgba(255,255,255,0.95) 0%, + rgba(215,238,255,0.95) 50%, + rgba(165,210,250,0.98) 100% + ); + border-color: rgba(24,120,232,0.70); + box-shadow: inset 0 1px 0 rgba(255,255,255,1), 0 0 8px rgba(24,120,232,0.25); +} + +/* ── Queue toolbar round buttons: Aero glass ── */ +[data-theme='aero-glass'] .queue-round-btn { + background: linear-gradient(180deg, + rgba(255,255,255,0.80) 0%, + rgba(185,218,248,0.88) 50%, + rgba(140,190,235,0.92) 100% + ); + color: #1e3250; + border: 1px solid rgba(110,165,220,0.60); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.90), 0 1px 2px rgba(0,0,0,0.18); +} +[data-theme='aero-glass'] .queue-round-btn:hover:not(:disabled):not(.active) { + background: linear-gradient(180deg, + rgba(255,255,255,0.95) 0%, + rgba(210,235,255,0.95) 50%, + rgba(165,208,250,0.98) 100% + ); + border-color: rgba(24,120,232,0.65); + box-shadow: inset 0 1px 0 rgba(255,255,255,1), 0 0 8px rgba(24,120,232,0.25); + color: #0d1a2e; +} [data-theme='aero-glass'] .queue-round-btn.active { + background: linear-gradient(180deg, + rgba(110,180,255,0.90) 0%, + rgba(24,100,210,0.96) 100% + ); color: #ffffff; - box-shadow: 0 0 6px rgba(51, 153, 255, 0.50); + border-color: rgba(12,60,155,0.70); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.45), 0 0 8px rgba(24,120,232,0.50); } -/* Cards / panels: frosted glass */ -[data-theme='aero-glass'] .glass, +/* ── Cards: frosted glass panels ── */ [data-theme='aero-glass'] .card { - background: rgba(230, 240, 250, 0.60); - backdrop-filter: blur(8px); - -webkit-backdrop-filter: blur(8px); - border: 1px solid rgba(169, 196, 235, 0.65); - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.70), - 0 2px 8px rgba(0, 0, 0, 0.12); -} - -/* Content header: glassy strip */ -[data-theme='aero-glass'] .content-header { - background: rgba(210, 230, 248, 0.55); + background: rgba(225, 240, 255, 0.62); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); - border-bottom: 1px solid rgba(169, 196, 235, 0.60); - box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.5); + border: 1px solid rgba(160, 200, 240, 0.60); + box-shadow: + inset 0 1px 0 rgba(255,255,255,0.80), + 0 2px 8px rgba(0,0,0,0.12); + border-radius: 6px; } +/* ── Content header: Aero chrome strip ── */ +[data-theme='aero-glass'] .content-header { + background: rgba(210, 232, 252, 0.58); + backdrop-filter: blur(14px); + -webkit-backdrop-filter: blur(14px); + border-bottom: 1px solid rgba(150, 195, 240, 0.55); + box-shadow: + inset 0 1px 0 rgba(255,255,255,0.70), + inset 0 -1px 0 rgba(255,255,255,0.35), + 0 2px 6px rgba(0,0,0,0.10); +} + +/* Connection indicators: dark navy, readable on glass */ +[data-theme='aero-glass'] .connection-type, +[data-theme='aero-glass'] .connection-server { + color: #0d1a2e; +} + +/* ── Theme accordion: glass hover ── */ +[data-theme='aero-glass'] .theme-accordion-header:hover { + background: rgba(24,120,232,0.18); + color: #0d1a2e; +} +[data-theme='aero-glass'] .theme-accordion-open .theme-accordion-header { + background: rgba(24,120,232,0.22); + color: #0d1a2e; +} + +/* ── Progress bar: Aero blue ── */ +[data-theme='aero-glass'] .progress-bar-track { + background: rgba(150, 195, 235, 0.45); + border-radius: 3px; + box-shadow: inset 0 1px 2px rgba(0,0,0,0.15); +} +[data-theme='aero-glass'] .progress-bar-fill { + background: linear-gradient(180deg, + rgba(110,185,255,0.95) 0%, + rgba(24,120,232,0.98) 50%, + rgba(12,90,200,1) 100% + ); + border-radius: 3px; + box-shadow: 0 0 6px rgba(24,120,232,0.50); +} + +/* ── Scrollbar: W7 thin glass style ── */ +[data-theme='aero-glass'] ::-webkit-scrollbar { width: 10px; height: 10px; } +[data-theme='aero-glass'] ::-webkit-scrollbar-track { + background: rgba(175, 210, 245, 0.25); + border-radius: 5px; +} +[data-theme='aero-glass'] ::-webkit-scrollbar-thumb { + background: rgba(110, 168, 225, 0.60); + border: 1px solid rgba(80, 140, 200, 0.45); + border-radius: 5px; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.45); +} +[data-theme='aero-glass'] ::-webkit-scrollbar-thumb:hover { + background: rgba(24, 120, 232, 0.72); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.50), 0 0 4px rgba(24,120,232,0.30); +} + +/* ── Glass / dropdowns: frosted glass panel ── */ +[data-theme='aero-glass'] .glass { + background: rgba(218, 236, 255, 0.88) !important; + backdrop-filter: blur(18px) !important; + -webkit-backdrop-filter: blur(18px) !important; + border: 1px solid rgba(150, 195, 240, 0.65) !important; + box-shadow: + inset 0 1px 0 rgba(255,255,255,0.75), + 2px 2px 12px rgba(0,0,0,0.18) !important; + border-radius: 8px !important; +} +[data-theme='aero-glass'] .glass [style*="var(--bg-hover)"] { + background: rgba(24,120,232,0.20) !important; + border-radius: 4px !important; +} +[data-theme='aero-glass'] .glass [style*="var(--text-primary)"] { color: #0d1a2e !important; } +[data-theme='aero-glass'] .glass [style*="var(--text-secondary)"] { color: #1e3250 !important; } +[data-theme='aero-glass'] .glass [style*="var(--text-muted)"] { color: #3a5070 !important; } + +/* ── Hover / selection: Aero blue glass ── */ +[data-theme='aero-glass'] .queue-tab-btn:hover { background: rgba(24,120,232,0.18); color: #0d1a2e; } +[data-theme='aero-glass'] .settings-tab:hover { background: rgba(24,120,232,0.18); color: #0d1a2e; } +[data-theme='aero-glass'] .settings-tab.active { + background: rgba(24,120,232,0.85); + color: #ffffff; +} +[data-theme='aero-glass'] .custom-select-trigger:hover { background: rgba(24,120,232,0.15); } +[data-theme='aero-glass'] .custom-select-option:hover { + background: rgba(24,120,232,0.85) !important; + color: #ffffff !important; +} +[data-theme='aero-glass'] .artist-ext-link:hover { + background: rgba(24,120,232,0.85); + color: #ffffff !important; +} +[data-theme='aero-glass'] .np-action-btn:hover { background: rgba(24,120,232,0.18); } +[data-theme='aero-glass'] .np-queue-item:hover, +[data-theme='aero-glass'] .np-queue-item.context-active { + background: rgba(24,120,232,0.85); + color: #ffffff; +} +[data-theme='aero-glass'] .track-row:hover, +[data-theme='aero-glass'] .track-row.context-active { + background: rgba(24,120,232,0.85) !important; +} +[data-theme='aero-glass'] .track-row:hover *, +[data-theme='aero-glass'] .track-row.context-active * { color: #ffffff !important; } +[data-theme='aero-glass'] .artist-row:hover { background: rgba(24,120,232,0.85); color: #ffffff; } +[data-theme='aero-glass'] .playlist-row:hover { background: rgba(24,120,232,0.85); } +[data-theme='aero-glass'] .playlist-row:hover, +[data-theme='aero-glass'] .playlist-row:hover * { color: #ffffff; } +[data-theme='aero-glass'] .queue-item:hover, +[data-theme='aero-glass'] .queue-item.context-active { + background: rgba(24,120,232,0.85) !important; +} +[data-theme='aero-glass'] .queue-item:hover .queue-item-title, +[data-theme='aero-glass'] .queue-item:hover .queue-item-artist, +[data-theme='aero-glass'] .queue-item:hover .queue-item-duration, +[data-theme='aero-glass'] .queue-item.context-active .queue-item-title, +[data-theme='aero-glass'] .queue-item.context-active .queue-item-artist, +[data-theme='aero-glass'] .queue-item.context-active .queue-item-duration { color: #ffffff; } + +/* ── Active queue / now-playing items ── */ +[data-theme='aero-glass'] .queue-item.active { + background: rgba(24, 120, 232, 0.14); + color: #1366c8; +} +[data-theme='aero-glass'] .queue-item.active .queue-item-artist, +[data-theme='aero-glass'] .queue-item.active .queue-item-duration { + color: #1878e8; + opacity: 0.85; +} +[data-theme='aero-glass'] .np-queue-item-active { color: #1366c8; } +[data-theme='aero-glass'] .np-queue-item.active { background: rgba(24, 120, 232, 0.10); } +[data-theme='aero-glass'] .np-album-track.active .np-album-track-title, +[data-theme='aero-glass'] .np-album-track.active .np-album-track-num { color: #1366c8; } + /* ─── Windows XP Luna — Classic 2001 ─── */ +/* ─── Windows XP Luna Teal ─── */ [data-theme='luna-teal'] { color-scheme: light; --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23444444%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); @@ -3584,21 +4114,20 @@ input[type="range"]:hover::-webkit-slider-thumb { --ctp-crust: #0041b8; --ctp-mantle: #0055e5; --ctp-base: #ece9d8; - --ctp-surface0: #f5f3ec; - --ctp-surface1: #faf9f6; - --ctp-surface2: #ffffff; + --ctp-surface0: #ffffff; + --ctp-surface1: #f5f3ec; + --ctp-surface2: #ece9d8; --ctp-overlay0: #c0bba8; --ctp-overlay1: #8a8675; --ctp-overlay2: #5e5a4c; --ctp-text: #000000; --ctp-subtext1: #1a1a1a; --ctp-subtext0: #444444; - /* XP green + Luna blue family */ --ctp-mauve: #3c9d29; --ctp-lavender: #52b83c; --ctp-green: #3c9d29; --ctp-teal: #007c8a; - --ctp-sky: #8fa8f4; + --ctp-sky: #316ac5; --ctp-blue: #0055e5; --ctp-sapphire: #0041b8; --ctp-pink: #cc2288; @@ -3611,246 +4140,331 @@ input[type="range"]:hover::-webkit-slider-thumb { /* ── Semantic tokens ── */ --bg-app: #ece9d8; - --bg-sidebar: #8fa8f4; - --bg-card: #f5f3ec; - --bg-hover: #dddac8; - --bg-player: #0055e5; - --bg-glass: rgba(236, 233, 216, 0.92); + --bg-sidebar: #c8daf5; + --bg-card: #ffffff; + --bg-hover: #316ac5; + --bg-player: #1248b8; + --bg-glass: rgba(255, 255, 255, 0.97); --accent: #3c9d29; --accent-dim: rgba(60, 157, 41, 0.14); --accent-glow: rgba(60, 157, 41, 0.35); --volume-accent: #3c9d29; --text-primary: #000000; --text-secondary:#333333; - --text-muted: #666666; + --text-muted: #555555; --border: #003399; - --border-subtle: #ccc8b4; + --border-subtle: #aca899; --positive: #3c9d29; --warning: #b87800; --danger: #cc1111; - --radius-sm: 4px; - --radius-md: 6px; - --radius-lg: 8px; + --radius-sm: 3px; + --radius-md: 4px; + --radius-lg: 6px; } -/* ── Luna: Explorer window background ── */ +/* ── App shell: XP sandy desktop ── */ [data-theme='luna-teal'] .app-shell { background: #ece9d8; } -/* ── Sidebar: Luna Explorer task pane ── */ +/* ── Sidebar: XP Explorer task pane / Folders panel ── */ [data-theme='luna-teal'] .sidebar { - background: linear-gradient(180deg, #a8bef8 0%, #8fa8f4 30%, #7a96ee 100%); - border-right: 2px solid #003399; - box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.35), 2px 0 6px rgba(0, 0, 0, 0.18); + background: linear-gradient(180deg, #d8e8fa 0%, #c0d4f5 40%, #b0c8f0 100%); + border-right: 1px solid #7090c0; + box-shadow: inset -1px 0 0 rgba(255,255,255,0.60), 2px 0 4px rgba(0,0,0,0.14); } -/* Sidebar text: dark on medium blue */ +/* Sidebar text: dark navy on ice blue — with white text-shadow for legibility */ [data-theme='luna-teal'] .sidebar-link, [data-theme='luna-teal'] .sidebar-section-title, [data-theme='luna-teal'] .sidebar-logo-text, [data-theme='luna-teal'] .nav-section-label, [data-theme='luna-teal'] .brand-name { - color: #000e40; -} - -/* Nav links: override accent-based active state */ -[data-theme='luna-teal'] .nav-link { - color: #000e40; -} -[data-theme='luna-teal'] .nav-link:hover { - background: rgba(255, 255, 255, 0.30); - color: #000000; -} -[data-theme='luna-teal'] .nav-link.active { - background: rgba(0, 0, 80, 0.18); - color: #ffffff; -} -[data-theme='luna-teal'] .nav-link.active::before { - background: #ffffff; -} -[data-theme='luna-teal'] .nav-link.active svg, -[data-theme='luna-teal'] .nav-link:hover svg { - opacity: 1; -} - -/* Now Playing nav link: same treatment */ -[data-theme='luna-teal'] .nav-link-nowplaying { - background: rgba(0, 0, 80, 0.14); - color: #000e40; -} -[data-theme='luna-teal'] .nav-link-nowplaying:hover { - background: rgba(255, 255, 255, 0.30); - color: #000000; -} -[data-theme='luna-teal'] .nav-link-nowplaying.active { - background: rgba(0, 0, 80, 0.22); - color: #ffffff; -} - -/* ── Player bar: Luna taskbar — glossy blue ── */ -[data-theme='luna-teal'] .player-bar { - background: linear-gradient(180deg, - #4488ff 0%, - #0055e5 40%, - #0044cc 70%, - #0038b0 100% - ); - border-top: 2px solid #6699ff; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.45), - inset 0 2px 0 rgba(255, 255, 255, 0.18), - 0 -2px 8px rgba(0, 0, 0, 0.30); -} - -/* Track name: white with XP title-bar glow */ -[data-theme='luna-teal'] .player-track-name { - color: #ffffff; - text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55), 0 0 8px rgba(100, 160, 255, 0.50); + color: #002060; + text-shadow: 0 1px 0 rgba(255,255,255,0.55); font-weight: 700; } -[data-theme='luna-teal'] .player-track-artist { - color: #b8d0ff; - opacity: 1; +/* Nav links */ +[data-theme='luna-teal'] .nav-link { color: #001850; } +[data-theme='luna-teal'] .nav-link:hover { + background: rgba(255,255,255,0.45); + color: #000000; + border-radius: 3px; +} +[data-theme='luna-teal'] .nav-link.active { + background: #316ac5; + color: #ffffff; + border-radius: 3px; + text-shadow: none; +} +[data-theme='luna-teal'] .nav-link.active::before { background: #ffffff; } +[data-theme='luna-teal'] .nav-link.active svg, +[data-theme='luna-teal'] .nav-link:hover svg { opacity: 1; } + +/* Now Playing nav link */ +[data-theme='luna-teal'] .nav-link-nowplaying { background: rgba(0,0,80,0.10); color: #001850; } +[data-theme='luna-teal'] .nav-link-nowplaying:hover { background: rgba(255,255,255,0.45); color: #000000; } +[data-theme='luna-teal'] .nav-link-nowplaying.active { background: #316ac5; color: #ffffff; } + +/* ── Player bar: authentic XP Luna taskbar blue ── */ +[data-theme='luna-teal'] .player-bar { + background: linear-gradient(180deg, + #4b8ee8 0%, + #2568d4 8%, + #1a56c4 30%, + #1248b8 70%, + #0e3da8 85%, + #1248b8 100% + ); + border-top: 1px solid #7aaaff; + box-shadow: + inset 0 1px 0 rgba(255,255,255,0.55), + inset 0 2px 0 rgba(255,255,255,0.18), + 0 -2px 8px rgba(0,0,0,0.30); } -[data-theme='luna-teal'] .player-time { - color: #b8d0ff; +/* Track name: white with XP glow */ +[data-theme='luna-teal'] .player-track-name { + color: #ffffff; + text-shadow: 0 1px 2px rgba(0,0,0,0.60), 0 0 10px rgba(120,180,255,0.40); + font-weight: 700; } +[data-theme='luna-teal'] .player-track-artist { color: #b8d4ff; opacity: 1; } +[data-theme='luna-teal'] .player-time { color: #b8d4ff; } -/* ── Transport buttons: Luna plastic/gel ── */ +/* ── Transport buttons: XP Luna gel circles ── */ [data-theme='luna-teal'] .player-btn, [data-theme='luna-teal'] .player-btn-primary { background: linear-gradient(180deg, - #6699ff 0%, - #3366ee 45%, - #0044cc 50%, - #0033aa 100% + #80aaff 0%, + #4477ee 45%, + #1a50dd 50%, + #0c3bb8 100% ); color: #ffffff; border: 1px solid #002288; border-radius: 50%; box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.60), - 0 2px 5px rgba(0, 0, 0, 0.40); + inset 0 1px 0 rgba(255,255,255,0.65), + 0 2px 5px rgba(0,0,0,0.45); } - [data-theme='luna-teal'] .player-btn:hover, [data-theme='luna-teal'] .player-btn-primary:hover { background: linear-gradient(180deg, - #88aaff 0%, - #4477ff 45%, - #1155dd 50%, - #0044bb 100% + #99bbff 0%, + #5588ff 45%, + #2264ee 50%, + #1a52d0 100% ); box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.70), - 0 3px 8px rgba(0, 0, 0, 0.40), - 0 0 10px rgba(100, 160, 255, 0.40); + inset 0 1px 0 rgba(255,255,255,0.75), + 0 3px 8px rgba(0,0,0,0.40), + 0 0 10px rgba(80,140,255,0.40); } -/* ── Regular buttons: XP 3D bevel ── */ -[data-theme='luna-teal'] .btn { - background: linear-gradient(180deg, #f5f3ec 0%, #f5f3ec 48%, #e0ddd0 50%, #d4d0c0 100%); +/* ── Regular buttons: XP bevel style ── */ +[data-theme='luna-teal'] .btn, +[data-theme='luna-teal'] .btn-surface, +[data-theme='luna-teal'] .btn-ghost { + background: linear-gradient(180deg, #f5f3ec 0%, #ece9d8 48%, #ddd9c8 50%, #d0cdb8 100%); color: #000000; border: 1px solid #888480; box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.90), - inset 1px 0 0 rgba(255, 255, 255, 0.70), - 0 1px 2px rgba(0, 0, 0, 0.22); - border-radius: 4px; + inset 0 1px 0 rgba(255,255,255,0.95), + inset 1px 0 0 rgba(255,255,255,0.70), + 0 1px 2px rgba(0,0,0,0.20); + border-radius: 3px; } - -[data-theme='luna-teal'] .btn:hover { - background: linear-gradient(180deg, #ffffff 0%, #ffffff 48%, #e8e5d8 50%, #dcd8c8 100%); +[data-theme='luna-teal'] .btn:hover, +[data-theme='luna-teal'] .btn-surface:hover, +[data-theme='luna-teal'] .btn-ghost:hover { + background: linear-gradient(180deg, #ffffff 0%, #f0ede0 48%, #e4e0d0 50%, #d8d4c4 100%); border-color: #0055e5; box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 1), - 0 1px 3px rgba(0, 0, 0, 0.20); + inset 0 1px 0 rgba(255,255,255,1), + 0 1px 3px rgba(0,0,0,0.18); } +/* ── Primary button: XP green gel ── */ [data-theme='luna-teal'] .btn-primary { background: linear-gradient(180deg, - #52cc3c 0%, + #66dd50 0%, #3c9d29 45%, #2e8020 50%, - #236618 100% + #1e6015 100% ); color: #ffffff; border: 1px solid #1a5010; box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.50), - 0 1px 3px rgba(0, 0, 0, 0.30); - border-radius: 6px; + inset 0 1px 0 rgba(255,255,255,0.55), + 0 1px 3px rgba(0,0,0,0.30); + border-radius: 4px; } - [data-theme='luna-teal'] .btn-primary:hover { background: linear-gradient(180deg, - #66dd50 0%, + #80ee68 0%, #4db035 45%, - #3c9d29 50%, + #3a9028 50%, #2e8020 100% ); box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.55), - 0 1px 4px rgba(0, 0, 0, 0.30), - 0 0 8px rgba(60, 157, 41, 0.40); + inset 0 1px 0 rgba(255,255,255,0.60), + 0 1px 4px rgba(0,0,0,0.30), + 0 0 8px rgba(60,157,41,0.40); } -[data-theme='luna-teal'] .btn-surface { - background: linear-gradient(180deg, #f5f3ec 0%, #e0ddd0 100%); +/* ── Hero / album-card play buttons ── */ +[data-theme='luna-teal'] .hero-play-btn, +[data-theme='luna-teal'] .album-card-details-btn { + background: linear-gradient(180deg, #f5f3ec 0%, #d0cdb8 100%); color: #000000; border: 1px solid #888480; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.95), 0 1px 2px rgba(0,0,0,0.20); +} +[data-theme='luna-teal'] .hero-play-btn:hover, +[data-theme='luna-teal'] .album-card-details-btn:hover { + background: linear-gradient(180deg, #ffffff 0%, #ddd9c8 100%); + border-color: #0055e5; } -/* ── Cards: XP dialog/panel style ── */ +/* ── Queue toolbar round buttons ── */ +[data-theme='luna-teal'] .queue-round-btn { + background: linear-gradient(180deg, #f5f3ec 0%, #d0cdb8 100%); + color: #333333; + border: 1px solid #888480; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.90), 0 1px 2px rgba(0,0,0,0.18); +} +[data-theme='luna-teal'] .queue-round-btn:hover:not(:disabled):not(.active) { + background: linear-gradient(180deg, #ffffff 0%, #e0ddd0 100%); + border-color: #0055e5; + color: #000000; +} +[data-theme='luna-teal'] .queue-round-btn.active { + background: #316ac5; + color: #ffffff; + border-color: #0033aa; + box-shadow: inset 0 1px 3px rgba(0,0,0,0.30), 0 1px 0 rgba(255,255,255,0.15); +} + +/* ── Cards: XP white window interior ── */ [data-theme='luna-teal'] .card { - background: #f5f3ec; - border: 1px solid #c0bba8; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.80), - 0 1px 4px rgba(0, 0, 0, 0.12); - border-radius: 6px; + background: #ffffff; + border: 1px solid #aca899; + box-shadow: inset 0 1px 0 rgba(255,255,255,1), 0 1px 3px rgba(0,0,0,0.15); + border-radius: 4px; } -/* ── Content header: Luna title bar strip ── */ +/* ── Content header: XP title bar gradient ── */ [data-theme='luna-teal'] .content-header { - background: linear-gradient(180deg, #b8c8f8 0%, #8fa8f4 100%); - border-bottom: 2px solid #003399; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.50), 0 2px 4px rgba(0, 0, 0, 0.12); + background: linear-gradient(180deg, + #5a9aee 0%, + #2a6ad4 25%, + #1a56c4 50%, + #0e48b8 75%, + #0a3aaa 100% + ); + border-bottom: 1px solid #0033aa; + color: #ffffff; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.40), 0 2px 4px rgba(0,0,0,0.18); } -/* Connection indicators: dark text on blue header */ +/* Connection indicators: white on blue header */ [data-theme='luna-teal'] .connection-type, [data-theme='luna-teal'] .connection-server { - color: #000e40; + color: #ffffff; + text-shadow: 0 1px 2px rgba(0,0,0,0.50); } -/* Active queue item: deep XP blue instead of green */ +/* ── Theme accordion: XP selection blue ── */ +[data-theme='luna-teal'] .theme-accordion-header:hover { background: #316ac5; color: #ffffff; } +[data-theme='luna-teal'] .theme-accordion-open .theme-accordion-header { background: #316ac5; color: #ffffff; } +[data-theme='luna-teal'] .theme-accordion-open .theme-accordion-chevron { color: #ffffff; } + +/* ── Progress bar: XP green ── */ +[data-theme='luna-teal'] .progress-bar-track { + background: #aca899; + border-radius: 2px; + box-shadow: inset 0 1px 2px rgba(0,0,0,0.25); +} +[data-theme='luna-teal'] .progress-bar-fill { + background: linear-gradient(180deg, #52cc3c 0%, #3c9d29 50%, #2e8020 100%); + border-radius: 2px; +} + +/* ── Scrollbar: XP 16px system style ── */ +[data-theme='luna-teal'] ::-webkit-scrollbar { width: 16px; height: 16px; } +[data-theme='luna-teal'] ::-webkit-scrollbar-track { background: #ece9d8; border-left: 1px solid #aca899; } +[data-theme='luna-teal'] ::-webkit-scrollbar-thumb { + background: linear-gradient(to right, #c8c4b8 0%, #e0ddd0 40%, #c0bbb4 100%); + border: 1px solid #888480; + box-shadow: inset 1px 1px 0 #ffffff, inset -1px -1px 0 #888480; + border-radius: 2px; +} +[data-theme='luna-teal'] ::-webkit-scrollbar-button { + background: linear-gradient(180deg, #f0ede0 0%, #d8d4c4 100%); + border: 1px solid #888480; + box-shadow: inset 1px 1px 0 #ffffff, inset -1px -1px 0 #888480; +} + +/* ── Glass / dropdowns: solid XP dialog style ── */ +[data-theme='luna-teal'] .glass { + background: #ffffff !important; + backdrop-filter: none !important; + border: 1px solid #aca899 !important; + box-shadow: 2px 2px 8px rgba(0,0,0,0.28) !important; + border-radius: 4px !important; +} +[data-theme='luna-teal'] .glass [style*="var(--bg-hover)"] { + background: #316ac5 !important; + border-radius: 0 !important; + color: #ffffff !important; +} +[data-theme='luna-teal'] .glass [style*="var(--text-primary)"] { color: #000000 !important; } +[data-theme='luna-teal'] .glass [style*="var(--text-secondary)"] { color: #333333 !important; } +[data-theme='luna-teal'] .glass [style*="var(--text-muted)"] { color: #555555 !important; } + +/* ── Hover / selection: XP classic blue ── */ +[data-theme='luna-teal'] .queue-tab-btn:hover { background: #316ac5; color: #ffffff; } +[data-theme='luna-teal'] .settings-tab:hover { background: #316ac5; color: #ffffff; } +[data-theme='luna-teal'] .settings-tab.active { background: #316ac5; color: #ffffff; } +[data-theme='luna-teal'] .custom-select-trigger:hover { background: #316ac5; color: #ffffff; } +[data-theme='luna-teal'] .custom-select-option:hover { background: #316ac5 !important; color: #ffffff !important; } +[data-theme='luna-teal'] .artist-ext-link:hover { background: #316ac5; color: #ffffff !important; } +[data-theme='luna-teal'] .np-action-btn:hover { background: #316ac5; color: #ffffff; } +[data-theme='luna-teal'] .np-queue-item:hover, +[data-theme='luna-teal'] .np-queue-item.context-active { background: #316ac5; color: #ffffff; } +[data-theme='luna-teal'] .track-row:hover, +[data-theme='luna-teal'] .track-row.context-active { background: #316ac5 !important; } +[data-theme='luna-teal'] .track-row:hover *, +[data-theme='luna-teal'] .track-row.context-active * { color: #ffffff !important; } +[data-theme='luna-teal'] .artist-row:hover { background: #316ac5; color: #ffffff; } +[data-theme='luna-teal'] .playlist-row:hover { background: #316ac5; } +[data-theme='luna-teal'] .playlist-row:hover, +[data-theme='luna-teal'] .playlist-row:hover * { color: #ffffff; } +[data-theme='luna-teal'] .queue-item:hover, +[data-theme='luna-teal'] .queue-item.context-active { background: #316ac5 !important; } +[data-theme='luna-teal'] .queue-item:hover .queue-item-title, +[data-theme='luna-teal'] .queue-item:hover .queue-item-artist, +[data-theme='luna-teal'] .queue-item:hover .queue-item-duration, +[data-theme='luna-teal'] .queue-item.context-active .queue-item-title, +[data-theme='luna-teal'] .queue-item.context-active .queue-item-artist, +[data-theme='luna-teal'] .queue-item.context-active .queue-item-duration { color: #ffffff; } + +/* ── Active queue / now-playing items ── */ [data-theme='luna-teal'] .queue-item.active { - background: rgba(0, 55, 180, 0.10); + background: rgba(49, 106, 197, 0.12); color: #0041b8; } [data-theme='luna-teal'] .queue-item.active .queue-item-artist, [data-theme='luna-teal'] .queue-item.active .queue-item-duration { color: #0055e5; - opacity: 0.8; + opacity: 0.85; } - -/* NowPlaying page active track title */ -[data-theme='luna-teal'] .np-queue-item-active { - color: #0041b8; -} -[data-theme='luna-teal'] .np-queue-item.active { - background: rgba(0, 55, 180, 0.08); -} - -/* NowPlaying album tracklist active */ +[data-theme='luna-teal'] .np-queue-item-active { color: #0041b8; } +[data-theme='luna-teal'] .np-queue-item.active { background: rgba(49, 106, 197, 0.10); } [data-theme='luna-teal'] .np-album-track.active .np-album-track-title, -[data-theme='luna-teal'] .np-album-track.active .np-album-track-num { - color: #0041b8; -} +[data-theme='luna-teal'] .np-album-track.active .np-album-track-num { color: #0041b8; } /* ─── macOS Ventura Light ─── */ [data-theme='cupertino-light'] { @@ -3897,7 +4511,7 @@ input[type="range"]:hover::-webkit-slider-thumb { --accent-glow: rgba(0, 113, 227, 0.30); --text-primary: #1c1c1e; --text-secondary:#3a3a3c; - --text-muted: #8e8e93; + --text-muted: #6d6d72; --border: #d1d1d6; --border-subtle: #e5e5ea; --positive: #34c759; @@ -4249,200 +4863,790 @@ input[type="range"]:hover::-webkit-slider-thumb { Middle Earth — Epic Fantasy / Cinematic ───────────────────────────────────────────────────────────── */ +/* ───────────────────────────────────────────────────────────── + Middle-Earth — The One Ring Inscription Glow + ───────────────────────────────────────────────────────────── */ + +/* Breathing glow of the Ring — applied to player-track-name. + Like the inscription heating up in Bag End's fireplace. */ +@keyframes ring-inscription-glow { + 0%, 100% { + text-shadow: + 0 0 8px rgba(240, 200, 60, 0.70), + 0 0 18px rgba(200, 140, 20, 0.38), + 0 0 36px rgba(160, 100, 10, 0.15); + } + 50% { + text-shadow: + 0 0 12px rgba(240, 200, 60, 0.95), + 0 0 28px rgba(200, 140, 20, 0.65), + 0 0 52px rgba(160, 100, 10, 0.32), + 0 0 80px rgba(100, 60, 5, 0.14); + } +} + +/* ─── Middle-Earth — Red Book of Westmarch ─── */ [data-theme='middle-earth'] { color-scheme: light; - --color-star-active: #4a3728; - --color-star-inactive: #6e5a42; + --color-star-active: #8c6800; + --color-star-inactive: #b8985a; --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%234a3728%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); - --ctp-crust: #2a1d15; - --ctp-mantle: #3b2a1e; - --ctp-base: #f4e4bc; - --ctp-surface0: #ebd5a3; - --ctp-surface1: #dec48d; - --ctp-surface2: #cbb07c; - --ctp-overlay0: #8c7356; - --ctp-overlay1: #6e5a42; - --ctp-overlay2: #4a3728; - --ctp-text: #2a1d15; - --ctp-subtext1: #4a3728; - --ctp-subtext0: #6e5a42; - --ctp-mauve: #d4af37; - --ctp-lavender: #e5c158; - --ctp-green: #4a7040; - --ctp-teal: #3e5a5a; - --ctp-sky: #78a2c0; - --ctp-blue: #4a6b8a; - --ctp-sapphire: #2a4b6a; - --ctp-pink: #b05a7e; - --ctp-flamingo: #c07a7a; - --ctp-rosewater:#e5caca; - --ctp-yellow: #d4af37; - --ctp-peach: #c08a4a; - --ctp-maroon: #6a2a2a; - --ctp-red: #8a2a2a; + /* ── Palette ── */ + /* Warm — Shire, Rohan, Dwarvish gold */ + --ctp-crust: #1a1008; + --ctp-mantle: #281808; + --ctp-base: #f0e0b0; + --ctp-surface0: #e8d498; + --ctp-surface1: #dcc482; + --ctp-surface2: #ccb06e; + --ctp-overlay0: #8a7250; + --ctp-overlay1: #6a5438; + --ctp-overlay2: #4a3828; + --ctp-text: #1e1408; + --ctp-subtext1: #3e2c1a; + --ctp-subtext0: #5e4a30; + /* Gold of the One Ring */ + --ctp-mauve: #d4a820; + --ctp-lavender: #f0d060; + --ctp-yellow: #f8e880; + --ctp-peach: #b88010; + /* Shire green, Rivendell silver, Elvish blue */ + --ctp-green: #4a7038; + --ctp-teal: #3a6858; + --ctp-sky: #7898b8; + --ctp-blue: #486888; + --ctp-sapphire: #2a4868; + /* Mordor / danger */ + --ctp-red: #8a2820; + --ctp-maroon: #5a1818; + --ctp-flamingo: #b05838; + --ctp-pink: #904868; + --ctp-rosewater: #e8c8a8; - --bg-app: #f4e4bc; - --bg-sidebar: #3b2a1e; - --bg-card: #ebd5a3; - --bg-hover: rgba(74, 55, 40, 0.1); - --bg-player: #2a1d15; - --bg-glass: rgba(244, 228, 188, 0.85); - - --accent: #d4af37; - --accent-dim: rgba(212, 175, 55, 0.2); - --accent-glow: rgba(212, 175, 55, 0.4); - - --text-primary: #2a1d15; - --text-secondary:#4a3728; - --text-muted: #8c7356; - - --border: #cbb07c; - --border-subtle: #dec48d; - - --radius-sm: 4px; - --radius-md: 8px; - --radius-lg: 12px; + /* ── Semantic tokens ── */ + --bg-app: #f0e0b0; + --bg-sidebar: #241a0e; /* Bag End — old oak wood, hearthlit */ + --bg-card: #f4e8c0; + --bg-hover: rgba(180, 130, 20, 0.12); + --bg-player: #1a1008; /* Orodruin / the forge-dark */ + --bg-glass: rgba(244, 232, 192, 0.92); + --accent: #d4a820; + --accent-dim: rgba(212, 168, 32, 0.16); + --accent-glow: rgba(212, 168, 32, 0.45); + --volume-accent: #d4a820; + --text-primary: #1e1408; + --text-secondary:#3e2c1a; + --text-muted: #6a5230; + --border: rgba(180, 140, 50, 0.38); + --border-subtle: rgba(180, 140, 50, 0.18); + --positive: #4a7038; + --warning: #c88a10; + --danger: #8a2820; + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; } -[data-theme='middle-earth'] .player-track-name { - color: #f4e4bc; - font-family: Georgia, 'Times New Roman', serif; - letter-spacing: 0.5px; +/* ── App shell: parchment map of Middle-Earth ── */ +/* Three-layer: warm gold illumination top-right (candlelight), + ember glow bottom-left (hearth), radial vignette darkening corners */ +[data-theme='middle-earth'] .app-shell { + background: + radial-gradient(ellipse at center, transparent 50%, rgba(60, 38, 18, 0.12) 100%), + radial-gradient(ellipse at 78% 18%, rgba(220, 180, 60, 0.08) 0%, transparent 50%), + radial-gradient(ellipse at 15% 88%, rgba(180, 110, 20, 0.07) 0%, transparent 45%), + linear-gradient(155deg, #f4e8c0 0%, #eed8a0 50%, #e8d098 100%); } -[data-theme='middle-earth'] .player-track-artist { color: #d4af37; } -[data-theme='middle-earth'] .player-time { color: #dec48d; } -[data-theme='middle-earth'] .sidebar { - border-right: 1px solid rgba(212, 175, 55, 0.3); -} -[data-theme='middle-earth'] .nav-link { color: #dec48d; } -[data-theme='middle-earth'] .nav-link:hover { background: rgba(212, 175, 55, 0.1); color: #f4e4bc; } -[data-theme='middle-earth'] .nav-link.active { color: #d4af37; background: rgba(212, 175, 55, 0.15); } -[data-theme='middle-earth'] .nav-link.active::before { background-color: #d4af37; box-shadow: 0 0 10px rgba(212, 175, 55, 0.6); } - -[data-theme='middle-earth'] .btn-primary { - background: #d4af37; - color: #2a1d15; - font-weight: 700; - box-shadow: 0 0 15px rgba(212, 175, 55, 0.3); -} -[data-theme='middle-earth'] .player-btn { color: #dec48d; } -[data-theme='middle-earth'] .player-btn:hover { color: #d4af37; } -[data-theme='middle-earth'] .player-btn-primary { color: #2a1d15; } -[data-theme='middle-earth'] .player-btn-primary:hover { color: #2a1d15; } - -/* Queue + Lyrics laufen auf dunklem Sidebar-Hintergrund — helle Textfarben nötig */ -[data-theme='middle-earth'] .queue-current-info h3 { color: #f4e4bc; } -[data-theme='middle-earth'] .queue-current-sub { color: #d4af37; } -[data-theme='middle-earth'] .queue-item-title { color: #f4e4bc; } -[data-theme='middle-earth'] .queue-item-artist { color: #cbb07c; } -[data-theme='middle-earth'] .queue-tab-btn { color: #cbb07c; } -[data-theme='middle-earth'] .queue-tab-btn:hover { color: #f4e4bc; background: rgba(212, 175, 55, 0.1); } -[data-theme='middle-earth'] .queue-tab-btn.active { color: #d4af37; } -[data-theme='middle-earth'] .lyrics-line { color: #8c7356; } -[data-theme='middle-earth'] .lyrics-line.active { color: #f4e4bc; } -[data-theme='middle-earth'] .lyrics-plain-line { color: #cbb07c; } -[data-theme='middle-earth'] .lyrics-status { color: #8c7356; } - -/* Dezentes Pergament-Noise über der App */ +/* Parchment grain overlay — the texture of the Red Book's pages */ [data-theme='middle-earth'] .app-shell::after { content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 9999; - opacity: 0.03; - background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); + opacity: 0.045; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-size: 200px 200px; } +/* ── Sidebar: Bag End oak paneling ── */ +/* Old Shire craftsmanship — vertical wood grain, warm hearthlight from right edge */ +[data-theme='middle-earth'] .sidebar { + background-color: #221608; + background-image: + repeating-linear-gradient( + 90deg, + rgba(255, 220, 120, 0.04) 0px, rgba(255, 220, 120, 0.04) 1px, + transparent 1px, transparent 14px + ), + linear-gradient(180deg, #261a0a 0%, #1e1408 55%, #241c0e 100%); + border-right: 2px solid rgba(200, 160, 40, 0.28); + box-shadow: + inset -3px 0 12px rgba(200, 140, 30, 0.10), + 2px 0 8px rgba(0, 0, 0, 0.50); +} + +/* Sidebar text: warm candlelight on dark oak */ +[data-theme='middle-earth'] .nav-link { color: #c8a060; } +[data-theme='middle-earth'] .nav-link:hover { + background: rgba(212, 168, 32, 0.12); + color: #f0d880; +} +[data-theme='middle-earth'] .nav-link.active { + background: linear-gradient(90deg, rgba(212,168,32,0.22) 0%, transparent 100%); + color: #f0d060; + border-left: 2px solid #d4a820; + box-shadow: inset 4px 0 18px rgba(212,168,32,0.12); +} +[data-theme='middle-earth'] .nav-link.active::before { + background: #d4a820; + box-shadow: 0 0 10px rgba(212,168,32,0.80), 0 0 20px rgba(212,168,32,0.40); +} +[data-theme='middle-earth'] .nav-link.active svg { color: #d4a820; } +[data-theme='middle-earth'] .nav-section-label { + color: #6a5030; + text-transform: uppercase; + letter-spacing: 0.14em; + font-size: 0.67em; + font-family: Georgia, 'Book Antiqua', serif; +} + +/* ── Player bar: Sammath Naur — the fires of Orodruin ── */ +/* Near-black volcanic dark, sealed with the gold of the Ring */ +[data-theme='middle-earth'] .player-bar { + background: linear-gradient(180deg, #1c1208 0%, #100c04 100%); + border-top: 2px solid rgba(212, 168, 32, 0.58); + box-shadow: + inset 0 1px 0 rgba(240, 200, 60, 0.22), + 0 -8px 40px rgba(180, 120, 20, 0.20), + 0 -20px 70px rgba(160, 100, 15, 0.09); +} + +/* Track name: THE ONE RING INSCRIPTION — breathing gold fire */ +[data-theme='middle-earth'] .player-track-name { + color: #f0d060; + font-family: Georgia, 'Book Antiqua', 'Palatino Linotype', Palatino, serif; + letter-spacing: 0.06em; + font-weight: 600; + animation: ring-inscription-glow 5s ease-in-out infinite; +} + +/* Artist: Elvish silver on the dark forge */ +[data-theme='middle-earth'] .player-track-artist { + color: #b8985a; + font-family: Georgia, 'Book Antiqua', serif; + letter-spacing: 0.03em; + opacity: 1; +} +[data-theme='middle-earth'] .player-time { color: #7a5c30; } + +/* ── Transport buttons: Mithril-crafted, hearthlit ── */ +[data-theme='middle-earth'] .player-btn, +[data-theme='middle-earth'] .player-btn-primary { + background: linear-gradient(180deg, #2e2010 0%, #1e1408 100%); + color: #d4a820; + border: 1px solid rgba(212, 168, 32, 0.38); + border-radius: 50%; + box-shadow: inset 0 1px 0 rgba(240,200,60,0.10), 0 2px 6px rgba(0,0,0,0.60); +} +[data-theme='middle-earth'] .player-btn:hover, +[data-theme='middle-earth'] .player-btn-primary:hover { + background: rgba(212, 168, 32, 0.14); + border-color: #d4a820; + color: #f0d060; + box-shadow: + 0 0 16px rgba(212, 168, 32, 0.48), + inset 0 0 8px rgba(200, 140, 20, 0.10); +} + +/* ── Regular buttons: parchment scroll / carved Shire wood ── */ +[data-theme='middle-earth'] .btn, +[data-theme='middle-earth'] .btn-surface, +[data-theme='middle-earth'] .btn-ghost { + background: linear-gradient(180deg, #f8f0d0 0%, #e8d898 50%, #dece88 100%); + color: #2a1c0e; + border: 1px solid rgba(160, 120, 40, 0.48); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.65), + inset 1px 0 0 rgba(255, 255, 255, 0.45), + 0 1px 3px rgba(80, 50, 10, 0.22); + border-radius: 6px; + font-family: Georgia, 'Book Antiqua', serif; +} +[data-theme='middle-earth'] .btn:hover, +[data-theme='middle-earth'] .btn-surface:hover, +[data-theme='middle-earth'] .btn-ghost:hover { + background: linear-gradient(180deg, #fffff0 0%, #f0e8a8 50%, #e8d890 100%); + border-color: rgba(180, 140, 40, 0.70); + box-shadow: + inset 0 1px 0 rgba(255,255,255,0.80), + 0 1px 4px rgba(80,50,10,0.20), + 0 0 8px rgba(212,168,32,0.18); +} + +/* ── Primary button: One Ring gold — the most precious craftsmanship ── */ +[data-theme='middle-earth'] .btn-primary { + background: linear-gradient(180deg, #e8bc28 0%, #c8940c 50%, #aa7808 100%); + color: #1a1008; + border: 1px solid #c89818; + box-shadow: + inset 0 1px 0 rgba(255, 240, 100, 0.45), + 0 0 16px rgba(212, 168, 32, 0.42), + 0 2px 4px rgba(80, 50, 0, 0.30); + border-radius: 6px; + font-weight: 700; + font-family: Georgia, 'Book Antiqua', serif; +} +[data-theme='middle-earth'] .btn-primary:hover { + background: linear-gradient(180deg, #f8cc38 0%, #d8a018 50%, #bc8810 100%); + box-shadow: + inset 0 1px 0 rgba(255, 240, 100, 0.55), + 0 0 24px rgba(212, 168, 32, 0.60), + 0 2px 6px rgba(80, 50, 0, 0.28); +} + +/* ── Hero / album-card play buttons: solid One Ring gold ── */ +/* These appear on dark album-art overlays — must be fully opaque and prominent */ +[data-theme='middle-earth'] .hero-play-btn, +[data-theme='middle-earth'] .album-card-details-btn { + background: linear-gradient(180deg, #e8bc28 0%, #c8940c 50%, #aa7808 100%); + color: #1a1008; + border: 1px solid #c89818; + font-family: Georgia, 'Book Antiqua', serif; + font-weight: 700; + box-shadow: + inset 0 1px 0 rgba(255, 240, 100, 0.45), + 0 0 14px rgba(212, 168, 32, 0.38), + 0 2px 6px rgba(0, 0, 0, 0.40); +} +[data-theme='middle-earth'] .hero-play-btn:hover, +[data-theme='middle-earth'] .album-card-details-btn:hover { + background: linear-gradient(180deg, #f8cc38 0%, #d8a018 50%, #bc8810 100%); + box-shadow: + inset 0 1px 0 rgba(255, 240, 100, 0.55), + 0 0 22px rgba(212, 168, 32, 0.58), + 0 2px 8px rgba(0, 0, 0, 0.35); + filter: none; +} + +/* ── Queue round buttons ── */ +[data-theme='middle-earth'] .queue-round-btn { + background: linear-gradient(180deg, #f0e4b0 0%, #dece88 100%); + color: #4a3828; + border: 1px solid rgba(150, 112, 38, 0.40); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.55), 0 1px 2px rgba(80,50,10,0.18); +} +[data-theme='middle-earth'] .queue-round-btn:hover:not(:disabled):not(.active) { + background: linear-gradient(180deg, #fffff0 0%, #f0e4a0 100%); + border-color: rgba(180,140,40,0.60); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.70), 0 0 8px rgba(212,168,32,0.22); + color: #2a1c0e; +} +[data-theme='middle-earth'] .queue-round-btn.active { + background: linear-gradient(180deg, #e8bc28 0%, #c8940c 100%); + color: #1a1008; + border-color: #c89818; + box-shadow: 0 0 14px rgba(212,168,32,0.45), inset 0 1px 0 rgba(255,240,100,0.35); +} + +/* ── Cards: leaves of the Red Book — layered parchment ── */ +[data-theme='middle-earth'] .card { + background: linear-gradient(180deg, #f8f0d0 0%, #f0e4b8 100%); + border: 1px solid rgba(168, 130, 48, 0.32); + border-radius: 10px; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.70), + 0 2px 8px rgba(80, 50, 10, 0.16), + 0 4px 16px rgba(60, 38, 10, 0.08); +} + +/* ── Content header: illuminated manuscript chapter heading ── */ +/* The gold ruled border at the bottom is the decorative line + that separates the chapter title from the body of the text */ +[data-theme='middle-earth'] .content-header { + position: relative; + background: linear-gradient(180deg, #f8f0d0 0%, #f0e4b8 100%); + border-bottom: 2px solid rgba(200, 158, 38, 0.45); + box-shadow: 0 3px 14px rgba(120, 80, 15, 0.12); +} +/* The gold rule — fades at edges like gold leaf on vellum */ +[data-theme='middle-earth'] .content-header::after { + content: ''; + position: absolute; + bottom: -3px; + left: 8%; + right: 8%; + height: 1px; + background: linear-gradient( + 90deg, transparent 0%, rgba(212,168,32,0.65) 20%, + rgba(240,210,60,0.85) 50%, rgba(212,168,32,0.65) 80%, transparent 100% + ); + pointer-events: none; +} + +/* Connection indicators */ +[data-theme='middle-earth'] .connection-type, +[data-theme='middle-earth'] .connection-server { color: #5a4828; } + +/* ── Theme accordion: old book binding ── */ +[data-theme='middle-earth'] .theme-accordion-header:hover { + background: rgba(212, 168, 32, 0.12); + color: #6a4820; +} +[data-theme='middle-earth'] .theme-accordion-open .theme-accordion-header { + background: rgba(212, 168, 32, 0.16); + color: #5a3818; +} +[data-theme='middle-earth'] .theme-accordion-open .theme-accordion-chevron { color: #c89818; } + +/* ── Progress bar: THE ROAD GOES EVER ON ── */ +/* From darkness into gold light — the long journey from the Shire to Mount Doom */ +[data-theme='middle-earth'] .progress-bar-track { + background: #d8c880; + border: 1px solid rgba(160, 120, 38, 0.40); + border-radius: 4px; + box-shadow: inset 0 1px 3px rgba(80,50,10,0.20); +} +[data-theme='middle-earth'] .progress-bar-fill { + background: linear-gradient(90deg, + #5a3802 0%, + #9a6808 25%, + #c89018 55%, + #d4a820 75%, + #f0d060 90%, + #fff0a0 100% + ); + border-radius: 4px; + box-shadow: 0 0 10px rgba(212,168,32,0.65), 0 0 3px rgba(255,230,100,0.55); +} + +/* ── Scrollbar: aged oak library shelves ── */ +[data-theme='middle-earth'] ::-webkit-scrollbar { width: 8px; height: 8px; } +[data-theme='middle-earth'] ::-webkit-scrollbar-track { + background: #dcc880; + border-radius: 4px; +} +[data-theme='middle-earth'] ::-webkit-scrollbar-thumb { + background: linear-gradient(to right, #6e4a28 0%, #9a7040 40%, #6a4420 100%); + border: 1px solid rgba(180, 130, 40, 0.45); + border-radius: 4px; + box-shadow: inset 0 1px 0 rgba(255,220,100,0.25); +} +[data-theme='middle-earth'] ::-webkit-scrollbar-thumb:hover { + background: linear-gradient(to right, #8a6038 0%, #b88a50 40%, #8a5a30 100%); + box-shadow: inset 0 1px 0 rgba(255,220,100,0.35), 0 0 5px rgba(212,168,32,0.28); +} + +/* ── Glass / dropdowns: a scroll held to the light ── */ +[data-theme='middle-earth'] .glass { + background: rgba(248, 238, 198, 0.96) !important; + backdrop-filter: none !important; + border: 1px solid rgba(180, 140, 48, 0.45) !important; + box-shadow: + inset 0 1px 0 rgba(255,255,255,0.70), + 0 4px 20px rgba(80, 50, 10, 0.20), + 0 8px 30px rgba(60, 38, 10, 0.10) !important; + border-radius: 10px !important; +} +[data-theme='middle-earth'] .glass [style*="var(--bg-hover)"] { + background: rgba(212, 168, 32, 0.12) !important; + border-radius: 6px !important; +} +[data-theme='middle-earth'] .glass [style*="var(--text-primary)"] { color: #1e1408 !important; } +[data-theme='middle-earth'] .glass [style*="var(--text-secondary)"] { color: #3e2c1a !important; } +[data-theme='middle-earth'] .glass [style*="var(--text-muted)"] { color: #8a7250 !important; } + +/* ── Hover / selection: candlelight — warm gold glow ── */ +[data-theme='middle-earth'] .settings-tab:hover { background: rgba(212,168,32,0.12); color: #2a1c0e; } +[data-theme='middle-earth'] .settings-tab.active { + background: rgba(212,168,32,0.18); + color: #2a1c0e; + box-shadow: inset 2px 0 0 #d4a820; +} +[data-theme='middle-earth'] .custom-select-trigger:hover { background: rgba(212,168,32,0.10); } +[data-theme='middle-earth'] .custom-select-option:hover { + background: rgba(212,168,32,0.15) !important; + color: #1e1408 !important; +} +[data-theme='middle-earth'] .artist-ext-link:hover { + background: rgba(212,168,32,0.12); + color: #2a1c0e !important; + border-color: rgba(180,140,40,0.55) !important; +} +[data-theme='middle-earth'] .np-action-btn:hover { background: rgba(212,168,32,0.10); } +[data-theme='middle-earth'] .np-queue-item:hover, +[data-theme='middle-earth'] .np-queue-item.context-active { + background: rgba(212,168,32,0.13); + box-shadow: inset 2px 0 0 #d4a820; +} +[data-theme='middle-earth'] .track-row:hover, +[data-theme='middle-earth'] .track-row.context-active { + background: rgba(212,168,32,0.10) !important; + box-shadow: inset 2px 0 0 #d4a820; +} +[data-theme='middle-earth'] .artist-row:hover { + background: rgba(212,168,32,0.10); + box-shadow: inset 2px 0 0 #d4a820; +} +[data-theme='middle-earth'] .playlist-row:hover { + background: rgba(212,168,32,0.10); + box-shadow: inset 2px 0 0 #d4a820; +} +[data-theme='middle-earth'] .queue-item:hover, +[data-theme='middle-earth'] .queue-item.context-active { + background: rgba(212,168,32,0.12) !important; + box-shadow: inset 2px 0 0 #d4a820; +} + +/* ── Active queue / now-playing: the bearer of the Ring ── */ +[data-theme='middle-earth'] .queue-item.active { + background: rgba(212, 168, 32, 0.10); + box-shadow: inset 2px 0 0 #d4a820; +} +[data-theme='middle-earth'] .queue-item.active .queue-item-title { color: #2a1c0e; } +[data-theme='middle-earth'] .queue-item.active .queue-item-artist, +[data-theme='middle-earth'] .queue-item.active .queue-item-duration { color: #8a6030; } +[data-theme='middle-earth'] .np-queue-item-active { + color: #2a1c0e; + text-shadow: 0 0 6px rgba(212,168,32,0.40); +} +[data-theme='middle-earth'] .np-queue-item.active { background: rgba(212,168,32,0.10); } +[data-theme='middle-earth'] .np-album-track.active .np-album-track-title, +[data-theme='middle-earth'] .np-album-track.active .np-album-track-num { + color: #2a1c0e; + text-shadow: 0 0 6px rgba(212,168,32,0.38); +} + +/* ── Queue + Lyrics on dark sidebar ── */ +[data-theme='middle-earth'] .queue-current-info h3 { color: #f0d880; } +[data-theme='middle-earth'] .queue-current-sub { color: #d4a820; } +[data-theme='middle-earth'] .queue-item-title { color: #f0d880; } +[data-theme='middle-earth'] .queue-item-artist { color: #c8a060; } +[data-theme='middle-earth'] .queue-item-duration { color: #8a6838; } +[data-theme='middle-earth'] .queue-tab-btn { color: #c8a060; font-family: Georgia, serif; } +[data-theme='middle-earth'] .queue-tab-btn:hover { color: #f0d880; background: rgba(212,168,32,0.10); } +[data-theme='middle-earth'] .queue-tab-btn.active { color: #d4a820; } +[data-theme='middle-earth'] .lyrics-line { color: #8a6840; } +[data-theme='middle-earth'] .lyrics-line.active { color: #f0d880; text-shadow: 0 0 6px rgba(212,168,32,0.35); } +[data-theme='middle-earth'] .lyrics-plain-line { color: #c8a060; } +[data-theme='middle-earth'] .lyrics-status { color: #7a5a30; } + /* ───────────────────────────────────────────────────────────── Morpheus — Matrix Style ───────────────────────────────────────────────────────────── */ +/* ─── The Matrix — Morpheus ─── */ [data-theme='morpheus'] { color-scheme: dark; - --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%2300ff41%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); - --ctp-crust: #000000; - --ctp-mantle: #050505; - --ctp-base: #0a0a0a; - --ctp-surface0: #0d1a0d; - --ctp-surface1: #1a2e1a; - --ctp-surface2: #243d24; - --ctp-overlay0: #003b00; - --ctp-overlay1: #008f11; - --ctp-overlay2: #00ff41; - --ctp-text: #00ff41; - --ctp-subtext1: #00cc33; - --ctp-subtext0: #008f11; - --ctp-mauve: #00ff41; - --ctp-lavender: #adff2f; - --ctp-green: #00ff41; - --ctp-teal: #20c20e; - --ctp-sky: #00ff41; - --ctp-blue: #00ff41; - --ctp-sapphire: #008f11; - --ctp-pink: #003b00; - --ctp-flamingo: #003b00; - --ctp-rosewater:#d2ff00; - --ctp-yellow: #adff2f; - --ctp-peach: #00ff41; - --ctp-maroon: #003b00; - --ctp-red: #ff0000; + /* ── Palette ── */ + --ctp-crust: #000000; + --ctp-mantle: #020502; + --ctp-base: #050905; + --ctp-surface0: #0a120a; + --ctp-surface1: #0f1c0f; + --ctp-surface2: #162416; + --ctp-overlay0: #003b00; + --ctp-overlay1: #008f11; + --ctp-overlay2: #00cc33; + --ctp-text: #00ff41; + --ctp-subtext1: #00cc33; + --ctp-subtext0: #008f11; + --ctp-mauve: #00ff41; + --ctp-lavender: #adff2f; + --ctp-green: #00ff41; + --ctp-teal: #20c20e; + --ctp-sky: #00ff41; + --ctp-blue: #00ff41; + --ctp-sapphire: #008f11; + --ctp-pink: #003b00; + --ctp-flamingo: #003b00; + --ctp-rosewater: #d2ff00; + --ctp-yellow: #adff2f; + --ctp-peach: #00ff41; + --ctp-maroon: #003b00; + --ctp-red: #ff0033; - --bg-app: #0a0a0a; + /* ── Semantic tokens ── */ + --bg-app: #050905; --bg-sidebar: #000000; - --bg-card: #0d1a0d; - --bg-hover: rgba(0, 255, 65, 0.1); + --bg-card: #0a120a; + --bg-hover: rgba(0, 255, 65, 0.10); --bg-player: #000000; - --bg-glass: rgba(0, 0, 0, 0.85); - + --bg-glass: rgba(0, 8, 0, 0.96); --accent: #00ff41; - --accent-dim: rgba(0, 255, 65, 0.15); - --accent-glow: rgba(0, 255, 65, 0.4); - + --accent-dim: rgba(0, 255, 65, 0.12); + --accent-glow: rgba(0, 255, 65, 0.45); + --volume-accent: #00ff41; --text-primary: #00ff41; --text-secondary:#00cc33; - --text-muted: #1a7a2a; - + --text-muted: #22cc44; --border: #003b00; --border-subtle: #001a00; - - --positive: #00ff41; - --warning: #adff2f; - --danger: #ff0033; - - --radius-sm: 0px; - --radius-md: 2px; - --radius-lg: 4px; + --positive: #00ff41; + --warning: #adff2f; + --danger: #ff0033; + --radius-sm: 0px; + --radius-md: 0px; + --radius-lg: 2px; } +/* ── App shell: solid dark base (scanlines moved to sidebar for perf) ── */ +[data-theme='morpheus'] .app-shell { + background-color: #050905; +} + +/* ── Sidebar: black with code-column ghost pattern ── */ +[data-theme='morpheus'] .sidebar { + background-color: #000000; + background-image: repeating-linear-gradient( + 90deg, transparent 0px, transparent 19px, + rgba(0, 255, 65, 0.03) 19px, rgba(0, 255, 65, 0.03) 20px + ); + border-right: 1px solid #003b00; +} + +/* Nav links */ +[data-theme='morpheus'] .nav-link { color: #00cc33; } +[data-theme='morpheus'] .nav-link:hover { + background: rgba(0, 255, 65, 0.08); + color: #00ff41; + text-shadow: 0 0 8px rgba(0, 255, 65, 0.50); +} +[data-theme='morpheus'] .nav-link.active { + background: rgba(0, 255, 65, 0.10); + color: #00ff41; + text-shadow: 0 0 6px rgba(0, 255, 65, 0.45); +} +[data-theme='morpheus'] .nav-link.active::before { + background: #00ff41; + box-shadow: 0 0 8px rgba(0, 255, 65, 0.70); +} +[data-theme='morpheus'] .nav-section-label { color: #003b00; } + +/* ── Player bar: black glass with phosphor glow ── */ +[data-theme='morpheus'] .player-bar { + background: #000000; + border-top: 1px solid rgba(0, 255, 65, 0.35); + box-shadow: + inset 0 1px 0 rgba(0, 255, 65, 0.12), + 0 -4px 24px rgba(0, 255, 65, 0.06); +} + +/* Track info: phosphor CRT glow */ [data-theme='morpheus'] .player-track-name { - font-family: 'JetBrains Mono', 'Fira Code', monospace; - text-shadow: 0 0 8px rgba(0, 255, 65, 0.6); - letter-spacing: 0.05em; + font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace; + color: #00ff41; + text-shadow: 0 0 10px rgba(0, 255, 65, 0.70), 0 0 20px rgba(0, 255, 65, 0.30); + letter-spacing: 0.04em; } [data-theme='morpheus'] .player-track-artist, [data-theme='morpheus'] .player-time { - font-family: 'JetBrains Mono', monospace; - opacity: 0.8; + font-family: 'JetBrains Mono', 'Courier New', monospace; + color: #00cc33; + opacity: 0.85; } -[data-theme='morpheus'] .nav-link.active { - background: linear-gradient(90deg, rgba(0, 255, 65, 0.1) 0%, transparent 100%); - text-shadow: 0 0 5px rgba(0, 255, 65, 0.4); + +/* ── Transport buttons: terminal command style ── */ +[data-theme='morpheus'] .player-btn, +[data-theme='morpheus'] .player-btn-primary { + background: #000000; + color: #00ff41; + border: 1px solid #003b00; + border-radius: 2px; + box-shadow: inset 0 0 6px rgba(0, 255, 65, 0.05); } -[data-theme='morpheus'] .nav-link.active::before { - box-shadow: 0 0 8px rgba(0, 255, 65, 0.6); +[data-theme='morpheus'] .player-btn:hover, +[data-theme='morpheus'] .player-btn-primary:hover { + background: rgba(0, 255, 65, 0.08); + border-color: #00ff41; + box-shadow: + 0 0 12px rgba(0, 255, 65, 0.35), + inset 0 0 8px rgba(0, 255, 65, 0.08); + color: #00ff41; } -[data-theme='morpheus'] .player-bar { - box-shadow: 0 -5px 15px rgba(0, 255, 65, 0.05); + +/* ── All buttons: terminal style ── */ +[data-theme='morpheus'] .btn, +[data-theme='morpheus'] .btn-surface, +[data-theme='morpheus'] .btn-ghost, +[data-theme='morpheus'] .btn-primary, +[data-theme='morpheus'] .hero-play-btn, +[data-theme='morpheus'] .album-card-details-btn, +[data-theme='morpheus'] .queue-round-btn { + background: #000000; + color: #00ff41; + border: 1px solid #003b00; + border-radius: 0; + font-family: 'JetBrains Mono', 'Courier New', monospace; + box-shadow: none; } -[data-theme='morpheus'] .sidebar { - border-right: 1px solid #003b00; +[data-theme='morpheus'] .btn:hover, +[data-theme='morpheus'] .btn-surface:hover, +[data-theme='morpheus'] .btn-ghost:hover, +[data-theme='morpheus'] .btn-primary:hover, +[data-theme='morpheus'] .hero-play-btn:hover, +[data-theme='morpheus'] .album-card-details-btn:hover { + background: rgba(0, 255, 65, 0.08); + border-color: #00ff41; + color: #00ff41; + box-shadow: 0 0 10px rgba(0, 255, 65, 0.28), inset 0 0 8px rgba(0, 255, 65, 0.05); +} +[data-theme='morpheus'] .btn-primary { + border-color: #00cc33; + box-shadow: 0 0 8px rgba(0, 255, 65, 0.20); +} +[data-theme='morpheus'] .btn-primary:hover { + border-color: #00ff41; + box-shadow: 0 0 16px rgba(0, 255, 65, 0.45), inset 0 0 10px rgba(0, 255, 65, 0.08); +} + +/* Queue round button active: bright green */ +[data-theme='morpheus'] .queue-round-btn:hover:not(:disabled):not(.active) { + background: rgba(0, 255, 65, 0.08); + border-color: #00ff41; + color: #00ff41; + box-shadow: 0 0 10px rgba(0, 255, 65, 0.28); +} +[data-theme='morpheus'] .queue-round-btn.active { + background: rgba(0, 255, 65, 0.15); + border-color: #00ff41; + color: #00ff41; + box-shadow: 0 0 12px rgba(0, 255, 65, 0.40), inset 0 0 8px rgba(0, 255, 65, 0.08); +} + +/* ── Cards: dark terminal panels ── */ +[data-theme='morpheus'] .card { + background: #0a120a; + border: 1px solid #003b00; + border-radius: 0; + box-shadow: inset 0 0 24px rgba(0, 255, 65, 0.02), 0 0 12px rgba(0, 0, 0, 0.60); +} + +/* ── Content header: terminal prompt bar ── */ +[data-theme='morpheus'] .content-header { + background: #000000; + border-bottom: 1px solid rgba(0, 255, 65, 0.25); + box-shadow: 0 2px 16px rgba(0, 255, 65, 0.04); +} + +/* ── Theme accordion: terminal hover ── */ +[data-theme='morpheus'] .theme-accordion-header:hover { + background: rgba(0, 255, 65, 0.08); + color: #00ff41; + text-shadow: 0 0 6px rgba(0, 255, 65, 0.40); +} +[data-theme='morpheus'] .theme-accordion-open .theme-accordion-header { + background: rgba(0, 255, 65, 0.10); + color: #00ff41; +} +[data-theme='morpheus'] .theme-accordion-open .theme-accordion-chevron { color: #00ff41; } + +/* ── Progress bar: terminal loading bar ── */ +[data-theme='morpheus'] .progress-bar-track { + background: #001a00; + border: 1px solid #003b00; + border-radius: 0; +} +[data-theme='morpheus'] .progress-bar-fill { + background: #00ff41; + border-radius: 0; + box-shadow: 0 0 8px rgba(0, 255, 65, 0.60), 0 0 2px rgba(0, 255, 65, 1); +} + +/* ── Scrollbar: CRT terminal style ── */ +[data-theme='morpheus'] ::-webkit-scrollbar { width: 6px; height: 6px; } +[data-theme='morpheus'] ::-webkit-scrollbar-track { background: #000000; } +[data-theme='morpheus'] ::-webkit-scrollbar-thumb { + background: #003b00; + border: 1px solid rgba(0, 255, 65, 0.30); +} +[data-theme='morpheus'] ::-webkit-scrollbar-thumb:hover { + background: rgba(0, 255, 65, 0.25); + box-shadow: 0 0 6px rgba(0, 255, 65, 0.40); +} + +/* ── Glass / dropdowns: black terminal window ── */ +[data-theme='morpheus'] .glass { + background: rgba(0, 8, 0, 0.97) !important; + backdrop-filter: none !important; + border: 1px solid rgba(0, 255, 65, 0.28) !important; + box-shadow: + 0 0 20px rgba(0, 255, 65, 0.08), + inset 0 0 16px rgba(0, 255, 65, 0.02) !important; + border-radius: 0 !important; +} +[data-theme='morpheus'] .glass [style*="var(--bg-hover)"] { + background: rgba(0, 255, 65, 0.10) !important; + border-radius: 0 !important; +} +[data-theme='morpheus'] .glass [style*="var(--text-primary)"] { color: #00ff41 !important; } +[data-theme='morpheus'] .glass [style*="var(--text-secondary)"] { color: #00cc33 !important; } +[data-theme='morpheus'] .glass [style*="var(--text-muted)"] { color: #006b10 !important; } + +/* ── Hover / selection: phosphor glow highlight ── */ +[data-theme='morpheus'] .queue-tab-btn:hover { + background: rgba(0, 255, 65, 0.08); + color: #00ff41; + text-shadow: 0 0 6px rgba(0, 255, 65, 0.40); +} +[data-theme='morpheus'] .settings-tab:hover { background: rgba(0, 255, 65, 0.08); color: #00ff41; } +[data-theme='morpheus'] .settings-tab.active { + background: rgba(0, 255, 65, 0.12); + color: #00ff41; + box-shadow: inset 2px 0 0 #00ff41; +} +[data-theme='morpheus'] .custom-select-trigger:hover { background: rgba(0, 255, 65, 0.08); } +[data-theme='morpheus'] .custom-select-option:hover { + background: rgba(0, 255, 65, 0.12) !important; + color: #00ff41 !important; + text-shadow: 0 0 6px rgba(0, 255, 65, 0.40) !important; +} +[data-theme='morpheus'] .artist-ext-link:hover { + background: rgba(0, 255, 65, 0.10); + color: #00ff41 !important; + border-color: #00ff41 !important; + text-shadow: 0 0 6px rgba(0, 255, 65, 0.40); +} +[data-theme='morpheus'] .np-action-btn:hover { background: rgba(0, 255, 65, 0.08); } +[data-theme='morpheus'] .np-queue-item:hover, +[data-theme='morpheus'] .np-queue-item.context-active { + background: rgba(0, 255, 65, 0.10); + box-shadow: inset 2px 0 0 #00ff41; +} +[data-theme='morpheus'] .track-row:hover, +[data-theme='morpheus'] .track-row.context-active { + background: rgba(0, 255, 65, 0.08) !important; + box-shadow: inset 2px 0 0 #00ff41; +} +[data-theme='morpheus'] .artist-row:hover { + background: rgba(0, 255, 65, 0.08); + box-shadow: inset 2px 0 0 #00ff41; +} +[data-theme='morpheus'] .playlist-row:hover { + background: rgba(0, 255, 65, 0.08); + box-shadow: inset 2px 0 0 #00ff41; +} +[data-theme='morpheus'] .queue-item:hover, +[data-theme='morpheus'] .queue-item.context-active { + background: rgba(0, 255, 65, 0.10) !important; + box-shadow: inset 2px 0 0 #00ff41; +} + +/* ── Active queue item: glowing green ── */ +[data-theme='morpheus'] .queue-item.active { + background: rgba(0, 255, 65, 0.08); + box-shadow: inset 2px 0 0 #00ff41, 0 0 8px rgba(0, 255, 65, 0.06); +} +[data-theme='morpheus'] .np-queue-item-active { text-shadow: 0 0 8px rgba(0, 255, 65, 0.60); } +[data-theme='morpheus'] .np-queue-item.active { background: rgba(0, 255, 65, 0.08); } +[data-theme='morpheus'] .np-album-track.active .np-album-track-title, +[data-theme='morpheus'] .np-album-track.active .np-album-track-num { + text-shadow: 0 0 8px rgba(0, 255, 65, 0.60); } /* ───────────────────────────────────────────────────────────── @@ -4589,7 +5793,7 @@ input[type="range"]:hover::-webkit-slider-thumb { --text-primary: #e0e0e0; --text-secondary:#b0b0b0; - --text-muted: #666666; + --text-muted: #888888; --border: #2a2a2a; --border-subtle: #1a1a1a; @@ -4713,172 +5917,377 @@ input[type="range"]:hover::-webkit-slider-thumb { border-left: 3px solid #00d4ff; } -/* ── B-Runner (Movies) ──────────────────────────────────────── */ -[data-theme='b-runner'] { - color-scheme: dark; - --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23ff9500%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); - - --ctp-crust: #080707; - --ctp-mantle: #0f0d0c; - --ctp-base: #141211; - --ctp-surface0: #1c1917; - --ctp-surface1: #262220; - --ctp-surface2: #332d2a; - --ctp-overlay0: #574f4a; - --ctp-overlay1: #8a7e78; - --ctp-overlay2: #a3958f; - --ctp-text: #ffeadb; - --ctp-subtext1: #d4c2b5; - --ctp-subtext0: #a38f84; - - --ctp-mauve: #ff9500; - --ctp-lavender: #ffb347; - --ctp-green: #82e600; - --ctp-teal: #ff7b00; - --ctp-sky: #ffa600; - --ctp-blue: #ff6200; - --ctp-sapphire: #8a3500; - --ctp-pink: #ff4400; - --ctp-flamingo: #ff5533; - --ctp-rosewater:#ffd8c4; - --ctp-yellow: #ffcc00; - --ctp-peach: #ff8800; - --ctp-maroon: #af3a03; - --ctp-red: #e63900; - - --bg-app: #141211; - --bg-sidebar: #0f0d0c; - --bg-card: #1c1917; - --bg-hover: rgba(255, 149, 0, 0.08); - --bg-player: #080707; - --bg-glass: rgba(15, 13, 12, 0.85); - - --accent: #ff9500; - --accent-dim: rgba(255, 149, 0, 0.12); - --accent-glow: rgba(255, 149, 0, 0.35); - --volume-accent:#ff4400; - - --text-primary: #ffeadb; - --text-secondary:#d4c2b5; - --text-muted: #6b5d56; - --border: #262220; - --border-subtle: #1c1917; - - --positive: #82e600; - --warning: #ffcc00; - --danger: #ff4400; - - --radius-md: 2px; - --radius-lg: 4px; -} - -[data-theme='b-runner'] .player-track-name { - color: var(--accent); - text-shadow: 0 0 10px rgba(255, 149, 0, 0.6); - letter-spacing: -0.5px; -} - -[data-theme='b-runner'] .sidebar { - border-right: 1px solid rgba(255, 149, 0, 0.15); -} - -[data-theme='b-runner'] .nav-link.active { - box-shadow: inset 4px 0 0 var(--accent); - background: linear-gradient(90deg, rgba(255, 149, 0, 0.1) 0%, transparent 100%); -} - -[data-theme='b-runner'] .player-bar { - border-top: 1px solid rgba(255, 149, 0, 0.2); - backdrop-filter: blur(20px); -} - -/* ── Dune (Movies) ──────────────────────────────────────────── */ +/* ─── Dune — Arrakis ─── */ [data-theme='dune'] { color-scheme: dark; - --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23ff8c00%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); + --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23c8780a%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); - --ctp-crust: #0c0a09; - --ctp-mantle: #171412; - --ctp-base: #1c1917; - --ctp-surface0: #292524; - --ctp-surface1: #44403c; - --ctp-surface2: #57534e; - --ctp-overlay0: #78716c; - --ctp-overlay1: #a8a29e; - --ctp-overlay2: #d6d3d1; - --ctp-text: #f5f5f4; - --ctp-subtext1: #e7e5e4; - --ctp-subtext0: #d6d3d1; + /* ── Palette — two-temperature Arrakis ── */ + /* Warm: spice / sand / desert sun */ + --ctp-crust: #0a0804; + --ctp-mantle: #120e06; + --ctp-base: #1c1408; + --ctp-surface0: #2e1e0a; + --ctp-surface1: #3e2a0e; + --ctp-surface2: #503614; + /* Cool: sietch / rock shadow / Fremen darkness */ + --ctp-overlay0: #2a2440; + --ctp-overlay1: #4a4268; + --ctp-overlay2: #6a6090; + /* Text: aged parchment, scrolls of the Bene Gesserit */ + --ctp-text: #f0deb0; + --ctp-subtext1: #d8c090; + --ctp-subtext0: #b09060; + /* Accent palette */ + --ctp-mauve: #c8780a; /* spice melange — cinnamon rust */ + --ctp-lavender: #e8a020; /* spice shimmer — bright amber */ + --ctp-yellow: #f5cc50; /* spice flare */ + --ctp-peach: #aa5a08; /* deep spice shadow */ + --ctp-green: #7a8c40; /* Caladan seagrass (far memory) */ + --ctp-teal: #1a80c0; /* Fremen eye blue — spice prescience */ + --ctp-sky: #2090d0; /* Guild Navigator blue */ + --ctp-blue: #1468a8; /* sietch pool depth */ + --ctp-sapphire: #0e4a80; /* deep cave water */ + --ctp-pink: #c84060; + --ctp-flamingo: #e06080; + --ctp-rosewater: #f0c0a0; + --ctp-red: #cc2800; + --ctp-maroon: #8c1c00; - --ctp-mauve: #ff8c00; - --ctp-lavender: #ffa500; - --ctp-green: #84cc16; - --ctp-teal: #06b6d4; - --ctp-sky: #38bdf8; - --ctp-blue: #00eeff; - --ctp-sapphire: #0ea5e9; - --ctp-pink: #f43f5e; - --ctp-flamingo: #fb7185; - --ctp-rosewater:#fecdd3; - --ctp-yellow: #fbbf24; - --ctp-peach: #f59e0b; - --ctp-maroon: #991b1b; - --ctp-red: #ef4444; - - --bg-app: #1c1917; - --bg-sidebar: #171412; - --bg-card: #292524; - --bg-hover: #44403c; - --bg-player: #0c0a09; - --bg-glass: rgba(28, 25, 23, 0.85); - - --accent: #ff8c00; - --accent-dim: rgba(255, 140, 0, 0.12); - --accent-glow: rgba(255, 140, 0, 0.35); - --volume-accent:#ff8c00; - - --text-primary: #f5f5f4; - --text-secondary:#d6d3d1; - --text-muted: #78716c; - --border: #44403c; - --border-subtle: #292524; - - --positive: #84cc16; - --warning: #fbbf24; - --danger: #ef4444; - - --radius-sm: 2px; - --radius-md: 4px; - --radius-lg: 8px; + /* ── Semantic tokens ── */ + --bg-app: #1c1408; + --bg-sidebar: #0e0c1a; /* sietch interior — cool rock */ + --bg-card: #2e1e0a; + --bg-hover: rgba(200, 120, 10, 0.14); + --bg-player: #0e0a04; + --bg-glass: rgba(10, 8, 4, 0.96); + --accent: #c8780a; + --accent-dim: rgba(200, 120, 10, 0.12); + --accent-glow: rgba(200, 120, 10, 0.40); + --volume-accent: #c8780a; + --text-primary: #f0deb0; + --text-secondary:#d8c090; + --text-muted: #a89870; + --border: rgba(200, 120, 10, 0.22); + --border-subtle: rgba(200, 120, 10, 0.10); + --positive: #7a8c40; + --warning: #f5cc50; + --danger: #cc2800; + --radius-sm: 2px; + --radius-md: 4px; + --radius-lg: 6px; } +/* ── App shell: Arrakis desert horizon at dusk ── */ +/* Sky (cool/dark at top) fading into burning sand (warm at bottom) */ [data-theme='dune'] .app-shell { - background-image: - radial-gradient(circle at 50% 50%, rgba(255, 140, 0, 0.03) 0%, transparent 80%), - linear-gradient(to bottom, #1c1917, #171412); + background: + radial-gradient(ellipse at 10% 90%, rgba(160, 90, 8, 0.10) 0%, transparent 50%), + radial-gradient(ellipse at 90% 15%, rgba(20, 100, 160, 0.07) 0%, transparent 45%), + radial-gradient(ellipse at 50% 100%, rgba(120, 70, 5, 0.12) 0%, transparent 55%), + linear-gradient(180deg, + #12101c 0%, /* deep sky — cold purple-black */ + #1a1408 30%, /* desert horizon, last light */ + #201608 60%, /* warm sand surface */ + #281e0a 100% /* deep sand shadow */ + ); } -[data-theme='dune'] .player-bar { - border-top: 1px solid rgba(255, 140, 0, 0.2); - box-shadow: 0 -10px 30px -10px rgba(0, 0, 0, 0.5); +/* ── Sidebar: sietch interior — cold carved rock ── */ +/* The Fremen lived in caves cut from rock — cool, dark, shadows of blue and purple */ +[data-theme='dune'] .sidebar { + background: linear-gradient(180deg, #141228 0%, #0e0c1c 40%, #0c0a16 100%); + border-right: 1px solid rgba(200, 120, 10, 0.22); + box-shadow: + inset -3px 0 10px rgba(200, 100, 8, 0.07), + 2px 0 8px rgba(0, 0, 0, 0.50); } -[data-theme='dune'] .player-track-name { - color: var(--accent); - text-shadow: 0 0 8px rgba(255, 140, 0, 0.4); - letter-spacing: 0.02em; +/* Nav text: parchment on cool rock */ +[data-theme='dune'] .nav-link { color: #b09060; } +[data-theme='dune'] .nav-link:hover { + background: rgba(200, 120, 10, 0.10); + color: #d8c090; +} +[data-theme='dune'] .nav-link.active { + background: linear-gradient(90deg, rgba(200,120,10,0.20) 0%, transparent 100%); + color: #e8a020; + border-left: 2px solid #c8780a; + box-shadow: inset 4px 0 14px rgba(200,120,10,0.10); } - [data-theme='dune'] .nav-link.active::before { - box-shadow: 2px 0 10px var(--accent-glow); + background: #c8780a; + box-shadow: 0 0 10px rgba(200,120,10,0.70); +} +[data-theme='dune'] .nav-link.active svg { color: #c8780a; } +[data-theme='dune'] .nav-section-label { + color: #4a4268; + letter-spacing: 0.08em; + text-transform: uppercase; + font-size: 0.70em; } +/* ── Player bar: spice harvester console — deep amber warmth ── */ +[data-theme='dune'] .player-bar { + background: linear-gradient(180deg, #140e04 0%, #0a0802 100%); + border-top: 2px solid rgba(200, 120, 10, 0.50); + box-shadow: + inset 0 1px 0 rgba(240, 180, 40, 0.16), + 0 -8px 40px rgba(180, 100, 8, 0.16), + 0 -2px 80px rgba(20, 100, 160, 0.04); +} + +/* Track name: the spice calls — amber prophetic glow */ +[data-theme='dune'] .player-track-name { + color: #e8a020; + text-shadow: + 0 0 8px rgba(232, 160, 32, 0.75), + 0 0 20px rgba(200, 120, 10, 0.40), + 0 0 40px rgba(200, 120, 10, 0.15); + letter-spacing: 0.04em; +} +/* Artist: deeper spice cinnamon */ +[data-theme='dune'] .player-track-artist { + color: #aa7030; + opacity: 1; + text-shadow: 0 0 8px rgba(170, 112, 48, 0.45); +} +[data-theme='dune'] .player-time { color: #7a5020; } + +/* ── Transport buttons: Fremen tech — minimal, earth-worn ── */ +[data-theme='dune'] .player-btn, +[data-theme='dune'] .player-btn-primary { + background: linear-gradient(180deg, #2e1e0a 0%, #1e1406 100%); + color: #c8780a; + border: 1px solid rgba(200, 120, 10, 0.38); + border-radius: 50%; + box-shadow: inset 0 1px 0 rgba(240,180,40,0.08), 0 2px 6px rgba(0,0,0,0.50); +} +[data-theme='dune'] .player-btn:hover, +[data-theme='dune'] .player-btn-primary:hover { + background: rgba(200, 120, 10, 0.14); + border-color: #c8780a; + color: #e8a020; + box-shadow: + 0 0 14px rgba(200, 120, 10, 0.42), + inset 0 0 8px rgba(200, 100, 8, 0.08); +} + +/* ── Regular buttons: desert stone / carved bone ── */ +[data-theme='dune'] .btn, +[data-theme='dune'] .btn-surface, +[data-theme='dune'] .btn-ghost { + background: linear-gradient(180deg, #2e1e0a 0%, #221608 100%); + color: #d8c090; + border: 1px solid rgba(200, 120, 10, 0.30); + box-shadow: inset 0 1px 0 rgba(240,200,80,0.06), 0 1px 4px rgba(0,0,0,0.40); + border-radius: 3px; +} +[data-theme='dune'] .btn:hover, +[data-theme='dune'] .btn-surface:hover, +[data-theme='dune'] .btn-ghost:hover { + background: rgba(200, 120, 10, 0.12); + border-color: rgba(200, 120, 10, 0.65); + color: #f0deb0; + box-shadow: 0 0 10px rgba(200, 120, 10, 0.24), inset 0 0 6px rgba(200,100,8,0.05); +} + +/* ── Primary button: spice melange — the most precious thing ── */ [data-theme='dune'] .btn-primary { - background: linear-gradient(135deg, #ff8c00 0%, #e67e22 100%); - border: none; - color: #0c0a09; + background: linear-gradient(180deg, #b86808 0%, #884e04 100%); + color: #ffe8a0; + border: 1px solid #d08010; + box-shadow: 0 0 14px rgba(200, 120, 10, 0.35), inset 0 1px 0 rgba(255,220,80,0.20); + border-radius: 3px; font-weight: 600; } +[data-theme='dune'] .btn-primary:hover { + background: linear-gradient(180deg, #d07a10 0%, #a05e06 100%); + box-shadow: 0 0 22px rgba(200, 120, 10, 0.55), inset 0 1px 0 rgba(255,220,80,0.25); +} + +/* ── Hero / album buttons ── */ +[data-theme='dune'] .hero-play-btn, +[data-theme='dune'] .album-card-details-btn { + background: rgba(200, 120, 10, 0.12); + color: #c8780a; + border: 1px solid rgba(200, 120, 10, 0.36); + box-shadow: inset 0 1px 0 rgba(240,180,40,0.06); +} +[data-theme='dune'] .hero-play-btn:hover, +[data-theme='dune'] .album-card-details-btn:hover { + background: rgba(200, 120, 10, 0.20); + border-color: #c8780a; + box-shadow: 0 0 12px rgba(200, 120, 10, 0.38); +} + +/* ── Queue round buttons ── */ +[data-theme='dune'] .queue-round-btn { + background: linear-gradient(180deg, #2e1e0a 0%, #1e1406 100%); + color: #8a6030; + border: 1px solid rgba(200, 120, 10, 0.24); +} +[data-theme='dune'] .queue-round-btn:hover:not(:disabled):not(.active) { + background: rgba(200, 120, 10, 0.10); + border-color: rgba(200, 120, 10, 0.55); + color: #c8780a; + box-shadow: 0 0 10px rgba(200, 120, 10, 0.22); +} +[data-theme='dune'] .queue-round-btn.active { + background: rgba(200, 120, 10, 0.20); + border-color: #c8780a; + color: #e8a020; + box-shadow: 0 0 12px rgba(200, 120, 10, 0.42), inset 0 0 6px rgba(200,100,8,0.08); +} + +/* ── Cards: ancient stone / sand-worn rock ── */ +[data-theme='dune'] .card { + background: linear-gradient(180deg, #2e1e0a 0%, #281808 100%); + border: 1px solid rgba(200, 120, 10, 0.16); + border-radius: 4px; + box-shadow: + inset 0 1px 0 rgba(240,200,80,0.04), + inset 0 0 24px rgba(200,100,8,0.03), + 0 2px 10px rgba(0,0,0,0.50); +} + +/* ── Content header: sietch entrance — cool rock above warm desert ── */ +/* The contrast between the cold header and warm body is intentional — Arrakis duality */ +[data-theme='dune'] .content-header { + background: linear-gradient(180deg, #151228 0%, #12101e 100%); + border-bottom: 1px solid rgba(200, 120, 10, 0.24); + box-shadow: 0 3px 16px rgba(200, 100, 8, 0.06); +} +/* Text on cool header: light but warm */ +[data-theme='dune'] .content-header .page-title, +[data-theme='dune'] .content-header h1, +[data-theme='dune'] .content-header h2 { color: #d8c090; } + +/* ── Connection indicators: parchment legible ── */ +[data-theme='dune'] .connection-type, +[data-theme='dune'] .connection-server { color: #b09060; } + +/* ── Theme accordion ── */ +[data-theme='dune'] .theme-accordion-header:hover { + background: rgba(200, 120, 10, 0.10); + color: #e8a020; +} +[data-theme='dune'] .theme-accordion-open .theme-accordion-header { + background: rgba(200, 120, 10, 0.14); + color: #e8a020; +} +[data-theme='dune'] .theme-accordion-open .theme-accordion-chevron { color: #c8780a; } + +/* ── Progress bar: spice flowing — from deep rust to bright amber ── */ +[data-theme='dune'] .progress-bar-track { + background: #1a1006; + border: 1px solid rgba(200, 120, 10, 0.22); + border-radius: 2px; +} +[data-theme='dune'] .progress-bar-fill { + background: linear-gradient(90deg, + #6a3604 0%, + #a85a08 30%, + #c8780a 65%, + #e8a020 85%, + #f5cc50 100% + ); + border-radius: 2px; + box-shadow: 0 0 10px rgba(200, 120, 10, 0.55), 0 0 3px rgba(240,200,60,0.40); +} + +/* ── Scrollbar: sand grain — thin, warm, minimal ── */ +[data-theme='dune'] ::-webkit-scrollbar { width: 5px; height: 5px; } +[data-theme='dune'] ::-webkit-scrollbar-track { background: #0a0804; } +[data-theme='dune'] ::-webkit-scrollbar-thumb { + background: rgba(200, 120, 10, 0.30); + border-radius: 2px; + border: 1px solid rgba(200, 120, 10, 0.16); +} +[data-theme='dune'] ::-webkit-scrollbar-thumb:hover { + background: rgba(200, 120, 10, 0.55); + box-shadow: 0 0 5px rgba(200, 120, 10, 0.40); +} + +/* ── Glass / dropdowns: deep sand shelter ── */ +[data-theme='dune'] .glass { + background: rgba(10, 8, 4, 0.97) !important; + backdrop-filter: none !important; + border: 1px solid rgba(200, 120, 10, 0.30) !important; + box-shadow: + 0 0 20px rgba(180, 100, 8, 0.10), + inset 0 0 16px rgba(200, 100, 8, 0.02) !important; + border-radius: 4px !important; +} +[data-theme='dune'] .glass [style*="var(--bg-hover)"] { + background: rgba(200, 120, 10, 0.12) !important; + border-radius: 2px !important; +} +[data-theme='dune'] .glass [style*="var(--text-primary)"] { color: #f0deb0 !important; } +[data-theme='dune'] .glass [style*="var(--text-secondary)"] { color: #d8c090 !important; } +[data-theme='dune'] .glass [style*="var(--text-muted)"] { color: #6a5830 !important; } + +/* ── Hover / selection: spice glow — warm amber indicator bar ── */ +[data-theme='dune'] .queue-tab-btn:hover { background: rgba(200,120,10,0.10); color: #c8780a; } +[data-theme='dune'] .settings-tab:hover { background: rgba(200,120,10,0.10); color: #c8780a; } +[data-theme='dune'] .settings-tab.active { + background: rgba(200,120,10,0.16); + color: #e8a020; + box-shadow: inset 2px 0 0 #c8780a; +} +[data-theme='dune'] .custom-select-trigger:hover { background: rgba(200,120,10,0.10); } +[data-theme='dune'] .custom-select-option:hover { + background: rgba(200,120,10,0.14) !important; + color: #e8a020 !important; +} +[data-theme='dune'] .artist-ext-link:hover { + background: rgba(200,120,10,0.10); + color: #c8780a !important; + border-color: rgba(200,120,10,0.45) !important; +} +[data-theme='dune'] .np-action-btn:hover { background: rgba(200,120,10,0.10); } +[data-theme='dune'] .np-queue-item:hover, +[data-theme='dune'] .np-queue-item.context-active { + background: rgba(200,120,10,0.12); + box-shadow: inset 2px 0 0 #c8780a; +} +[data-theme='dune'] .track-row:hover, +[data-theme='dune'] .track-row.context-active { + background: rgba(200,120,10,0.09) !important; + box-shadow: inset 2px 0 0 #c8780a; +} +[data-theme='dune'] .artist-row:hover { + background: rgba(200,120,10,0.09); + box-shadow: inset 2px 0 0 #c8780a; +} +[data-theme='dune'] .playlist-row:hover { + background: rgba(200,120,10,0.09); + box-shadow: inset 2px 0 0 #c8780a; +} +[data-theme='dune'] .queue-item:hover, +[data-theme='dune'] .queue-item.context-active { + background: rgba(200,120,10,0.10) !important; + box-shadow: inset 2px 0 0 #c8780a; +} +[data-theme='dune'] .queue-item:hover .queue-item-title, +[data-theme='dune'] .queue-item:hover .queue-item-artist, +[data-theme='dune'] .queue-item:hover .queue-item-duration, +[data-theme='dune'] .queue-item.context-active .queue-item-title, +[data-theme='dune'] .queue-item.context-active .queue-item-artist, +[data-theme='dune'] .queue-item.context-active .queue-item-duration { color: #c8780a; } + +/* ── Active queue / now-playing: the worm has come ── */ +[data-theme='dune'] .queue-item.active { + background: rgba(200, 120, 10, 0.08); + box-shadow: inset 2px 0 0 #c8780a; +} +[data-theme='dune'] .np-queue-item-active { color: #c8780a; text-shadow: 0 0 8px rgba(200,120,10,0.55); } +[data-theme='dune'] .np-queue-item.active { background: rgba(200,120,10,0.08); } +[data-theme='dune'] .np-album-track.active .np-album-track-title, +[data-theme='dune'] .np-album-track.active .np-album-track-num { + color: #c8780a; + text-shadow: 0 0 8px rgba(200,120,10,0.50); +} /* ── TetraStack (Games) ─────────────────────────────────────── */ [data-theme='tetrastack'] { @@ -4927,7 +6336,7 @@ input[type="range"]:hover::-webkit-slider-thumb { --text-primary: #ffffff; --text-secondary:#00f0f0; - --text-muted: #666666; + --text-muted: #888888; --border: #333333; --border-subtle: #1a1a1a; @@ -5018,7 +6427,7 @@ input[type="range"]:hover::-webkit-slider-thumb { --text-primary: #050505; --text-secondary:#65676B; - --text-muted: #8A8D91; + --text-muted: #606369; --border: #CED0D4; --border-subtle: #E4E6EB; @@ -5311,96 +6720,357 @@ input[type="range"]:hover::-webkit-slider-thumb { } /* ── Hill Valley 85 (Movies) ────────────────────────────────── */ +/* ─── Back to the Future — Hill Valley '85 ─── */ [data-theme='hill-valley-85'] { color-scheme: dark; - --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%239ca3af%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); + --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23ff8c00%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); - --ctp-crust: #0a0a0c; - --ctp-mantle: #121417; - --ctp-base: #1a1d23; - --ctp-surface0: #252a33; - --ctp-surface1: #313844; - --ctp-surface2: #3d4554; - --ctp-overlay0: #565f73; - --ctp-overlay1: #7f8a9e; - --ctp-overlay2: #9ca3af; - --ctp-text: #e2e8f0; - --ctp-subtext1: #cbd5e1; - --ctp-subtext0: #94a3b8; + /* ── Palette ── */ + --ctp-crust: #020106; + --ctp-mantle: #07060f; + --ctp-base: #0d0b18; + --ctp-surface0: #151220; + --ctp-surface1: #1e1a2c; + --ctp-surface2: #272338; + --ctp-overlay0: #3d3455; + --ctp-overlay1: #5a4e70; + --ctp-overlay2: #7a6e90; + --ctp-text: #ede0c8; + --ctp-subtext1: #c8b898; + --ctp-subtext0: #a09070; + /* BTTF palette: flame orange, DeLorean red, lightning blue, flux yellow */ + --ctp-mauve: #ff8c00; + --ctp-lavender: #ffaa33; + --ctp-red: #ff2200; + --ctp-blue: #3d88ff; + --ctp-sapphire: #1a5ccc; + --ctp-sky: #66aaff; + --ctp-teal: #00ccff; + --ctp-green: #44dd00; + --ctp-yellow: #ffe033; + --ctp-peach: #ff6600; + --ctp-pink: #ff44aa; + --ctp-flamingo: #ff2266; + --ctp-rosewater: #ffd0b0; + --ctp-maroon: #cc1100; - --ctp-mauve: #ff9900; - --ctp-lavender: #ffb84d; - --ctp-green: #00ff41; - --ctp-yellow: #ffcc00; - --ctp-red: #ff3131; - --ctp-teal: #00d4ff; - --ctp-blue: #3b82f6; - --ctp-sapphire: #1d4ed8; - --ctp-sky: #00d4ff; - --ctp-pink: #f472b6; - --ctp-flamingo: #fb7185; - --ctp-rosewater:#fecdd3; - --ctp-peach: #fb923c; - --ctp-maroon: #991b1b; - - --bg-app: #1a1d23; - --bg-sidebar: #121417; - --bg-card: #252a33; - --bg-hover: #313844; - --bg-player: #0a0a0c; - --bg-glass: rgba(10, 10, 12, 0.85); - - --accent: #ff9900; - --accent-dim: rgba(255, 153, 0, 0.12); - --accent-glow: rgba(255, 153, 0, 0.3); - --volume-accent:#ff9900; - - --text-primary: #e2e8f0; - --text-secondary:#cbd5e1; - --text-muted: #565f73; - --border: #313844; - --border-subtle: #252a33; - - --radius-sm: 2px; - --radius-md: 4px; - --radius-lg: 8px; + /* ── Semantic tokens ── */ + --bg-app: #0d0b18; + --bg-sidebar: #08060f; + --bg-card: #141120; + --bg-hover: rgba(255, 140, 0, 0.12); + --bg-player: #040209; + --bg-glass: rgba(6, 4, 12, 0.96); + --accent: #ff8c00; + --accent-dim: rgba(255, 140, 0, 0.12); + --accent-glow: rgba(255, 140, 0, 0.40); + --volume-accent: #ff8c00; + --text-primary: #ede0c8; + --text-secondary:#c8b898; + --text-muted: #b0a0c8; + --border: rgba(255, 140, 0, 0.20); + --border-subtle: rgba(255, 140, 0, 0.10); + --positive: #44dd00; + --warning: #ffe033; + --danger: #ff2200; + --radius-sm: 2px; + --radius-md: 4px; + --radius-lg: 6px; } +/* ── App shell: Hill Valley night sky — orange fire & blue lightning ── */ +[data-theme='hill-valley-85'] .app-shell { + background: + radial-gradient(ellipse at 15% 80%, rgba(255, 110, 0, 0.07) 0%, transparent 55%), + radial-gradient(ellipse at 85% 15%, rgba(60, 130, 255, 0.06) 0%, transparent 50%), + #0d0b18; +} + +/* ── Sidebar: DeLorean stainless steel panels ── */ [data-theme='hill-valley-85'] .sidebar { - background: linear-gradient(135deg, #121417 0%, #1a1d23 100%); - border-right: 1px solid #313844; + background-color: #08060f; + background-image: repeating-linear-gradient( + 90deg, + rgba(255,255,255,0.025) 0px, rgba(255,255,255,0.025) 1px, + transparent 1px, transparent 10px + ); + border-right: 1px solid rgba(255, 140, 0, 0.22); + box-shadow: inset -2px 0 8px rgba(255, 100, 0, 0.05), 2px 0 6px rgba(0,0,0,0.40); } -[data-theme='hill-valley-85'] .player-bar { - border-top: 2px solid #252a33; - background: linear-gradient(to bottom, #0d0d0f, #050506); - box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.5); +/* Nav links */ +[data-theme='hill-valley-85'] .nav-link { color: #c8b898; } +[data-theme='hill-valley-85'] .nav-link:hover { + background: rgba(255, 140, 0, 0.10); + color: #ede0c8; } - -[data-theme='hill-valley-85'] .player-track-name { - color: var(--ctp-mauve); - text-shadow: 0 0 8px rgba(255, 153, 0, 0.6); - letter-spacing: -0.5px; -} - -[data-theme='hill-valley-85'] .player-track-artist { - color: var(--ctp-green); - text-shadow: 0 0 5px rgba(0, 255, 65, 0.4); - opacity: 0.9; -} - [data-theme='hill-valley-85'] .nav-link.active { - background: linear-gradient(90deg, rgba(255, 153, 0, 0.15) 0%, transparent 100%); - border-left: 3px solid var(--ctp-mauve); - box-shadow: inset 2px 0 5px rgba(255, 153, 0, 0.1); + background: linear-gradient(90deg, rgba(255,140,0,0.18) 0%, transparent 100%); + color: #ff8c00; + border-left: 2px solid #ff8c00; + box-shadow: inset 4px 0 12px rgba(255,140,0,0.10); +} +[data-theme='hill-valley-85'] .nav-link.active::before { + background: #ff8c00; + box-shadow: 0 0 8px rgba(255,140,0,0.70); +} +[data-theme='hill-valley-85'] .nav-link.active svg { color: #ff8c00; } + +/* ── Player bar: DeLorean time circuit console ── */ +[data-theme='hill-valley-85'] .player-bar { + background: linear-gradient(180deg, #060410 0%, #030208 100%); + border-top: 2px solid rgba(255, 140, 0, 0.45); + box-shadow: + inset 0 1px 0 rgba(255, 140, 0, 0.18), + 0 -6px 30px rgba(255, 100, 0, 0.12), + 0 -2px 60px rgba(60, 130, 255, 0.04); } -[data-theme='hill-valley-85'] .player-btn:hover { - color: var(--ctp-teal); - filter: drop-shadow(0 0 5px var(--ctp-teal)); +/* Track name: DeLorean time circuit red LED display */ +[data-theme='hill-valley-85'] .player-track-name { + color: #ff2200; + font-family: 'Courier New', 'Courier', monospace; + text-shadow: + 0 0 8px rgba(255, 34, 0, 0.90), + 0 0 18px rgba(255, 34, 0, 0.50), + 0 0 30px rgba(255, 34, 0, 0.20); + letter-spacing: 1.5px; + text-transform: uppercase; + font-weight: 700; +} + +/* Artist name: amber LED — second row of the time display */ +[data-theme='hill-valley-85'] .player-track-artist { + color: #ff8c00; + font-family: 'Courier New', monospace; + text-shadow: 0 0 8px rgba(255, 140, 0, 0.65); + letter-spacing: 0.5px; + opacity: 1; +} + +/* Time readout: amber LCD */ +[data-theme='hill-valley-85'] .player-time { + color: #cc6a00; + font-family: 'Courier New', monospace; + text-shadow: 0 0 6px rgba(255, 140, 0, 0.40); +} + +/* ── Transport buttons: illuminated 80s switches ── */ +[data-theme='hill-valley-85'] .player-btn, +[data-theme='hill-valley-85'] .player-btn-primary { + background: linear-gradient(180deg, #100d1c 0%, #0a0815 100%); + color: #ff8c00; + border: 1px solid rgba(255, 140, 0, 0.35); + border-radius: 50%; + box-shadow: inset 0 0 6px rgba(255,100,0,0.06), 0 1px 3px rgba(0,0,0,0.50); +} +[data-theme='hill-valley-85'] .player-btn:hover, +[data-theme='hill-valley-85'] .player-btn-primary:hover { + background: rgba(255, 140, 0, 0.12); + border-color: #ff8c00; + color: #ffaa33; + box-shadow: + 0 0 14px rgba(255, 140, 0, 0.40), + inset 0 0 8px rgba(255, 100, 0, 0.08); +} + +/* ── Regular buttons: DeLorean console switches ── */ +[data-theme='hill-valley-85'] .btn, +[data-theme='hill-valley-85'] .btn-surface, +[data-theme='hill-valley-85'] .btn-ghost { + background: linear-gradient(180deg, #141120 0%, #0e0c1a 100%); + color: #c8b898; + border: 1px solid rgba(255, 140, 0, 0.28); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 1px 3px rgba(0,0,0,0.40); + border-radius: 4px; +} +[data-theme='hill-valley-85'] .btn:hover, +[data-theme='hill-valley-85'] .btn-surface:hover, +[data-theme='hill-valley-85'] .btn-ghost:hover { + background: rgba(255, 140, 0, 0.10); + border-color: rgba(255, 140, 0, 0.60); + color: #ede0c8; + box-shadow: 0 0 10px rgba(255, 140, 0, 0.22), inset 0 0 6px rgba(255,100,0,0.05); +} + +/* ── Primary button: fire orange ── */ +[data-theme='hill-valley-85'] .btn-primary { + background: linear-gradient(180deg, #cc5500 0%, #993d00 100%); + color: #ffffff; + border: 1px solid #ff6600; + box-shadow: 0 0 12px rgba(255, 140, 0, 0.30), inset 0 1px 0 rgba(255,180,0,0.25); + border-radius: 4px; +} +[data-theme='hill-valley-85'] .btn-primary:hover { + background: linear-gradient(180deg, #e86000 0%, #b04800 100%); + box-shadow: 0 0 18px rgba(255, 140, 0, 0.50), inset 0 1px 0 rgba(255,200,0,0.25); +} + +/* ── Hero / album-card buttons ── */ +[data-theme='hill-valley-85'] .hero-play-btn, +[data-theme='hill-valley-85'] .album-card-details-btn { + background: rgba(255, 140, 0, 0.10); + color: #ff8c00; + border: 1px solid rgba(255, 140, 0, 0.35); + box-shadow: inset 0 1px 0 rgba(255,180,0,0.08); +} +[data-theme='hill-valley-85'] .hero-play-btn:hover, +[data-theme='hill-valley-85'] .album-card-details-btn:hover { + background: rgba(255, 140, 0, 0.18); + border-color: #ff8c00; + box-shadow: 0 0 12px rgba(255, 140, 0, 0.35); +} + +/* ── Queue toolbar round buttons ── */ +[data-theme='hill-valley-85'] .queue-round-btn { + background: linear-gradient(180deg, #141120 0%, #0e0c1a 100%); + color: #a09070; + border: 1px solid rgba(255, 140, 0, 0.22); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.03); +} +[data-theme='hill-valley-85'] .queue-round-btn:hover:not(:disabled):not(.active) { + background: rgba(255, 140, 0, 0.10); + border-color: rgba(255, 140, 0, 0.55); + color: #ff8c00; + box-shadow: 0 0 10px rgba(255, 140, 0, 0.22); +} +[data-theme='hill-valley-85'] .queue-round-btn.active { + background: rgba(255, 140, 0, 0.18); + border-color: #ff8c00; + color: #ff8c00; + box-shadow: 0 0 12px rgba(255, 140, 0, 0.40), inset 0 0 6px rgba(255,100,0,0.08); +} + +/* ── Cards: dark interior panels ── */ +[data-theme='hill-valley-85'] .card { + background: #141120; + border: 1px solid rgba(255, 140, 0, 0.14); + box-shadow: inset 0 0 20px rgba(255, 100, 0, 0.03), 0 2px 8px rgba(0,0,0,0.40); +} + +/* ── Content header: console panel strip ── */ +[data-theme='hill-valley-85'] .content-header { + background: linear-gradient(180deg, #100d1c 0%, #0d0b18 100%); + border-bottom: 1px solid rgba(255, 140, 0, 0.22); + box-shadow: 0 2px 12px rgba(255, 100, 0, 0.05); +} + +/* ── Theme accordion ── */ +[data-theme='hill-valley-85'] .theme-accordion-header:hover { + background: rgba(255, 140, 0, 0.10); + color: #ff8c00; +} +[data-theme='hill-valley-85'] .theme-accordion-open .theme-accordion-header { + background: rgba(255, 140, 0, 0.12); + color: #ff8c00; +} +[data-theme='hill-valley-85'] .theme-accordion-open .theme-accordion-chevron { color: #ff8c00; } + +/* ── Progress bar: speedometer reaching 88 mph ── */ +[data-theme='hill-valley-85'] .progress-bar-track { + background: #0a0815; + border: 1px solid rgba(255, 140, 0, 0.20); + border-radius: 2px; +} +[data-theme='hill-valley-85'] .progress-bar-fill { + background: linear-gradient(90deg, #993d00 0%, #cc5500 40%, #ff8c00 80%, #ffaa33 100%); + border-radius: 2px; + box-shadow: 0 0 10px rgba(255, 140, 0, 0.55), 0 0 3px rgba(255, 200, 0, 0.40); +} + +/* ── Scrollbar: fire trail minimal ── */ +[data-theme='hill-valley-85'] ::-webkit-scrollbar { width: 6px; height: 6px; } +[data-theme='hill-valley-85'] ::-webkit-scrollbar-track { background: #07060e; } +[data-theme='hill-valley-85'] ::-webkit-scrollbar-thumb { + background: rgba(255, 140, 0, 0.28); + border: 1px solid rgba(255, 140, 0, 0.18); + border-radius: 3px; +} +[data-theme='hill-valley-85'] ::-webkit-scrollbar-thumb:hover { + background: rgba(255, 140, 0, 0.55); + box-shadow: 0 0 6px rgba(255, 140, 0, 0.40); +} + +/* ── Glass / dropdowns: dark DeLorean interior ── */ +[data-theme='hill-valley-85'] .glass { + background: rgba(6, 4, 12, 0.97) !important; + backdrop-filter: none !important; + border: 1px solid rgba(255, 140, 0, 0.28) !important; + box-shadow: + 0 0 20px rgba(255, 100, 0, 0.08), + inset 0 0 16px rgba(255, 100, 0, 0.02) !important; + border-radius: 4px !important; +} +[data-theme='hill-valley-85'] .glass [style*="var(--bg-hover)"] { + background: rgba(255, 140, 0, 0.10) !important; + border-radius: 2px !important; +} +[data-theme='hill-valley-85'] .glass [style*="var(--text-primary)"] { color: #ede0c8 !important; } +[data-theme='hill-valley-85'] .glass [style*="var(--text-secondary)"] { color: #c8b898 !important; } +[data-theme='hill-valley-85'] .glass [style*="var(--text-muted)"] { color: #5a4e70 !important; } + +/* ── Hover / selection: fire orange glow ── */ +[data-theme='hill-valley-85'] .queue-tab-btn:hover { background: rgba(255,140,0,0.10); color: #ff8c00; } +[data-theme='hill-valley-85'] .settings-tab:hover { background: rgba(255,140,0,0.10); color: #ff8c00; } +[data-theme='hill-valley-85'] .settings-tab.active { + background: rgba(255,140,0,0.15); + color: #ff8c00; + box-shadow: inset 2px 0 0 #ff8c00; +} +[data-theme='hill-valley-85'] .custom-select-trigger:hover { background: rgba(255,140,0,0.10); } +[data-theme='hill-valley-85'] .custom-select-option:hover { + background: rgba(255,140,0,0.14) !important; + color: #ffaa33 !important; +} +[data-theme='hill-valley-85'] .artist-ext-link:hover { + background: rgba(255,140,0,0.10); + color: #ff8c00 !important; + border-color: rgba(255,140,0,0.50) !important; +} +[data-theme='hill-valley-85'] .np-action-btn:hover { background: rgba(255,140,0,0.10); } +[data-theme='hill-valley-85'] .np-queue-item:hover, +[data-theme='hill-valley-85'] .np-queue-item.context-active { + background: rgba(255,140,0,0.12); + box-shadow: inset 2px 0 0 #ff8c00; +} +[data-theme='hill-valley-85'] .track-row:hover, +[data-theme='hill-valley-85'] .track-row.context-active { + background: rgba(255,140,0,0.08) !important; + box-shadow: inset 2px 0 0 #ff8c00; +} +[data-theme='hill-valley-85'] .artist-row:hover { + background: rgba(255,140,0,0.08); + box-shadow: inset 2px 0 0 #ff8c00; +} +[data-theme='hill-valley-85'] .playlist-row:hover { + background: rgba(255,140,0,0.08); + box-shadow: inset 2px 0 0 #ff8c00; +} +[data-theme='hill-valley-85'] .queue-item:hover, +[data-theme='hill-valley-85'] .queue-item.context-active { + background: rgba(255,140,0,0.10) !important; + box-shadow: inset 2px 0 0 #ff8c00; +} +[data-theme='hill-valley-85'] .queue-item:hover .queue-item-title, +[data-theme='hill-valley-85'] .queue-item:hover .queue-item-artist, +[data-theme='hill-valley-85'] .queue-item:hover .queue-item-duration, +[data-theme='hill-valley-85'] .queue-item.context-active .queue-item-title, +[data-theme='hill-valley-85'] .queue-item.context-active .queue-item-artist, +[data-theme='hill-valley-85'] .queue-item.context-active .queue-item-duration { color: #ff8c00; } + +/* ── Active queue item: glowing orange ── */ +[data-theme='hill-valley-85'] .queue-item.active { + background: rgba(255, 140, 0, 0.08); + box-shadow: inset 2px 0 0 #ff8c00; +} +[data-theme='hill-valley-85'] .np-queue-item-active { color: #ff8c00; text-shadow: 0 0 8px rgba(255,140,0,0.55); } +[data-theme='hill-valley-85'] .np-queue-item.active { background: rgba(255,140,0,0.08); } +[data-theme='hill-valley-85'] .np-album-track.active .np-album-track-title, +[data-theme='hill-valley-85'] .np-album-track.active .np-album-track-num { + color: #ff8c00; + text-shadow: 0 0 8px rgba(255,140,0,0.50); } -/* ── Turtle Power (Series) ──────────────────────────────────── */ [data-theme='turtle-power'] { color-scheme: dark; --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%2333cc33%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); @@ -5504,51 +7174,59 @@ input[type="range"]:hover::-webkit-slider-thumb { color-scheme: light; --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000000%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); - --ctp-crust: #c0c0c0; - --ctp-mantle: #c0c0c0; - --ctp-base: #008080; + /* ── Authentische W3.1 Palette ── */ + --ctp-crust: #808080; + --ctp-mantle: #a0a0a0; + --ctp-base: #c0c0c0; /* Reines W3.1 Grau */ --ctp-surface0: #ffffff; --ctp-surface1: #e0e0e0; - --ctp-surface2: #808080; + --ctp-surface2: #c0c0c0; --ctp-overlay0: #808080; --ctp-overlay1: #404040; --ctp-overlay2: #000000; --ctp-text: #000000; --ctp-subtext1: #000000; - --ctp-subtext0: #404040; + --ctp-subtext0: #000000; --ctp-mauve: #000080; --ctp-lavender: #0000a0; --ctp-green: #008000; - --ctp-yellow: #ffff00; - --ctp-red: #ff0000; - --ctp-blue: #000080; --ctp-teal: #008080; --ctp-sky: #0000ff; + --ctp-blue: #000080; --ctp-sapphire: #000080; --ctp-pink: #ff00ff; --ctp-flamingo: #ff00ff; --ctp-rosewater:#ffffff; + --ctp-yellow: #ffff00; --ctp-peach: #ff8000; --ctp-maroon: #800000; + --ctp-red: #ff0000; - --bg-app: #008080; - --bg-sidebar: #c0c0c0; - --bg-card: #ffffff; - --bg-hover: rgba(0, 0, 128, 0.1); - --bg-player: #c0c0c0; - --bg-glass: rgba(192, 192, 192, 0.9); + --bg-app: #008080; /* Teal Desktop */ + --bg-sidebar: #c0c0c0; + --bg-card: #ffffff; + --bg-hover: #000080; + --bg-player: #c0c0c0; + --bg-glass: #c0c0c0; - --accent: #000080; - --accent-dim: rgba(0, 0, 128, 0.15); - --accent-glow: transparent; - --volume-accent:#000080; + --accent: #000080; + --accent-dim: rgba(0, 0, 128, 0.12); + --accent-glow: transparent; + --volume-accent: #000080; --text-primary: #000000; --text-secondary:#000000; - --text-muted: #404040; + --text-muted: #000000; + --border: #000000; --border-subtle: #808080; + --border-dropdown: #000000; + --shadow-dropdown: rgba(0, 0, 0, 0.4); + + --positive: #008000; + --warning: #808000; + --danger: #ff0000; --radius-sm: 0px; --radius-md: 0px; @@ -5557,45 +7235,214 @@ input[type="range"]:hover::-webkit-slider-thumb { --radius-full: 0px; } -[data-theme='w3-1'] .sidebar { - border-right: 2px solid #000; - box-shadow: inset -1px -1px #808080, inset 1px 1px #fff; +/* Teal Desktop */ +[data-theme='w3-1'] .app-shell { + background: #008080; } -[data-theme='w3-1'] .player-bar { - border-top: 2px solid #000; - box-shadow: inset 1px 1px #fff; -} - -[data-theme='w3-1'] .btn, -[data-theme='w3-1'] .player-btn { +/* ── W3.1 Bevel (2-Layer, schlichter als W98) ── */ +[data-theme='w3-1'] .sidebar, +[data-theme='w3-1'] .player-bar, +[data-theme='w3-1'] .card { background: #c0c0c0; - border: 1px solid #000; - box-shadow: inset 1px 1px #fff, inset -1px -1px #808080; - color: #000 !important; + border: 2px solid #000000; + box-shadow: + inset 1px 1px #ffffff, + inset -1px -1px #808080; } -[data-theme='w3-1'] .btn:active, -[data-theme='w3-1'] .player-btn:active { - box-shadow: inset -1px -1px #fff, inset 1px 1px #808080; +[data-theme='w3-1'] .sidebar { + border-right: 2px solid #000000; } +/* Titelbalken-Stil: solides Navy — der Kern-Unterschied zu W98 */ +[data-theme='w3-1'] .player-bar { + border-top: 2px solid #000000; +} + +[data-theme='w3-1'] .player-track-name { + background: #000080; + color: #ffffff !important; + padding: 2px 6px; + font-weight: bold; + text-align: center; + letter-spacing: 0.03em; +} + +[data-theme='w3-1'] .player-track-artist, +[data-theme='w3-1'] .player-time { + color: #000000 !important; +} + +/* Nav */ [data-theme='w3-1'] .nav-link.active { background: #000080 !important; color: #ffffff !important; } +[data-theme='w3-1'] .nav-link.active svg { color: #ffffff !important; } +[data-theme='w3-1'] .nav-link:hover:not(.active) { + background: #000080 !important; + color: #ffffff !important; +} +[data-theme='w3-1'] .nav-link:hover:not(.active) svg { color: #ffffff !important; } -[data-theme='w3-1'] .player-track-name, -[data-theme='w3-1'] .player-time { - color: #000 !important; - font-weight: bold; +/* Accordion (Settings Theme Picker) */ +[data-theme='w3-1'] .nav-section-label { color: #000000 !important; } +[data-theme='w3-1'] .theme-accordion-header:hover { background: #000080; color: #ffffff; } +[data-theme='w3-1'] .theme-accordion-open .theme-accordion-header { background: #000080; color: #ffffff; } +[data-theme='w3-1'] .theme-accordion-open .theme-accordion-chevron { color: #ffffff; } + +/* Alle Buttons: W3.1 Bevel (einfach, ohne doppelte Inset-Schicht) */ +[data-theme='w3-1'] .btn, +[data-theme='w3-1'] .btn-primary, +[data-theme='w3-1'] .btn-surface, +[data-theme='w3-1'] .btn-ghost, +[data-theme='w3-1'] .hero-play-btn, +[data-theme='w3-1'] .queue-round-btn, +[data-theme='w3-1'] .player-btn, +[data-theme='w3-1'] .album-card-details-btn { + background: #c0c0c0 !important; + color: #000000 !important; + border: 1px solid #000000 !important; + border-radius: 0 !important; + box-shadow: inset 1px 1px #ffffff, inset -1px -1px #808080 !important; + text-shadow: none !important; + filter: none !important; + transform: none !important; } +/* Gedrückt */ +[data-theme='w3-1'] .btn:active, +[data-theme='w3-1'] .btn-primary:active, +[data-theme='w3-1'] .btn-surface:active, +[data-theme='w3-1'] .btn-ghost:active, +[data-theme='w3-1'] .hero-play-btn:active, +[data-theme='w3-1'] .queue-round-btn:active, +[data-theme='w3-1'] .player-btn:active, +[data-theme='w3-1'] .album-card-details-btn:active { + box-shadow: inset -1px -1px #ffffff, inset 1px 1px #808080 !important; +} + +/* Hover */ +[data-theme='w3-1'] .btn:hover, +[data-theme='w3-1'] .btn-primary:hover, +[data-theme='w3-1'] .btn-surface:hover, +[data-theme='w3-1'] .btn-ghost:hover, +[data-theme='w3-1'] .hero-play-btn:hover, +[data-theme='w3-1'] .album-card-details-btn:hover { + background: #d0d0d0 !important; + color: #000000 !important; +} + +/* Aktive Queue-Buttons */ +[data-theme='w3-1'] .queue-round-btn.active { + background: #000080 !important; + color: #ffffff !important; + box-shadow: inset -1px -1px #ffffff, inset 1px 1px #808080 !important; +} +[data-theme='w3-1'] .queue-round-btn:hover:not(:disabled):not(.active) { + background: #d0d0d0 !important; + color: #000000 !important; +} + +/* Progress Bar */ +[data-theme='w3-1'] .progress-bar-track { + background: #ffffff; + box-shadow: inset 1px 1px #808080, inset -1px -1px #ffffff; + border-radius: 0; +} +[data-theme='w3-1'] .progress-bar-fill { + background: #000080; + border-radius: 0; + box-shadow: none; +} + +/* Scrollbar */ +[data-theme='w3-1'] ::-webkit-scrollbar { width: 16px; height: 16px; } +[data-theme='w3-1'] ::-webkit-scrollbar-track { background: #c0c0c0; } +[data-theme='w3-1'] ::-webkit-scrollbar-thumb { + background: #c0c0c0; + border: 1px solid #000000; + box-shadow: inset 1px 1px #ffffff, inset -1px -1px #808080; +} + +/* Cards */ [data-theme='w3-1'] .card { - border: 1px solid #000; - box-shadow: 2px 2px 0px #000; + background: #ffffff; + border: 2px solid #000000; + box-shadow: inset 1px 1px #ffffff, inset -1px -1px #808080; } +/* Glass (Live Dropdown etc.) */ +[data-theme='w3-1'] .glass { + background: #c0c0c0 !important; + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; + border: 2px solid #000000; + box-shadow: inset 1px 1px #ffffff, inset -1px -1px #808080; + color: #000000; +} +[data-theme='w3-1'] .glass [style*="var(--bg-hover)"] { + background: #d8d8d8 !important; + border: 1px solid #808080; + border-radius: 0 !important; +} +[data-theme='w3-1'] .glass [style*="var(--text-primary)"], +[data-theme='w3-1'] .glass [style*="var(--text-secondary)"], +[data-theme='w3-1'] .glass [style*="var(--text-muted)"] { color: #000000 !important; } + +/* Universelle Hover-Zustände → navy + weiß */ +[data-theme='w3-1'] .queue-tab-btn:hover { background: #d0d0d0; color: #000000; } +[data-theme='w3-1'] .settings-tab:hover { background: #000080; color: #ffffff; } +[data-theme='w3-1'] .custom-select-trigger:hover { background: #000080; color: #ffffff; } +[data-theme='w3-1'] .custom-select-option:hover { background: #000080 !important; color: #ffffff !important; } +[data-theme='w3-1'] .artist-ext-link:hover { background: #000080; color: #ffffff !important; } +[data-theme='w3-1'] .np-action-btn:hover { background: #000080; color: #ffffff; } +[data-theme='w3-1'] .np-queue-item:hover, +[data-theme='w3-1'] .np-queue-item.context-active { background: #000080; color: #ffffff; } +[data-theme='w3-1'] .track-row:hover, +[data-theme='w3-1'] .track-row.context-active { background: #000080 !important; } +[data-theme='w3-1'] .track-row:hover *, +[data-theme='w3-1'] .track-row.context-active * { color: #ffffff !important; } +[data-theme='w3-1'] .artist-row:hover { background: #000080; color: #ffffff; } +[data-theme='w3-1'] .playlist-row:hover { background: #000080; } +[data-theme='w3-1'] .playlist-row:hover, +[data-theme='w3-1'] .playlist-row:hover * { color: #ffffff; } +[data-theme='w3-1'] .queue-item:hover, +[data-theme='w3-1'] .queue-item.context-active { background: #000080 !important; } +[data-theme='w3-1'] .queue-item:hover .queue-item-title, +[data-theme='w3-1'] .queue-item:hover .queue-item-artist, +[data-theme='w3-1'] .queue-item:hover .queue-item-duration, +[data-theme='w3-1'] .queue-item.context-active .queue-item-title, +[data-theme='w3-1'] .queue-item.context-active .queue-item-artist, +[data-theme='w3-1'] .queue-item.context-active .queue-item-duration { color: #ffffff; } +[data-theme='w3-1'] .player-btn:hover { background: #000080; color: #ffffff; } +[data-theme='w3-1'] .player-btn-primary { background: #c0c0c0 !important; color: #000000 !important; } +[data-theme='w3-1'] .player-btn-primary:hover { background: #000080 !important; color: #ffffff !important; } +[data-theme='w3-1'] .search-result-item:hover, +[data-theme='w3-1'] .search-result-item.active { background: #000080; } +[data-theme='w3-1'] .search-result-item:hover .search-result-name, +[data-theme='w3-1'] .search-result-item:hover .search-result-sub, +[data-theme='w3-1'] .search-result-item.active .search-result-name, +[data-theme='w3-1'] .search-result-item.active .search-result-sub { color: #ffffff; } +[data-theme='w3-1'] .np-title { color: #000080 !important; } +[data-theme='w3-1'] .changelog-code { background: #ffffff; color: #000080; border: 1px solid #808080; } +[data-theme='w3-1'] .keybind-badge { background: #c0c0c0 !important; color: #000000 !important; border: 1px solid #808080 !important; } +[data-theme='w3-1'] .genre-keyword-badge { background: #c0c0c0 !important; color: #000000 !important; border: 1px solid #808080 !important; } +[data-theme='w3-1'] .eq-ctrl-btn { background: #c0c0c0; color: #000000; border: 1px solid #808080; box-shadow: inset 1px 1px #ffffff, inset -1px -1px #808080; } +[data-theme='w3-1'] .eq-ctrl-btn:hover { background: #000080; color: #ffffff; } +[data-theme='w3-1'] .toggle-track::before { background: #c0c0c0; border: 1px solid #808080; } +[data-theme='w3-1'] .hero-eyebrow { color: rgba(255,255,255,0.9); } +[data-theme='w3-1'] .hero-meta .badge { background: rgba(255,255,255,0.15); } +[data-theme='w3-1'] .connection-type, +[data-theme='w3-1'] .connection-server { color: #000000; } +[data-theme='w3-1'] .collapse-btn { border-color: #808080 !important; } +[data-theme='w3-1'] .collapse-btn:hover { background: #000080 !important; color: #ffffff !important; } +[data-theme='w3-1'] .album-row-nav .nav-btn:hover:not(.disabled) { background: #000080; color: #ffffff; } +[data-theme='w3-1'] .help-question:hover { color: #000080; } +[data-theme='w3-1'] .help-item-open .help-question { color: #000080; font-weight: bold; } +[data-theme='w3-1'] .year-toggle:hover { color: #000080; } + [data-theme='aqua-quartz'] { color-scheme: light; --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23666666%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); @@ -5658,14 +7505,6 @@ input[type="range"]:hover::-webkit-slider-thumb { /* Aluminium pinstripe background */ [data-theme='aqua-quartz'] .app-shell { background: #e8e8e8; - background-image: - repeating-linear-gradient( - to bottom, - transparent 0px, - transparent 1px, - rgba(255,255,255,0.55) 1px, - rgba(255,255,255,0.55) 2px - ); } /* Iconic Aqua blue Source List sidebar */ @@ -5858,11 +7697,14 @@ input[type="range"]:hover::-webkit-slider-thumb { box-shadow: 0 2px 8px rgba(49,101,196,0.5), inset 0 1px 0 rgba(255,255,255,0.7); color: white; text-shadow: 0 1px 1px rgba(0,0,0,0.4); + transition: filter var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast); } [data-theme='aqua-quartz'] .hero-play-btn:hover { + background: linear-gradient(to bottom, rgba(255,255,255,0.98) 0%, rgba(185,215,255,0.95) 20%, #3a72d8 48%, #2058c0 52%, #2d62cc 75%, #5585e0 100%); filter: brightness(1.08); box-shadow: 0 3px 12px rgba(49,101,196,0.6), inset 0 1px 0 rgba(255,255,255,0.7); + transform: scale(1.02); } /* Album card hover play button — blue jelly */ @@ -5874,91 +7716,204 @@ input[type="range"]:hover::-webkit-slider-thumb { text-shadow: 0 1px 1px rgba(0,0,0,0.4); } +/* ─── Spider-Tech — Spider-Man ─── */ [data-theme='spider-tech'] { color-scheme: dark; - --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23CBD5E1%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); - - --ctp-crust: #050C1A; - --ctp-mantle: #0A192F; - --ctp-base: #0F172A; - --ctp-surface0: #1E293B; - --ctp-surface1: #334155; - --ctp-surface2: #475569; - --ctp-overlay0: #64748B; - --ctp-overlay1: #94A3B8; - --ctp-overlay2: #CBD5E1; - --ctp-text: #F8FAFC; - --ctp-subtext1: #E2E8F0; - --ctp-subtext0: #94A3B8; + --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23E62429%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); + /* Palette — suit red, night-sky navy, web black */ + --ctp-crust: #060408; + --ctp-mantle: #0a0610; + --ctp-base: #0e0c18; + --ctp-surface0: #181428; + --ctp-surface1: #241e3a; + --ctp-surface2: #302848; + --ctp-overlay0: #4a3e68; + --ctp-overlay1: #6a5888; + --ctp-overlay2: #9080a8; + --ctp-text: #f0ecf8; + --ctp-subtext1: #d0c8e0; + --ctp-subtext0: #a898c0; --ctp-mauve: #E62429; - --ctp-lavender: #FF4D4D; - --ctp-green: #22C55E; - --ctp-teal: #00D4FF; - --ctp-sky: #38BDF8; - --ctp-blue: #0055A2; - --ctp-sapphire: #0044cc; - --ctp-pink: #f43f5e; - --ctp-flamingo: #fb7185; - --ctp-rosewater:#fecdd3; - --ctp-yellow: #FACC15; - --ctp-peach: #f97316; - --ctp-maroon: #9f1239; + --ctp-lavender: #ff4a50; + --ctp-pink: #ff4a50; + --ctp-flamingo: #cc1a1f; + --ctp-rosewater:#f0ecf8; + --ctp-green: #4adf80; + --ctp-teal: #3ab8d0; + --ctp-sky: #4a88ff; + --ctp-blue: #1e52c8; + --ctp-sapphire: #1e52c8; + --ctp-yellow: #f0c030; + --ctp-peach: #E62429; + --ctp-maroon: #8b0010; --ctp-red: #E62429; - --bg-app: #0F172A; - --bg-sidebar: #0A192F; - --bg-card: #1E293B; - --bg-hover: rgba(230, 36, 41, 0.1); - --bg-player: #050C1A; - --bg-glass: rgba(15, 23, 42, 0.85); - + --bg-app: #0e0c18; + --bg-sidebar: #0a0610; + --bg-card: #181428; + --bg-hover: #241e3a; + --bg-player: #060408; + --bg-glass: rgba(10, 6, 16, 0.92); --accent: #E62429; - --accent-dim: rgba(230, 36, 41, 0.15); - --accent-glow: rgba(230, 36, 41, 0.4); - --volume-accent: #E62429; - - --text-primary: #F8FAFC; - --text-secondary:#CBD5E1; - --text-muted: #64748B; - - --border: #1E293B; - --border-subtle: rgba(255, 255, 255, 0.05); - - --radius-sm: 4px; - --radius-md: 8px; - --radius-lg: 12px; - --radius-xl: 16px; - --radius-full: 999px; + --accent-dim: rgba(230, 36, 41, 0.14); + --accent-glow: rgba(230, 36, 41, 0.38); + --text-primary: #f0ecf8; + --text-secondary:#9080a8; + --text-muted: #a898c0; + --border: rgba(230, 36, 41, 0.18); + --border-subtle: rgba(230, 36, 41, 0.08); + --border-dropdown: rgba(230, 36, 41, 0.30); + --shadow-dropdown: rgba(0, 0, 0, 0.92); + --positive: #4adf80; + --warning: #f0c030; + --danger: #E62429; + --radius-sm: 2px; + --radius-md: 4px; + --radius-lg: 6px; } -[data-theme='spider-tech'] .player-bar { - border-top: 2px solid var(--accent); - box-shadow: 0 -4px 20px rgba(230, 36, 41, 0.15); +/* App shell — Into the Spider-Verse comic halftone dots */ +[data-theme='spider-tech'] .app-shell { + background-image: radial-gradient( + circle, + rgba(230, 36, 41, 0.055) 1px, + transparent 1px + ); + background-size: 14px 14px; } +/* Sidebar — CSS spider web radiating from top-left corner */ [data-theme='spider-tech'] .sidebar { - border-right: 1px solid rgba(0, 85, 162, 0.3); - background-image: radial-gradient(circle at 2px 2px, rgba(255,255,255,0.12) 1.5px, transparent 0); - background-size: 20px 20px; + background: #080510; + border-right: 1px solid rgba(230, 36, 41, 0.22); + background-image: + repeating-radial-gradient( + circle at 0% 0%, + transparent 0px, + transparent 38px, + rgba(230, 36, 41, 0.10) 39px, + rgba(230, 36, 41, 0.10) 40px + ), + repeating-conic-gradient( + from 0deg at 0% 0%, + transparent 0deg, + transparent 19deg, + rgba(230, 36, 41, 0.07) 19deg, + rgba(230, 36, 41, 0.07) 20deg + ); } -[data-theme='spider-tech'] .player-btn-primary { - background: var(--accent); - color: white; - box-shadow: 0 0 15px var(--accent-glow); -} - -[data-theme='spider-tech'] .nav-link.active { - background: linear-gradient(90deg, var(--accent-dim) 0%, transparent 100%); - color: var(--accent); - border-left: 3px solid var(--accent); +/* Player bar — deep black with red suit border + glow */ +[data-theme='spider-tech'] .player-bar { + background: #060408; + border-top: 2px solid #E62429; + box-shadow: 0 -6px 28px rgba(230, 36, 41, 0.20), 0 -1px 0 rgba(0,0,0,0.9); } +/* Track name — Spider-Man red, bold */ [data-theme='spider-tech'] .player-track-name { - color: var(--text-primary); + color: #E62429; font-weight: 700; - text-shadow: 0 0 10px rgba(230, 36, 41, 0.2); + text-shadow: 0 0 10px rgba(230,36,41,0.45), 0 0 24px rgba(230,36,41,0.20); +} + +/* Artist name — Spider suit blue */ +[data-theme='spider-tech'] .player-artist-name { + color: #4a88ff; +} + +/* Nav active — red left bar */ +[data-theme='spider-tech'] .nav-link.active { + background: linear-gradient(90deg, rgba(230,36,41,0.18) 0%, transparent 100%); + border-left: 3px solid #E62429; + color: #E62429; +} + +[data-theme='spider-tech'] .nav-link:hover:not(.active) { + background: linear-gradient(90deg, rgba(230,36,41,0.08) 0%, transparent 100%); + border-left: 3px solid rgba(230,36,41,0.35); +} + +/* Content header */ +[data-theme='spider-tech'] .content-header { + border-bottom: 1px solid rgba(230,36,41,0.14); +} + +/* Cards — red border glow on hover */ +[data-theme='spider-tech'] .album-card:hover, +[data-theme='spider-tech'] .artist-card:hover { + box-shadow: 0 0 0 1px rgba(230,36,41,0.55), 0 4px 20px rgba(230,36,41,0.16); +} + +/* Track / queue rows */ +[data-theme='spider-tech'] .track-row:hover, +[data-theme='spider-tech'] .queue-item:hover { + box-shadow: inset 2px 0 0 #E62429; + background: rgba(230,36,41,0.06); +} + +/* Primary play button — suit red */ +[data-theme='spider-tech'] .player-btn-primary { + background: linear-gradient(180deg, #ff4a50 0%, #E62429 50%, #b81820 100%); + color: #ffffff; + box-shadow: 0 0 16px rgba(230,36,41,0.50); + border: 1px solid #9c1018; +} + +[data-theme='spider-tech'] .player-btn-primary:hover { + background: linear-gradient(180deg, #ff6065 0%, #f03035 50%, #cc2025 100%); + box-shadow: 0 0 26px rgba(230,36,41,0.72); +} + +/* btn-primary */ +[data-theme='spider-tech'] .btn-primary { + background: linear-gradient(180deg, #ff4a50 0%, #E62429 50%, #b81820 100%); + color: #ffffff; + border: 1px solid #9c1018; +} + +[data-theme='spider-tech'] .btn-primary:hover { + background: linear-gradient(180deg, #ff6065 0%, #f03035 50%, #cc2025 100%); +} + +/* Hero play button */ +[data-theme='spider-tech'] .hero-play-btn { + background: linear-gradient(180deg, #ff4a50 0%, #E62429 50%, #b81820 100%); + color: #ffffff; + border: 1px solid #9c1018; + box-shadow: 0 2px 16px rgba(230,36,41,0.50); + transition: filter var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast); +} + +[data-theme='spider-tech'] .hero-play-btn:hover { + background: linear-gradient(180deg, #ff6065 0%, #f03035 50%, #cc2025 100%); + box-shadow: 0 4px 26px rgba(230,36,41,0.72); + transform: scale(1.02); +} + +/* Album card overlay button */ +[data-theme='spider-tech'] .album-card-details-btn { + background: linear-gradient(180deg, #ff4a50 0%, #E62429 50%, #b81820 100%); + color: #ffffff; + border: 1px solid #9c1018; + box-shadow: 0 2px 12px rgba(230,36,41,0.45); +} + +/* Scrollbar — dark with red thumb */ +[data-theme='spider-tech'] ::-webkit-scrollbar { width: 5px; height: 5px; } + +[data-theme='spider-tech'] ::-webkit-scrollbar-track { + background: #0a0610; +} + +[data-theme='spider-tech'] ::-webkit-scrollbar-thumb { + background: rgba(230,36,41,0.40); + border-radius: 3px; +} + +[data-theme='spider-tech'] ::-webkit-scrollbar-thumb:hover { + background: #E62429; } /* ── Jayfin (Mediaplayer) ─────────────────────────────────────── */ @@ -6011,7 +7966,7 @@ input[type="range"]:hover::-webkit-slider-thumb { --text-primary: #ffffff; --text-secondary:#c8c8c8; - --text-muted: #585858; + --text-muted: #888888; --border: #2a2a2a; --border-subtle: #1e1e1e; @@ -6104,3 +8059,913 @@ input[type="range"]:hover::-webkit-slider-thumb { /* Connection indicators: schwarz auf warmem Grau */ [data-theme='w98'] .connection-type, [data-theme='w98'] .connection-server { color: #000000; } + +/* ─── MS-DOS ─── */ +@keyframes dos-blink { + 0%, 49% { opacity: 1; } + 50%, 100% { opacity: 0; } +} + +[data-theme='dos'] { + color-scheme: dark; + font-family: 'Courier New', Courier, 'Lucida Console', monospace; + --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23AAAAAA%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); + + /* Pure ANSI color palette */ + --ctp-crust: #000000; + --ctp-mantle: #000080; + --ctp-base: #0000AA; + --ctp-surface0: #000080; + --ctp-surface1: #0000AA; + --ctp-surface2: #0000CC; + --ctp-overlay0: #8888AA; + --ctp-overlay1: #BBBBCC; + --ctp-overlay2: #E8E8E8; + --ctp-text: #E8E8E8; + --ctp-subtext1: #BBBBCC; + --ctp-subtext0: #8888AA; + --ctp-mauve: #FF55FF; + --ctp-lavender: #FF55FF; + --ctp-pink: #FF55FF; + --ctp-flamingo: #FF5555; + --ctp-rosewater:#FFFFFF; + --ctp-green: #55FF55; + --ctp-teal: #55FFFF; + --ctp-sky: #55FFFF; + --ctp-blue: #5555FF; + --ctp-sapphire: #5555FF; + --ctp-yellow: #FFFF55; + --ctp-peach: #FF5555; + --ctp-maroon: #AA0000; + --ctp-red: #FF5555; + + --bg-app: #0000AA; + --bg-sidebar: #000080; + --bg-card: #000080; + --bg-hover: rgba(170, 170, 170, 0.15); + --bg-player: #000000; + --bg-glass: rgba(0, 0, 128, 0.95); + --accent: #FFFF55; + --accent-dim: rgba(255, 255, 85, 0.15); + --accent-glow: rgba(255, 255, 85, 0.3); + --text-primary: #E8E8E8; + --text-secondary:#BBBBCC; + --text-muted: #8888AA; + --border: #AAAAAA; + --border-subtle: #4444AA; + --border-dropdown: #AAAAAA; + --shadow-dropdown: rgba(0, 0, 0, 0.95); + --positive: #55FF55; + --warning: #FFFF55; + --danger: #FF5555; + /* Square everything — no rounded corners in DOS */ + --radius-sm: 0px; + --radius-md: 0px; + --radius-lg: 0px; + --radius-full: 0px; +} + +/* Monospace override — html inherits to most elements; form controls need explicit override */ +[data-theme='dos'] button, +[data-theme='dos'] input, +[data-theme='dos'] textarea, +[data-theme='dos'] select { + font-family: 'Courier New', Courier, 'Lucida Console', monospace; +} + +/* Sidebar — dark navy with CRT scanlines, thick grey right border like a DOS panel edge */ +[data-theme='dos'] .sidebar { + background-color: #000080; + background-image: repeating-linear-gradient( + 0deg, + rgba(0, 0, 0, 0.20) 0px, + rgba(0, 0, 0, 0.20) 1px, + transparent 1px, + transparent 3px + ); + border-right: 2px solid #AAAAAA; +} + +/* Active nav — classic DOS inverted selection */ +[data-theme='dos'] .nav-link.active { + background: #AAAAAA; + color: #000080; + border-left: none; + font-weight: 700; +} + +[data-theme='dos'] .nav-link:hover:not(.active) { + background: rgba(170, 170, 170, 0.18); + color: #FFFF55; +} + +/* Player bar — pure black, the C:\> command prompt */ +[data-theme='dos'] .player-bar { + background-color: #000000; + background-image: repeating-linear-gradient( + 0deg, + rgba(0, 0, 0, 0.20) 0px, + rgba(0, 0, 0, 0.20) 1px, + transparent 1px, + transparent 3px + ); + border-top: 2px solid #AAAAAA; + box-shadow: none; +} + +/* Track name — bright yellow with blinking block cursor */ +[data-theme='dos'] .player-track-name { + color: #FFFF55; + text-shadow: none; +} + +[data-theme='dos'] .player-track-name::after { + content: '\258B'; + animation: dos-blink 1s step-end infinite; + margin-left: 3px; + font-size: 0.8em; + vertical-align: baseline; +} + +/* Artist name — bright cyan (ANSI 11) */ +[data-theme='dos'] .player-artist-name { + color: #55FFFF; +} + +/* Content header — simple grey border, no ornate gradient */ +[data-theme='dos'] .content-header { + border-bottom: 1px solid #AAAAAA; +} + +/* Album/artist cards — flat navy panels with grey border */ +[data-theme='dos'] .album-card, +[data-theme='dos'] .artist-card { + background: #000080; + border: 1px solid #AAAAAA; + box-shadow: none; +} + +[data-theme='dos'] .album-card:hover, +[data-theme='dos'] .artist-card:hover { + background: #0000AA; + border-color: #FFFFFF; + box-shadow: none; +} + +/* Track / queue row hover — inverted DOS selection */ +[data-theme='dos'] .track-row:hover, +[data-theme='dos'] .queue-item:hover { + background: #AAAAAA !important; + color: #000080; + box-shadow: none; +} + +/* Primary play button — flat grey, sharp, DOS dialog style */ +[data-theme='dos'] .player-btn-primary { + background: #AAAAAA; + color: #000000; + border: 2px solid #FFFFFF; + box-shadow: none; +} + +[data-theme='dos'] .player-btn-primary:hover { + background: #FFFFFF; + color: #000000; + box-shadow: none; + transform: none; +} + +/* btn-primary — uppercase DOS dialog button */ +[data-theme='dos'] .btn-primary { + background: #AAAAAA; + color: #000000; + border: 1px solid #FFFFFF; + text-transform: uppercase; + letter-spacing: 0.06em; + box-shadow: none; +} + +[data-theme='dos'] .btn-primary:hover { + background: #FFFFFF; + color: #000000; + box-shadow: none; +} + +/* btn-surface */ +[data-theme='dos'] .btn-surface, +[data-theme='dos'] .btn { + border: 1px solid #AAAAAA; + box-shadow: none; +} + +/* Hero play button */ +[data-theme='dos'] .hero-play-btn { + background: #AAAAAA; + color: #000000; + border: 2px solid #FFFFFF; + text-transform: uppercase; + letter-spacing: 0.08em; + box-shadow: none; + transition: background var(--transition-fast), color var(--transition-fast); +} + +[data-theme='dos'] .hero-play-btn:hover { + background: #FFFFFF; + color: #000000; + transform: none; + filter: none; + box-shadow: none; +} + +/* Album card overlay play button */ +[data-theme='dos'] .album-card-details-btn { + background: #AAAAAA; + color: #000000; + border: 2px solid #FFFFFF; + box-shadow: none; +} + +[data-theme='dos'] .album-card-details-btn:hover { + background: #FFFFFF; + color: #000000; +} + +/* Queue round buttons — square in DOS */ +[data-theme='dos'] .queue-round-btn { + border: 1px solid #AAAAAA; + box-shadow: none; +} + +[data-theme='dos'] .queue-round-btn.active { + background: #AAAAAA; + color: #000000; + border-color: #FFFFFF; + box-shadow: none; +} + +/* Input fields */ +[data-theme='dos'] input, +[data-theme='dos'] textarea { + background: #000080; + border: 1px solid #AAAAAA; + border-radius: 0; +} + +[data-theme='dos'] input:focus, +[data-theme='dos'] textarea:focus { + border-color: #FFFF55; + outline: none; + box-shadow: none; +} + +/* Scrollbar — wide 16px DOS style with sharp thumb */ +[data-theme='dos'] ::-webkit-scrollbar { + width: 16px; + height: 16px; +} + +[data-theme='dos'] ::-webkit-scrollbar-track { + background: #000080; + border-left: 1px solid #AAAAAA; +} + +[data-theme='dos'] ::-webkit-scrollbar-thumb { + background: #AAAAAA; + border-radius: 0; + border: 1px solid #FFFFFF; +} + +[data-theme='dos'] ::-webkit-scrollbar-thumb:hover { + background: #FFFFFF; +} + + +/* ─── Unix Shell ─── */ +@keyframes unix-cursor-blink { + 0%, 49% { opacity: 1; } + 50%, 100% { opacity: 0; } +} + +[data-theme='unix'] { + color-scheme: dark; + font-family: 'Courier New', Courier, 'Lucida Console', monospace; + --select-arrow: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%2322C55E%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E"); + + /* ANSI colors mapped to semantic palette */ + --ctp-crust: #000000; + --ctp-mantle: #0a0a0a; + --ctp-base: #111111; + --ctp-surface0: #1a1a1a; + --ctp-surface1: #222222; + --ctp-surface2: #2e2e2e; + --ctp-overlay0: #666666; + --ctp-overlay1: #888888; + --ctp-overlay2: #AAAAAA; + --ctp-text: #C8C8C8; + --ctp-subtext1: #AAAAAA; + --ctp-subtext0: #888888; + --ctp-mauve: #C678DD; + --ctp-lavender: #5588FF; + --ctp-pink: #E06C75; + --ctp-flamingo: #FF6B6B; + --ctp-rosewater:#FFFFFF; + --ctp-green: #22C55E; + --ctp-teal: #55FFFF; + --ctp-sky: #55FFFF; + --ctp-blue: #5588FF; + --ctp-sapphire: #5588FF; + --ctp-yellow: #E5C07B; + --ctp-peach: #E06C75; + --ctp-maroon: #AA0000; + --ctp-red: #E06C75; + + --bg-app: #000000; + --bg-sidebar: #0a0a0a; + --bg-card: #111111; + --bg-hover: #1a1a1a; + --bg-player: #000000; + --bg-glass: rgba(0, 0, 0, 0.92); + --accent: #22C55E; + --accent-dim: rgba(34, 197, 94, 0.10); + --accent-glow: rgba(34, 197, 94, 0.25); + --text-primary: #C8C8C8; + --text-secondary:#999999; + --text-muted: #666666; + --border: #222222; + --border-subtle: #1a1a1a; + --border-dropdown: #333333; + --shadow-dropdown: rgba(0, 0, 0, 0.95); + --positive: #22C55E; + --warning: #E5C07B; + --danger: #E06C75; + --radius-sm: 0px; + --radius-md: 0px; + --radius-lg: 0px; + --radius-full: 0px; +} + +/* Monospace override — html inherits to most elements; form controls need explicit override */ +[data-theme='unix'] button, +[data-theme='unix'] input, +[data-theme='unix'] textarea, +[data-theme='unix'] select { + font-family: 'Courier New', Courier, 'Lucida Console', monospace; +} + +/* Sidebar — slightly off-black, thin separator */ +[data-theme='unix'] .sidebar { + background: #0a0a0a; + border-right: 1px solid #222222; +} + +/* Nav active — green left bar */ +[data-theme='unix'] .nav-link.active { + background: rgba(34, 197, 94, 0.10); + border-left: 2px solid #22C55E; + color: #22C55E; +} + +[data-theme='unix'] .nav-link:hover:not(.active) { + background: rgba(34, 197, 94, 0.05); + color: #C8C8C8; +} + +/* Player bar — pure black, thin grey separator */ +[data-theme='unix'] .player-bar { + background-color: #000000; + background-image: repeating-linear-gradient( + 0deg, + rgba(0, 0, 0, 0.10) 0px, + rgba(0, 0, 0, 0.10) 1px, + transparent 1px, + transparent 2px + ); + border-top: 1px solid #222222; + box-shadow: none; +} + +/* Track name — white text, green $ prompt prefix, blinking _ cursor */ +[data-theme='unix'] .player-track-name { + color: #FFFFFF; + text-shadow: none; +} + +[data-theme='unix'] .player-track-name::before { + content: '$ '; + color: #22C55E; + font-weight: 700; +} + +[data-theme='unix'] .player-track-name::after { + content: '_'; + animation: unix-cursor-blink 1s step-end infinite; + color: #C8C8C8; + margin-left: 1px; +} + +/* Artist name — ANSI bright blue (ls directory color) */ +[data-theme='unix'] .player-artist-name { + color: #5588FF; +} + +/* Content header — minimal grey rule */ +[data-theme='unix'] .content-header { + border-bottom: 1px solid #1e1e1e; +} + +/* Album/artist cards — dark panel, fine border */ +[data-theme='unix'] .album-card, +[data-theme='unix'] .artist-card { + background: #111111; + border: 1px solid #1e1e1e; + box-shadow: none; +} + +[data-theme='unix'] .album-card:hover, +[data-theme='unix'] .artist-card:hover { + background: #1a1a1a; + border-color: #22C55E; + box-shadow: none; +} + +/* Track / queue row hover — green left accent */ +[data-theme='unix'] .track-row:hover, +[data-theme='unix'] .queue-item:hover { + background: rgba(34, 197, 94, 0.06); + box-shadow: inset 2px 0 0 #22C55E; +} + +/* Primary play button — solid green */ +[data-theme='unix'] .player-btn-primary { + background: #22C55E; + color: #000000; + border: none; + box-shadow: none; +} + +[data-theme='unix'] .player-btn-primary:hover { + background: #16A34A; + box-shadow: none; + transform: none; +} + +/* btn-primary */ +[data-theme='unix'] .btn-primary { + background: #22C55E; + color: #000000; + border: none; + box-shadow: none; +} + +[data-theme='unix'] .btn-primary:hover { + background: #16A34A; + box-shadow: none; +} + +/* Hero play button */ +[data-theme='unix'] .hero-play-btn { + background: #22C55E; + color: #000000; + border: none; + text-transform: lowercase; + letter-spacing: 0.02em; + box-shadow: none; + transition: background var(--transition-fast), transform var(--transition-fast); +} + +[data-theme='unix'] .hero-play-btn:hover { + background: #16A34A; + transform: scale(1.02); + filter: none; + box-shadow: none; +} + +/* Album card overlay button */ +[data-theme='unix'] .album-card-details-btn { + background: #22C55E; + color: #000000; + border: none; + box-shadow: none; +} + +[data-theme='unix'] .album-card-details-btn:hover { + background: #16A34A; +} + +/* Queue round buttons */ +[data-theme='unix'] .queue-round-btn { + border: 1px solid #222222; + box-shadow: none; +} + +[data-theme='unix'] .queue-round-btn.active { + background: #22C55E; + color: #000000; + border-color: #22C55E; + box-shadow: none; +} + +/* Input fields */ +[data-theme='unix'] input, +[data-theme='unix'] textarea { + background: #0a0a0a; + border: 1px solid #222222; + border-radius: 0; +} + +[data-theme='unix'] input:focus, +[data-theme='unix'] textarea:focus { + border-color: #22C55E; + outline: none; + box-shadow: none; +} + +/* Scrollbar — thin 6px, modern terminal style */ +[data-theme='unix'] ::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +[data-theme='unix'] ::-webkit-scrollbar-track { + background: #0a0a0a; +} + +[data-theme='unix'] ::-webkit-scrollbar-thumb { + background: #333333; + border-radius: 0; +} + +[data-theme='unix'] ::-webkit-scrollbar-thumb:hover { + background: #22C55E; +} + +/* Connection indicator — server name and Last.fm username */ +[data-theme='unix'] .connection-type, +[data-theme='unix'] .connection-server { color: #888888; } +/* Connection indicators + Now Playing username */ +[data-theme='spider-tech'] .connection-type, +[data-theme='spider-tech'] .connection-server { color: #9080a8; } +/* Connection indicators */ +[data-theme='dos'] .connection-type, +[data-theme='dos'] .connection-server { color: #AAAAAA; } +/* Track row hover — all child text to navy so nothing drowns on grey */ +[data-theme='dos'] .track-row:hover .track-title, +[data-theme='dos'] .track-row:hover .track-num, +[data-theme='dos'] .track-row:hover .track-artist, +[data-theme='dos'] .track-row:hover .track-duration, +[data-theme='dos'] .track-row:hover .track-codec, +[data-theme='dos'] .track-row:hover button, +[data-theme='dos'] .track-row.context-active .track-title, +[data-theme='dos'] .track-row.context-active .track-num, +[data-theme='dos'] .track-row.context-active .track-artist, +[data-theme='dos'] .track-row.context-active .track-duration, +[data-theme='dos'] .track-row.context-active .track-codec, +[data-theme='dos'] .track-row.context-active button { color: #000080 !important; background: transparent !important; } + +/* ═══════════════════════════════════════════════════════════════════ + HORDE — World of Warcraft, Durotar blood-red earth, forge-fire + ═══════════════════════════════════════════════════════════════════ */ +[data-theme='horde'] { + /* Catppuccin-compatible palette — dark blood-iron */ + --ctp-base: #1a0500; + --ctp-mantle: #140300; + --ctp-crust: #0e0200; + --ctp-surface0: #2e0a02; + --ctp-surface1: #3e1104; + --ctp-surface2: #521806; + --ctp-overlay0: #8a5030; + --ctp-overlay1: #a06038; + --ctp-overlay2: #b87048; + --ctp-subtext0: #c88850; + --ctp-subtext1: #d89860; + --ctp-text: #e8d4b8; + --ctp-lavender: #cc4422; + --ctp-blue: #cc2200; + --ctp-sapphire: #aa1800; + --ctp-sky: #dd3300; + --ctp-teal: #cc5500; + --ctp-green: #887722; + --ctp-yellow: #ffd890; + --ctp-peach: #ff8844; + --ctp-maroon: #991100; + --ctp-red: #cc2200; + --ctp-mauve: #cc4422; + --ctp-pink: #dd5533; + --ctp-flamingo: #ee6644; + --ctp-rosewater: #ffaa66; + + /* Semantic tokens */ + --bg-app: #1a0500; + --bg-sidebar: #110300; + --bg-player: #120400; + --bg-card: #2e0a02; + --bg-card-hover: #3e1104; + --bg-input: #2e0a02; + --bg-overlay: rgba(26,5,0,0.92); + --bg-selection: rgba(204,34,0,0.25); + --border-subtle: rgba(140,60,20,0.30); + --border-default: rgba(180,80,30,0.35); + --border-strong: rgba(220,120,50,0.50); + --text-primary: #e8d4b8; + --text-secondary: #c09070; + --text-muted: #a07848; + --text-disabled: #5a3820; + --accent: #cc2200; + --accent-hover: #e02800; + --accent-glow: rgba(204,34,0,0.35); + --accent-subtle: rgba(204,34,0,0.15); + --danger: #ff4422; + --success: #887722; + --warning: #ff8844; + --nav-active-bg: rgba(204,34,0,0.22); + --nav-active-text: #ffd890; + --scrollbar-thumb: rgba(140,50,10,0.60); + --scrollbar-track: transparent; + --shadow-card: 0 2px 10px rgba(0,0,0,0.70); + --shadow-player: 0 -4px 20px rgba(150,30,0,0.25); + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; + --space-1: 4px; --space-2: 8px; --space-3: 12px; + --space-4: 16px; --space-5: 20px; --space-6: 24px; +} + +/* Track name — blood-gold glow, as if lit by forge-fire */ +[data-theme='horde'] .player-track-name, +[data-theme='horde'] .queue-track-title { + color: #ffd890; + text-shadow: 0 0 16px rgba(220,80,0,0.55), 0 0 4px rgba(220,80,0,0.25); +} + +/* Sidebar — iron plate lines + subtle red glow on active */ +[data-theme='horde'] .sidebar { + background-color: #110300; + background-image: repeating-linear-gradient( + 180deg, + transparent 0px, + transparent 39px, + rgba(100,20,0,0.18) 39px, + rgba(100,20,0,0.18) 40px + ); + border-right: 1px solid rgba(140,40,10,0.35); +} + +/* Nav active — ember glow */ +[data-theme='horde'] .sidebar-nav-item.active { + background: rgba(204,34,0,0.20); + border-left: 3px solid #cc2200; + box-shadow: inset 0 0 12px rgba(204,34,0,0.10); +} + +/* Player bar — forge-fire glow from below */ +[data-theme='horde'] .player-bar { + background-color: #120400; + background-image: linear-gradient(to bottom, rgba(80,10,0,0.35), transparent); + border-top: 1px solid rgba(180,60,20,0.40); + box-shadow: 0 -4px 24px rgba(150,30,0,0.30); +} + +/* App-shell — safe single-pass radial, no repeating */ +[data-theme='horde'] .app-shell { + background: radial-gradient(ellipse at 65% 110%, rgba(160,25,0,0.18) 0%, transparent 55%); +} + +/* Cards — iron-tinted hover */ +[data-theme='horde'] .album-card:hover, +[data-theme='horde'] .artist-card:hover { + box-shadow: 0 4px 18px rgba(180,40,0,0.30); + border-color: rgba(200,60,10,0.50); +} + +/* Connection indicators */ +[data-theme='horde'] .connection-type, +[data-theme='horde'] .connection-server { color: #a07848; } + + +/* ═══════════════════════════════════════════════════════════════════ + ALLIANCE — World of Warcraft, Stormwind navy, cathedral stone & gold + ═══════════════════════════════════════════════════════════════════ */ +[data-theme='alliance'] { + /* Catppuccin-compatible palette — deep navy / cathedral stone */ + --ctp-base: #06101e; + --ctp-mantle: #040c18; + --ctp-crust: #020810; + --ctp-surface0: #0c1e34; + --ctp-surface1: #122440; + --ctp-surface2: #1a2e50; + --ctp-overlay0: #506888; + --ctp-overlay1: #607898; + --ctp-overlay2: #7088a8; + --ctp-subtext0: #8098b8; + --ctp-subtext1: #90a8c8; + --ctp-text: #d8e8f8; + --ctp-lavender: #5588cc; + --ctp-blue: #3388cc; + --ctp-sapphire: #2266aa; + --ctp-sky: #44aadd; + --ctp-teal: #3399cc; + --ctp-green: #88bb44; + --ctp-yellow: #f0c840; + --ctp-peach: #dd9944; + --ctp-maroon: #aa3322; + --ctp-red: #cc4433; + --ctp-mauve: #7766cc; + --ctp-pink: #997acc; + --ctp-flamingo: #aa88cc; + --ctp-rosewater: #bbaacc; + + /* Semantic tokens */ + --bg-app: #06101e; + --bg-sidebar: #040c18; + --bg-player: #050e1a; + --bg-card: #0c1e34; + --bg-card-hover: #122440; + --bg-input: #0c1e34; + --bg-overlay: rgba(6,16,30,0.92); + --bg-selection: rgba(51,136,204,0.25); + --border-subtle: rgba(60,100,160,0.28); + --border-default: rgba(80,120,180,0.35); + --border-strong: rgba(120,160,210,0.50); + --text-primary: #d8e8f8; + --text-secondary: #8098b8; + --text-muted: #6880a0; + --text-disabled: #2a3e58; + --accent: #3388cc; + --accent-hover: #4499dd; + --accent-glow: rgba(51,136,204,0.35); + --accent-subtle: rgba(51,136,204,0.15); + --danger: #cc4433; + --success: #88bb44; + --warning: #dd9944; + --nav-active-bg: rgba(51,136,204,0.20); + --nav-active-text: #e8f4ff; + --scrollbar-thumb: rgba(60,110,180,0.55); + --scrollbar-track: transparent; + --shadow-card: 0 2px 10px rgba(0,0,0,0.60); + --shadow-player: 0 -4px 20px rgba(20,70,160,0.22); + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; + --space-1: 4px; --space-2: 8px; --space-3: 12px; + --space-4: 16px; --space-5: 20px; --space-6: 24px; +} + +/* Track name — paladin holy-light glow */ +[data-theme='alliance'] .player-track-name, +[data-theme='alliance'] .queue-track-title { + color: #e8f4ff; + text-shadow: 0 0 14px rgba(80,160,220,0.50), 0 0 4px rgba(80,160,220,0.20); +} + +/* Sidebar — cathedral stone columns with gold right-border */ +[data-theme='alliance'] .sidebar { + background-color: #040c18; + background-image: repeating-linear-gradient( + 180deg, + transparent 0px, + transparent 47px, + rgba(60,100,180,0.14) 47px, + rgba(60,100,180,0.14) 48px + ); + border-right: 2px solid rgba(200,170,50,0.30); +} + +/* Nav active — royal blue with gold left accent */ +[data-theme='alliance'] .sidebar-nav-item.active { + background: rgba(51,136,204,0.20); + border-left: 3px solid #f0c840; + box-shadow: inset 0 0 12px rgba(51,136,204,0.10); +} + +/* Player bar — paladin aura glow */ +[data-theme='alliance'] .player-bar { + background-color: #050e1a; + background-image: linear-gradient(to bottom, rgba(20,60,130,0.30), transparent); + border-top: 1px solid rgba(100,140,200,0.35); + box-shadow: 0 -4px 22px rgba(30,80,180,0.22); +} + +/* App-shell — safe single-pass radial, no repeating */ +[data-theme='alliance'] .app-shell { + background: radial-gradient(ellipse at 38% 110%, rgba(25,70,170,0.15) 0%, transparent 55%); +} + +/* Cards — blue-glow hover */ +[data-theme='alliance'] .album-card:hover, +[data-theme='alliance'] .artist-card:hover { + box-shadow: 0 4px 18px rgba(40,100,200,0.28); + border-color: rgba(80,140,210,0.50); +} + +/* Connection indicators */ +[data-theme='alliance'] .connection-type, +[data-theme='alliance'] .connection-server { color: #6880a0; } + +/* ═══════════════════════════════════════════════════════════════════ + W11 — Windows 11 Fluent Design, dark mode, Mica material + ═══════════════════════════════════════════════════════════════════ */ +[data-theme='w11'] { + /* Catppuccin-compatible palette — Fluent dark neutrals */ + --ctp-base: #202020; + --ctp-mantle: #1c1c1c; + --ctp-crust: #181818; + --ctp-surface0: #2c2c2c; + --ctp-surface1: #363636; + --ctp-surface2: #404040; + --ctp-overlay0: #797979; + --ctp-overlay1: #8a8a8a; + --ctp-overlay2: #9a9a9a; + --ctp-subtext0: #ababab; + --ctp-subtext1: #bebebe; + --ctp-text: #f3f3f3; + --ctp-lavender: #6ccbf8; + --ctp-blue: #0078d4; + --ctp-sapphire: #0067c0; + --ctp-sky: #4cc2ff; + --ctp-teal: #00b7c3; + --ctp-green: #6ccb5f; + --ctp-yellow: #f9f1a5; + --ctp-peach: #f7630c; + --ctp-maroon: #e81123; + --ctp-red: #e81123; + --ctp-mauve: #8764b8; + --ctp-pink: #b146c2; + --ctp-flamingo: #e3008c; + --ctp-rosewater: #f5e1ff; + + /* Semantic tokens */ + --bg-app: #202020; + --bg-sidebar: #2b2b2b; + --bg-player: #1c1c1c; + --bg-card: #2c2c2c; + --bg-card-hover: #363636; + --bg-input: #2c2c2c; + --bg-overlay: rgba(32,32,32,0.92); + --bg-selection: rgba(0,120,212,0.25); + --border-subtle: rgba(255,255,255,0.06); + --border-default: rgba(255,255,255,0.10); + --border-strong: rgba(255,255,255,0.18); + --text-primary: #f3f3f3; + --text-secondary: #9a9a9a; + --text-muted: #797979; + --text-disabled: #4a4a4a; + --accent: #0078d4; + --accent-hover: #1086e0; + --accent-glow: rgba(0,120,212,0.30); + --accent-subtle: rgba(0,120,212,0.15); + --danger: #e81123; + --success: #6ccb5f; + --warning: #f7630c; + --nav-active-bg: rgba(0,120,212,0.18); + --nav-active-text: #f3f3f3; + --scrollbar-thumb: rgba(255,255,255,0.18); + --scrollbar-track: transparent; + --shadow-card: 0 2px 8px rgba(0,0,0,0.50); + --shadow-player: 0 -1px 0 rgba(255,255,255,0.06); + --radius-sm: 6px; + --radius-md: 8px; + --radius-lg: 12px; + --space-1: 4px; --space-2: 8px; --space-3: 12px; + --space-4: 16px; --space-5: 20px; --space-6: 24px; +} + +/* Track name — clean white, no glow (Fluent is minimal) */ +[data-theme='w11'] .player-track-name, +[data-theme='w11'] .queue-track-title { + color: #f3f3f3; +} + +/* Sidebar — Mica-like: very slightly lighter than app bg, clean border */ +[data-theme='w11'] .sidebar { + background-color: #2b2b2b; + border-right: 1px solid rgba(255,255,255,0.08); +} + +/* Nav active — Fluent accent fill, rounded */ +[data-theme='w11'] .sidebar-nav-item.active { + background: rgba(0,120,212,0.20); + border-left: 3px solid #0078d4; +} + +/* Player bar — taskbar-inspired: very dark, hairline top border */ +[data-theme='w11'] .player-bar { + background-color: #1c1c1c; + border-top: 1px solid rgba(255,255,255,0.08); + box-shadow: none; +} + +/* App-shell — flat, no gradient (Fluent dark is clean/minimal) */ +[data-theme='w11'] .app-shell { + background: none; +} + +/* Cards — Fluent hover: slight elevation via border brightening */ +[data-theme='w11'] .album-card:hover, +[data-theme='w11'] .artist-card:hover { + box-shadow: 0 4px 14px rgba(0,0,0,0.45); + border-color: rgba(255,255,255,0.16); +} + +/* Connection indicators */ +[data-theme='w11'] .connection-type, +[data-theme='w11'] .connection-server { color: #797979; }