28605b8a2c
- theme_picker: drop .max() floors that could produce dimensions larger
than the available area on small terminals; return early on a zero
area instead of underflowing the centering arithmetic.
- theme_picker: reject the '0' digit shortcut (previously
`saturating_sub('1')` quietly remapped it to row 0).
- theme_picker: cache the System UiTheme at construction so the per-row
swatch loop and chrome lookup don't re-invoke `UiTheme::detect()`
(which reads `COLORFGBG`) on every keystroke.
- color_compat: backend now carries the resolved `UiTheme` alongside
`ThemeId`, and `adapt_{fg,bg}_for_theme` read from that instead of
re-resolving from `theme_id.ui_theme()`. Fixes the case where
`theme = "tokyo-night"` + `background_color = "#000000"` was being
silently overwritten back to tokyo-night's surface_bg by the remap.
Added a test pinning the override.
- ui: the `ConfigUpdated` handler now only appends the confirmation
`System` cell when `persist == true`, so live-preview navigation in
the picker stops spamming "theme = ... (session only)" rows into the
transcript per arrow keystroke.
- ui: `AppAction::OpenThemePicker` reads the active name from
`app.theme_id` instead of reloading `settings.toml` from disk.
- settings: collapse the double `ThemeId::from_name` pass in load()
into a single map+unwrap_or.
Added tests for digit '0' rejection and tiny/zero-sized render paths.