Skip to content

Commit 8dee27c

Browse files
Rebuild web UI with editorial product theme
1 parent 0f094b3 commit 8dee27c

File tree

9 files changed

+796
-268
lines changed

9 files changed

+796
-268
lines changed

web/app/globals.css

Lines changed: 131 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
@tailwind utilities;
44

55
:root {
6-
--bg: #eef4ff;
7-
--fg: #11223a;
8-
--muted: #5f6c84;
9-
--panel: rgba(255, 255, 255, 0.82);
10-
--stroke: rgba(17, 34, 58, 0.1);
6+
--page: #f3ede5;
7+
--paper: #fcf8f2;
8+
--paper-strong: #fffdfa;
9+
--sand: #efe7dc;
10+
--line: #dfd3c7;
11+
--line-strong: #cab8a3;
12+
--ink: #161412;
13+
--muted: #6d655d;
14+
--dark: #181715;
15+
--dark-soft: #242220;
16+
--accent: #b89972;
17+
--accent-soft: #d6c3aa;
18+
--shadow: 0 24px 60px rgba(36, 28, 18, 0.08);
1119
}
1220

1321
* {
@@ -20,12 +28,10 @@ html {
2028

2129
body {
2230
margin: 0;
23-
color: var(--fg);
31+
color: var(--ink);
2432
background:
25-
radial-gradient(circle at top left, rgba(255, 122, 61, 0.2), transparent 28%),
26-
radial-gradient(circle at top right, rgba(102, 217, 186, 0.22), transparent 24%),
27-
linear-gradient(135deg, rgba(255, 255, 255, 0.55), rgba(229, 239, 255, 0.25)),
28-
linear-gradient(180deg, #f7faff 0%, #e7eefc 100%);
33+
linear-gradient(to right, transparent 88px, rgba(202, 184, 163, 0.58) 88px, rgba(202, 184, 163, 0.58) 89px, transparent 89px, transparent calc(100% - 89px), rgba(202, 184, 163, 0.58) calc(100% - 89px), rgba(202, 184, 163, 0.58) calc(100% - 88px), transparent calc(100% - 88px)),
34+
linear-gradient(180deg, var(--paper) 0%, var(--page) 100%);
2935
min-height: 100vh;
3036
position: relative;
3137
}
@@ -35,25 +41,126 @@ body::before {
3541
position: fixed;
3642
inset: 0;
3743
pointer-events: none;
38-
background-image:
39-
linear-gradient(rgba(17, 34, 58, 0.035) 1px, transparent 1px),
40-
linear-gradient(90deg, rgba(17, 34, 58, 0.035) 1px, transparent 1px);
41-
background-size: 72px 72px;
42-
mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.4), transparent 88%);
44+
background-image: radial-gradient(rgba(110, 98, 86, 0.16) 1px, transparent 1px);
45+
background-size: 14px 14px;
46+
opacity: 0.42;
47+
mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.3), transparent 76%);
4348
}
4449

4550
::selection {
46-
background: rgba(255, 122, 61, 0.22);
51+
background: rgba(184, 153, 114, 0.28);
4752
}
4853

