A TextPreviewController (owned by the viewer, bound by MediaTextPreview)
mirrors the editing/dirty/saving state out so the top bar draws the buttons;
Save shows a spinner while saving. Located and tested via a Codex consult
(its end-to-end widget test, with the provider fixed and the saving state
adapted); the controller design replaces its builder-wrapping patch.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>