# Details → Player Stream Pre-Resolution

The Details screen now pre-resolves the best stream URL before handing off to the Player, avoiding a redundant re-fetch and re-rank in `PlayerViewModel.initialize()`.

## How it works

1. `DetailsViewModel.loadDetails()` fetches and ranks streams via `SourceRanker.rankStreams()`.
2. The best stream URL is resolved: `bestStream?.debridUrl ?: bestStream?.url`
3. Stored in `SourceListState.bestStreamUrl`
4. Both play buttons (Hero section + Stream section) check `sourceList.bestStreamUrl`:
   - **If resolved:** navigate to `Screen.DirectPlayer.createRoute(url, title)` — Player plays the URL directly, bypassing stream fetch
   - **If null:** fall back to `Screen.Player.createRoute(mediaType, mediaId)` — Player does its own fetch

## Key types

```kotlin
@Stable
data class SourceListState(
    val bestStream: Stream? = null,
    val bestStreamUrl: String? = null,  // ← pre-resolved
    val streams: List<Stream> = emptyList(),
    val rankedStreams: List<RankedStream> = emptyList(),
    val cacheBadge: CacheBadge? = null,
)
```

`DirectPlayer` route: `player-direct?url={encoded}&title={encoded}`

## Caveats
- The pre-resolved URL may expire/token-timeout between resolution and playback. Player still has its own error handling + fallback engine.
- Works for the first-ranked stream only. "All Sources" screen still uses regular Player route.
