# Casting UI Redesign — Implementation Plan

> **Consultation:** `consultations/casting_ui_redesign/SYNTHESIS.md` (13 ADRs, 3 rounds with Gemini 2.5 Pro)

**Goal:** Replace the two-level tab navigation + random-variation grids with a production-workflow UI: Workflow Bar, Look Dev with Hero Select, Continuity View with phase cards, and The Bin generation pool.

**Scope:** Frontend only for Phase 1 (casting.js + console.css). Backend phase-generation endpoints in Phase 2.

---

## Phase 1: Workflow Bar + Look Dev Refactor (Frontend)

### Task 1: Replace Two-Level Tabs with Workflow Bar

**Files:** `recoil/editors/modules/casting.js`

**Steps:**
1. Replace `renderNav()` (lines ~156-177) — remove the 3 view tabs (Casting Grid, Angles, Expressions)
2. Replace `renderAssetTypeNav()` (lines ~296-323) — remove the 4 asset type buttons
3. Create new `renderWorkflowBar()` function that renders:
   ```
   ← Back to Characters   CHARACTER_NAME
   [ 1. LOOK DEV ] → [ 2. WARDROBE ] → [ 3. HAIR & MAKEUP ] → [ 4. REFERENCE ]
   ```
4. Update `activeView` values from `'grid'|'turnaround'|'expressions'` to `'lookdev'|'wardrobe'|'hair_makeup'|'reference'`
5. Update `render()` to dispatch based on new view values
6. Update `saveCastingNav()` / `restoreCastingNav()` to use new view names
7. Remove `activeAssetType` variable — it's now implicit in the view

**Verify:** Character gallery → click character → see Workflow Bar with 4 stages. LOOK DEV active by default.

### Task 2: Refactor Look Dev View (Hero Select Flow)

**Files:** `recoil/editors/modules/casting.js`

**Steps:**
1. Create `renderLookDev(session)` function (replaces `renderRefSelector` for character type)
2. Layout sections (top to bottom):
   - **Mood Reference card** (160px, labeled "MOOD REFERENCE — Sets palette & tone. Face is NOT used.")
   - **Hero Select area** (only visible when a candidate is promoted):
     - Large image (~300px)
     - Two buttons: `LOCK AS HERO` (green) + `GENERATE FROM THIS LOOK` (cyan)
   - **Candidate Grid** (2x3, same as current but with `★ Promote` replacing `✓ Lock`)
   - **Reroll controls** (same as current)
   - **The Bin** (new — see Task 4)
3. Candidate actions change:
   - `✗ Reject` — same as current
   - `★ Keep` → renamed to `★ Promote` — moves to Hero Select area
   - Remove direct `✓ Lock as Hero` from candidates
4. `LOCK AS HERO` from Hero Select:
   - Triggers beauty pass
   - On completion, auto-advances to WARDROBE view
5. `GENERATE FROM THIS LOOK`:
   - Confirmation dialog: "This will re-extract mood text. Visual tone may shift."
   - Promotes image to anchor/mood reference slot
   - Re-extracts mood text
   - Regenerates other 5 slots
6. Keep existing `lockAnchorAsHero()` for the MidJourney anchor path

**Verify:** Generate candidates → promote one → see Hero Select with two actions → lock → auto-advance to Wardrobe.

### Task 3: Hero Identity Card in Continuity Views

**Files:** `recoil/editors/modules/casting.js`

**Steps:**
1. Create `renderHeroIdentityCard(charId)` — returns HTML for a 120px sticky card:
   - Hero headshot
   - Character name
   - "CHANGE HERO" link (navigates back to LOOK DEV)
2. Render this card at the top of WARDROBE and HAIR & MAKEUP views
3. Position: fixed top-left of the continuity view content area

**Verify:** Lock hero in Look Dev → switch to Wardrobe → see hero identity card with image + name.

### Task 4: The Bin (Generation Pool)

**Files:** `recoil/editors/modules/casting.js`, `recoil/editors/styles/console.css`

**Steps:**
1. Create `renderBin(sessionId, assetType)` function:
   - Fetches all candidate images for this asset type from server
   - Filters out currently-assigned images
   - Collapse behavior:
     - 0 images: hidden
     - 1-12: expanded, single row of thumbnails (80px each)
     - 13+: collapsed header ("THE BIN — N images"), click to expand
