The Rust half of the trigger/status UI:
- offline_cache.rs: cache_track / cache_tracks / remove_cached + row_sink — a
CacheEventSink that reflects download status (queued/downloading%/ready/failed)
and the unlock padlock onto every visible row, plus terminal toasts. cache_*
pre-flight the limit, insert the queued row, and spawn the shared
spawn_track_cache_download with the core client.
- TrackItem gains cache-status / cache-progress / unlocking; set_row_cache_status
+ set_row_unlocking mirror set_row_favorite (walk the 6 track models + search
hero). All 7 exhaustive initializers updated.
- media-action arms ("track","cache"|"download"|"uncache") dispatch to the
controller; the play path now passes row_sink so UnlockStart/End fire the
padlock state during CMAF decrypt.
Compiles clean. Next: the TrackRow.slint affordance (make-offline button + ring
/ check / warn) and the padlock glyph that render these fields.
cc