Files
character-browser/plans/gallery-enhancement-plan.md
Aodhan Collins 5e4348ebc1 Add extra prompts, endless generation, random character default, and small fixes
- Add extra positive/negative prompt textareas to all 9 detail pages with session persistence
- Add Endless generation button to all detail pages (continuous preview generation until stopped)
- Default character selector to "Random Character" on all secondary detail pages
- Fix queue clear endpoint (remove spurious auth check)
- Refactor app.py into routes/ and services/ modules
- Update CLAUDE.md with new architecture documentation
- Various data file updates and cleanup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 02:07:16 +00:00

776 lines
34 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GAZE Gallery Enhancement Plan
## Executive Summary
This plan outlines a comprehensive enhancement to the GAZE Image Gallery, transforming it from a basic grid-and-lightbox viewer into an immersive, multi-modal viewing experience. The enhancement introduces **three major feature categories**: Slideshow Modes, Image Wall Layouts, and Interactive Viewing Tools.
---
## Current State Analysis
### Existing Implementation
| Component | Current State | File Location |
|-----------|--------------|---------------|
| Grid View | Auto-fill grid, 160-210px cards, hover overlays | [`templates/gallery.html`](templates/gallery.html:88) |
| Lightbox | Bootstrap modal, arrow navigation, keyboard support | [`templates/layout.html`](templates/layout.html:123) |
| Filtering | Category, item, sort, pagination | [`templates/gallery.html`](templates/gallery.html:11) |
| Metadata | Prompt modal with LoRA chips, generation params | [`templates/gallery.html`](templates/gallery.html:194) |
### Design System Variables
```css
/* From static/style.css — these will guide our new components */
--bg-base: #07070f;
--bg-card: #0c0c1c;
--accent: #8b7eff;
--accent-glow: rgba(139, 126, 255, 0.14);
--border: #16163a;
--text: #e8e8f5;
--text-muted: #6a6a9a;
--radius: 12px;
--font-display: 'Space Grotesk';
--font-body: 'Inter';
```
---
## Architecture Overview
```mermaid
graph TB
subgraph Gallery Page
A[View Mode Selector] --> B[Grid View]
A --> C[Masonry View]
A --> D[Justified View]
A --> E[Collage View]
end
subgraph Viewer Modes
F[Cinema Slideshow]
G[Classic Slideshow]
H[Showcase Frame]
I[Comparison Mode]
J[Discovery Mode]
K[Ambient Screensaver]
end
subgraph Core Engine
L[GalleryController]
M[ImageLoader - lazy/preload]
N[TransitionEngine]
O[MetadataProvider]
end
B & C & D & E --> L
L --> F & G & H & I & J & K
L --> M
L --> N
L --> O
```
---
## Feature Specifications
### 1. View Mode Selector
A floating toolbar that allows switching between gallery layouts.
**UI Design:**
```
┌─────────────────────────────────────────────────────────────┐
│ [≡ Grid] [◫ Masonry] [▬ Justified] [◱ Collage] │ [▶ Slideshow ▾] │
└─────────────────────────────────────────────────────────────┘
```
**Slideshow Dropdown:**
```
┌──────────────────┐
│ 🎬 Cinema │
│ ⏯ Classic │
│ 🖼 Showcase │
│ ⚡ Discovery │
│ 🌌 Ambient │
│ ⚖ Comparison │
└──────────────────┘
```
---
### 2. Image Wall Layouts
#### 2.1 Masonry Layout (Pinterest-style)
Variable height columns that create a waterfall effect.
```
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ │ │ │ │ │ │ │
│ 1 │ │ 2 │ │ │ │ 4 │
│ │ └──────┘ │ 3 │ │ │
└──────┘ ┌──────┐ │ │ └──────┘
┌──────┐ │ │ │ │ ┌──────┐
│ 5 │ │ 6 │ └──────┘ │ │
└──────┘ │ │ ┌──────┐ │ 8 │
┌──────┐ └──────┘ │ 7 │ │ │
│ 9 │ ┌──────┐ └──────┘ └──────┘
└──────┘ │ 10 │
└──────┘
```
**Technical Approach:**
- CSS columns or CSS Grid with `grid-auto-rows: 1px` and `span` calculation
- JavaScript to calculate optimal column count based on viewport
- Preserve natural aspect ratios of images
- Lazy loading with Intersection Observer
**CSS Variables:**
```css
--masonry-column-width: 280px;
--masonry-gap: 12px;
--masonry-min-columns: 2;
--masonry-max-columns: 6;
```
#### 2.2 Justified Layout (Google Photos-style)
Rows with perfect edge alignment, variable widths.
```
┌────────────┬──────────┬─────────────────┐
│ 1 │ 2 │ 3 │
└────────────┴──────────┴─────────────────┘
┌─────────────────┬────────────┬─────────┐
│ 4 │ 5 │ 6 │
└─────────────────┴────────────┴─────────┘
┌──────────┬─────────────────┬───────────┐
│ 7 │ 8 │ 9 │
└──────────┴─────────────────┴───────────┘
```
**Technical Approach:**
- Linear partition algorithm to distribute images across rows
- Target row height with flex-grow distribution
- Smart breakpoints based on aspect ratios
- Each row is a flex container
**Configuration:**
```javascript
{
targetRowHeight: 240,
minRowHeight: 180,
maxRowHeight: 320,
containerPadding: 16,
imageSpacing: 8
}
```
#### 2.3 Collage Layout (Magazine-style)
Creative mixed-size layout with featured images.
```
┌───────────────────┬─────────┐
│ │ 2 │
│ 1 ├─────────┤
│ FEATURED │ 3 │
│ ├─────────┤
├─────────┬─────────┤ 4 │
│ 5 │ 6 │ │
└─────────┴─────────┴─────────┘
```
**Technical Approach:**
- CSS Grid with named areas
- Template patterns that rotate/cycle
- Special "featured" designation based on:
- User favorites (if implemented)
- Most recent
- Random selection
- Subtle rotation transforms (-2° to +2°) on some tiles
- Optional overlap with z-index layering
**Template Patterns:**
```javascript
const collagePatterns = [
'hero-right', // Large left, stack right
'hero-left', // Stack left, large right
'hero-center', // Center featured, corners fill
'magazine', // Asymmetric editorial style
'scattered' // Random positions with overlap
];
```
---
### 3. Slideshow Modes
#### 3.1 Cinema Mode
Full-screen immersive experience with cinematic effects.
**Features:**
- **Ambient glow**: Extract dominant colors from image, project as soft backdrop glow
- **Ken Burns effect**: Subtle pan/zoom animation on images
- **Vignette overlay**: Soft dark edges for focus
- **Particle system**: Optional floating light particles/orbs
- **Audio reactive**: Optional ambient music visualization (future)
**Visual Design:**
```
┌─────────────────────────────────────────────────────────────────┐
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░░┌─────────────────────────────────────────────┐░░░░░░░░░░░░│
│░░░░░░│ │░░░░░░░░░░░░│
│░░░░░░│ [Image with Ken Burns] │░░░░░░░░░░░░│
│░░░░░░│ │░░░░░░░░░░░░│
│░░░░░░│ │░░░░░░░░░░░░│
│░░░░░░└─────────────────────────────────────────────┘░░░░░░░░░░░░│
│░░░░░░░░░░░░░░░░░░░ ● ● ● ○ ○ ○ ○ ○ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░░░░░░░░░░░░░░░░░ 4 / 24 ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░ = Ambient glow from image colors ░░░░░░░░░░░░░░░░░░░░░░░░░░░│
└─────────────────────────────────────────────────────────────────┘
```
**Controls (appear on hover/touch):**
```
┌─────────────────────────────────────────────────────────────────┐
│ ⏮ ⏯ ⏭ │ ⏱ 5s ▾ │ 🔀 Shuffle │ Info │ ✕ │
└─────────────────────────────────────────────────────────────────┘
```
**Ken Burns Patterns:**
```javascript
const kenBurnsPatterns = [
{ start: 'scale(1) translate(0, 0)', end: 'scale(1.15) translate(-3%, -2%)' },
{ start: 'scale(1.1) translate(-5%, 0)', end: 'scale(1) translate(0, 0)' },
{ start: 'scale(1) translate(0, 5%)', end: 'scale(1.12) translate(2%, -3%)' },
// ... more patterns
];
```
**Ambient Glow Implementation:**
```javascript
// Use canvas to extract dominant colors
async function extractAmbientColors(imageSrc) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = await loadImage(imageSrc);
canvas.width = 50; // Downscale for performance
canvas.height = 50;
ctx.drawImage(img, 0, 0, 50, 50);
const imageData = ctx.getImageData(0, 0, 50, 50);
// Quantize colors and find dominant clusters
return dominantColors(imageData); // Returns [primary, secondary, accent]
}
```
#### 3.2 Classic Slideshow
Clean, professional presentation mode.
**Features:**
- Multiple transition types: fade, slide, zoom, cube
- Progress bar or dot indicators
- Timer controls (3s, 5s, 8s, 15s, manual)
- Loop toggle
- Random/sequential order
**UI:**
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ │
│ ┌───────────────┐ │
│ ◀ │ │ ▶ │
│ │ IMAGE │ │
│ │ │ │
│ └───────────────┘ │
│ │
│ ● ● ● ○ ○ ○ ○ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ │
│ └─────────────────────────────────────────────────────────────┘ │
│ ⏮ ⏯ ⏭ 🔀 Shuffle ⏱ 5s ✕ │
└─────────────────────────────────────────────────────────────────┘
```
**Transitions CSS:**
```css
.slide-transition-fade { transition: opacity 0.8s ease; }
.slide-transition-slide { transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1); }
.slide-transition-zoom { transition: transform 0.7s ease, opacity 0.7s ease; }
.slide-transition-cube {
transform-style: preserve-3d;
perspective: 1000px;
transition: transform 0.8s ease;
}
```
#### 3.3 Showcase Frame Mode
Digital picture frame aesthetic with metadata.
**Features:**
- Image displayed with decorative frame/mat
- Metadata panel (character name, category, date)
- Ambient room simulation (optional)
- Clock widget (optional)
- Subtle animations
**Layout:**
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ╔══════════════════════════════════════════════╗ │
│ ║ ┌──────────────────────────────────────────┐ ║ │
│ ║ │ │ ║ │
│ ║ │ │ ║ │
│ ║ │ IMAGE │ ║ │
│ ║ │ │ ║ │
│ ║ │ │ ║ │
│ ║ └──────────────────────────────────────────┘ ║ │
│ ╚══════════════════════════════════════════════╝ │
│ │
│ Character: Luna Eclipse │
│ Category: characters • Style: anime │
│ Created: March 8, 2026 │
│ 12:34 │
└─────────────────────────────────────────────────────────────────┘
```
**Frame Styles:**
```javascript
const frameStyles = [
'minimal', // Thin elegant border
'classic', // Traditional wooden frame look
'modern', // Thick black mat, thin metal frame
'gallery', // White mat, thin black frame
'floating', // Shadow box effect
'none' // No frame, edge-to-edge
];
```
#### 3.4 Discovery Mode (Random Shuffle)
Explore your collection with serendipity.
**Features:**
- Random image selection with no repeats until all shown
- "Like" button to save favorites (session-based)
- Quick category jump
- Surprise effects (occasional zoom, pan variations)
- Stats display ("You've discovered 47 of 234 images")
**Controls:**
```
┌─────────────────────────────────────────────────────────────────┐
│ ⚡ DISCOVERY MODE │
│ │
│ ┌───────────────────┐ │
│ │ │ │
│ │ IMAGE │ │
│ │ │ │
│ └───────────────────┘ │
│ │
│ ❤️ Like 🔀 Next Random ⏯ Auto │
│ │
│ Discovered: 47 / 234 ━━━━━━━░░░░░░░░░░░░ │
│ │
│ Quick jump: [Characters] [Actions] [Outfits] [Scenes] [All] │
└─────────────────────────────────────────────────────────────────┘
```
#### 3.5 Ambient Screensaver Mode
Artistic background display with effects.
**Features:**
- Fullscreen with auto-hide UI
- Particle effects (floating light orbs, subtle sparkles)
- Slow crossfade transitions (10-30 seconds)
- Color-matched gradient backgrounds
- Clock overlay option
- Wake on mouse move
**Particle System:**
```javascript
const particleConfig = {
count: 50,
colors: ['#8b7eff', '#c084fc', '#60a5fa', '#ffffff'],
minSize: 2,
maxSize: 8,
speed: 0.3,
opacity: [0.1, 0.6],
blur: [0, 4],
drift: true // Slight random movement
};
```
**Visual Effect:**
```
┌─────────────────────────────────────────────────────────────────┐
│ · · · │
│ · · · │
│ · ┌─────────────────┐ · │
│ · │ │ · │
│ · │ IMAGE │ · · │
│ │ │ · │
│ · └─────────────────┘ · │
│ · · · · · │
│ · · · │
│ 12:34 │
│ · = floating light particles │
└─────────────────────────────────────────────────────────────────┘
```
#### 3.6 Comparison Mode
Side-by-side or overlay comparison.
**Features:**
- Two image selection
- Slider overlay (before/after style)
- Side-by-side split
- Onion skin overlay (opacity blend)
- Difference highlight mode
- Zoom sync (both images zoom together)
**Layouts:**
```
SLIDER MODE: SPLIT MODE:
┌─────────────────────────────┐ ┌───────────┬───────────┐
│ │ │ │ │ │
│ IMAGE A │ IMAGE B │ │ IMAGE A │ IMAGE B │
│ │ │ │ │ │
│ ◄═══|═══► │ │ │ │
│ │ │ │ │ │
└─────────────────────────────┘ └───────────┴───────────┘
ONION SKIN: DIFFERENCE:
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ │ │ │
│ IMAGE A + B BLENDED │ │ PIXEL DIFFERENCE VIEW │
│ │ │ (highlights changes) │
│ Opacity: ●━━━━━━━○ │ │ │
│ │ │ │
└─────────────────────────────┘ └─────────────────────────────┘
```
---
### 4. Enhanced Lightbox Viewer
Upgrade the existing lightbox with professional features.
#### 4.1 Zoom & Pan Controls
**Features:**
- Mouse wheel zoom
- Double-click to fit/fill toggle
- Click-and-drag panning when zoomed
- Pinch-to-zoom on touch devices
- Zoom level indicator
- Reset button
**Implementation:**
```javascript
class ZoomPanController {
constructor(element) {
this.scale = 1;
this.translateX = 0;
this.translateY = 0;
this.minScale = 0.5;
this.maxScale = 5;
}
handleWheel(e) {
const delta = e.deltaY > 0 ? 0.9 : 1.1;
const newScale = Math.min(this.maxScale, Math.max(this.minScale, this.scale * delta));
// Zoom toward cursor position
this.zoomToPoint(newScale, e.clientX, e.clientY);
}
handleDrag(e) {
if (this.scale > 1) {
this.translateX += e.movementX;
this.translateY += e.movementY;
this.applyTransform();
}
}
}
```
#### 4.2 Info Overlay Panel
Slide-out panel with image details.
```
┌─────────────────────────────────────────────────────────────────┐
│ ┌───────────┐│
│ │ℹ INFO ││
│ ├───────────┤│
│ ┌─────────────────────┐ │ ││
│ │ │ │ Luna ││
│ │ IMAGE │ │ Eclipse ││
│ │ │ │ ││
│ │ │ │ Category: ││
│ └─────────────────────┘ │ characters││
│ │ ││
│ │ Actions: ││
│ │ standing ││
│ │ ││
│ │ [Prompt] ││
│ │ [Generate]││
│ └───────────┘│
└─────────────────────────────────────────────────────────────────┘
```
#### 4.3 Thumbnail Strip
Quick navigation with visual preview.
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────────┐ │
│ │ │ │
│ │ MAIN │ │
│ │ IMAGE │ │
│ │ │ │
│ └─────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ ▢ ▢ ▢ [▣] ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ ▢ │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
---
### 5. Keyboard Shortcuts
| Key | Action |
|-----|--------|
| `←` / `→` | Previous / Next image |
| `↑` / `↓` | Zoom in / out |
| `Space` | Toggle slideshow play/pause |
| `F` | Toggle fullscreen |
| `I` | Toggle info panel |
| `G` | Open grid view |
| `M` | Toggle masonry view |
| `S` | Start slideshow |
| `C` | Enter comparison mode |
| `R` | Random image |
| `Esc` | Close viewer / exit fullscreen |
| `1-5` | Set slideshow speed preset |
| `+` / `-` | Zoom in / out |
| `0` | Reset zoom |
---
### 6. Mobile & Touch Optimization
**Gestures:**
- **Swipe left/right**: Navigate images
- **Swipe up**: Show info panel
- **Swipe down**: Close viewer
- **Pinch**: Zoom
- **Double-tap**: Toggle fit/fill
- **Long press**: Show context menu
**Responsive Breakpoints:**
```css
/* Mobile - single column, touch optimized */
@media (max-width: 576px) { }
/* Tablet - 2-3 columns */
@media (min-width: 577px) and (max-width: 991px) { }
/* Desktop - 4-6 columns */
@media (min-width: 992px) { }
/* Large displays - up to 8 columns */
@media (min-width: 1400px) { }
```
---
## File Structure
```
static/
├── style.css # Add gallery enhancement styles
├── js/
│ └── gallery/
│ ├── gallery-core.js # Main controller
│ ├── layout-masonry.js # Masonry layout engine
│ ├── layout-justified.js # Justified layout engine
│ ├── layout-collage.js # Collage layout engine
│ ├── slideshow-cinema.js # Cinema mode
│ ├── slideshow-classic.js # Classic slideshow
│ ├── slideshow-showcase.js # Showcase frame
│ ├── mode-discovery.js # Discovery mode
│ ├── mode-ambient.js # Ambient screensaver
│ ├── mode-comparison.js # Comparison mode
│ ├── viewer-zoom.js # Zoom/pan controller
│ ├── effects-particles.js # Particle system
│ ├── effects-ambient.js # Ambient color extraction
│ └── effects-kenburns.js # Ken Burns animations
templates/
├── gallery.html # Enhanced with view mode selector
└── partials/
└── gallery-viewer.html # New standalone viewer partial
```
---
## Implementation Phases
### Phase 1: Foundation
- [ ] Create gallery core controller class
- [ ] Implement view mode selector UI
- [ ] Add masonry layout with lazy loading
- [ ] Enhanced lightbox with zoom/pan
- [ ] Keyboard shortcut system
### Phase 2: Layouts
- [ ] Justified gallery layout
- [ ] Collage layout with templates
- [ ] Thumbnail strip navigation
- [ ] Mobile swipe gestures
### Phase 3: Slideshows
- [ ] Classic slideshow with transitions
- [ ] Cinema mode with ambient glow
- [ ] Ken Burns effect engine
- [ ] Showcase frame mode
### Phase 4: Advanced Features
- [ ] Discovery mode with favorites
- [ ] Comparison mode slider
- [ ] Ambient screensaver with particles
- [ ] Info panel with metadata
### Phase 5: Polish
- [ ] Performance optimization
- [ ] Accessibility improvements
- [ ] Settings persistence
- [ ] Documentation
---
## Technical Considerations
### Performance
- Use `IntersectionObserver` for lazy loading
- Preload next 2 images in slideshow
- Use `requestAnimationFrame` for animations
- Debounce resize handlers
- Use CSS transforms instead of layout properties
- Consider web workers for color extraction
### Browser Support
- Modern browsers (Chrome, Firefox, Safari, Edge)
- CSS Grid and Flexbox required
- Fullscreen API
- Intersection Observer API
- Web Animations API preferred
### Accessibility
- ARIA labels on all controls
- Focus management in modals
- Reduced motion preference respected
- Screen reader announcements for image changes
- Keyboard navigation throughout
---
## CSS Variables for Gallery Enhancement
```css
/* Gallery Enhancement Variables */
:root {
/* Layouts */
--gallery-gap: 8px;
--gallery-card-radius: 12px;
--gallery-masonry-width: 280px;
--gallery-justified-height: 240px;
/* Viewer */
--viewer-bg: rgba(0, 0, 0, 0.97);
--viewer-accent: var(--accent);
--viewer-transition: 0.3s ease;
/* Slideshow */
--slideshow-interval: 5000;
--kenburns-duration: 8000;
--transition-duration: 800;
/* Effects */
--ambient-blur: 100px;
--ambient-opacity: 0.3;
--particle-count: 50;
--vignette-opacity: 0.4;
/* Frames */
--frame-color-light: #f5f5f5;
--frame-color-dark: #1a1a2e;
--mat-width: 40px;
}
```
---
## Mockup: Cinema Mode
```
╔═══════════════════════════════════════════════════════════════════════╗
║▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓║
║▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓║
║▓▓▓▓▓░░░░░░ ░░░░░▓▓▓▓▓▓║
║▓▓░░░░░ ░░░░▓▓▓║
║▓░░░░ ╭─────────────────────────────╮ ░░░▓║
║░░░░ │ │ ░░║
║░░ │ │ ░║
║░ │ ★ IMAGE ★ │ ░║
║░ │ │ ░║
║░ │ │ ░║
║░░ │ │ ░░║
║░░░ ╰─────────────────────────────╯ ░░░║
║▓░░░░ ░░▓▓║
║▓▓░░░░░ • • • ○ ○ ░░░░▓▓▓║
║▓▓▓▓░░░░░░░ 4 / 24 ░░░░░▓▓▓▓▓▓║
║▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▓▓▓║
║▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓║
╚═══════════════════════════════════════════════════════════════════════╝
Legend:
▓ = Darkest vignette
░ = Ambient glow (color-matched to image)
★ = Image with Ken Burns animation
• = Active indicator, ○ = Inactive
Controls appear on hover:
┌──────────────────────────────────────────────────────────────────────┐
│ ⏮ │ ⏸ │ ⏭ │ ⏱ 5s ▾ │ 🔀 Shuffle │ Info │ ✕ │
└──────────────────────────────────────────────────────────────────────┘
```
---
## Next Steps
1. **Review and approve** this plan
2. **Prioritize features** for MVP
3. **Begin Phase 1** implementation
4. **Iterate** based on feedback
Would you like me to proceed with implementation, or would you like to adjust any aspects of this plan?