# S01: Interaction Delight & Discovery

**Goal:** Cards animate on hover with scale+shadow. Card grids stagger entrance. Featured technique has glow treatment. Random Technique button navigates to a random page.
**Demo:** After this: Cards animate on hover with scale+shadow. Card grids stagger entrance. Featured technique has glow treatment. Random Technique button navigates to a random page.

## Tasks
- [x] **T01: Added scale(1.02) hover to all 6 card types, cardEnter stagger animation across 5 pages, and gradient-border glow on featured technique** — ## Description

CSS-first visual polish covering R016 (card hover + stagger) and R017 (featured glow). Touches all 6 card hover states, adds a new `cardEnter` keyframe with stagger delay pattern, applies stagger indices via JSX style props across 5 page components, and redesigns the `.home-featured` section with gradient border + box-shadow glow.

## Steps

1. **Card hover scale** — In `frontend/src/App.css`, add `transform: scale(1.02)` to hover states for `.recent-card`, `.creator-technique-card`, `.subtopic-technique-card`, `.search-result-card`, and `.topic-card`. For `.nav-card`, augment existing `translateY(-1px)` to `scale(1.02) translateY(-1px)`. Add `transition: ... transform 0.2s` where not already present. Ensure `will-change: transform` is on the base card class.

2. **Stagger keyframe + utility class** — Add `@keyframes cardEnter` (opacity 0→1, translateY(12px→0), 300ms ease-out) to `App.css`. Add `.card-stagger` class that applies the animation with `animation-delay: calc(var(--stagger-index, 0) * 60ms)` and `animation-fill-mode: both`. 

3. **Stagger indices on Home.tsx** — Add `className="card-stagger"` and `style={{ '--stagger-index': i } as React.CSSProperties}` to recent cards `.map()` loop (line ~202). Also add to nav-cards (indices 0, 1).

4. **Stagger indices on TopicsBrowse.tsx** — Add stagger class + index to `.topic-card` elements in the `.map()` loop (line ~117).

5. **Stagger indices on CreatorDetail.tsx** — Add stagger class + index to `.creator-technique-card` elements in the `.map()` loop (line ~141).

6. **Stagger indices on SubTopicPage.tsx** — Add stagger class + index to `.subtopic-technique-card` elements in the `.map()` loops (line ~139). Reset index per group.

7. **Stagger indices on SearchResults.tsx** — Add stagger class + index to `.search-result-card` elements in the `.map()` loop (line ~80).

8. **Featured technique glow** — Redesign `.home-featured` in `App.css`: replace `border-left: 3px solid var(--color-accent)` with a gradient border using `border-image: linear-gradient(135deg, var(--color-accent), #a855f7) 1` or pseudo-element approach, add `box-shadow: 0 0 20px rgba(34, 211, 238, 0.15), 0 0 40px rgba(34, 211, 238, 0.05)` for glow effect. Keep it subtle — accent glow, not neon. Ensure it stays GPU-composited (only box-shadow + opacity, no layout properties).

## Must-Haves

- [ ] All 6 card types have scale(1.02) hover with smooth transition
- [ ] `@keyframes cardEnter` and `.card-stagger` class defined in App.css
- [ ] Stagger indices applied in all 5 page components
- [ ] `.home-featured` has visible glow/gradient treatment
- [ ] `npx tsc --noEmit` passes
- [ ] `npm run build` succeeds

## Verification

- `cd frontend && npx tsc --noEmit` — no type errors
- `cd frontend && npm run build` — Vite build succeeds
- `grep -q 'cardEnter' frontend/src/App.css` — keyframe exists
- `grep -q 'card-stagger' frontend/src/App.css` — utility class exists
- `grep -c 'stagger-index' frontend/src/pages/Home.tsx frontend/src/pages/TopicsBrowse.tsx frontend/src/pages/CreatorDetail.tsx frontend/src/pages/SubTopicPage.tsx frontend/src/pages/SearchResults.tsx` — all 5 pages have stagger indices
  - Estimate: 45m
  - Files: frontend/src/App.css, frontend/src/pages/Home.tsx, frontend/src/pages/TopicsBrowse.tsx, frontend/src/pages/CreatorDetail.tsx, frontend/src/pages/SubTopicPage.tsx, frontend/src/pages/SearchResults.tsx
  - Verify: cd frontend && npx tsc --noEmit && npm run build && grep -q 'cardEnter' src/App.css && grep -q 'card-stagger' src/App.css
- [x] **T02: Added GET /api/v1/techniques/random endpoint returning {slug}, fetchRandomTechnique() client function, and 🎲 Random Technique button with loading/error states on homepage** — ## Description

Vertical feature for R018: backend endpoint, API client function, and frontend button with navigation. The existing `GET /api/v1/techniques?sort=random&limit=1` works but returns the full paginated list response. A dedicated `GET /api/v1/techniques/random` returning just `{ slug: string }` is cleaner.

## Failure Modes

| Dependency | On error | On timeout | On malformed response |
|------------|----------|-----------|----------------------|
| `GET /techniques/random` | Button shows brief error state, stays on page | Same as error — fetch has default timeout | Shouldn't happen (typed response), but guard with optional chaining |
| No techniques in DB | Endpoint returns 404 | N/A | Button hidden or disabled |

## Steps

1. **Backend endpoint** — In `backend/routers/techniques.py`, add `GET /random` endpoint BEFORE the `/{slug}` route (line ~185) to avoid slug capture. The endpoint queries `SELECT slug FROM technique_pages ORDER BY random() LIMIT 1`, returns `{"slug": "..."}`. If no techniques exist, return 404.

2. **API client function** — In `frontend/src/api/public-client.ts`, add `fetchRandomTechnique(): Promise<{ slug: string }>` that calls `GET /api/v1/techniques/random`.

3. **Random button in Home.tsx** — Add a "Random Technique" button after the nav-cards section (or near the CTA area). Use a dice/shuffle icon (SVG inline or emoji 🎲). On click: set loading state, call `fetchRandomTechnique()`, then `navigate(`/techniques/${slug}`)`. If fetch fails, briefly show error then reset. The button should have the `.btn` base class with a secondary style.

4. **Button CSS** — Add `.btn--random` styles in `App.css` if needed (may just use existing `.btn` with minor tweaks). Consider a subtle shuffle icon animation on hover.

## Must-Haves

- [ ] `GET /api/v1/techniques/random` returns `{ slug: string }` with 200, or 404 if empty
- [ ] Route registered before `/{slug}` to avoid capture
- [ ] `fetchRandomTechnique()` in public-client.ts
- [ ] Button visible on homepage, navigates to a technique on click
- [ ] Button has loading state during fetch
- [ ] `npx tsc --noEmit` passes
- [ ] `npm run build` succeeds

## Verification

- `cd frontend && npx tsc --noEmit` — no type errors
- `cd frontend && npm run build` — Vite build succeeds
- `grep -q 'fetchRandomTechnique' frontend/src/api/public-client.ts` — client function exists
- `grep -q '/random' backend/routers/techniques.py` — endpoint exists
- `grep -q 'Random' frontend/src/pages/Home.tsx` — button exists in homepage
  - Estimate: 30m
  - Files: backend/routers/techniques.py, frontend/src/api/public-client.ts, frontend/src/pages/Home.tsx, frontend/src/App.css
  - Verify: cd frontend && npx tsc --noEmit && npm run build && grep -q 'fetchRandomTechnique' src/api/public-client.ts && grep -q '/random' ../backend/routers/techniques.py
