Bolder, more delightful frontend across all pages
- app.css: replace flat --shadow-sm token with real shadows; add --shadow-card and --shadow-dialog tokens; add @keyframes status-ping and .animate-status-ping utility (outward ring ripple, GPU-composited via will-change) for live running status dots - login: headline 5rem → 6.5rem with tighter leading/tracking; expand container to 460px; add sage-green dot grid texture layer beneath the mouse-reactive glow for industrial depth - capsules: upgrade all running dots (header chip + row indicators + status bar) from opacity-fade to ring ripple; apply --shadow-dialog to Launch and Snapshot dialogs - keys: apply --shadow-dialog to all three dialogs - audit: remove duplicate @keyframes fadeUp and iconFloat (redundant with app.css definitions, audit's fadeUp also subtly diverged) - sidebar: active indicator bar taller and thicker (h-5 w-[3px] → h-6 w-1); active bg more vivid (accent/12%); label font-medium → font-semibold; team dialog gets --shadow-dialog
This commit is contained in:
@ -69,8 +69,10 @@
|
||||
--radius-avatar: 5px;
|
||||
--radius-logo: 6px;
|
||||
|
||||
/* Shadows — flat aesthetic */
|
||||
--shadow-sm: 0 0 #0000;
|
||||
/* Shadows */
|
||||
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.35), 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
--shadow-card: 0 4px 12px rgba(0, 0, 0, 0.4), 0 1px 3px rgba(0, 0, 0, 0.25);
|
||||
--shadow-dialog: 0 16px 48px rgba(0, 0, 0, 0.6), 0 4px 12px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
/* Base styles */
|
||||
@ -131,6 +133,24 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
/* Outward ring ripple — for live/running status dots; more delightful than opacity-only */
|
||||
@keyframes status-ping {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 0.8;
|
||||
}
|
||||
80%,
|
||||
100% {
|
||||
transform: scale(2.8);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-status-ping {
|
||||
animation: status-ping 2s cubic-bezier(0, 0, 0.2, 1) infinite;
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
|
||||
/* Fade-up entrance animation */
|
||||
@keyframes fadeUp {
|
||||
from {
|
||||
|
||||
@ -342,19 +342,19 @@
|
||||
{:else if isActive(item.href)}
|
||||
<a
|
||||
href={item.href}
|
||||
class="group relative flex items-center rounded-[var(--radius-input)] bg-[var(--color-accent-glow-mid)] px-2.5 py-2.5 transition-colors duration-150 {collapsed
|
||||
? 'justify-center px-2'
|
||||
: 'gap-3'}"
|
||||
class="group relative flex items-center rounded-[var(--radius-input)] px-2.5 py-2.5 transition-colors duration-150 {collapsed
|
||||
? 'justify-center px-2 bg-[var(--color-accent-glow-mid)]'
|
||||
: 'gap-3 bg-[var(--color-accent)]/[0.12]'}"
|
||||
title={collapsed ? item.label : undefined}
|
||||
>
|
||||
{#if !collapsed}
|
||||
<div
|
||||
class="absolute left-0 top-1/2 h-5 w-[3px] -translate-y-1/2 rounded-r-full bg-[var(--color-accent)]"
|
||||
class="absolute left-0 top-1/2 h-6 w-1 -translate-y-1/2 rounded-r-full bg-[var(--color-accent)]"
|
||||
></div>
|
||||
{/if}
|
||||
<item.icon size={16} class="shrink-0 text-[var(--color-accent-bright)]" />
|
||||
{#if !collapsed}
|
||||
<span class="text-ui font-medium text-[var(--color-accent-bright)]">
|
||||
<span class="text-ui font-semibold text-[var(--color-accent-bright)]">
|
||||
{item.label}
|
||||
</span>
|
||||
{/if}
|
||||
@ -396,7 +396,7 @@
|
||||
|
||||
<div
|
||||
class="relative w-full max-w-[380px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6"
|
||||
style="animation: fadeUp 0.2s ease both"
|
||||
style="animation: fadeUp 0.2s ease both; box-shadow: var(--shadow-dialog)"
|
||||
>
|
||||
<h2 class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">
|
||||
Create Team
|
||||
|
||||
@ -556,15 +556,7 @@
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@keyframes fadeUp {
|
||||
from { opacity: 0; transform: translateY(8px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
@keyframes iconFloat {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-6px); }
|
||||
}
|
||||
/* fadeUp and iconFloat are defined globally in app.css — no need to redeclare them here */
|
||||
|
||||
@keyframes stripePulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
|
||||
@ -327,14 +327,13 @@
|
||||
<div class="flex items-center gap-3">
|
||||
<!-- Status chip -->
|
||||
<div
|
||||
class="flex items-center gap-2.5 rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] px-3.5 py-2"
|
||||
class="flex items-center gap-2.5 rounded-[var(--radius-card)] border border-[var(--color-accent)]/20 bg-[var(--color-bg-2)] px-3.5 py-2"
|
||||
>
|
||||
<span class="relative flex h-[7px] w-[7px]">
|
||||
<span class="relative flex h-[8px] w-[8px]">
|
||||
<span
|
||||
class="absolute inline-flex h-full w-full rounded-full bg-[var(--color-accent)]"
|
||||
style="animation: wrenn-glow 2.5s ease-in-out infinite"
|
||||
class="animate-status-ping absolute inline-flex h-full w-full rounded-full bg-[var(--color-accent)]"
|
||||
></span>
|
||||
<span class="relative inline-flex h-[7px] w-[7px] rounded-full bg-[var(--color-accent)]"></span>
|
||||
<span class="relative inline-flex h-[8px] w-[8px] rounded-full bg-[var(--color-accent)]"></span>
|
||||
</span>
|
||||
<span class="font-mono text-body font-semibold text-[var(--color-accent-bright)]">{runningCount}</span>
|
||||
<span class="text-ui text-[var(--color-text-secondary)]">running now</span>
|
||||
@ -531,7 +530,7 @@
|
||||
<div class="flex items-center gap-2.5 px-5 py-4">
|
||||
{#if capsule.status === 'running'}
|
||||
<span class="relative flex h-[6px] w-[6px] shrink-0">
|
||||
<span class="absolute inline-flex h-full w-full rounded-full bg-[var(--color-accent)]" style="animation: wrenn-glow 2.5s ease-in-out infinite"></span>
|
||||
<span class="animate-status-ping absolute inline-flex h-full w-full rounded-full bg-[var(--color-accent)]"></span>
|
||||
<span class="relative inline-flex h-[6px] w-[6px] rounded-full bg-[var(--color-accent)]"></span>
|
||||
</span>
|
||||
{:else if capsule.status === 'paused'}
|
||||
@ -621,7 +620,10 @@
|
||||
class="flex h-7 shrink-0 items-center justify-end border-t border-[var(--color-border)] bg-[var(--color-bg-1)] px-7"
|
||||
>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="inline-flex h-[5px] w-[5px] rounded-full bg-[var(--color-accent)]"></span>
|
||||
<span class="relative flex h-[5px] w-[5px]">
|
||||
<span class="animate-status-ping absolute inline-flex h-full w-full rounded-full bg-[var(--color-accent)]"></span>
|
||||
<span class="relative inline-flex h-[5px] w-[5px] rounded-full bg-[var(--color-accent)]"></span>
|
||||
</span>
|
||||
<span class="font-mono text-label uppercase tracking-[0.04em] text-[var(--color-text-secondary)]">All systems operational</span>
|
||||
</div>
|
||||
</footer>
|
||||
@ -703,7 +705,7 @@
|
||||
onkeydown={(e) => { if (e.key === 'Escape' && !snapshotting) snapshotTarget = null; }}
|
||||
></div>
|
||||
|
||||
<div class="relative w-full max-w-[420px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] overflow-hidden" style="animation: fadeUp 0.2s ease both">
|
||||
<div class="relative w-full max-w-[420px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] overflow-hidden" style="animation: fadeUp 0.2s ease both; box-shadow: var(--shadow-dialog)">
|
||||
<!-- Header band -->
|
||||
<div class="flex items-center gap-4 border-b border-[var(--color-border)] bg-[var(--color-bg-3)] px-6 py-5">
|
||||
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-[var(--radius-input)] bg-[var(--color-accent)]/15 text-[var(--color-accent)] shadow-[0_0_12px_var(--color-accent-glow)]">
|
||||
@ -793,7 +795,7 @@
|
||||
onkeydown={(e) => { if (e.key === 'Escape' && !creating) showCreateDialog = false; }}
|
||||
></div>
|
||||
|
||||
<div class="relative w-full max-w-[420px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both">
|
||||
<div class="relative w-full max-w-[420px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both; box-shadow: var(--shadow-dialog)">
|
||||
<h2 class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">Launch Capsule</h2>
|
||||
<p class="mt-1 text-ui text-[var(--color-text-tertiary)]">Configure resources and launch. The VM will be ready in under a second.</p>
|
||||
|
||||
|
||||
@ -262,7 +262,7 @@
|
||||
onkeydown={(e) => { if (e.key === 'Escape' && !creating) showCreate = false; }}
|
||||
></div>
|
||||
|
||||
<div class="relative w-full max-w-[420px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both">
|
||||
<div class="relative w-full max-w-[420px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both; box-shadow: var(--shadow-dialog)">
|
||||
<h2 class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">New API Key</h2>
|
||||
<p class="mt-1 text-ui text-[var(--color-text-tertiary)]">Name it after its environment or purpose — production, staging, CI. You can't rename it later.</p>
|
||||
|
||||
@ -323,7 +323,7 @@
|
||||
onkeydown={(e) => { if (e.key === 'Escape') dismissReveal(); }}
|
||||
></div>
|
||||
|
||||
<div class="relative w-full max-w-[480px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both">
|
||||
<div class="relative w-full max-w-[480px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both; box-shadow: var(--shadow-dialog)">
|
||||
<!-- Success indicator -->
|
||||
<div class="mb-4 flex items-center gap-2.5">
|
||||
<span class="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-glow-mid)]" style="animation: circlePop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) both">
|
||||
@ -404,7 +404,7 @@
|
||||
onkeydown={(e) => { if (e.key === 'Escape' && !revoking) revokeTarget = null; }}
|
||||
></div>
|
||||
|
||||
<div class="relative w-full max-w-[380px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both">
|
||||
<div class="relative w-full max-w-[380px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both; box-shadow: var(--shadow-dialog)">
|
||||
<h2 class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">Revoke Key</h2>
|
||||
<p class="mt-2 text-ui text-[var(--color-text-tertiary)]">
|
||||
Permanently revoke <span class="font-medium text-[var(--color-text-secondary)]">{revokeTarget.name || revokeTarget.id}</span>.
|
||||
|
||||
@ -117,10 +117,17 @@
|
||||
class="relative hidden w-1/2 flex-col items-center justify-center overflow-hidden bg-[var(--color-bg-1)] lg:flex"
|
||||
onmousemove={handleMouseMove}
|
||||
>
|
||||
<!-- Mouse-reactive radial glow -->
|
||||
<!-- Dot grid texture — industrial depth layer -->
|
||||
<div
|
||||
class="pointer-events-none absolute inset-0 opacity-60"
|
||||
style="background-image: radial-gradient(circle, rgba(94,140,88,0.09) 1px, transparent 1px); background-size: 24px 24px;"
|
||||
aria-hidden="true"
|
||||
></div>
|
||||
|
||||
<!-- Mouse-reactive radial glow — renders above dot grid -->
|
||||
<div
|
||||
class="pointer-events-none absolute inset-0"
|
||||
style="background: radial-gradient(ellipse 55% 45% at {glowX}% {glowY}%, rgba(94, 140, 88, 0.14) 0%, transparent 70%)"
|
||||
style="background: radial-gradient(ellipse 60% 50% at {glowX}% {glowY}%, rgba(94, 140, 88, 0.18) 0%, transparent 70%)"
|
||||
aria-hidden="true"
|
||||
></div>
|
||||
|
||||
@ -137,13 +144,13 @@
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Tagline below logo -->
|
||||
<!-- Tagline below logo — larger, more commanding -->
|
||||
<div
|
||||
class="relative z-10 mt-16 max-w-[360px] text-center"
|
||||
class="relative z-10 mt-14 max-w-[460px] text-center"
|
||||
style="animation: fadeUp 0.35s ease 0.1s both"
|
||||
>
|
||||
<h1
|
||||
class="font-serif text-[5rem] leading-[1.1] tracking-[-0.04em] text-[var(--color-text-bright)]"
|
||||
class="font-serif text-[6.5rem] leading-[0.95] tracking-[-0.06em] text-[var(--color-text-bright)]"
|
||||
>
|
||||
Scale Up.<br /><span class="text-[var(--color-accent-bright)]">Spin Out.</span>
|
||||
</h1>
|
||||
@ -151,7 +158,7 @@
|
||||
|
||||
<!-- Sub-tagline -->
|
||||
<p
|
||||
class="relative z-10 mt-12 font-mono text-ui uppercase tracking-[0.08em] text-[var(--color-text-tertiary)]"
|
||||
class="relative z-10 mt-10 font-mono text-ui uppercase tracking-[0.1em] text-[var(--color-text-tertiary)]"
|
||||
style="animation: fadeUp 0.35s ease 0.2s both"
|
||||
>
|
||||
Isolated VMs. Milliseconds to live.
|
||||
|
||||
Reference in New Issue
Block a user