* feat(appearance): add Calm/Signature visual style, readability mode, and chart palette
Turn the "too intense / italic headers hurt / the security graph fights my
eyes" feedback into a token-driven Visual style with Calm as the new default
and Signature one click back to the prior look.
- Heading family routes through a `.font-heading` utility driven by
`--font-heading`/`--heading-style`: operational headings render upright in the
interface face under Calm and italic Instrument Serif under Signature. Base
rule sets family + style only, so each call site keeps its own weight/tracking
and Signature stays a true no-op; the Calm lift is a `[data-headings="clean"]`
descendant rule. Brand lockup, empty-state heroes, and onboarding stay serif.
- Severity charts resolve through `--sev-*` tokens with Muted, Heat, and
Signature palettes; FindingsByType routes its series through the severity ramp
plus a neutral so no brand-cyan sits next to rose. The risk trend flattens its
gradient under Muted/Heat/reduced and keeps the gradient under Signature.
- Appearance settings gain Visual style cards, a Security visualization palette,
a Readability master toggle, a Motion & effects group, and a "Reset to default"
button (restores the Calm axes, disabled while readability is on). Contrast
moves under Readability and Ambient glow under Motion & effects. A card is
selected only while the stored sub-axes match its preset, so a custom
combination de-selects both.
- The topbar Theme quick-switch swaps the interface/data font pickers for a
Visual style switch and a Readability toggle (text size kept); its footer
Settings link jumps straight to Appearance.
- Readability is a sticky master that forces the calm resolution and a contrast
lift at apply time without mutating the stored sub-axes.
- New users default to Calm; any pre-existing persisted appearance state keeps
the Signature look. The pre-paint script mirrors the store.
- SegmentedControl gains a `disabled` prop and a nullable value (no active
segment for a custom combination, with a roving-tabindex keyboard anchor).
Adds unit/component coverage for the store, migration, chart shape logic, the
disabled control, the reset/de-selection, and the quick-switch.
* fix(appearance): migrate Blueprint serif headings and surface readability locks
- Migrate the two operational Blueprint headings (catalog tile name, drift-policy
option title) from font-serif italic to the .font-heading utility; the first
pass only covered font-display, so Calm still left these italic. font-serif and
font-display both resolve to the same display face, so this is the same fix.
- Lock the Visual style cards under Readability (parity with the topbar switch and
the on-screen guidance to turn Readability off to choose a style by hand).
- Lock the Border brightness slider under Readability and show its forced +0.03
readout, since Readability overrides the stored value; dragging it previously
appeared to do nothing.
- Correct the Appearance docs sentence for the topbar quick switch (it listed
fonts; the quick switch now carries visual style, readability, and text size).
Move the browser-local Deploy progress, Progress style, and Diff preview
before save controls out of Appearance into a new Stacks section under the
Infrastructure group. These are stack lifecycle and editor workflow
preferences, not visual style, so Settings now groups them where operators
expect to find them.
Add a browser-local masthead scope so these localStorage-backed sections read
SCOPE browser instead of the misleading global, and apply it to both
Appearance and Stacks. Control behavior, storage keys, and backing hooks are
unchanged; this is an information-architecture move only.
* feat: add a compact icon-only top navigation toggle
Add a browser-local "Top navigation labels" preference under Settings >
Appearance. With it off, the desktop top navigation renders icon-only;
each destination keeps an aria-label, gains a hover/focus tooltip, and
stays reachable from the command palette. The setting defaults on, so
current behavior is preserved, and the mobile navigation always keeps
its labels.
Also left-align the desktop nav (previously centered) and shorten the
longest nav label from "Auto-Update" to "Update" so the bar scans faster.
* feat: let the icon-only top nav be left or centered
Add a "Top navigation alignment" preference under Settings > Appearance
that appears only when top navigation labels are off. It places the
icon-only bar against the left edge (the default) or centered. With
labels on, the nav always stays left so the longer labels read from the
edge. The choice is browser-local and persists per device.
* feat: add an inline deploy-progress style for the stack detail
Deploy progress gains a presentation choice under Settings > Appearance >
Display: Modal (the default centered overlay) or Inline. In Inline style a
compact status band on the stack detail shows the running operation, its
elapsed time, the live phase, the latest output line, and the post-update
health gate result. A "View output" button opens the full log modal on
demand, a dismiss control clears the band, and the band auto-clears a few
seconds after a clean completion.
The live progress socket is lifted to an always-mounted owner so the band
streams without the modal; the default Modal style is unchanged. Operations
carry their node so a band never bleeds onto a same-named stack on another
node.
The stack detail's redundant "CONTAINERS" section heading is removed; the
band reserves that vertical space.
* fix: keep inline deploy progress reachable off the stack detail
Review of the inline presentation found a gap: a failed operation, an App
Store install, or navigating away leaves the inline session with no visible
surface, since the band only renders on the operation's own stack detail.
Restore the minimized pill as the inline fallback, shown only when the band
is not covering the session, so there is always a click-through to the log
without ever overlapping the band. Closing the modal for a failed op now
ends the session (the band has stepped aside) instead of only hiding it.
Also document the unsupported mid-operation style switch, and refresh the
deploy-progress, settings, appearance, and app-store docs for the renamed
"Deploy progress" setting and the Modal/Inline choice.
* feat(appearance): add theme, accent, contrast, and typography personalization
Expand Settings to Appearance into a full personalization surface and add a
quick switcher to the top bar (the palette button between search and
notifications). Choices are saved to the browser, sync across tabs, and apply
before first paint so there is no flash on reload.
- Themes: Dim (the default raised charcoal), OLED true black, Light, and Auto
(follows the OS and re-resolves live when it flips).
- Accent: an eight-hue wheel (cyan default) that drives the one data color
across charts, rails, focus rings, active states, and the ambient glow.
- Fine-tune sliders: a master Contrast that spreads page, ink, and borders
together, plus Border brightness and Ambient glow.
- Typography: swappable interface (Geist / IBM Plex Sans / Hanken Grotesk) and
data (Geist Mono / IBM Plex Mono / Fira Code) faces, and a text-size control
(continuous slider in Settings, S/M/L/XL presets in the popover, kept in
sync). The display serif stays locked as the signature face.
Surfaces, borders, and ink derive from per-theme lightness values so the live
knobs scale the whole UI through CSS, and the opaque directional borders read on
every panel including true black. A live preview reflects changes in real time.
Adds a documentation page under Features.
* fix(appearance): keep contrast-driven tokens in gamut and add picker keyboard nav
Clamp the contrast and knob driven surface, border, and ink lightness so the
full slider range stays a valid color. The page now always sits below the card
tone, so page/card separation no longer collapses at high contrast in Light; the
lit border edge never reaches white in Light at the low end of the knobs; and the
OLED and Dim extremes resolve to valid black/white instead of out-of-range values.
Add the radiogroup keyboard model (roving tabindex plus Arrow / Home / End) to the
accent and type pickers through a shared hook, matching the segmented control. One
item is tabbable and arrow keys move focus and selection together.