- New Tools page (video nav + subpage, mirrors music tools styling): a Library
Scan tool card with Incremental / Full Refresh / Deep Scan buttons + a live
status line. Room for more maintenance jobs later.
- Dashboard Library card now has Refresh (full) + Deep Scan buttons, like the
music dashboard.
- Shared video-scan.js controller: one place triggers + polls scans for all
surfaces (wires any [data-video-scan-mode]/[data-video-scan]); emits
soulsync:video-scan-progress/done. Library/Tools/Dashboard just listen — no
duplicated fetch/poll. video-library.js refactored onto it; dashboard reloads
stats on scan-done.
- All isolated IIFEs, data-attr wired (no inline onclick). video-tools added to
the nav (13 pages). 110 tests green.
- GET /api/video/library -> {movies, shows} from video.db (VideoDatabase.
list_movies/list_shows; shows carry episode_count + owned_count).
- Library page (video-library subpage, isolated video-library.js): tabbed
Movies/Shows grid of poster cards, count, empty-state. A 'Scan Library'
button POSTs /api/video/scan/request then polls /api/video/scan/status,
showing live phase/counts, and refreshes the grid when done.
- Reuses the music dashboard-header chrome (icon title, sweep hidden) + the
watchlist-button styling for the scan button; video-card grid styles added.
- All data-attr wired (no inline onclick); module is an isolated IIFE that
listens for soulsync:video-page-shown. 105 tests green.
Now: video.db -> scanner -> /api/video -> live dashboard + Library page, all
isolated from music. Scanner adapters await live Plex/Jellyfin validation.