diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b9c736..ed60db9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
## [Unreleased]
### Changed
+- **Rehearser playback extraction.** WebAudio playback, transport controls, bounded decoded-audio prefetch, persistent
+ line-audio caching, and synth-all controls now live in `rehearser-playback.js`.
- **Audiobook namespace wiring.** Network helpers and public casting, recast, export, and save actions now register
after their lazy modules load, completing the namespace bridge without removing legacy global entry points.
- **Audiobook live cast-view extraction.** The live cast feed, roster, settings, and prompt controls now live in
diff --git a/TODO.md b/TODO.md
index 9bd0229..39b1ced 100644
--- a/TODO.md
+++ b/TODO.md
@@ -120,8 +120,9 @@ architecture change: the larger Audiobook/Rehearser/style split.
## P1 — Modular frontend architecture
-- [ ] Split `audiobook.js`, `rehearser.js`, and `style.css` by responsibility; the Rehearser cast renderer is now isolated,
- with the remaining transport/matching blocks still in the monolith.
+- [ ] Split `audiobook.js`, `rehearser.js`, and `style.css` by responsibility; Rehearser casting, playback, training,
+ voice design, library, and stage blocks are now isolated, with import/event wiring and remaining Audiobook orchestration
+ still in the monolith.
- [x] Extract Rehearser stage display and cast-sidebar controls into `rehearser-stage.js`.
- [ ] Replace broad globals with namespaces such as `window.TTVC.audiobook`; a compatibility namespace bridge now
exposes the existing Audiobook, Rehearser, and job APIs while responsibility-by-responsibility migration continues.
diff --git a/VERSION b/VERSION
index a359225..e607a19 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.24.49
+1.24.50
diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md
index d30255a..c7aebd3 100644
--- a/docs/ARCHITECTURE.md
+++ b/docs/ARCHITECTURE.md
@@ -32,7 +32,8 @@ The global scope + monkey-patching is the root cause of the recurring "wiring/ti
Done incrementally as global-scope ordered files (no ES-module change needed) — each loaded before `rehearser.js` in `loader.js` + added to the bundle list in `scripts/minify.mjs`, verified by `tests/rehearser.spec.js` (parse → cast) and the smoke suite:
- ✅ `rehearser-parse.js` — `parseScript`, `detectCharacters` (pure; only call-time `SPEAKER_COLORS`).
- ✅ `rehearser-cast.js` — `renderCastList`, sort/filter, online voice picker, and character research.
-- ✅ `rehearser-stage.js` — stage font/cast sidebar controls and cast-strip rendering; playback and transport remain in `rehearser.js`.
+- ✅ `rehearser-stage.js` — stage font/cast sidebar controls and cast-strip rendering.
+- ✅ `rehearser-playback.js` — WebAudio playback, transport state, bounded decoded-audio prefetch, and persistent line-audio cache/synthesis controls.
- ✅ `rehearser-voice-picker.js` — voice preview state, local matching, fish.audio search/import, and candidate assignment; DOM event registration remains in `rehearser-cast.js`.
- ✅ `rehearser-cast.js` — cast view, full cast-card rendering, sort/filter state handlers, and delegated cast toolbar wiring.
- ✅ `rehearser-voice-design.js` — character development, backend selection, and backend-refresh synchronization.
diff --git a/static/index.html b/static/index.html
index 655721c..577fd77 100644
--- a/static/index.html
+++ b/static/index.html
@@ -10,7 +10,7 @@
-
+
@@ -27,12 +27,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
@@ -397,7 +397,7 @@ window.toggleNavTree = function(treeId, chevronId) {
-
+