# Apply View — Desktop Split-Pane Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Refactor the Apply view for desktop into a master-detail split pane (28% job list / 72% workspace) with an expand-from-divider animation, while leaving mobile completely unchanged. **Architecture:** `ApplyWorkspace.vue` is extracted from `ApplyWorkspaceView.vue` as a prop-driven component, allowing it to render both inline (split pane) and as a standalone route (mobile). `ApplyView.vue` owns the split layout, selection state, and three easter eggs. The fourth easter egg (Perfect Match shimmer) lives inside `ApplyWorkspace.vue` since it needs access to the loaded job's score. **Tech Stack:** Vue 3 + TypeScript + Pinia-free (local `ref` state) + CSS Grid column transitions + `useEasterEgg.ts` composables (existing) --- ## File Map | File | Action | Responsibility | |------|--------|----------------| | `web/src/assets/peregrine.css` | Modify | Add `--score-mid-high` CSS variable; add `.score-badge--mid-high` class | | `web/src/components/ApplyWorkspace.vue` | **Create** | Extracted workspace: `jobId: number` prop, emits `job-removed` + `cover-letter-generated`, Perfect Match shimmer | | `web/src/views/ApplyWorkspaceView.vue` | Modify | Slim to thin wrapper: `` | | `web/src/views/ApplyView.vue` | **Replace** | Split-pane layout, narrow list rows, Speed Demon + Marathon + (Konami already global) | No router changes — `/apply/:id` stays as-is. --- ## Task 1: Score Badge 4-Tier CSS **Files:** - Modify: `web/src/assets/peregrine.css` The current badge CSS has 3 tiers with outdated thresholds (`≥80`, `≥60`). The new spec uses 4 tiers aligned with the existing CSS variable comments: green ≥70%, **blue 50–69%** (new), amber 30–49%, red <30%. **Why `peregrine.css`?** Score tokens (`--score-high`, `--score-mid`, `--score-low`) are defined there. The new `--score-mid-high` token and the `.score-badge--mid-high` class belong alongside them. **Note:** `ApplyWorkspaceView.vue` defines `.score-badge--*` classes in its ` ``` - [ ] **Step 2: Run type-check** ```bash cd /Library/Development/CircuitForge/peregrine/.worktrees/feature-vue-spa/web ./node_modules/.bin/vue-tsc --noEmit ``` Expected: 0 errors. Fix any type errors before continuing. - [ ] **Step 3: Smoke-test in the browser** Start the dev stack: ```bash # Terminal 1 cd /Library/Development/CircuitForge/peregrine/.worktrees/feature-vue-spa conda run -n job-seeker uvicorn dev-api:app --port 8601 --reload & # Terminal 2 cd web && npm run dev ``` Open http://localhost:5173/apply and verify: - Desktop (≥1024px): split pane renders, list is narrow on left, right shows empty state with 🦅 - Click a job → panel expands from the divider with animation; workspace loads - Click another job → panel content switches, selected row highlight updates - Mark a job as Applied → panel closes, job disappears from list - Mobile emulation (DevTools → 375px) → single-column list with RouterLink navigation (no split) - [ ] **Step 4: Test Speed Demon easter egg** Quickly click 5 different jobs within 3 seconds. Expected: 🦅 streaks across the panel, "You're on the hunt!" toast appears. With DevTools → Rendering → `prefers-reduced-motion: reduce`: toast only, no canvas animation. - [ ] **Step 5: Test Marathon easter egg** Generate cover letters for 5 jobs (or temporarily lower the threshold to 2 for testing, then revert). Expected: `📬 5 today` badge appears in list header. Tooltip on hover: "You're on a roll!". - [ ] **Step 6: Commit** ```bash cd /Library/Development/CircuitForge/peregrine/.worktrees/feature-vue-spa git add web/src/views/ApplyView.vue git commit -m "feat(apply): desktop split-pane layout with narrow list, expand animation, speed demon + marathon easter eggs" ``` --- ## Task 4: Type-Check and Test Suite **Files:** - No changes — verification only - [ ] **Step 1: Run full type-check** ```bash cd /Library/Development/CircuitForge/peregrine/.worktrees/feature-vue-spa/web ./node_modules/.bin/vue-tsc --noEmit ``` Expected: 0 errors. - [ ] **Step 2: Run full test suite** ```bash ./node_modules/.bin/vitest run ``` Expected: all tests pass (minimum 3 from `interviews.test.ts`; any other tests that exist). - [ ] **Step 3: Commit fixes if needed** If any fixes were required: ```bash cd /Library/Development/CircuitForge/peregrine/.worktrees/feature-vue-spa git add -p git commit -m "fix(apply): type-check and test fixes" ``` --- ## Done Criteria - [ ] `--score-mid-high` CSS token added; `.score-badge--mid-high` class works - [ ] `scoreBadgeClass()` uses 4-tier thresholds (≥70 / ≥50 / ≥30 / else) in all apply-flow files - [ ] `ApplyWorkspace.vue` renders the full workspace from a `jobId: number` prop - [ ] `ApplyWorkspace.vue` emits `job-removed` on mark-applied / reject-listing - [ ] `ApplyWorkspace.vue` emits `cover-letter-generated` when polling completes - [ ] Perfect Match shimmer fires once when a ≥70% job opens (`.score-badge--shimmer` keyframe) - [ ] `ApplyWorkspaceView.vue` is a thin wrapper with `` - [ ] Desktop (≥1024px): 28/72 CSS Grid split with `grid-template-columns` transition - [ ] Panel expand animation uses `overflow: clip` + `min-width: 0` (not `overflow: hidden`) - [ ] Panel content fades in with 100ms delay after column expands - [ ] `prefers-reduced-motion`: no grid transition, no canvas animation (toast only for Speed Demon) - [ ] Narrow list rows: title + score badge (top row), company + ✓ tick (bottom row) - [ ] Selected row: border-left accent + tinted background (`color-mix` with `--app-primary-light` fallback) - [ ] Empty panel state shows 🦅 + "Select a job to open the workspace" - [ ] `@job-removed` clears `selectedJobId` + re-fetches job list - [ ] Speed Demon: 5 clicks in <3s → canvas bird + toast (reduced-motion: toast only) - [ ] Marathon: 5+ cover letters in session → `📬 N today` badge in list header - [ ] Konami: already global in `App.vue` — no additional code needed - [ ] Mobile (<1024px): unchanged — full-width list with `RouterLink` navigation - [ ] Type-check: 0 errors; all tests pass