The previous .rr-current was a 1.15× scale on top of an animated pulsing
::after ring — subtle, and the pulse was easy to miss against the cream
ground. Replaced with a static box-shadow ring at 6px offset in 45%
terracotta, plus a 1.3× scale on the dot itself. The pulse is gone;
the ring is now visible at rest, which is what the marker needs to do.
Hover/focus on a milestone card now scales its sibling dot via :has():
- any card hover/focus → its dot 1.15
- the current-shipping card hover/focus → its dot 1.4
The dot acknowledges that you've engaged with its card. Cleaner than
tying scroll position or click state.
:has() ships in every evergreen browser since 2023; older Firefox just
won't grow the dot, which degrades to no harm.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The route was clipping at three places: top and bottom of hovered
cards (the track was only 460 tall) and at the left/right viewport
edges (first card half-off-screen at scrollLeft 0, last card off the
right at scrollEnd).
Track height: default trackHeight in roadmap-layout 460 → 580; .rr-track
inline-style and the SVG height matched. midY now 290. Path centreline
stays in the visual centre and gains 60px breathing room above + 60px
below — which is exactly the room a hovered card needs to expand into.
Scroll-container padding: .rr-scroll gains 140px of horizontal padding
plus matching scroll-padding-left/right so snap-stops land cleanly.
The 140 figure is 220px card-width / 2 + 30px buffer, so the first and
last cards have a full card-width of clear space inside the viewport
at the scroll extremes.
Layout helper test verifies midY === 290.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The treasure-map metaphor is a desktop affordance — on phones it
becomes a vertical timeline instead. Markup was rendered alongside the
desktop track in commit RM.5; this commit adds the styles to actually
show it and hides the desktop bits.
Per-row layout — 32px / 1fr grid:
- Left column holds the 12px round status-coloured dot and a 1px
rgba(0,0,0,0.18) vertical line continuing down to the next dot. The
last row has no line (rendered conditionally in the markup), so the
trail ends cleanly at the final milestone.
- Right column holds the same eyebrow / serif title / description /
trailing line — but always visible. No hover, no reveal. Reading is
the only interaction.
Arrow buttons and progress dots both hidden at this breakpoint. The
mobile timeline needs no JS — pure markup + CSS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Vanilla TS script at the bottom of RoadmapRoute.astro. No library.
- Arrows scrollBy ±72% of the scroll-container's clientWidth, smooth
behaviour. Disabled at scroll start/end.
- Edge fades (.rr-fade-left / -right) flip opacity 0↔1 at scroll start /
end so the affordance disappears when there's nowhere further to go.
- Progress dots track scrollLeft/(scrollWidth-clientWidth) percentage,
bucketing into dots.length slots. Active dot gets .active (themed in
CSS as --on-surface).
- On mount, the script reads section.data-initial-x — the SVG x position
of the most recent shipping milestone (computed server-side from the
layout helper) — and scrolls so that x sits ~25% from the left edge
of the viewport. Clamped to [0, scrollWidth-clientWidth]. Member opens
/roadmap and immediately sees one shipped item + several ahead-of-them
items, not the very start of history.
- setTimeout(update, 50) re-measures after first paint settles
(especially relevant when SVG fonts or other late-arriving assets
shift the trackWidth by a couple of px).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The treasure-map. Static render only; nav script lands in the next commit.
Section header: serif 'The route' + tracked-uppercase legend
(Shipping / In beta / Exploring / Considering) on the left; two 32px
round arrow buttons on the right (matching the /pulse RoadmapCarousel
chrome).
Body — desktop layout (.rr-desktop):
- Outer .rr-wrap holds an overflow-x: auto .rr-scroll with snap-x.
- Track is sized to layout.trackWidth × 460. Cubic-bezier SVG path
rendered behind milestones, stroked with a horizontal gradient that
fades from #2a2520 / 0.55 alpha through to #2a2520 / 0.15 at the
travelled-stop position (computed by travelledStopFor in step 3).
- Each milestone is a 14px round dot in its status colour, with a 5px
cream halo cutting the path beneath. The 'you are here' marker (most
recent shipping item) gets a 1.15× scale + a quiet 2.4s pulse ring.
- Cards hang from each dot via a 1px / 30px vertical connector, on the
alternating cardSide returned by layout. .rr-card is the anchor target;
hover and :focus-visible both reveal the description + trailing line
via max-height + opacity transitions, so keyboard tab is a first-class
interaction (no mouse required).
- Trailing line: item.metadata_text if set, else 'Shaped by {first
names}' if attributed_members non-empty, else nothing.
- Edge fades on both sides for scroll affordance (left fade hidden when
at scrollLeft 0; right fade hides when at scrollEnd — the JS in step 6
will toggle their opacity).
Progress dots row underneath — count = max(2, min(6, ceil(items/2))).
First dot starts active; nav script will move it.
Mobile vertical fallback (.rr-mobile) markup is included now but kept
display:none on desktop. Step 7 turns it on at the (max-width: 767px)
breakpoint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>