Add modern UI enhancements over the classic redesign

Layered progressive polish on the warm classic + brass theme:
- Card entrance animation on first mount (virtualizer-aware)
- Cursor-tracking brass spotlight border on cards
- Thumbnail skeleton shimmer until the poster paints
- Hover video preview after a short dwell (only when formats resolved)
- View Transition + blurred-poster ambient backdrop on player open
- Favorite heart pop + expanding ring on add
- ⌘K command palette (search, theme, density, reels, source/channel)
- Scroll-progress bar + back-to-top FAB
- Grid density toggle (comfortable/compact)
- Reels HUD: serif title, brass scrubber, muted-state pulse

All new motion respects prefers-reduced-motion; no JS/HTML structure
changes to the core grid/feed. New glue lives in frontend/js/enhance.js.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Simon
2026-06-30 08:25:37 +00:00
parent 382a637b95
commit 138c3224de
11 changed files with 715 additions and 51 deletions

View File

@@ -294,7 +294,25 @@ App.player = App.player || {};
attempt(0);
if (state.playerMode === 'modal') {
modal.style.display = 'flex';
// Ambient backdrop: a blurred copy of the poster fills the letterbox
// behind the contained video for a richer, less sterile player.
const modalContent = modal.querySelector('.modal-content');
if (modalContent) {
let poster = (source && (source.thumb || (source.meta && (source.meta.thumbnail || source.meta.thumb)))) || '';
if (!poster && originEl) {
const img = originEl.querySelector('img');
if (img) poster = img.currentSrc || img.src || '';
}
if (poster) modalContent.style.setProperty('--poster', `url("${poster.replace(/"/g, '%22')}")`);
else modalContent.style.removeProperty('--poster');
}
const reveal = () => { modal.style.display = 'flex'; };
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (!reduce && document.startViewTransition) {
document.startViewTransition(reveal);
} else {
reveal();
}
document.body.style.overflow = 'hidden';
} else {
modal.style.display = 'none';