diff --git a/media_server/static/css/styles.css b/media_server/static/css/styles.css index 254331d..1dfc7f6 100644 --- a/media_server/static/css/styles.css +++ b/media_server/static/css/styles.css @@ -113,7 +113,8 @@ --copper: #E08038; --copper-hi: #F4A064; --copper-lo: #B0561F; - --copper-glow: rgba(224, 128, 56, 0.35); + --copper-rgb: 224, 128, 56; + --copper-glow: rgba(var(--copper-rgb), 0.35); --amber: #F5C26B; --jade: #7AB294; @@ -167,7 +168,8 @@ --copper: #1F4E3D; /* hunter emerald in light mode */ --copper-hi: #2D6A53; --copper-lo: #143E2F; - --copper-glow: rgba(31, 78, 61, 0.18); + --copper-rgb: 31, 78, 61; + --copper-glow: rgba(var(--copper-rgb), 0.18); --amber: #C29D31; --jade: #4D8C6F; @@ -4751,7 +4753,7 @@ body.visualizer-active .vinyl-stage .spectrogram-canvas { justify-content: center; } :root[data-theme="light"] .vinyl-stage .vinyl-wrap .vinyl-label { - background: linear-gradient(135deg, #1F4E3D 0%, #143E2F 100%); + background: linear-gradient(135deg, var(--copper) 0%, var(--copper-lo) 100%); box-shadow: inset 0 0 18px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.06), @@ -4946,7 +4948,7 @@ body.visualizer-active .vinyl-stage .spectrogram-canvas { border: 1px solid var(--rule-strong); border-radius: 4px 4px 0 0; overflow: hidden; - box-shadow: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 0 30px rgba(224,128,56,0.08); + box-shadow: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 0 30px rgba(var(--copper-rgb), 0.08); } .vu-meter::before { content: ""; @@ -5128,7 +5130,7 @@ body.visualizer-active .vinyl-stage .spectrogram-canvas { height: 10px; background: var(--copper); border-radius: 50%; - box-shadow: 0 0 14px var(--copper-glow), 0 0 0 4px rgba(224, 128, 56, 0.12); + box-shadow: 0 0 14px var(--copper-glow), 0 0 0 4px rgba(var(--copper-rgb), 0.12); transition: none; } @@ -5169,7 +5171,7 @@ body.visualizer-active .vinyl-stage .spectrogram-canvas { transition: all 220ms var(--ease); } .controls button:hover { - background: rgba(224, 128, 56, 0.06); + background: rgba(var(--copper-rgb), 0.06); border-color: var(--copper); color: var(--copper); } @@ -5213,7 +5215,7 @@ body.visualizer-active .vinyl-stage .spectrogram-canvas { .mute-btn:hover { border-color: var(--copper); color: var(--copper); - background: rgba(224, 128, 56, 0.06); + background: rgba(var(--copper-rgb), 0.06); } #volume-slider { @@ -5232,7 +5234,7 @@ body.visualizer-active .vinyl-stage .spectrogram-canvas { height: 14px; background: var(--copper); border-radius: 50%; - box-shadow: 0 0 12px var(--copper-glow), 0 0 0 4px rgba(224, 128, 56, 0.12); + box-shadow: 0 0 12px var(--copper-glow), 0 0 0 4px rgba(var(--copper-rgb), 0.12); border: 0; cursor: grab; } @@ -5297,7 +5299,7 @@ body.visualizer-active .vinyl-stage .spectrogram-canvas { .vinyl-toggle-btn.active { border-color: var(--copper); color: var(--copper); - background: rgba(224, 128, 56, 0.06); + background: rgba(var(--copper-rgb), 0.06); } /* ═══════════════════════════════════════════════════════════════ @@ -5581,7 +5583,7 @@ body.visualizer-active .vinyl-stage .spectrogram-canvas { .view-toggle-btn:last-child { border-right: 0; } .view-toggle-btn:hover { color: var(--copper); - background: rgba(224, 128, 56, 0.04); + background: rgba(var(--copper-rgb), 0.04); } .view-toggle-btn.active { background: var(--ink); @@ -5987,7 +5989,7 @@ body.visualizer-active .vinyl-stage .spectrogram-canvas { border-color: var(--copper); border-style: solid; color: var(--copper); - background: rgba(224, 128, 56, 0.04); + background: rgba(var(--copper-rgb), 0.04); } .add-card-icon { font-family: var(--serif); @@ -6356,7 +6358,7 @@ dialog::backdrop { font-size: 10px; } .icon-select-cell:hover { - background: rgba(224, 128, 56, 0.06); + background: rgba(var(--copper-rgb), 0.06); color: var(--copper); } @@ -6848,7 +6850,7 @@ body.audio-spectrum-live .now-playing .spectrum span { width: 10px; height: 10px; background: var(--copper); border-radius: 50%; - box-shadow: 0 0 14px var(--copper-glow), 0 0 0 4px rgba(224, 128, 56, 0.12); + box-shadow: 0 0 14px var(--copper-glow), 0 0 0 4px rgba(var(--copper-rgb), 0.12); transition: none; } @@ -6879,7 +6881,7 @@ body.audio-spectrum-live .now-playing .spectrum span { .now-playing .btn-trans:hover { border-color: var(--copper); color: var(--copper); - background: rgba(224, 128, 56, 0.06); + background: rgba(var(--copper-rgb), 0.06); } .now-playing .btn-trans:disabled { opacity: 0.35; @@ -6955,7 +6957,7 @@ body.audio-spectrum-live .now-playing .spectrum span { .now-playing .vu-volume .mute-btn:hover { border-color: var(--copper); color: var(--copper); - background: rgba(224, 128, 56, 0.06); + background: rgba(var(--copper-rgb), 0.06); } .now-playing .vu-volume .mute-btn svg { width: 14px; @@ -7007,7 +7009,7 @@ body.audio-spectrum-live .now-playing .spectrum span { border: 1px solid var(--rule-strong); border-radius: 4px 4px 0 0; overflow: hidden; - box-shadow: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 0 30px rgba(224,128,56,0.08); + box-shadow: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 0 30px rgba(var(--copper-rgb), 0.08); flex-shrink: 0; } .now-playing .vu-meter::before { @@ -7066,7 +7068,7 @@ body.audio-spectrum-live .now-playing .spectrum span { border-color: var(--rule-strong); box-shadow: inset 0 1px 2px rgba(26, 23, 21, 0.08), - inset 0 0 24px rgba(31, 78, 61, 0.05); + inset 0 0 24px rgba(var(--copper-rgb), 0.05); } :root[data-theme="light"] .now-playing .vu-meter::before { background: repeating-conic-gradient(from 195deg at 50% 100%, @@ -7079,7 +7081,7 @@ body.audio-spectrum-live .now-playing .spectrum span { } :root[data-theme="light"] .now-playing .vu-needle { background: linear-gradient(to top, var(--copper) 0%, var(--copper-lo) 70%, var(--ink) 100%); - box-shadow: 0 0 6px rgba(31, 78, 61, 0.25); + box-shadow: 0 0 6px rgba(var(--copper-rgb), 0.25); } /* Mobile VU cluster: stack below controls */ @@ -7233,7 +7235,7 @@ body.audio-spectrum-live .now-playing .spectrum span { .browser-container .browser-refresh-btn:hover, .browser-container .browser-play-all-btn:hover { color: var(--copper) !important; - background: rgba(224, 128, 56, 0.06) !important; + background: rgba(var(--copper-rgb), 0.06) !important; } .browser-container .view-toggle-btn.active { background: var(--ink) !important; @@ -7752,7 +7754,7 @@ select option { border-color: var(--copper) !important; border-style: solid !important; color: var(--copper) !important; - background: rgba(224, 128, 56, 0.04) !important; + background: rgba(var(--copper-rgb), 0.04) !important; } .settings-container .add-card-icon { font-family: var(--serif); @@ -7987,7 +7989,7 @@ select option { .display-container .display-power-btn:hover { color: var(--copper) !important; border-color: var(--copper) !important; - background: rgba(224, 128, 56, 0.06) !important; + background: rgba(var(--copper-rgb), 0.06) !important; } /* Brightness control row */ @@ -8138,7 +8140,7 @@ select option { font-size: 10px; } .icon-select-cell:hover { - background: rgba(224, 128, 56, 0.06) !important; + background: rgba(var(--copper-rgb), 0.06) !important; color: var(--copper) !important; } @@ -8396,7 +8398,7 @@ select option { } .mini-control-btn:hover { border-color: var(--copper) !important; - background: rgba(224, 128, 56, 0.08) !important; + background: rgba(var(--copper-rgb), 0.08) !important; color: var(--copper) !important; } .mini-control-btn svg { @@ -8768,7 +8770,7 @@ body.is-fullscreen-player .player-container { margin: 0; padding: 0; background: - radial-gradient(ellipse at 30% 35%, rgba(224, 128, 56, 0.05) 0%, transparent 55%), + radial-gradient(ellipse at 30% 35%, rgba(var(--copper-rgb), 0.05) 0%, transparent 55%), radial-gradient(ellipse at center, var(--bg-paper) 0%, var(--bg-deep) 75%); display: grid; place-items: stretch; @@ -9069,7 +9071,7 @@ body.is-fullscreen-player .now-playing .meta-cell .label { font-family: var(--mono); font-size: 9px; letter-spacing: 0.32em; - color: var(--ink-faint); + color: var(--copper); } body.is-fullscreen-player .now-playing .meta-cell .value { font-family: var(--mono); diff --git a/media_server/static/js/player.js b/media_server/static/js/player.js index 2aac0ee..c4d861c 100644 --- a/media_server/static/js/player.js +++ b/media_server/static/js/player.js @@ -145,6 +145,22 @@ export function lightenColor(hex, percent) { return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`; } +function darkenColor(hex, percent) { + const num = parseInt(hex.replace('#', ''), 16); + const r = Math.max(0, (num >> 16) - Math.round(255 * percent / 100)); + const g = Math.max(0, ((num >> 8) & 0xff) - Math.round(255 * percent / 100)); + const b = Math.max(0, (num & 0xff) - Math.round(255 * percent / 100)); + return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`; +} + +function hexToRgbTriple(hex) { + const num = parseInt(hex.replace('#', ''), 16); + const r = (num >> 16) & 0xff; + const g = (num >> 8) & 0xff; + const b = num & 0xff; + return `${r}, ${g}, ${b}`; +} + export function initAccentColor() { const saved = localStorage.getItem('accentColor'); if (saved) { @@ -159,8 +175,18 @@ export function initAccentColor() { } export function applyAccentColor(color, hover) { - document.documentElement.style.setProperty('--accent', color); - document.documentElement.style.setProperty('--accent-hover', hover); + const root = document.documentElement.style; + root.setProperty('--accent', color); + root.setProperty('--accent-hover', hover); + // Editorial palette tokens — the redesign reads these directly, + // so the picker must drive them too (the --accent alias alone has + // no effect once components moved off it). + root.setProperty('--copper', color); + root.setProperty('--copper-hi', hover); + root.setProperty('--copper-lo', darkenColor(color, 12)); + root.setProperty('--copper-rgb', hexToRgbTriple(color)); + // --copper-glow inherits the rgba(var(--copper-rgb), 0.35) formula + // declared in styles.css, so it picks up the new RGB automatically. localStorage.setItem('accentColor', color); const dot = document.getElementById('accentDot'); if (dot) dot.style.background = color;