189c534315
The two-page dashboard/review split becomes a proper information architecture: Pipeline (stages + live activity), Photos (drag-and-drop, gallery with per-photo extraction state, reshoot tickets — photo work lives with photos), Review (decisions only, keyboard-first), Catalog (the full title ledger with filtering), Queue (what upload will do and everything it has done), and Library (the enriched collection browser, with an honest empty state until real BGG data lands). Pages render server-side from a shared shell — sidebar rail with the rainbow path running its edge, live count badges on Photos/Review/Queue, and Juniper's full portrait finally displayed, with her credit and a standard third-party trademark attribution beneath it (one notice, not per-mention symbols — the convention for referring to another party's mark). Shared client plumbing moves to static/app.js (escaping contract documented at the innerHTML sink). New endpoints: /api/photos-list, /api/queue, /api/library, plus a reshoot count in /api/pipeline. Screenshot review caught two real bugs: photos-list crashed on bare-array raw caches, and .DS_Store was listed as a shelf photo — photo_names() now filters by suffix everywhere, including the /photos allowlist. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>