The status page appearance form saves a customer-picked brand color
(`statusPage.color`), but `StatusPageThemeProvider` never consumed it —
every rendered surface styled from `tokens.up`, so the picker had no
visible effect on the public page.
Rather than overriding `tokens.up` (the semantic OK/up status color,
which would let a red or orange brand color render the "all
operational" indicator in a red that reads as downtime), this
introduces a separate `brand` / `brandStrong` / `brandSoft` token
triple that is distinct from the up/OK color.
## Changes
- `themes/tokens.ts`: add optional `brand` / `brandStrong` / `brandSoft`
fields on `StatusPageThemeTokens`. Themes leave them undefined; the
provider falls back to the theme's `up*` values so nothing regresses
before individual themes opt in.
- `themes/StatusPageThemeProvider.tsx`: add `brandColor` prop and a
`resolveBrandTokens` helper. When a valid hex is provided it feeds
`brand`, `brandStrong = darken(x, 0.2)`, `brandSoft = alpha(x, 0.15)`
using MUI's shared `alpha`/`darken` (replaces the ad-hoc hex helpers).
Invalid or empty values fall through cleanly.
- `Status/index.tsx`: pass `brandColor={statusPage.color}` only at the
public route. The admin preview provider wraps an iframe whose
document renders itself, so passing the prop there had no effect and
is dropped.
- `themes/refined/styles.ts`: switch accent surfaces (hero logo, active
chart-switch button, hardware pill, footer link) from `tokens.up` to
`tokens.brand`. Uptime bars, status pills, and OK indicators stay on
`tokens.up`. Other themes keep their current styling until a designer
decides which surfaces should switch.
## Benefits
- Brand Color picker actually changes the rendered accent surfaces.
- The semantic "OK/up" status color is never repainted by the brand
color, so operational-state indicators stay green regardless of the
customer's brand.
- Reuses MUI's `alpha` / `darken` helpers already used across the
client; no divergent color utilities.
- Small, incremental adoption: themes opt in at their own pace by
reading `tokens.brand*` where they want the brand accent.