Pair the legend visually with the route by widening the gap above it and narrowing the gap below. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
111 lines
3.4 KiB
Text
111 lines
3.4 KiB
Text
---
|
|
import AppLayout from '../layouts/AppLayout.astro';
|
|
import LatestDispatchBanner from '../components/LatestDispatchBanner.astro';
|
|
import RoadmapRoute from '../components/RoadmapRoute.astro';
|
|
import { getAllRoadmapItems } from '../lib/db';
|
|
|
|
const user = Astro.locals.user;
|
|
|
|
const items = getAllRoadmapItems()
|
|
.sort((a, b) => a.display_order - b.display_order || a.id - b.id);
|
|
---
|
|
<AppLayout title="Roadmap" user={user}>
|
|
<article class="roadmap-page">
|
|
|
|
<!-- Single centred header — merges the page lead with the route's
|
|
interaction hints. -->
|
|
<header class="roadmap-header">
|
|
<h1 class="roadmap-title">Roadmap</h1>
|
|
<p class="roadmap-sub">
|
|
A live picture of the work. What's in motion, what's queued,
|
|
what we're still thinking about. Tap or hover any milestone
|
|
for the full story. Drag or scroll to move.
|
|
</p>
|
|
</header>
|
|
|
|
<!-- Legend lives above the route now — reads as a key the eye picks
|
|
up just before walking the path. -->
|
|
<div class="roadmap-legend" aria-label="Status legend">
|
|
<span><i style="background:#6d8c7c"></i>Shipping</span>
|
|
<span><i style="background:#b96b58"></i>In beta</span>
|
|
<span><i style="background:#b4b2a9"></i>Exploring</span>
|
|
<span><i style="background:#d4d2c8"></i>Considering</span>
|
|
</div>
|
|
|
|
<RoadmapRoute items={items} />
|
|
|
|
<!-- Latest dispatch sits at the foot of the page with generous
|
|
space above so it reads as a separate beat, not a continuation
|
|
of the route. -->
|
|
<LatestDispatchBanner />
|
|
|
|
</article>
|
|
</AppLayout>
|
|
|
|
<style>
|
|
.roadmap-page {
|
|
padding: 0 36px 80px;
|
|
max-width: var(--content-max);
|
|
margin: 0 auto;
|
|
}
|
|
|
|
/* ── Centred header ──────────────────────────────────────────── */
|
|
.roadmap-header {
|
|
text-align: center;
|
|
max-width: 640px;
|
|
margin: 0 auto 56px; /* generous gap to the legend */
|
|
padding-top: 32px;
|
|
}
|
|
.roadmap-title {
|
|
font-family: var(--font-serif);
|
|
font-weight: 400;
|
|
font-size: 48px;
|
|
line-height: 1.05;
|
|
letter-spacing: var(--tracking-tight);
|
|
color: var(--on-surface);
|
|
margin: 0 0 14px;
|
|
}
|
|
.roadmap-sub {
|
|
font-size: 14px;
|
|
line-height: 1.65;
|
|
color: var(--on-surface-variant);
|
|
margin: 0 auto;
|
|
max-width: 520px;
|
|
}
|
|
|
|
/* ── Legend (above the route, key-style) ─────────────────────── */
|
|
.roadmap-legend {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 24px;
|
|
margin: 0 auto 14px; /* tight to the route — they're paired */
|
|
flex-wrap: wrap;
|
|
}
|
|
.roadmap-legend span {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 7px;
|
|
font-family: var(--font-sans);
|
|
font-size: 10px;
|
|
letter-spacing: 1px;
|
|
text-transform: uppercase;
|
|
color: var(--on-surface-variant);
|
|
}
|
|
.roadmap-legend i {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* ── Dispatch banner (foot of page, generous breathing room) ── */
|
|
.roadmap-page :global(.rr-dispatch) { margin-top: 112px; }
|
|
|
|
@media (max-width: 767px) {
|
|
.roadmap-page { padding: 0 24px 64px; }
|
|
.roadmap-header { padding-top: 24px; margin-bottom: 40px; }
|
|
.roadmap-title { font-size: 36px; }
|
|
.roadmap-legend { margin-bottom: 12px; }
|
|
.roadmap-page :global(.rr-dispatch) { margin-top: 72px; }
|
|
}
|
|
</style>
|