Files
psysonic/src/styles/theme.css
T
Psychotoxical 623a6a4a54 feat: UI polish, DnD fix, navigation, and installer improvements (v1.0.10)
- Fix queue DnD on macOS/Windows: delay ref cleanup in onDragEnd so onDropQueue
  reads correct source/destination before dragend clears them
- Active track highlighting in album tracklist (pulsing accent bg + play icon)
- Marquee scrolling for long titles in Fullscreen Player
- Clickable artist/album in Player Bar and Queue now-playing strip
- Tracklist: format column moved after duration, auto width, kHz/filesize removed
- Settings dropdowns: visible border (base bg + overlay0 border)
- Sidebar: fixed responsive width via clamp(), removed drag-to-resize
- Favorites icon: HandMetal → Star in Random Mix page
- Linux app menu category set to Multimedia (AudioVideo)
- Windows MSI: stable upgradeCode for in-place upgrades
- Bundle: category/description fields at correct config level
- About: Claude Code credit, fixed German MIT licence wording

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 11:36:03 +01:00

749 lines
23 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ─────────────────────────────────────────────────────────────
Psysonic Design System
Catppuccin Mocha Color Palette + Inter Typography
───────────────────────────────────────────────────────────── */
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Space+Grotesk:wght@400;500;600;700&display=swap');
/* ─── Catppuccin Mocha Variables ─── */
:root, [data-theme='mocha'] {
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%23bac2de%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-rosewater: #f5e0dc;
--ctp-flamingo: #f2cdcd;
--ctp-pink: #f5c2e7;
--ctp-mauve: #cba6f7;
--ctp-red: #f38ba8;
--ctp-maroon: #eba0ac;
--ctp-peach: #fab387;
--ctp-yellow: #f9e2af;
--ctp-green: #a6e3a1;
--ctp-teal: #94e2d5;
--ctp-sky: #89dceb;
--ctp-sapphire: #74c7ec;
--ctp-blue: #89b4fa;
--ctp-lavender: #b4befe;
--ctp-text: #cdd6f4;
--ctp-subtext1: #bac2de;
--ctp-subtext0: #a6adc8;
--ctp-overlay2: #9399b2;
--ctp-overlay1: #7f849c;
--ctp-overlay0: #6c7086;
--ctp-surface2: #585b70;
--ctp-surface1: #45475a;
--ctp-surface0: #313244;
--ctp-base: #1e1e2e;
--ctp-mantle: #181825;
--ctp-crust: #11111b;
/* Semantic tokens */
--bg-app: var(--ctp-base);
--bg-sidebar: var(--ctp-mantle);
--bg-card: var(--ctp-surface0);
--bg-hover: var(--ctp-surface1);
--bg-player: var(--ctp-crust);
--bg-glass: rgba(30, 30, 46, 0.75);
--accent: var(--ctp-mauve);
--accent-dim: rgba(203, 166, 247, 0.15);
--accent-glow: rgba(203, 166, 247, 0.3);
--text-primary: var(--ctp-text);
--text-secondary:var(--ctp-subtext1);
--text-muted: var(--ctp-overlay1);
--border: var(--ctp-surface1);
--border-subtle: var(--ctp-surface0);
--positive: var(--ctp-green);
--warning: var(--ctp-yellow);
--danger: var(--ctp-red);
}
/* ─── Catppuccin Macchiato Variables ─── */
[data-theme='macchiato'] {
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%23b8c0e0%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-rosewater: #f4dbd6;
--ctp-flamingo: #f0c6c6;
--ctp-pink: #f5bde6;
--ctp-mauve: #c6a0f6;
--ctp-red: #ed8796;
--ctp-maroon: #ee99a0;
--ctp-peach: #f5a97f;
--ctp-yellow: #eed49f;
--ctp-green: #a6da95;
--ctp-teal: #8bd5ca;
--ctp-sky: #91d7e3;
--ctp-sapphire: #7dc4e4;
--ctp-blue: #8aadf4;
--ctp-lavender: #b7bdf8;
--ctp-text: #cad3f5;
--ctp-subtext1: #b8c0e0;
--ctp-subtext0: #a5adcb;
--ctp-overlay2: #939ab7;
--ctp-overlay1: #8087a2;
--ctp-overlay0: #6e738d;
--ctp-surface2: #5b6078;
--ctp-surface1: #494d64;
--ctp-surface0: #363a4f;
--ctp-base: #24273a;
--ctp-mantle: #1e2030;
--ctp-crust: #181926;
--bg-app: var(--ctp-base);
--bg-sidebar: var(--ctp-mantle);
--bg-card: var(--ctp-surface0);
--bg-hover: var(--ctp-surface1);
--bg-player: var(--ctp-crust);
--bg-glass: rgba(36, 39, 58, 0.75);
--accent: var(--ctp-mauve);
--accent-dim: rgba(198, 160, 246, 0.15);
--accent-glow: rgba(198, 160, 246, 0.3);
--text-primary: var(--ctp-text);
--text-secondary:var(--ctp-subtext1);
--text-muted: var(--ctp-overlay1);
--border: var(--ctp-surface1);
--border-subtle: var(--ctp-surface0);
--positive: var(--ctp-green);
--warning: var(--ctp-yellow);
--danger: var(--ctp-red);
}
/* ─── Catppuccin Frappé Variables ─── */
[data-theme='frappe'] {
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%23b5bfe2%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-rosewater: #f2d5cf;
--ctp-flamingo: #eebebe;
--ctp-pink: #f4b8e4;
--ctp-mauve: #ca9ee6;
--ctp-red: #e78284;
--ctp-maroon: #ea999c;
--ctp-peach: #ef9f76;
--ctp-yellow: #e5c890;
--ctp-green: #a6d189;
--ctp-teal: #81c8be;
--ctp-sky: #99d1db;
--ctp-sapphire: #85c1dc;
--ctp-blue: #8caaee;
--ctp-lavender: #babbf1;
--ctp-text: #c6d0f5;
--ctp-subtext1: #b5bfe2;
--ctp-subtext0: #a5adce;
--ctp-overlay2: #949cbb;
--ctp-overlay1: #838ba7;
--ctp-overlay0: #737994;
--ctp-surface2: #626880;
--ctp-surface1: #51576d;
--ctp-surface0: #414559;
--ctp-base: #303446;
--ctp-mantle: #292c3c;
--ctp-crust: #232634;
--bg-app: var(--ctp-base);
--bg-sidebar: var(--ctp-mantle);
--bg-card: var(--ctp-surface0);
--bg-hover: var(--ctp-surface1);
--bg-player: var(--ctp-crust);
--bg-glass: rgba(48, 52, 70, 0.75);
--accent: var(--ctp-mauve);
--accent-dim: rgba(202, 158, 230, 0.15);
--accent-glow: rgba(202, 158, 230, 0.3);
--text-primary: var(--ctp-text);
--text-secondary:var(--ctp-subtext1);
--text-muted: var(--ctp-overlay1);
--border: var(--ctp-surface1);
--border-subtle: var(--ctp-surface0);
--positive: var(--ctp-green);
--warning: var(--ctp-yellow);
--danger: var(--ctp-red);
}
/* ─── Catppuccin Latte Variables (Light Theme) ─── */
[data-theme='latte'] {
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%235c5f77%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-rosewater: #dc8a78;
--ctp-flamingo: #dd7878;
--ctp-pink: #ea76cb;
--ctp-mauve: #8839ef;
--ctp-red: #d20f39;
--ctp-maroon: #e64553;
--ctp-peach: #fe640b;
--ctp-yellow: #df8e1d;
--ctp-green: #40a02b;
--ctp-teal: #179299;
--ctp-sky: #04a5e5;
--ctp-sapphire: #209fb5;
--ctp-blue: #1e66f5;
--ctp-lavender: #7287fd;
--ctp-text: #4c4f69;
--ctp-subtext1: #5c5f77;
--ctp-subtext0: #6c6f85;
--ctp-overlay2: #7c7f93;
--ctp-overlay1: #8c8fa1;
--ctp-overlay0: #9ca0b0;
--ctp-surface2: #acb0be;
--ctp-surface1: #bcc0cc;
--ctp-surface0: #ccd0da;
--ctp-base: #eff1f5;
--ctp-mantle: #e6e9ef;
--ctp-crust: #dce0e8;
/* Semantic tokens */
--bg-app: var(--ctp-base);
--bg-sidebar: var(--ctp-mantle);
--bg-card: var(--ctp-surface0);
--bg-hover: var(--ctp-surface1);
--bg-player: var(--ctp-crust);
--bg-glass: rgba(239, 241, 245, 0.75);
--accent: var(--ctp-mauve);
--accent-dim: rgba(136, 57, 239, 0.15);
--accent-glow: rgba(136, 57, 239, 0.3);
--text-primary: var(--ctp-text);
--text-secondary:var(--ctp-subtext1);
--text-muted: var(--ctp-overlay1);
--border: var(--ctp-surface1);
--border-subtle: var(--ctp-surface0);
--positive: var(--ctp-green);
--warning: var(--ctp-yellow);
--danger: var(--ctp-red);
}
/* ─── Nord Polar Night (Dark) ─── */
[data-theme='nord'] {
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%23e5e9f0%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");
/* Polar Night */
--ctp-crust: #2e3440;
--ctp-mantle: #2e3440;
--ctp-base: #3b4252;
--ctp-surface0: #434c5e;
--ctp-surface1: #4c566a;
--ctp-surface2: #576070;
--ctp-overlay0: #7a8898;
--ctp-overlay1: #8894a4;
--ctp-overlay2: #96a2b0;
/* Snow Storm as text */
--ctp-text: #eceff4;
--ctp-subtext1: #e5e9f0;
--ctp-subtext0: #d8dee9;
/* Frost */
--ctp-teal: #8fbcbb;
--ctp-sky: #88c0d0;
--ctp-sapphire: #81a1c1;
--ctp-blue: #5e81ac;
--ctp-lavender: #81a1c1;
--ctp-mauve: #88c0d0;
/* Aurora */
--ctp-red: #bf616a;
--ctp-maroon: #d08770;
--ctp-peach: #d08770;
--ctp-yellow: #ebcb8b;
--ctp-green: #a3be8c;
--ctp-pink: #b48ead;
--ctp-flamingo: #bf616a;
--ctp-rosewater: #d08770;
--bg-app: #3b4252;
--bg-sidebar: #2e3440;
--bg-card: #434c5e;
--bg-hover: #4c566a;
--bg-player: #2e3440;
--bg-glass: rgba(59, 66, 82, 0.75);
--accent: #88c0d0;
--accent-dim: rgba(136, 192, 208, 0.15);
--accent-glow: rgba(136, 192, 208, 0.3);
--text-primary: #eceff4;
--text-secondary:#e5e9f0;
--text-muted: #8894a4;
--border: #434c5e;
--border-subtle: #3b4252;
--positive: #a3be8c;
--warning: #ebcb8b;
--danger: #bf616a;
}
/* ─── Nord Snow Storm (Light) ─── */
[data-theme='nord-snowstorm'] {
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%233b4252%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");
/* Snow Storm as backgrounds */
--ctp-crust: #d8dee9;
--ctp-mantle: #e5e9f0;
--ctp-base: #eceff4;
--ctp-surface0: #d8dee9;
--ctp-surface1: #c8d0de;
--ctp-surface2: #b8c2d0;
--ctp-overlay0: #7a8898;
--ctp-overlay1: #636e7e;
--ctp-overlay2: #4c566a;
/* Polar Night as text */
--ctp-text: #2e3440;
--ctp-subtext1: #3b4252;
--ctp-subtext0: #434c5e;
/* Frost */
--ctp-teal: #8fbcbb;
--ctp-sky: #88c0d0;
--ctp-sapphire: #81a1c1;
--ctp-blue: #5e81ac;
--ctp-lavender: #81a1c1;
--ctp-mauve: #5e81ac;
/* Aurora */
--ctp-red: #bf616a;
--ctp-maroon: #d08770;
--ctp-peach: #d08770;
--ctp-yellow: #9a7200;
--ctp-green: #4e7c3f;
--ctp-pink: #7e5d8c;
--ctp-flamingo: #bf616a;
--ctp-rosewater: #d08770;
--bg-app: #eceff4;
--bg-sidebar: #e5e9f0;
--bg-card: #d8dee9;
--bg-hover: #c8d0de;
--bg-player: #e5e9f0;
--bg-glass: rgba(236, 239, 244, 0.80);
--accent: #5e81ac;
--accent-dim: rgba(94, 129, 172, 0.15);
--accent-glow: rgba(94, 129, 172, 0.3);
--text-primary: #2e3440;
--text-secondary:#3b4252;
--text-muted: #636e7e;
--border: #c8d0de;
--border-subtle: #d8dee9;
--positive: #4e7c3f;
--warning: #9a7200;
--danger: #bf616a;
}
/* ─── Nord Frost (Deep Ocean Blue) ─── */
[data-theme='nord-frost'] {
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%23e5e9f0%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");
/* Deep ocean blue Frost-inspired dark backgrounds */
--ctp-crust: #1a2535;
--ctp-mantle: #1d2b3a;
--ctp-base: #253545;
--ctp-surface0: #2d3f52;
--ctp-surface1: #354a60;
--ctp-surface2: #3d546e;
--ctp-overlay0: #6888a4;
--ctp-overlay1: #7898b4;
--ctp-overlay2: #88a8c4;
/* Snow Storm as text */
--ctp-text: #eceff4;
--ctp-subtext1: #e5e9f0;
--ctp-subtext0: #d8dee9;
/* Frost accent */
--ctp-teal: #8fbcbb;
--ctp-sky: #88c0d0;
--ctp-sapphire: #81a1c1;
--ctp-blue: #5e81ac;
--ctp-lavender: #8fbcbb;
--ctp-mauve: #88c0d0;
/* Aurora */
--ctp-red: #bf616a;
--ctp-maroon: #d08770;
--ctp-peach: #d08770;
--ctp-yellow: #ebcb8b;
--ctp-green: #a3be8c;
--ctp-pink: #b48ead;
--ctp-flamingo: #bf616a;
--ctp-rosewater: #d08770;
--bg-app: #253545;
--bg-sidebar: #1d2b3a;
--bg-card: #2d3f52;
--bg-hover: #354a60;
--bg-player: #1a2535;
--bg-glass: rgba(37, 53, 69, 0.75);
--accent: #88c0d0;
--accent-dim: rgba(136, 192, 208, 0.15);
--accent-glow: rgba(136, 192, 208, 0.35);
--text-primary: #eceff4;
--text-secondary:#e5e9f0;
--text-muted: #7898b4;
--border: #2d3f52;
--border-subtle: #253545;
--positive: #a3be8c;
--warning: #ebcb8b;
--danger: #bf616a;
}
/* ─── Nord Aurora (Dark + Aurora Purple) ─── */
[data-theme='nord-aurora'] {
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%23e5e9f0%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");
/* Polar Night base */
--ctp-crust: #2e3440;
--ctp-mantle: #2e3440;
--ctp-base: #3b4252;
--ctp-surface0: #434c5e;
--ctp-surface1: #4c566a;
--ctp-surface2: #576070;
--ctp-overlay0: #7a8898;
--ctp-overlay1: #8894a4;
--ctp-overlay2: #96a2b0;
/* Snow Storm as text */
--ctp-text: #eceff4;
--ctp-subtext1: #e5e9f0;
--ctp-subtext0: #d8dee9;
/* Aurora accents — purple as mauve/lavender for button gradients */
--ctp-mauve: #b48ead;
--ctp-lavender: #a3be8c;
--ctp-pink: #b48ead;
--ctp-teal: #8fbcbb;
--ctp-sky: #88c0d0;
--ctp-sapphire: #81a1c1;
--ctp-blue: #5e81ac;
--ctp-red: #bf616a;
--ctp-maroon: #d08770;
--ctp-peach: #d08770;
--ctp-yellow: #ebcb8b;
--ctp-green: #a3be8c;
--ctp-flamingo: #bf616a;
--ctp-rosewater: #d08770;
--bg-app: #3b4252;
--bg-sidebar: #2e3440;
--bg-card: #434c5e;
--bg-hover: #4c566a;
--bg-player: #2e3440;
--bg-glass: rgba(59, 66, 82, 0.75);
--accent: #b48ead;
--accent-dim: rgba(180, 142, 173, 0.15);
--accent-glow: rgba(180, 142, 173, 0.3);
--text-primary: #eceff4;
--text-secondary:#e5e9f0;
--text-muted: #8894a4;
--border: #434c5e;
--border-subtle: #3b4252;
--positive: #a3be8c;
--warning: #ebcb8b;
--danger: #bf616a;
}
/* ─── Global Base Settings ─── */
:root {
/* Typography */
--font-sans: 'Inter', system-ui, -apple-system, sans-serif;
--font-display: 'Space Grotesk', 'Inter', sans-serif;
/* Spacing */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
/* Radii */
--radius-sm: 6px;
--radius-md: 10px;
--radius-lg: 16px;
--radius-xl: 24px;
--radius-full: 9999px;
/* Shadows */
--shadow-sm: 0 1px 3px rgba(0,0,0,0.4);
--shadow-md: 0 4px 16px rgba(0,0,0,0.5);
--shadow-lg: 0 8px 32px rgba(0,0,0,0.6);
--shadow-glow: 0 0 24px var(--accent-glow);
/* Transitions */
--transition-fast: 120ms ease;
--transition-base: 200ms ease;
--transition-slow: 350ms ease;
/* Layout */
--sidebar-width: 220px;
--player-height: 88px;
}
/* ─── Reset ─── */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body, #root {
height: 100%;
overflow: hidden;
}
body {
font-family: var(--font-sans);
font-size: 14px;
line-height: 1.5;
color: var(--text-primary);
background: var(--bg-app);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
user-select: none;
}
/* Allow text selection in specific areas */
input, textarea, [data-selectable] {
user-select: text;
}
a { color: inherit; text-decoration: none; }
button { cursor: pointer; border: none; background: none; font: inherit; color: inherit; }
img { display: block; max-width: 100%; }
ul, ol { list-style: none; }
/* ─── Scrollbars ─── */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--ctp-surface2); border-radius: var(--radius-full); }
::-webkit-scrollbar-thumb:hover { background: var(--ctp-overlay0); }
/* ─── Focus ─── */
:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: var(--radius-sm);
}
/* ─── Global Dragging State ─── */
body.is-dragging,
body.is-dragging * {
user-select: none !important;
cursor: col-resize !important;
}
/* ─── Utility Classes ─── */
.glass {
background: var(--bg-glass, rgba(30, 30, 46, 0.75));
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid var(--border-subtle);
}
.gradient-text {
background: linear-gradient(135deg, var(--ctp-mauve), var(--ctp-blue));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0,0,0,0);
}
/* ─── Button Variants ─── */
.btn {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-4);
border-radius: var(--radius-md);
font-size: 14px;
font-weight: 500;
transition: all var(--transition-fast);
white-space: nowrap;
}
.btn-primary {
background: var(--accent);
color: var(--ctp-crust);
font-weight: 600;
}
.btn-primary:hover { background: var(--ctp-lavender); transform: translateY(-1px); box-shadow: var(--shadow-glow); }
.btn-primary:active { transform: translateY(0); }
.btn-ghost {
background: transparent;
color: var(--text-secondary);
}
.btn-ghost:hover { background: var(--bg-hover); color: var(--text-primary); }
.btn-surface {
background: var(--bg-card);
color: var(--text-primary);
}
.btn-surface:hover { background: var(--bg-hover); }
/* ─── Input ─── */
.input {
width: 100%;
padding: var(--space-3) var(--space-4);
background: var(--ctp-base);
border: 1px solid var(--ctp-overlay0);
border-radius: var(--radius-md);
color: var(--text-primary);
font-family: var(--font-sans);
font-size: 14px;
transition: border-color var(--transition-fast), box-shadow var(--transition-fast), background var(--transition-fast);
outline: none;
}
.input::placeholder { color: var(--text-muted); }
.input:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-dim);
}
select.input {
appearance: none;
-webkit-appearance: none;
background-image: var(--select-arrow);
background-repeat: no-repeat;
background-position: right 12px center;
background-size: 16px;
padding-right: 40px;
cursor: pointer;
}
select.input.input:focus {
background-image: var(--select-arrow); /* Keep arrow on focus */
}
/* ─── Card ─── */
.card {
background: var(--bg-card);
border-radius: var(--radius-lg);
border: 1px solid var(--border-subtle);
overflow: hidden;
transition: transform var(--transition-base), box-shadow var(--transition-base);
}
.card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
/* ─── Album Grid ─── */
.album-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
gap: var(--space-4);
}
/* ─── Scrollable area ─── */
.scroll-area {
overflow-y: auto;
overflow-x: hidden;
flex: 1;
}
/* ─── Divider ─── */
.divider {
height: 1px;
background: var(--border-subtle);
margin: var(--space-4) 0;
}
/* ─── Badge ─── */
.badge {
display: inline-flex;
align-items: center;
padding: 2px var(--space-2);
border-radius: var(--radius-full);
font-size: 11px;
font-weight: 600;
letter-spacing: 0.03em;
background: var(--accent-dim);
color: var(--accent);
}
/* ─── Star Rating ─── */
.star-rating {
display: flex;
gap: 2px;
color: var(--ctp-overlay1);
}
.star-rating .star.filled { color: var(--ctp-yellow); }
.star-rating .star:hover { color: var(--ctp-yellow); cursor: pointer; }
/* ─── Animations ─── */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes slideIn {
from { opacity: 0; transform: translateX(-12px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes wave {
0%, 100% { transform: scaleY(0.4); }
50% { transform: scaleY(1); }
}
.animate-fade-in { animation: fadeIn var(--transition-slow) both; }
.animate-slide-in { animation: slideIn var(--transition-slow) both; }
.animate-pulse { animation: pulse 1.5s ease infinite; }
.animate-spin { animation: spin 1s linear infinite; }
/* ─── Progress / Range ─── */
input[type="range"] {
-webkit-appearance: none;
appearance: none;
height: 4px;
border-radius: var(--radius-full);
background: var(--ctp-surface2);
outline: none;
cursor: pointer;
transition: all var(--transition-fast);
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 14px;
height: 14px;
border-radius: 50%;
background: var(--text-primary);
cursor: pointer;
transition: transform var(--transition-fast), background var(--transition-fast);
box-shadow: var(--shadow-sm);
}
input[type="range"]:hover::-webkit-slider-thumb {
transform: scale(1.2);
background: var(--accent);
}
/* ─── Loading Spinner ─── */
.spinner {
width: 24px;
height: 24px;
border: 2px solid var(--border);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 0.7s linear infinite;
}
/* ─── Equalizer bars animation ─── */
.eq-bar {
display: inline-block;
width: 3px;
background: var(--accent);
border-radius: 2px;
transform-origin: bottom;
}
.eq-bar:nth-child(1) { animation: wave 0.8s ease-in-out 0.0s infinite; }
.eq-bar:nth-child(2) { animation: wave 0.8s ease-in-out 0.15s infinite; }
.eq-bar:nth-child(3) { animation: wave 0.8s ease-in-out 0.3s infinite; }
.eq-bar:nth-child(4) { animation: wave 0.8s ease-in-out 0.45s infinite; }