# Trailer Architecture (NuvioTV → Unspooled port)

## Pipeline (all layers exist)
```
DetailsScreen.DetailsHeroSection
  ├─ TrailerButton (shows when HeroState.hasTrailer == true)
  ├─ TrailerPlayer composable (inline, backdrop fades to 0 alpha)
  └─ onPlayTrailer → DetailsViewModel.prepareTrailerPlayback()
       └─ TrailerService.getTrailerPlaybackSource()
            ├─ TMDB /videos API → rankTrailerCandidates (official trailers first)
            └─ InAppYouTubeExtractor.extractPlaybackSource()
                 └─ InnerTube player API → adaptive/progressive/HLS URL
  ├─ SharedTrailerOverlay (full-screen dialog, pause/seek)
  └─ TrailerSection (LazyRow of YouTube thumbnails — not yet ported)
```

## Key files
- `data/trailer/TrailerService.kt` — TMDB → YouTube ranking (122 lines)
- `data/trailer/InAppYouTubeExtractor.kt` — InnerTube extraction (881 lines)
- `data/trailer/TrailerPlaybackSource.kt` — videoUrl + audioUrl model
- `data/trailer/YoutubeChunkedDataSourceFactory.kt` — custom DataSource for YouTube streams
- `ui/components/TrailerPlayer.kt` — ExoPlayer composable (227 lines, upgraded)
- `ui/components/SharedTrailerOverlay.kt` — full-screen trailer dialog (288 lines)
- `ui/screens/details/DetailsScreen.kt` — hero section with inline TrailerPlayer
- `ui/screens/details/DetailsViewModel.kt` — prepareTrailerPlayback(), auto-play timer, state mgmt
- `player/TrailerPlayerPool.kt` — Application-scoped shared ExoPlayer pool
- `player/LocalTrailerPlayerPool.kt` — CompositionLocal provider

## TrailerPlayer params (upgraded from NuvioTV)
```
trailerUrl, trailerAudioUrl, isPlaying, isPaused, onEnded,
onFirstFrameRendered, muted, seekRequestToken, seekDeltaMs,
onProgressChanged, onRemoteKey, cropToFill, overscanZoom
```
Lifecycle-aware: ON_RESUME restores playback, ON_PAUSE stops.

## SharedTrailerOverlay
Full-screen Dialog with D-pad: CENTER=play/pause, LEFT/RIGHT=seek (3s→5s→8s→12s accelerating),
UP=show bar, DOWN=hide bar, BACK=dismiss. Animated seek bar with time display.
