The shared tier-walk compose methods both frontends call (player untouched):
- play_track_resolved: offline-first (resolve_offline_bytes -> play_data, warms
L1) else Player::play_track (which already does L1/L2 -> CMAF -> legacy).
- fetch_for_gapless_resolved: L1/L2 (player cache) -> offline -> network; the
offline tier is only tried when the track is NOT in the player cache (the
CMAF decrypt is slow, so a cached copy wins — matches the Tauri gapless order).
Both take the frontend's OfflineCacheState by ref (no duplicate DB handle) and
an optional CacheEventSink for the unlock animation. Compiles green.
cc