# RC117 · iPhone-safe pass-list progress QA

## Scope

RC117 builds directly on RC116 after real-device feedback:

- Auto-scroll in the pass list works well.
- Active-row progress fill did not appear reliably on iPhone/Safari.

RC117 keeps the RC116 pass-list model intact and changes only how the active-row fill is driven.

No player lifecycle, video source priority, timer behavior, wake-lock behavior, image model, cutout/layered model, or renderer model was changed.

## Reused code paths / classes

RC117 continues to use:

- `preview.html` active pass structure.
- `.next-pass-screen`
- `.next-pass-layout`
- `.next-pass-media-card`
- `#videoWrap.next-pass-video-wrap`
- `#passVideoControls.next-pass-video-controls`
- `.next-pass-info-card`
- `.next-pass-progress-below`
- `.next-pass-playlist-card`
- `#miniList.next-pass-mini-list`
- `assets/js/renderers/pass-player-renderer.js`
- `assets/js/core/exercise-catalog.js`
- `assets/js/app.js` player lifecycle: `startWorkout`, `renderStep`, `renderVideo`, `renderRest`, timers, preload, wake lock.

## Changes

### JS-driven active fill

RC116 used a CSS keyframe animation for `.next-pass-mini-fill`. That was fine in Chromium real-DOM QA, but real iPhone testing showed that the fill was not reliably visible.

RC117 changes the active-row fill to be driven by `requestAnimationFrame` in `app.js`:

- `miniListFillRaf`
- `stopMiniListFillLoop()`
- `setMiniListFillProgress()`
- `startMiniListFill()`

The active fill width is now written as an inline important percentage width on `.next-pass-mini-fill`.

This avoids relying on Safari/iPhone CSS keyframe behavior and also avoids the previous reduced-motion override that could force the fill to 100% immediately.

### CSS ownership remains centralized

Pass-list visual styling remains in `assets/css/next-system.css` under the RC116/RC117 pass-list section.

The `.filling` class still marks the active item visually, but CSS no longer owns the fill animation:

- `animation:none!important`
- `transition:none!important`
- `will-change:width!important`

The fill itself is controlled by JS inline width.

### Reduced-motion check

RC117 no longer sets active fill width to `100%` inside `prefers-reduced-motion: reduce`.

QA includes a reduced-motion mobile simulation to verify that active fill still advances gradually and does not jump to full.

## Real-DOM QA

Real-DOM QA was run with actual `preview.html`, actual CSS and actual JS via Playwright `page.set_content()`. External network/iframe requests were blocked/mocked as in RC108–RC116 QA.

Generated RC117 screenshots:

- `qa_screenshots/rc117_pass_list_video_mobile_390x844.png`
- `qa_screenshots/rc117_pass_list_video_ipad_820x1180.png`
- `qa_screenshots/rc117_pass_list_video_desktop_1440x1024.png`
- `qa_screenshots/rc117_pass_list_rest_desktop_1440x1024.png`
- `qa_screenshots/rc117_pass_list_video_mobile_reduced_motion_390x844.png`

Measured checks in `qa_screenshots/rc117_pass_list_js_fill_dom_metrics.json`:

- Playlist is visible when enabled.
- Active item is first in DOM order.
- Active item is aligned to top of list.
- Desktop active item spans the full first row.
- Active fill has inline percentage width.
- Active fill ratio is greater than zero after the QA wait.
- Active fill does not rely on CSS animation (`animation-name: none`).
- Reduced-motion mobile simulation does not force fill to 100%.
- Rest active fill uses exact rest duration.
- Burpee timing helper still returns `6s` for `3 reps`.
- No broken local images.

Observed metric sample:

- Mobile normal video: inline fill around 9.6% after wait.
- Desktop normal video: inline fill around 9.2% after wait.
- Desktop rest: inline fill around 10.2% after wait.
- Mobile reduced-motion: inline fill around 7.6% after wait.

## Commands run

```bash
node tests/rc117_iphone_safe_pass_list_progress_smoke.js
node tests/rc116_pass_list_progress_smoke.js
node tests/rc115_pass_player_scale_smoke.js
python3 tests/rc117_pass_list_js_fill_real_dom_qa.py
find assets/js -name '*.js' -print0 | xargs -0 -n1 node --check
php -l ota_youtube_proxy.php
php -l video_backup_api.php
unzip -t next_v96_rc117_iphone_safe_pass_list_progress.zip
```

## Caveat

The actual deployed host and real iPhone Safari runtime were not testable from this sandbox. The fix is based on the real-device symptom and makes the progress fill robust by replacing CSS keyframe dependency with JS-driven inline width. Final confirmation should still be made on the iPhone where RC116 failed.
