refactor: unify overlay styling with animated synthwave plasma backdrop

- Replace static gradient backdrops with spinning conic-gradient plasma on both lightbox and now-playing overlays
- Add smooth fade animations (`lb-fade-in-synthwave`/`lb-fade-out-synthwave`) using a dark neutral base
- Introduce `overlay-plasma-spin` animation for continuous rotation and scale pulsing
- Ensure proper z-index stacking and overflow handling for plasma layer (`::before`)
- Clean up single-mode toggle logic: clear stale content before switching modes, reset playlist state when queue changes from single to multi-track
This commit is contained in:
Brian Fertig 2026-04-12 13:07:27 -06:00
parent ce287886aa
commit 335e7d46f6
2 changed files with 78 additions and 13 deletions

View File

@ -655,6 +655,7 @@ a.detail-creator-card:hover {
z-index: 3000; z-index: 3000;
align-items: center; justify-content: center; align-items: center; justify-content: center;
cursor: zoom-out; cursor: zoom-out;
overflow: hidden;
} }
#lb-overlay.lb-open { #lb-overlay.lb-open {
display: flex; display: flex;
@ -664,14 +665,61 @@ a.detail-creator-card:hover {
animation: lb-fade-out-synthwave 0.2s ease forwards; animation: lb-fade-out-synthwave 0.2s ease forwards;
} }
/* Synthwave pink→orange gradient backdrop, matched to the Three.js sky colors */ /* Dark fade for overlay open/close — color comes from the animated ::before */
@keyframes lb-fade-in-synthwave { @keyframes lb-fade-in-synthwave {
from { background: linear-gradient(135deg, rgba(102, 15, 87, 0), rgba(107, 66, 31, 0)); } from { background: rgba(0, 0, 0, 0); }
to { background: linear-gradient(135deg, rgba(102, 15, 87, 0.92), rgba(107, 66, 31, 0.92)); } to { background: rgba(5, 6, 13, 0.82); }
} }
@keyframes lb-fade-out-synthwave { @keyframes lb-fade-out-synthwave {
from { background: linear-gradient(135deg, rgba(102, 15, 87, 0.92), rgba(107, 66, 31, 0.92)); } from { background: rgba(5, 6, 13, 0.82); }
to { background: linear-gradient(135deg, rgba(102, 15, 87, 0), rgba(107, 66, 31, 0)); } to { background: rgba(0, 0, 0, 0); }
}
/* Animated synthwave plasma — spins on both overlays */
#lb-overlay::before,
#np-overlay::before {
content: '';
position: absolute;
top: 50%; left: 50%;
width: 220vmax; height: 220vmax;
transform: translate(-50%, -50%) rotate(0deg) scale(1);
background: conic-gradient(
from 0deg at 50% 50%,
rgba(102, 15, 87, 0.90) 0deg,
rgba(255, 43, 214, 0.78) 60deg,
rgba(143, 91, 255, 0.68) 110deg,
rgba( 8, 10, 45, 0.88) 155deg,
rgba( 8, 10, 45, 0.88) 185deg,
rgba(150, 72, 12, 0.84) 225deg,
rgba(230, 105, 18, 0.75) 275deg,
rgba(255, 43, 214, 0.60) 320deg,
rgba(102, 15, 87, 0.90) 360deg
);
filter: blur(42px);
opacity: 0;
pointer-events: none;
z-index: -1;
}
#lb-overlay.lb-open::before,
#np-overlay.np-open::before {
animation:
overlay-plasma-in 0.4s ease forwards,
overlay-plasma-spin 60s linear infinite;
}
#lb-overlay.lb-closing::before,
#np-overlay.np-closing::before {
animation: overlay-plasma-out 0.22s ease forwards;
}
@keyframes overlay-plasma-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes overlay-plasma-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes overlay-plasma-spin {
0% { transform: translate(-50%, -50%) rotate( 0deg) scale(1.00); }
25% { transform: translate(-50%, -50%) rotate( 90deg) scale(1.06); }
50% { transform: translate(-50%, -50%) rotate(180deg) scale(0.97); }
75% { transform: translate(-50%, -50%) rotate(270deg) scale(1.04); }
100% { transform: translate(-50%, -50%) rotate(360deg) scale(1.00); }
} }
@keyframes lb-fade-in { from { background: rgba(0,0,0,0); } to { background: rgba(0,0,0,0.88); } } @keyframes lb-fade-in { from { background: rgba(0,0,0,0); } to { background: rgba(0,0,0,0.88); } }
@ -679,6 +727,7 @@ a.detail-creator-card:hover {
.lb-container { .lb-container {
position: relative; position: relative;
z-index: 1;
cursor: default; cursor: default;
border-radius: var(--radius); border-radius: var(--radius);
overflow: hidden; overflow: hidden;
@ -725,12 +774,13 @@ a.detail-creator-card:hover {
background: rgba(0,0,0,0); background: rgba(0,0,0,0);
z-index: 2600; z-index: 2600;
align-items: center; justify-content: center; align-items: center; justify-content: center;
overflow: hidden;
} }
#np-overlay.np-open { display: flex; animation: lb-fade-in-synthwave 0.25s ease forwards; } #np-overlay.np-open { display: flex; animation: lb-fade-in-synthwave 0.25s ease forwards; }
#np-overlay.np-closing { animation: lb-fade-out-synthwave 0.2s ease forwards; } #np-overlay.np-closing { animation: lb-fade-out-synthwave 0.2s ease forwards; }
#np-modal { #np-modal {
position: relative; display: flex; position: relative; z-index: 1; display: flex;
background: var(--bg-panel); background: var(--bg-panel);
border: 1px solid var(--neon-violet); border: 1px solid var(--neon-violet);
border-radius: var(--radius); border-radius: var(--radius);
@ -842,6 +892,7 @@ a.detail-creator-card:hover {
/* ── Right panel ─────────────────────────────────────────────────── */ /* ── Right panel ─────────────────────────────────────────────────── */
#np-right { flex: 1; display: flex; flex-direction: column; min-width: 0; position: relative; z-index: 0; } #np-right { flex: 1; display: flex; flex-direction: column; min-width: 0; position: relative; z-index: 0; }
#np-playlist-view { flex: 1; display: flex; flex-direction: column; min-height: 0; }
#np-header { #np-header {
padding: 0.9rem 1.25rem 0.8rem; padding: 0.9rem 1.25rem 0.8rem;
@ -1216,6 +1267,7 @@ a.detail-creator-card:hover {
overflow: hidden; overflow: hidden;
min-height: 0; min-height: 0;
} }
.np-single #np-playlist-view { display: none; }
.np-single #np-bigroom-view { display: flex; } .np-single #np-bigroom-view { display: flex; }
.np-single #np-btn-next { visibility: hidden; } .np-single #np-btn-next { visibility: hidden; }

View File

@ -292,22 +292,26 @@
// ── Open / close ─────────────────────────────────────────────────────────── // ── Open / close ───────────────────────────────────────────────────────────
function open(metaData) { function open(metaData) {
if (closing) return; if (closing) return;
// Clear stale content from the previous mode before applying new state.
stopBigViz();
tracksList.innerHTML = '';
bigroomTitle.textContent = '';
bigroomArtist.textContent = '';
bigroomMeta.textContent = '';
meta = metaData; meta = metaData;
singleMode = !!(meta && meta.singleMode); singleMode = !!(meta && meta.singleMode);
overlay.classList.toggle('np-single', singleMode); overlay.classList.toggle('np-single', singleMode);
if (singleMode) { if (singleMode) {
playlistView.hidden = true;
bigroomView.hidden = false;
bigroomTitle.textContent = meta.title || ''; bigroomTitle.textContent = meta.title || '';
bigroomArtist.textContent = meta.artist || ''; bigroomArtist.textContent = meta.artist || '';
bigroomMeta.textContent = meta.description || ''; bigroomMeta.textContent = meta.description || '';
// Delay viz start so canvas has layout dimensions // Delay viz start so canvas has layout dimensions
setTimeout(startBigViz, 60); setTimeout(startBigViz, 60);
} else { } else {
playlistView.hidden = false;
bigroomView.hidden = true;
stopBigViz(); stopBigViz();
plTitle.textContent = meta.title || ''; plTitle.textContent = meta.title || '';
@ -410,7 +414,16 @@
window.addEventListener('briTunes:queue', (e) => { window.addEventListener('briTunes:queue', (e) => {
queueFromNpBtn = false; queueFromNpBtn = false;
queue = e.detail.queue || []; queue = e.detail.queue || [];
if (isOpen && !singleMode) buildTrackList(); // If the overlay was in single-song mode and a playlist just started, reset to playlist mode.
if (singleMode) {
singleMode = false;
overlay.classList.remove('np-single');
stopBigViz();
bigroomTitle.textContent = '';
bigroomArtist.textContent = '';
bigroomMeta.textContent = '';
}
if (isOpen) buildTrackList();
setReopenBtn(false); setReopenBtn(false);
}); });