2. Create `binSelectImage(src)` — enters bin-select mode:
   - Selected image gets blue border
   - All active grid slots show "PLACE HERE" overlay on hover
3. Create `binAssignToSlot(sessionId, slot, binImagePath)` — swaps images:
   - POST to server to update assignment
   - Old slot image moves to bin
   - Bin image moves to slot
4. Add bin rendering to Look Dev view (below reroll controls)
5. CSS: `.casting-bin`, `.casting-bin-header`, `.casting-bin-grid`, `.casting-bin-image`, `.bin-selected`, `.bin-target`

**Verify:** Generate candidates → reject some → reroll → see bin accumulate images → click bin image → click target slot → swap.

### Task 5: Reference View (Sub-tabs)

**Files:** `recoil/editors/modules/casting.js`

**Steps:**
1. Create `renderReferenceView()` — the REFERENCE workflow stage
2. Add sub-tab bar: `ANGLES | EXPRESSIONS`
3. Default to ANGLES sub-tab
4. Hero-lock gating: if no hero locked, show "LOCK A HERO IN LOOK DEV FIRST"
5. Move existing `renderTurnaroundView()` → `renderAnglesSubView()`
6. Move existing `renderExpressionLibrary()` → `renderExpressionsSubView()`
7. Track sub-tab state: `activeReferenceSubTab = 'angles' | 'expressions'`

**Verify:** Lock hero → switch to REFERENCE tab → see ANGLES sub-tab → switch to EXPRESSIONS.

### Task 6: CSS Styling for New Layout

**Files:** `recoil/editors/styles/console.css`

**Steps:**
1. `.workflow-bar` — horizontal flex, gap 4px, items centered
2. `.workflow-step` — button style, numbered, arrow separator between steps
3. `.workflow-step.active` — highlighted (cyan border/text)
4. `.workflow-step.completed` — check mark, green accent
5. `.hero-select` — centered, large image area, two-button row
6. `.mood-reference` — 160px card, labeled, subdued
7. `.hero-identity-card` — 120px sticky card, top-left
8. `.phase-card` — full-width row, phase label + candidates + prompt
9. `.casting-bin` — collapsible panel, bottom
10. `.reference-subtabs` — sub-tab bar within Reference stage

**Verify:** Visual inspection — workflow bar looks professional, phase cards stack cleanly, bin collapses/expands.

---

## Phase 2: Continuity View + Backend Phase Generation

### Task 7: Continuity View (Wardrobe)

**Files:** `recoil/editors/modules/casting.js`

**Steps:**
1. Create `renderContinuityView(assetType)` — shared by WARDROBE and HAIR & MAKEUP
2. Layout:
   - Hero Identity Card (top-left, from Task 3)
   - "GENERATE ALL PHASES" button (prominent, top)
   - Vertical stack of Phase Cards (one per phase from bible)
3. Phase Card layout:
   ```
   [Phase Label + Ep Range] [Candidate 1] [Candidate 2] [Candidate 3] [+] [↻ Reroll Phase]
   [Prompt text (read-only)] [COPY TO OVERRIDE] [EDIT OVERRIDE]
   ```
4. Per-candidate actions: `✓ Lock` (green), `✗ Reject` (red)
5. Phase states: `empty → generating → ready → locked`
6. Override management: per-phase override text field (session-level, not bible)
7. The Bin below (shared for all phases of this asset type)

**Verify:** Navigate to WARDROBE → see 7 phase cards → each shows label + ep range + prompt.

### Task 8: Phase-Aware Server Endpoints

**Files:** `starsend/editors/review_server.py`

**Steps:**
1. New endpoint: `POST /api/project/{name}/casting/generate-phases`
   - Body: `{ character_id, asset_type, phases: ["phase_1", ...] }`
   - Creates one ContinuitySession with 7 phase slots
   - Dispatches 21 parallel_singles calls (3 per phase)
   - Returns session with per-phase candidates
2. New endpoint: `POST /api/project/{name}/casting/reroll-phase`
   - Body: `{ session_id, phase_id }`
   - Regenerates 3 candidates for one phase (unlocked/rejected only)
3. New endpoint: `GET /api/project/{name}/casting/bin/{character_id}/{asset_type}`
   - Returns all image paths for this character's asset type minus active assignments
   - Derived from filesystem (glob candidates dir)
