feat(glass): per-scheme background images + glass-over-image mode

Land the UAT-approved backdrop direction as a real feature (replacing the dev
thumbnail prototype):
- 6 generated abstract SVG backdrops in public/backdrops/, one tuned to each
  accent scheme (dark, mixed-colour, few light areas). Non-figurative + generated
  = repo-safe, tiny, accent-matched.
- New data-backdrop="on" state (dark theme + the setting + not perf) paints the
  per-scheme image on <body> (app root now transparent so it shows app-wide and
  the glass refracts it) AND switches the glass to its translucent tier (the
  user's tuned values: surface 50 / card 60 / scrim 30 / blur 10 / edge 25).
  Off / light / perf -> flat colour + solid glass (the readable fallback).
- Settings > Appearance 'Background image' toggle (bgImage pref, dark-only),
  trilingual. Flat is the fallback + opt-out.
- Remove the FeedBackdrop prototype + its tuner controls; tuner baseline resynced
  to the glass-over-image tier, add a Backdrop-fade slider.
GOTCHA fixed: the dark-mode ambient 'background' shorthand reset background-size
to auto (image rendered un-covered); out-specified it with [data-theme="dark"].
This commit is contained in:
npeter83 2026-07-12 21:20:40 +02:00
parent 036e2fe7ea
commit f9f90cf609
15 changed files with 191 additions and 162 deletions

View file

@ -158,6 +158,17 @@ function Appearance({ prefs }: { prefs: PrefsController }) {
onChange={(v) => setTheme({ ...theme, mode: v ? "dark" : "light" })}
/>
</SettingRow>
<SettingRow
label={t("settings.appearance.backgroundImage")}
hint={t("settings.appearance.backgroundImageHint")}
>
<Switch
label={t("settings.appearance.backgroundImage")}
checked={theme.bgImage}
disabled={theme.mode !== "dark"}
onChange={(v) => setTheme({ ...theme, bgImage: v })}
/>
</SettingRow>
<SettingRow label={t("settings.appearance.listView")} hint={t("settings.appearance.listViewHint")}>
<Switch
label={t("settings.appearance.listView")}