Cobb reproduced 2026-05-26: clicking video B from detail A's related
section opens detail B (title, description correct), minibar/media
notification show A's title, and AUDIO plays A. The bug everyone
was hitting as 'video bugs are back'.
Root cause — VideoDetailViewModel is activity-scoped, so navigating
A→B shows ONE composition frame with the previous video's state
before vm.load(B)'s reset propagates. During that frame:
1. VideoDetailScreen body runs with streamUrl=B but
state.detail=A and state.resolved=A's playback URLs (stale).
2. InlinePlayer is called with title=A, streamUrl=B, resolved=A's.
3. Its LaunchedEffect launches a coroutine. Body is synchronous
(no suspend), runs to completion before cancellation can
interrupt.
4. setPlayingFrom(streamUrl=B, resolved=A's URLs) fires. claim()
succeeds → NowPlaying = {streamUrl=B, title=A's title}.
setMediaItem with A's playback URIs → player loads + plays A.
5. State reset propagates. InlinePlayer disposes.
6. After vm.load completes with B's data, InlinePlayer recomposes
with B's resolved. Its NEW LaunchedEffect fires. The check
'NowPlaying.streamUrl == streamUrl' returns true (because step 4
already stamped streamUrl=B). RETURN EARLY. setPlayingFrom(B)
NEVER fires with the correct B data.
Fix — add a loadedUrl field to VideoDetailUiState that tracks
which streamUrl the current detail/resolved actually belong to.
Gate VideoDetailScreen's player composition on
state.loadedUrl == streamUrl, so the stale-state frame can't fire
setPlayingFrom with mismatched data.
vm.load sets loadedUrl in the initial reset AND the success/error
updates — every state transition carries the URL that owns it.