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,110 @@
<script lang="ts">
import type { Snippet } from 'svelte';
type Padding = 'none' | 'sm' | 'md' | 'lg';
type Elevation = 'flat' | 'raised' | 'interactive';
interface Props {
padding?: Padding;
elevation?: Elevation;
href?: string | null;
as?: 'div' | 'section' | 'article' | 'a';
ariaLabel?: string;
class?: string;
style?: string;
children?: Snippet;
onclick?: (e: MouseEvent) => void;
}
let {
padding = 'md',
elevation = 'flat',
href = null,
as = 'div',
ariaLabel,
class: klass = '',
style,
children,
onclick
}: Props = $props();
let isLink = $derived(href !== null && href !== undefined);
let tag = $derived(isLink ? 'a' : as);
// When the container isn't a link but does have a click handler, assign
// a role so screen readers announce it as interactive (a11y_no_static).
let role = $derived(!isLink && onclick ? 'button' : undefined);
let tabindex = $derived(!isLink && onclick ? 0 : undefined);
</script>
<svelte:element
this={tag}
class="card p-{padding} e-{elevation} {klass}"
href={isLink ? href : undefined}
aria-label={ariaLabel}
{role}
{tabindex}
{style}
{onclick}
>
{@render children?.()}
</svelte:element>
<style>
.card {
position: relative;
display: flex;
flex-direction: column;
border-radius: var(--radius-lg);
background: color-mix(in oklab, var(--surface) 90%, transparent);
color: var(--text-primary);
text-decoration: none;
transition:
transform var(--dur-fast) var(--ease-standard),
box-shadow var(--dur-base) var(--ease-standard),
background-color var(--dur-fast) var(--ease-standard);
}
/* Inner highlight — a single hairline of light at the top edge. */
.card::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
/* Backdrop blur only where the browser supports it — some rendering
backends downgrade poorly, and we don't want blurred noise. */
@supports (backdrop-filter: blur(4px)) {
.card {
backdrop-filter: blur(10px) saturate(1.2);
-webkit-backdrop-filter: blur(10px) saturate(1.2);
}
}
/* Padding scale */
.p-none { padding: 0; }
.p-sm { padding: var(--space-4); }
.p-md { padding: var(--space-5); }
.p-lg { padding: var(--space-6); }
/* Elevation */
.e-flat { box-shadow: var(--shadow-ambient); }
.e-raised { box-shadow: var(--shadow-raised); }
.e-interactive {
box-shadow: var(--shadow-ambient);
cursor: pointer;
}
.e-interactive:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-raised);
background: color-mix(in oklab, var(--surface-raised) 92%, transparent);
}
.e-interactive:focus-visible {
outline: none;
box-shadow: var(--focus-ring), var(--shadow-raised);
}
.e-interactive:active { transform: translateY(-1px); }
</style>