Redesign UI with new token system, primitives, and motion

Restraint-first design language: neutral gray surfaces + one blue accent
(cyan/amber/red reserved for state), 8pt spacing, softer radii, one
ambient + one raised shadow, standardized motion tokens. Alfa Slab One
demoted to BrandMark only; Inter carries all page copy.

New primitives (Button, Card, Badge, Stat, SectionHeader, Skeleton,
EmptyState, Tabs, Breadcrumbs, StatusPip, Field, Input, Select, Textarea)
plus motion utilities (tweenNumber, viewTransition) and a global toast
system. All eight route surfaces rewritten on top: Fleet gains an
overview hero, Server detail restructures into tabs, Deployments gets a
collapsible drift summary + per-server pipeline visual, and the
scripts/configs/plugins/betas flows adopt the new form primitives.

Sticky translucent nav with backdrop blur, view-transition cross-fades
between routes, staggered card entrance on Fleet, breathing status pip
halo, tabular-numeric player counts. Gmail-style g-key nav shortcuts.
Mobile stacks below 720px; prefers-reduced-motion neutralizes durations.
Legacy tokens preserved as aliases so any un-migrated code still renders.
This commit is contained in:
2026-09-14 19:48:48 -04:00
parent efd4a4fa66
commit a2d4a38925
34 changed files with 5093 additions and 3144 deletions
@@ -0,0 +1,64 @@
<script lang="ts">
import type { Health } from '$ui/stores/servers.js';
interface Props {
health?: Health;
size?: 'sm' | 'md';
label?: string | null;
}
let { health = 'offline', size = 'md', label = null }: Props = $props();
let toneClass = $derived(
health === 'online' ? 't-online' :
health === 'stale' ? 't-warning' :
't-danger'
);
let announceLabel = $derived(
label ?? (
health === 'online' ? 'online' :
health === 'stale' ? 'stale' :
'offline'
)
);
</script>
<span class="pip s-{size} {toneClass}" role="status" aria-label={announceLabel}>
<span class="halo" aria-hidden="true"></span>
<span class="dot" aria-hidden="true"></span>
</span>
<style>
.pip {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.s-sm { width: 8px; height: 8px; }
.s-md { width: 10px; height: 10px; }
.dot {
position: relative;
z-index: 1;
width: 100%;
height: 100%;
border-radius: 50%;
}
/* Halo — opacity+scale only, GPU-cheap, no box-shadow ring. */
.halo {
position: absolute;
inset: 0;
border-radius: 50%;
opacity: 0;
}
.t-online .dot { background: var(--state-online); box-shadow: 0 0 4px rgba(124, 212, 255, 0.55); }
.t-online .halo { background: var(--state-online); animation: pip-breathe 2.4s var(--ease-standard) infinite; }
.t-warning .dot { background: var(--state-warning); }
.t-danger .dot { background: var(--state-danger); opacity: 0.7; }
</style>