- Add .health step to onboarding between frequency and ready
- HealthStep with non-blocking permission flow (Not Now skips)
- Remove requestAuthorization() from PlayerViewModel.startWorkout()
- Guard live session start with isAuthorized check
- Remove heart rate write from HealthKit authorization popup
- Remove HR sample writing from saveWorkout (now without permission)
- Add L10n keys: healthAccess, healthAccessSubtitle, allowHealthAccess, notNow
- Add EN/DE/ES/FR translations
- Track permission decisions through analytics
- Entry animation on HealthStep (fade-in + slide-up)
HealthKit permission is now asked once during onboarding,
never interrupting workouts again.
When airplane mode is active, the Supabase client hung indefinitely
waiting for a network response, blocking the mock track fallback.
Now races the query against a 6-second Task.sleep so mock tracks
load immediately after timeout.
## What changed
### Player Redesign (video-first layout)
- New compact timer ring (110pt) with phase label, replaces 240pt ring
- Auto-hide top bar with block progress dots (3s auto-dismiss)
- Expandable now-playing music pill with skip control
- Bottom control bar with heart rate, play/pause, and skip
- Exercise caption with 'Next' preview during rest phases
- Compact round counter (capsule dots)
### Dynamic Island & Live Activities
- WorkoutLiveActivity widget: expanded, compact, and minimal views
- Phase-colored timers with Text(timerInterval:) countdown
- Shows exercise name, round progress, heart rate, music track
- MusicLiveActivity: standalone music now-playing widget
- LiveActivityMusicBars animated component
- Deep link from Dynamic Island back to app
### Timer Drift Fix (critical)
- Store a stable phaseEndDate once per phase instead of
recalculating Date() + timeRemaining on every update
- Prevents dynamic island countdown from rubber-banding
due to 5-second periodic update recalculation drift
- Reset phaseEndDate on phase change and resume from pause
- Guard Live Activity updates behind vm.isRunning to prevent
premature creation when music track loads before workout start
- Fixes timer showing 0 in Dynamic Island when expanding
from home screen
### New PlayerViewModel timer engine
- Full phase support: prep, warmup, work, rest,
interBlockRest, cooldown, complete
- 1-second countdown with audio cues at 3-2-1
- Phase transitions with spring animation and haptics
- HealthKit live session integration
- Workout session recording with completion
### Music Service
- New MusicPlayerViewModel with vibe-based playlist loading
- Track info exposed for Dynamic Island display
- Skip track support from Dynamic Island notification action
- Automatic play/pause based on phase and running state
### Additional
- ZoneHighlightIcon component for HomeTab zone cards
- Updated watchOS localizations with complication strings
- Info.plist updated for widget extension