# S01 Research: Interaction Delight & Discovery

## Summary

This slice covers three requirements: R016 (card hover + staggered entrance), R017 (featured technique glow), R018 (random technique button). All are CSS-first frontend work with one small backend addition (random endpoint). The codebase already has the patterns and data plumbing — this is applying polish to existing elements.

**Risk:** Medium only because CSS animation scope touches many card types across multiple pages. No architectural unknowns.

## Recommendation

Straightforward CSS + minor JSX work. Split into: (1) card hover/stagger animations (CSS-only, all card types), (2) featured technique glow redesign (CSS + minor JSX), (3) random technique button (backend endpoint + frontend button + navigation).

## Implementation Landscape

### Card Types Requiring Hover Animation (R016)

Six distinct card CSS classes need hover treatment (scale + shadow + 200ms transition):

| Card class | Page | Container class | Current hover |
|---|---|---|---|
| `.nav-card` | Home | `.nav-cards` | translateY(-1px), border-color, box-shadow ✓ already good |
| `.recent-card` | Home | `.recent-list` | border-color, box-shadow only — needs scale |
| `.creator-technique-card` | CreatorDetail | direct children | border-color, box-shadow only — needs scale |
| `.subtopic-technique-card` | SubTopicPage | `.subtopic-group__list` | border-color, box-shadow only — needs scale |
| `.search-result-card` | SearchResults | `.search-group` | has hover — needs scale |
| `.topic-card` | TopicsBrowse | `.topics-grid` | no explicit hover — needs full treatment |

**Note:** `.nav-card` already has `transform: translateY(-1px)` on hover. Augment to `scale(1.02) translateY(-1px)` rather than replacing.

CreatorsBrowse uses `.creator-row` (table rows, not cards) — not in scope for card hover.

### Staggered Entrance Animations (R016)

Existing animation: `@keyframes pageEnter` applies `translateY(8px)` fade-in to all page containers. Cards within pages don't have individual entrance animations.

**Approach:** Define a `@keyframes cardEnter` (opacity 0→1, translateY(12px→0)) and apply via a `.card-stagger` utility class. Use CSS `animation-delay` with `calc(var(--stagger-index) * 60ms)` pattern — set `--stagger-index` via `style` prop in JSX `.map()` loops. This avoids JS animation libraries entirely.

**Pages needing stagger:**
- Home: `.recent-list` (4 cards)
- TopicsBrowse: `.topics-grid` (7 cards)
- CreatorDetail: technique cards list
- SubTopicPage: technique cards per group
- SearchResults: result cards

### Featured Technique Glow (R017)

Current `.home-featured` is a plain bordered box with `border-left: 3px solid var(--color-accent)`. Needs a visually distinct glow/gradient treatment.

**Approach:** Replace the left-border accent with a gradient border (using `border-image` or pseudo-element with `background: linear-gradient`) plus a subtle `box-shadow` glow using the cyan accent color (`--color-accent: #22d3ee`). Keep it GPU-composited (box-shadow + opacity).

**File:** Only `frontend/src/App.css` lines ~1231-1293 (`.home-featured` block). No JSX changes needed — the existing class structure supports the redesign purely in CSS.

### Random Technique Button (R018)

**Backend:** The existing `GET /api/v1/techniques?sort=random&limit=1` already returns a random technique (uses `ORDER BY func.random()` in `backend/routers/techniques.py:158`). A dedicated `GET /api/v1/techniques/random` endpoint would be cleaner (single redirect-style response), but the existing list endpoint works fine. Decision: add a lightweight `/techniques/random` endpoint that returns `{ slug: string }` — avoids fetching full list response for one item.

**Frontend API client:** Add `fetchRandomTechnique()` to `frontend/src/api/public-client.ts`.

**Frontend button:** Add a "Random Technique" button to `Home.tsx`, near the hero section or below nav-cards. On click: fetch random slug → `navigate(`/techniques/${slug}`)`. Button needs a dice/shuffle icon and loading state.

**Note:** Home.tsx already fetches a random technique for the "Featured Technique" section (line 29-37: `fetchTechniques({ sort: "random", limit: 1 })`). The Random button should use a separate fetch to avoid navigating to the already-displayed featured technique.

### CSS Custom Properties Available

The theme system (`App.css` lines 1-60) provides all needed tokens:
- `--color-accent: #22d3ee` (cyan) — for glow
- `--color-accent-subtle: rgba(34, 211, 238, 0.1)` — for subtle glow rings
- `--color-shadow: rgba(0, 0, 0, 0.2)` — existing shadow base
- `--color-bg-surface: #1a1a24` — card backgrounds

### Animation Performance Constraint

Per KNOWLEDGE.md and M011-CONTEXT.md: CSS animations must use GPU-composited properties only (`transform`, `opacity`). Box-shadow transitions are technically not GPU-composited but are acceptable at this scale (static elements, not scrolling). Avoid animating `width`, `height`, `padding`, `margin`.

## Key Files

| File | Role | Changes |
|---|---|---|
| `frontend/src/App.css` | All styles | Add hover scale, stagger keyframes, featured glow, random button styles |
| `frontend/src/pages/Home.tsx` | Homepage | Add random technique button, stagger indices on recent cards |
| `frontend/src/pages/TopicsBrowse.tsx` | Topics grid | Add stagger indices to topic cards |
| `frontend/src/pages/CreatorDetail.tsx` | Creator page | Add stagger indices to technique cards |
| `frontend/src/pages/SubTopicPage.tsx` | Subtopic page | Add stagger indices to technique cards |
| `frontend/src/pages/SearchResults.tsx` | Search results | Add stagger indices to result cards |
| `frontend/src/api/public-client.ts` | API client | Add `fetchRandomTechnique()` |
| `backend/routers/techniques.py` | API | Add `GET /techniques/random` endpoint |

## Task Seams

Natural decomposition:

1. **Card hover animations** (CSS-only) — Add `transform: scale(1.02)` and enhanced shadow to all card hover states. Pure CSS, no JSX changes. Can verify visually.

2. **Staggered entrance animations** (CSS + JSX) — Define `@keyframes cardEnter` and `.card-stagger` class. Add `style={{ '--stagger-index': i }}` to card `.map()` loops across 5 pages. Slightly more work due to touching multiple files.

3. **Featured technique glow** (CSS-only) — Redesign `.home-featured` with gradient border and box-shadow glow. Pure CSS.

4. **Random technique button** (backend + frontend) — Add endpoint, API client function, button in Home.tsx with navigation. Riskiest piece (backend change), should be built first or second to validate the API works.

## Verification Strategy

- `cd frontend && npx tsc --noEmit` — TypeScript compiles
- `cd frontend && npm run build` — Vite build succeeds
- Visual verification in browser at `http://ub01:8096`:
  - Hover any card → see scale + shadow transition
  - Load any listing page → cards stagger in
  - Homepage featured technique → visible glow/gradient
  - Click Random Technique → navigates to a technique page
  - Click Random Technique again → navigates to a different page (probabilistic)
