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,62 @@
<script lang="ts">
import type { Snippet } from 'svelte';
interface Props {
title: string;
description?: string | null;
icon?: Snippet;
actions?: Snippet;
}
let { title, description = null, icon, actions }: Props = $props();
</script>
<div class="empty" role="status">
{#if icon}
<div class="icon">{@render icon()}</div>
{:else}
<div class="icon default">
<svg viewBox="0 0 24 24" width="28" height="28" aria-hidden="true">
<circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="1.5" stroke-dasharray="3 4" />
</svg>
</div>
{/if}
<h3 class="title">{title}</h3>
{#if description}<p class="desc">{description}</p>{/if}
{#if actions}<div class="actions">{@render actions()}</div>{/if}
</div>
<style>
.empty {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
padding: var(--space-16) var(--space-6);
gap: var(--space-3);
color: var(--text-secondary);
border-radius: var(--radius-lg);
background: color-mix(in oklab, var(--surface) 60%, transparent);
}
.icon {
color: var(--text-tertiary);
margin-bottom: var(--space-2);
}
.title {
margin: 0;
font-size: var(--text-md);
font-weight: var(--weight-semibold);
color: var(--text-primary);
}
.desc {
margin: 0;
font-size: var(--text-sm);
color: var(--text-tertiary);
max-width: 44ch;
}
.actions {
margin-top: var(--space-4);
display: flex;
gap: var(--space-2);
}
</style>