4. New endpoint: `POST /api/project/{name}/casting/bin-assign`
   - Body: `{ session_id, phase_id, slot, bin_image_path }`
   - Swaps bin image into active slot, old slot image goes to bin
5. Update `_get_description_for_session()` to accept `phase_id` and return phase-specific description

**Verify:** POST generate-phases with Torch wardrobe → get back 21 generating slots → poll → all complete.

### Task 9: Phase-Aware Prompt Building

**Files:** `starsend/lib/ref_selector.py`

**Steps:**
1. Add `generate_phase_candidates()` function:
   - Takes: `descriptor, phases_data, output_dir, hero_image_path, mood_text`
   - Fires 3 × len(phases) parallel_singles calls
   - Each call uses phase-specific `wardrobe_description` or `hair_makeup` from bible
   - Returns: `{ phase_id: [panel_paths], cost: float }`
2. Per-phase prompt: costume_designer template with specific wardrobe_description
3. All calls share the same hero image as identity ref
4. Stagger calls by 200ms to avoid Flash rate limits
5. Save to: `{output_dir}/candidates/{char_id}/{asset_type}/{phase_id}/candidate_{N}.png`

**Verify:** Call generate_phase_candidates with 7 phases → 21 images saved to correct phase subdirectories.

### Task 10: Generation Progress Streaming

**Files:** `recoil/editors/modules/casting.js`, `starsend/editors/review_server.py`

**Steps:**
1. Server: Track per-phase generation progress in session state:
   ```json
   "phases": {
     "phase_1": { "status": "generating", "candidates_ready": 1, "candidates_total": 3 }
   }
   ```
2. Client: Poll session at 2s interval (existing pattern)
3. Each phase card shows: `Empty → Generating (1/3) → (2/3) → Ready (3/3)`
4. Images pop in as each API call completes

**Verify:** Click GENERATE ALL PHASES → see individual phase cards progressively fill with images.

### Task 11: Lightbox Integration with Bin

**Files:** `recoil/editors/modules/casting.js`

**Steps:**
1. Update `showLightbox(src)` to collect images from BOTH active slots AND bin
2. Navigation order: active slots first (Phase 1 C1, C2, C3, Phase 2 C1...), then bin images
3. Add source label overlay: "Phase 3, Candidate 2" or "The Bin"
4. Bin images also get lightbox click handler

**Verify:** Open lightbox → arrow through all active candidates → continues into bin images → source label shows correctly.

---

## Phase 3: State Model + Polish

### Task 12: ContinuitySession State Model

**Files:** `starsend/editors/review_server.py`

**Steps:**
1. Define ContinuitySession structure (extends GridSession pattern):
   ```json
   {
     "session_id": "uuid",
     "session_type": "continuity",
     "asset_type": "wardrobe",
     "character_id": "TORCH",
     "phases": {
       "torch_phase_1_full_mask": {
         "phase_id": "...",
         "label": "Full Mask",
         "ep_range": "Ep. 1-10",
         "candidates": [
           { "slot": 0, "path": "...", "state": "new" },
           { "slot": 1, "path": "...", "state": "locked" },
           { "slot": 2, "path": null, "state": "empty" }
         ],
         "override_text": "",
         "description": "Worn, ribbed, off-white..."
       }
     },
     "cost": 0.819,
     "status": "active"
   }
   ```
2. Persistence: save to `casting_state.json` under `continuity_sessions`
3. CRUD operations parallel to existing grid_sessions

**Verify:** Create continuity session → persist to JSON → reload page → session restored.

### Task 13: Props Panel

**Files:** `recoil/editors/modules/casting.js`

**Steps:**
1. Add PROPS button to character detail header (outside workflow bar)
2. Click opens a slide-out panel or modal
3. Inside: standard grid session for props (existing GridSession, 3x3 grid)
4. Separate from the main workflow flow

**Verify:** Click PROPS button → see modal with prop grid → generate → close modal.

### Task 14: Cache Buster + Final Integration

**Files:** `recoil/editors/prepro-console.html`

**Steps:**
1. Bump casting.js cache buster
2. Test full workflow: Gallery → Look Dev → Lock Hero → Wardrobe → Hair & Makeup → Reference
3. Verify session state persists across tab switches
4. Verify lightbox works in all views
5. Verify bin accumulates correctly

**Verify:** Full end-to-end walkthrough without errors.