49-
.glass-panel {
50-
background: var(--panel);
51-
backdrop-filter: blur(18px);
52-
border: 1px solid var(--stroke);
54+
a {
55+
color: inherit;
56+
text-decoration: none;
5357
}
5458

55-
.grid-accent {
56-
background-image:
57-
linear-gradient(rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.7)),
58-
linear-gradient(135deg, rgba(255, 122, 61, 0.08), rgba(102, 217, 186, 0.08));
59+
.site-shell {
60+
margin: 0 auto;
61+
width: 100%;
62+
max-width: 1360px;
63+
padding: 0 24px 88px;
64+
}
65+
66+
.site-panel {
67+
border: 1px solid var(--line);
68+
background: rgba(255, 253, 250, 0.92);
69+
box-shadow: var(--shadow);
70+
}
71+
72+
.site-soft-panel {
73+
border: 1px solid var(--line);
74+
background: rgba(239, 231, 220, 0.86);
75+
}
76+
77+
.site-dark-panel {
78+
border: 1px solid #2b2823;
79+
background: var(--dark);
80+
color: #f8f2ea;
81+
box-shadow: 0 24px 60px rgba(17, 16, 13, 0.24);
82+
}
83+
84+
.dot-matrix {
85+
background-image: radial-gradient(rgba(255, 255, 255, 0.14) 1px, transparent 1px);
86+
background-size: 11px 11px;
87+
}
88+
89+
.paper-matrix {
90+
background-image: radial-gradient(rgba(108, 101, 93, 0.12) 1px, transparent 1px);
91+
background-size: 12px 12px;
92+
}
93+
94+
.section-kicker {
95+
display: inline-flex;
96+
align-items: center;
97+
gap: 8px;
98+
font-size: 11px;
99+
font-weight: 700;
100+
letter-spacing: 0.2em;
101+
text-transform: uppercase;
102+
color: var(--muted);
103+
}
104+
105+
.section-kicker::before {
106+
content: "";
107+
display: inline-block;
108+
height: 14px;
109+
width: 3px;
110+
border-radius: 999px;
111+
background: var(--line-strong);
112+
}
113+
114+
.brand-accent {
115+
font-family: var(--font-serif);
116+
font-style: italic;
117+
font-weight: 700;
118+
}
119+
120+
.button-primary {
121+
border-radius: 14px;
122+
background: var(--ink);
123+
color: #fffdfa;
124+
transition: transform 160ms ease, opacity 160ms ease;
125+
}
126+
127+
.button-primary:hover,
128+
.button-secondary:hover {
129+
transform: translateY(-1px);
130+
}
131+
132+
.button-secondary {
133+
border-radius: 14px;
134+
border: 1px solid var(--line-strong);
135+
background: rgba(255, 253, 250, 0.88);
136+
color: var(--ink);
137+
transition: transform 160ms ease, border-color 160ms ease;
138+
}
139+
140+
.eyebrow-tab {
141+
border-right: 1px solid var(--line);
142+
border-top: 1px solid var(--line);
143+
padding: 18px 20px;
144+
text-align: center;
145+
font-size: 14px;
146+
font-weight: 600;
147+
color: var(--muted);
148+
}
149+
150+
.eyebrow-tab:first-child {
151+
border-left: 1px solid var(--line);
152+
}
153+
154+
.eyebrow-tab.is-active {
155+
background: rgba(255, 255, 255, 0.74);
156+
color: var(--ink);
157+
}
158+
159+
.footer-link {
160+
color: var(--muted);
161+
transition: color 160ms ease;
162+
}
163+
164+
.footer-link:hover {
165+
color: var(--ink);
59166
}

web/app/layout.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
import type { Metadata } from "next";
2-
import { IBM_Plex_Mono, Space_Grotesk } from "next/font/google";
2+
import { Cormorant_Garamond, IBM_Plex_Mono, Manrope } from "next/font/google";
33

44
import { Nav } from "@/components/nav";
55
import { Providers } from "@/components/providers";
6+
import { SiteFooter } from "@/components/site-footer";
67
import "./globals.css";
78

8-
const spaceGrotesk = Space_Grotesk({ subsets: ["latin"], variable: "--font-space" });
9+
const manrope = Manrope({ subsets: ["latin"], variable: "--font-sans" });
10+
const cormorant = Cormorant_Garamond({
11+
subsets: ["latin"],
12+
variable: "--font-serif",
13+
weight: ["600", "700"]
14+
});
915
const plexMono = IBM_Plex_Mono({ subsets: ["latin"], variable: "--font-mono", weight: ["400", "500"] });
1016

1117
export const metadata: Metadata = {
@@ -45,11 +51,12 @@ export const metadata: Metadata = {
4551

4652
export default function RootLayout({ children }: { children: React.ReactNode }) {
4753
return (
48-
<html lang="en" className={`${spaceGrotesk.variable} ${plexMono.variable}`}>
49-
<body className="font-[var(--font-space)]">
54+
<html lang="en" className={`${manrope.variable} ${cormorant.variable} ${plexMono.variable}`}>
55+
<body className="font-[var(--font-sans)]">
5056
<Providers>
5157
<Nav />
52-
<main className="mx-auto w-full max-w-6xl px-4 py-6">{children}</main>
58+
<main className="site-shell pt-8">{children}</main>
59+
<SiteFooter />
5360
</Providers>
5461
</body>
5562
</html>

web/app/leaderboard/page.tsx

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,71 +21,76 @@ export default function LeaderboardPage() {
2121
const fastestPlanner = rows.length > 0 ? Math.min(...rows.map((row) => row.planning_cost_ms_per_step)) : 0;
2222

2323
return (
24-
<section className="space-y-5">
25-
<div className="glass-panel rounded-[30px] p-7 shadow-card">
24+
<section className="space-y-8">
25+
<section className="border-b border-t border-[var(--line)] py-10">
2626
<div className="flex flex-wrap items-center justify-between gap-4">
2727
<div>
28-
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-slate-500">Leaderboard</p>
29-
<h2 className="mt-2 text-4xl font-semibold tracking-tight text-ink">Track planning quality, not just screenshots.</h2>
30-
<p className="mt-3 max-w-3xl text-sm leading-7 text-slate-600">
28+
<p className="section-kicker">Leaderboard</p>
29+
<h2 className="mt-5 max-w-4xl text-5xl font-semibold leading-[1.06] tracking-[-0.05em] text-[var(--ink)]">
30+
Track planning quality with the same finish as a product launch page.
31+
</h2>
32+
<p className="mt-5 max-w-3xl text-lg leading-8 text-[var(--muted)]">
3133
Compare runs by success rate, return, and per-step planning cost across reproducible benchmark tracks.
3234
</p>
3335
</div>
34-
<div className="flex flex-wrap gap-2">
35-
<div className="rounded-[24px] bg-white/85 px-4 py-3">
36-
<p className="text-[11px] font-semibold uppercase tracking-[0.22em] text-slate-500">Runs</p>
37-
<p className="mt-1 text-2xl font-semibold text-ink">{rows.length}</p>
36+
<div className="grid gap-3 sm:grid-cols-3">
37+
<div className="site-panel rounded-[22px] px-5 py-4">
38+
<p className="text-[11px] font-semibold uppercase tracking-[0.22em] text-[var(--muted)]">Runs</p>
39+
<p className="mt-2 text-3xl font-semibold tracking-[-0.04em] text-[var(--ink)]">{rows.length}</p>
3840
</div>
39-
<div className="rounded-[24px] bg-white/85 px-4 py-3">
40-
<p className="text-[11px] font-semibold uppercase tracking-[0.22em] text-slate-500">Best Success</p>
41-
<p className="mt-1 text-2xl font-semibold text-ink">{topSuccess.toFixed(2)}</p>
41+
<div className="site-panel rounded-[22px] px-5 py-4">
42+
<p className="text-[11px] font-semibold uppercase tracking-[0.22em] text-[var(--muted)]">Best Success</p>
43+
<p className="mt-2 text-3xl font-semibold tracking-[-0.04em] text-[var(--ink)]">{topSuccess.toFixed(2)}</p>
4244
</div>
43-
<div className="rounded-[24px] bg-white/85 px-4 py-3">
44-
<p className="text-[11px] font-semibold uppercase tracking-[0.22em] text-slate-500">Fastest Cost</p>
45-
<p className="mt-1 text-2xl font-semibold text-ink">{rows.length > 0 ? fastestPlanner.toFixed(2) : "--"}</p>
45+
<div className="site-panel rounded-[22px] px-5 py-4">
46+
<p className="text-[11px] font-semibold uppercase tracking-[0.22em] text-[var(--muted)]">Fastest Cost</p>
47+
<p className="mt-2 text-3xl font-semibold tracking-[-0.04em] text-[var(--ink)]">
48+
{rows.length > 0 ? fastestPlanner.toFixed(2) : "--"}
49+
</p>
4650
</div>
4751
</div>
4852
</div>
49-
<div className="mt-6 flex flex-wrap gap-2">
50-
{tracks.map((item) => (
51-
<button
52-
key={item}
53-
onClick={() => setTrack(item)}
54-
className={`rounded-full px-4 py-2 text-sm font-medium transition ${
55-
track === item ? "bg-ink text-white" : "bg-white text-ink hover:-translate-y-0.5"
56-
}`}
57-
>
58-
{item}
59-
</button>
60-
))}
61-
</div>
53+
</section>
54+
55+
<div className="grid grid-cols-3 md:grid-cols-3">
56+
{tracks.map((item) => (
57+
<button
58+
key={item}
59+
onClick={() => setTrack(item)}
60+
className={`eyebrow-tab ${track === item ? "is-active" : ""}`}
61+
>
62+
{item}
63+
</button>
64+
))}
6265
</div>
6366

6467
{isLoading ? (
65-
<div className="glass-panel rounded-[28px] p-6 shadow-card">
66-
<p className="text-sm font-medium text-slate-600">Loading leaderboard signals...</p>
68+
<div className="site-panel rounded-[30px] p-6">
69+
<p className="text-sm font-medium text-[var(--muted)]">Loading leaderboard signals...</p>
6770
<div className="mt-4 grid gap-3 md:grid-cols-3">
68-
<div className="h-28 animate-pulse rounded-[22px] bg-white/80" />
69-
<div className="h-28 animate-pulse rounded-[22px] bg-white/80" />
70-
<div className="h-28 animate-pulse rounded-[22px] bg-white/80" />
71+
<div className="h-28 animate-pulse rounded-[22px] bg-[var(--sand)]" />
72+
<div className="h-28 animate-pulse rounded-[22px] bg-[var(--sand)]" />
73+
<div className="h-28 animate-pulse rounded-[22px] bg-[var(--sand)]" />
7174
</div>
7275
</div>
7376
) : null}
7477

7578
{isError ? (
76-
<div className="rounded-[28px] border border-amber-200 bg-amber-50 p-6 shadow-card">
77-
<p className="text-xs font-semibold uppercase tracking-[0.22em] text-amber-800">Live API unavailable</p>
78-
<h3 className="mt-2 text-2xl font-semibold text-amber-950">The frontend is up, but the backend URL is not serving leaderboard data.</h3>
79-
<p className="mt-3 text-sm leading-7 text-amber-900">
79+
<div className="rounded-[30px] border border-[var(--line-strong)] bg-[#f8ede1] p-6">
80+
<p className="text-xs font-semibold uppercase tracking-[0.22em] text-[#9b6b40]">Live API unavailable</p>
81+
<h3 className="mt-3 text-3xl font-semibold tracking-[-0.03em] text-[#4e3218]">
82+
The frontend theme is live, but the backend URL is not serving leaderboard data.
83+
</h3>
84+
<p className="mt-4 text-base leading-7 text-[#7c5330]">
8085
{error instanceof Error ? error.message : "Failed to load leaderboard data."}
8186
</p>
8287
<div className="mt-4 flex flex-wrap gap-3">
83-
<Link href="/" className="rounded-full bg-ink px-5 py-2.5 text-sm font-semibold text-white">
88+
<Link href="/" className="button-primary px-5 py-3 text-sm font-semibold">
8489
Back to Home
8590
</Link>
8691
<Link
8792
href="/tasks"
88-
className="rounded-full border border-amber-300 bg-white px-5 py-2.5 text-sm font-semibold text-amber-900"
93+
className="button-secondary px-5 py-3 text-sm font-semibold"
8994
>
9095
Browse Tasks Instead
9196
</Link>
@@ -94,10 +99,12 @@ export default function LeaderboardPage() {
9499
) : null}
95100

96101
{!isLoading && !isError && rows.length === 0 ? (
97-
<div className="glass-panel rounded-[28px] border border-dashed border-ink/20 p-8 text-center shadow-card">
98-
<p className="text-xs font-semibold uppercase tracking-[0.22em] text-slate-500">No runs yet</p>
99-
<h3 className="mt-2 text-2xl font-semibold text-ink">This track is waiting for its first uploaded evaluation.</h3>
100-
<p className="mt-3 text-sm leading-7 text-slate-600">
102+
<div className="site-panel rounded-[30px] border border-dashed border-[var(--line-strong)] p-10 text-center">
103+
<p className="text-xs font-semibold uppercase tracking-[0.22em] text-[var(--muted)]">No runs yet</p>
104+
<h3 className="mt-3 text-3xl font-semibold tracking-[-0.04em] text-[var(--ink)]">
105+
This track is waiting for its first uploaded evaluation.
106+
</h3>
107+
<p className="mx-auto mt-4 max-w-2xl text-base leading-7 text-[var(--muted)]">
101108
Run the demo pipeline or upload benchmark artifacts to populate charts, rankings, and individual run views.
102109
</p>
103110
</div>
@@ -106,10 +113,10 @@ export default function LeaderboardPage() {
106113
{rows.length > 0 ? (
107114
<>
108115
<LeaderboardChart data={rows} />
109-
<div className="glass-panel overflow-x-auto rounded-[28px] p-5 shadow-card">
116+
<div className="site-panel overflow-x-auto rounded-[30px] p-5">
110117
<table className="w-full min-w-[780px] text-left text-sm">
111-
<thead>
112-
<tr className="border-b border-slate-200 text-slate-500">
118+
<thead className="text-[var(--muted)]">
119+
<tr className="border-b border-[var(--line)]">
113120
<th className="py-2">Run</th>
114121
<th className="py-2">Env</th>
115122
<th className="py-2">Agent</th>
@@ -120,9 +127,9 @@ export default function LeaderboardPage() {
120127
</thead>
121128
<tbody>
122129
{rows.map((row, index) => (
123-
<tr key={row.run_id} className="border-b border-slate-100 last:border-b-0">
130+
<tr key={row.run_id} className="border-b border-[var(--line)]/70 last:border-b-0">
124131
<td className="py-3 font-mono text-xs">
125-
<Link className="text-ember hover:underline" href={`/runs/${row.run_id}`}>
132+
<Link className="text-[var(--ink)] underline-offset-4 hover:underline" href={`/runs/${row.run_id}`}>
126133
#{index + 1} {row.run_id}
127134
</Link>
128135
</td>

0 commit comments

Comments
 (0)