Add visual redesign OpenSpec change with mockups and logo concepts

Design direction: D1 warmth + D3 lightness (warm off-whites, sage green,
Outfit + Geist Mono). Includes desktop + mobile HTML mockup, 5 logo
concepts, and 33 implementation tasks across 7 phases.

Logo decision: Waypoint Dot mark (3 connected dots) + wordmark combo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ullrich Schäfer 2026-03-28 19:28:08 +01:00
parent 28d6d02858
commit 36b9b6b382
No known key found for this signature in database
GPG key ID: A32FF691A0F752D9
6 changed files with 2072 additions and 0 deletions

View file

@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-03-28

View file

@ -0,0 +1,179 @@
## Context
The Planner was built function-first with default Tailwind styling. A design
exploration ("D1 warmth + D3 lightness") produced desktop and mobile mockups.
The reference HTML mockup is at `mockup.html`.
## Goals / Non-Goals
**Goals:**
- Implement the visual design from the mockup across all Planner components
- Establish a design token system (CSS vars + Tailwind) for consistency
- Make the Planner mobile-responsive with a bottom sheet sidebar
- Style aspirational features (day breakdown, waypoint notes) as muted/coming-soon
**Non-Goals:**
- Redesigning the Journal app (separate change)
- Implementing multi-day splitting logic (just the visual containers)
- Implementing waypoint notes logic (just the UI placeholders)
- Dark mode (later)
- Landing page redesign (separate)
## Decisions
### D1: Design tokens as CSS custom properties
```css
:root {
/* Surface */
--bg: #F5F2EB; /* warm off-white, main background */
--bg-subtle: #EDEAE1; /* card backgrounds */
--bg-raised: #FAF8F4; /* topbar, sidebar, elevated surfaces */
--map-tint: #E4DFD2; /* map background tone */
/* Text */
--text-hi: #1A1916; /* primary */
--text-md: #5C5847; /* secondary labels */
--text-lo: #9A9484; /* tertiary, placeholders */
--text-inv: #FAF8F4; /* on dark surfaces */
/* Accent: muted sage-forest green */
--accent: #4A6B40;
--accent-dim: #6A8B5E;
--accent-bg: rgba(74,107,64,.08);
--accent-border: rgba(74,107,64,.2);
/* Overnight stop: warm amber-brown */
--stop: #8B6D3A;
--stop-bg: rgba(139,109,58,.1);
--stop-border:rgba(139,109,58,.25);
/* Danger / no-go */
--nogo: rgba(160,60,60,.12);
--nogo-border:rgba(160,60,60,.3);
/* UI chrome */
--border: #DDD9D0;
--border-md: #CAC6BC;
--shadow-sm: 0 1px 3px rgba(0,0,0,.06), 0 1px 2px rgba(0,0,0,.04);
--shadow-md: 0 4px 12px rgba(0,0,0,.08), 0 1px 4px rgba(0,0,0,.05);
/* Elevation gradient (route + chart) */
--eg-lo: #5A8F46; /* green, low elevation */
--eg-mid: #C4A840; /* amber, mid elevation */
--eg-hi: #C46040; /* terracotta, high elevation */
/* Typography */
--font-body: 'Outfit', sans-serif;
--font-mono: 'Geist Mono', monospace;
}
```
Extended into Tailwind via `tailwind.config.ts` theme extension so utility
classes work: `text-text-hi`, `bg-bg-raised`, `border-border`, etc.
### D2: Typography & Logo
- **Body**: Outfit (clean, geometric, friendly) — 14px base
- **Stats/distances**: Geist Mono — used for km, elevation, coordinates
- **Logo**: Two-part system:
- **Mark**: "Waypoint Dot" — three connected dots with a curved route line
(sage green, SVG). Used as favicon, app icon, and topbar mark.
- **Wordmark**: "trails" (Outfit 700) + ".cool" (Outfit 300, muted). Used
alongside the mark in the topbar, standalone for large displays.
- See `logo-concepts.html` for all sizes (24px, 48px, 128px).
- Loaded via Google Fonts or self-hosted for performance
### D3: Topbar layout
```
┌─────────────────────────────────────────────────────────────┐
│ [∧ trails.cool] │ [🚴 Cycling (safe) ▾] │ [Y] You │ [A][S][M] +3 │ [+ Invite] ││ [Plain │ Elevation │ Surface] │ [↓ Export GPX] │
└─────────────────────────────────────────────────────────────┘
```
- Waypoint Dot mark + "trails .cool" wordmark, separated by vertical divider
- Profile selector with bike icon
- Participant avatars with "You" label and Host badge
- "+ Invite" button (copies session link)
- Segmented toggle for color mode (replaces dropdown)
- Export GPX right-aligned
### D4: Sidebar layout
```
┌─────────────────────────┐
│ [WAYPOINTS] [NOTES] │
├─────────────────────────┤
│ ACTIVE ROUTE │
│ Berlin → Erfurt │
│ via Dessau │
│ 343 km ↑868m 3 days │
├─────────────────────────┤
│ DAY BREAKDOWN [SOON] │
│ ┌─────────────────────┐ │
│ │ 01 Berlin→Dessau │ │
│ │ ↑340m 120 km │ │
│ │ ● Berlin Alexplatz │ │
│ │ ○ Zossen │ │
│ │ ○ Jüterbog │ │
│ │ ● Dessau OVERNIGHT │ │
│ │ "Elbe crossing" │ │
│ └─────────────────────┘ │
│ ▸ 02 Dessau→Halle 130km│
│ ▸ 03 Halle→Erfurt 93km│
└─────────────────────────┘
```
- Route summary always visible at top
- Day breakdown collapsible, with waypoints nested inside
- Overnight stops marked with amber badge
- Waypoint notes as italic text under waypoint name
- Day 01 expanded by default, others collapsed
### D5: Map marker styling
- **Waypoint markers**: Dark olive circles (#4A6B40) with white number, not blue
- **Overnight stops**: Amber-brown (#8B6D3A) circle with "NIGHT N" badge above
- **Waypoint notes**: Small note icon on marker, hover/tap to read
- **Day labels**: White pill on route line ("Day 1 · 120 km")
- **No-go areas**: Use `--nogo` / `--nogo-border` tokens (muted red)
- **Ghost marker**: Sage green circle matching accent
### D6: Elevation chart redesign
- Day dividers as dashed vertical lines with "Day 1", "Day 2" labels
- Elevation gradient uses `--eg-lo``--eg-mid``--eg-hi`
- Min/max elevation labels on Y axis
- Km marker tooltip on hover (not just crosshair)
- Stats right-aligned: "343.3 km distance ↑ 868 m ascent"
### D7: Mobile bottom sheet
Replace hidden sidebar with a draggable bottom sheet:
- **Collapsed**: Route summary + elevation mini-chart visible
- **Half-expanded**: Tabs (Days/Waypoints/Notes) + scrollable content
- **Full-expanded**: Full sidebar content
- Swipe up/down to toggle states
- Map takes full viewport, sheet overlays from bottom
### D8: Implementation phases
1. **Design tokens + fonts**: CSS vars, Tailwind config, font loading
2. **Topbar**: New layout, segmented toggle, invite button, avatar styling
3. **Sidebar**: Route summary, day breakdown placeholder, waypoint styling
4. **Map markers**: New waypoint icons, overnight badges, ghost marker color
5. **Elevation chart**: New gradient, day dividers, hover label
6. **Mobile**: Bottom sheet component, responsive header
7. **Polish**: Transitions, hover states, loading states, empty states
## Risks / Trade-offs
- **Font loading**: Two Google Fonts add ~40KB. Mitigate with `display=swap`
and preconnect. Can self-host later.
- **Aspirational features shown as muted**: Users might expect them to work.
Mitigate with clear "SOON" badges.
- **Custom CSS vars + Tailwind**: Slight complexity. But ensures consistency
and makes future dark mode straightforward.
- **Bottom sheet on mobile**: Complex to build well. Can use a library like
`vaul` or build minimal version first.

View file

@ -0,0 +1,231 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>trails.cool — Logo Concepts</title>
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
body { background: #F5F2EB; font-family: 'Outfit', sans-serif; color: #1A1916; padding: 40px; }
h1 { font-size: 24px; font-weight: 300; margin-bottom: 8px; }
.subtitle { color: #9A9484; font-size: 14px; margin-bottom: 48px; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 40px; }
.concept { background: #FAF8F4; border: 1px solid #DDD9D0; border-radius: 12px; padding: 32px; }
.concept h2 { font-size: 16px; font-weight: 600; margin-bottom: 4px; }
.concept p { font-size: 13px; color: #5C5847; margin-bottom: 24px; }
.sizes { display: flex; align-items: end; gap: 32px; flex-wrap: wrap; }
.size-label { font-size: 11px; color: #9A9484; font-family: 'Geist Mono', monospace; text-align: center; margin-top: 8px; }
.size-group { display: flex; flex-direction: column; align-items: center; }
.wordmark { display: flex; align-items: center; gap: 10px; }
.wordmark-text { font-family: 'Outfit', sans-serif; }
.wordmark-text .brand { font-weight: 700; }
.wordmark-text .tld { font-weight: 300; color: #5C5847; }
hr { border: none; border-top: 1px solid #DDD9D0; margin: 48px 0; }
.on-dark { background: #1A1916; border-radius: 8px; padding: 20px; display: inline-flex; align-items: center; gap: 10px; margin-top: 16px; }
</style>
</head>
<body>
<h1>trails.cool — Logo Concepts</h1>
<p class="subtitle">5 directions. Sage green (#4A6B40) on warm off-white. Avoiding mountain silhouettes (AllTrails territory).</p>
<div class="grid">
<!-- 1. ROUTE TRACE -->
<div class="concept">
<h2>1. Route Trace</h2>
<p>An organic curved line — the shape of a real route. Suggests movement, planning, flow.</p>
<div class="sizes">
<div class="size-group">
<svg width="128" height="128" viewBox="0 0 128 128" fill="none">
<path d="M20 95 C35 95, 40 30, 55 30 S75 70, 85 50 S100 15, 110 25" stroke="#4A6B40" stroke-width="5" stroke-linecap="round" fill="none"/>
<circle cx="20" cy="95" r="5" fill="#4A6B40"/>
<circle cx="110" cy="25" r="5" fill="#4A6B40"/>
</svg>
<div class="size-label">128px</div>
</div>
<div class="size-group">
<svg width="48" height="48" viewBox="0 0 128 128" fill="none">
<path d="M20 95 C35 95, 40 30, 55 30 S75 70, 85 50 S100 15, 110 25" stroke="#4A6B40" stroke-width="7" stroke-linecap="round" fill="none"/>
<circle cx="20" cy="95" r="7" fill="#4A6B40"/>
<circle cx="110" cy="25" r="7" fill="#4A6B40"/>
</svg>
<div class="size-label">48px</div>
</div>
<div class="size-group">
<svg width="24" height="24" viewBox="0 0 128 128" fill="none">
<path d="M20 95 C35 95, 40 30, 55 30 S75 70, 85 50 S100 15, 110 25" stroke="#4A6B40" stroke-width="12" stroke-linecap="round" fill="none"/>
<circle cx="20" cy="95" r="10" fill="#4A6B40"/>
<circle cx="110" cy="25" r="10" fill="#4A6B40"/>
</svg>
<div class="size-label">24px</div>
</div>
</div>
<div class="wordmark" style="margin-top: 24px;">
<svg width="28" height="28" viewBox="0 0 128 128" fill="none">
<path d="M20 95 C35 95, 40 30, 55 30 S75 70, 85 50 S100 15, 110 25" stroke="#4A6B40" stroke-width="8" stroke-linecap="round" fill="none"/>
<circle cx="20" cy="95" r="8" fill="#4A6B40"/>
<circle cx="110" cy="25" r="8" fill="#4A6B40"/>
</svg>
<span class="wordmark-text" style="font-size: 22px;"><span class="brand">trails</span><span class="tld"> .cool</span></span>
</div>
</div>
<!-- 2. CONTOUR RING -->
<div class="concept">
<h2>2. Contour Ring</h2>
<p>Topographic contour lines seen from above. Says "terrain" without being a mountain.</p>
<div class="sizes">
<div class="size-group">
<svg width="128" height="128" viewBox="0 0 128 128" fill="none">
<ellipse cx="64" cy="64" rx="50" ry="40" stroke="#4A6B40" stroke-width="3.5" transform="rotate(-8 64 64)"/>
<ellipse cx="64" cy="64" rx="34" ry="26" stroke="#4A6B40" stroke-width="3.5" transform="rotate(-8 64 64)"/>
<ellipse cx="64" cy="64" rx="16" ry="11" stroke="#4A6B40" stroke-width="3.5" transform="rotate(-8 64 64)"/>
</svg>
<div class="size-label">128px</div>
</div>
<div class="size-group">
<svg width="48" height="48" viewBox="0 0 128 128" fill="none">
<ellipse cx="64" cy="64" rx="50" ry="40" stroke="#4A6B40" stroke-width="5" transform="rotate(-8 64 64)"/>
<ellipse cx="64" cy="64" rx="34" ry="26" stroke="#4A6B40" stroke-width="5" transform="rotate(-8 64 64)"/>
<ellipse cx="64" cy="64" rx="16" ry="11" stroke="#4A6B40" stroke-width="5" transform="rotate(-8 64 64)"/>
</svg>
<div class="size-label">48px</div>
</div>
<div class="size-group">
<svg width="24" height="24" viewBox="0 0 128 128" fill="none">
<ellipse cx="64" cy="64" rx="50" ry="40" stroke="#4A6B40" stroke-width="8" transform="rotate(-8 64 64)"/>
<ellipse cx="64" cy="64" rx="34" ry="26" stroke="#4A6B40" stroke-width="8" transform="rotate(-8 64 64)"/>
</svg>
<div class="size-label">24px</div>
</div>
</div>
<div class="wordmark" style="margin-top: 24px;">
<svg width="28" height="28" viewBox="0 0 128 128" fill="none">
<ellipse cx="64" cy="64" rx="50" ry="40" stroke="#4A6B40" stroke-width="5" transform="rotate(-8 64 64)"/>
<ellipse cx="64" cy="64" rx="34" ry="26" stroke="#4A6B40" stroke-width="5" transform="rotate(-8 64 64)"/>
<ellipse cx="64" cy="64" rx="16" ry="11" stroke="#4A6B40" stroke-width="5" transform="rotate(-8 64 64)"/>
</svg>
<span class="wordmark-text" style="font-size: 22px;"><span class="brand">trails</span><span class="tld"> .cool</span></span>
</div>
</div>
<!-- 3. WAYPOINT DOT -->
<div class="concept">
<h2>3. Waypoint Dot</h2>
<p>Three connected dots — the core gesture of the app. Place waypoints, get a route. Most ownable.</p>
<div class="sizes">
<div class="size-group">
<svg width="128" height="128" viewBox="0 0 128 128" fill="none">
<path d="M28 90 C45 90, 50 50, 64 45 S85 70, 100 35" stroke="#4A6B40" stroke-width="4" stroke-linecap="round" fill="none"/>
<circle cx="28" cy="90" r="10" fill="#4A6B40"/>
<circle cx="64" cy="45" r="10" fill="#4A6B40"/>
<circle cx="100" cy="35" r="10" fill="#4A6B40"/>
<text x="28" y="94" text-anchor="middle" fill="#FAF8F4" font-family="Outfit" font-weight="600" font-size="13">1</text>
<text x="64" y="49" text-anchor="middle" fill="#FAF8F4" font-family="Outfit" font-weight="600" font-size="13">2</text>
<text x="100" y="39" text-anchor="middle" fill="#FAF8F4" font-family="Outfit" font-weight="600" font-size="13">3</text>
</svg>
<div class="size-label">128px</div>
</div>
<div class="size-group">
<svg width="48" height="48" viewBox="0 0 128 128" fill="none">
<path d="M28 90 C45 90, 50 50, 64 45 S85 70, 100 35" stroke="#4A6B40" stroke-width="6" stroke-linecap="round" fill="none"/>
<circle cx="28" cy="90" r="12" fill="#4A6B40"/>
<circle cx="64" cy="45" r="12" fill="#4A6B40"/>
<circle cx="100" cy="35" r="12" fill="#4A6B40"/>
</svg>
<div class="size-label">48px</div>
</div>
<div class="size-group">
<svg width="24" height="24" viewBox="0 0 128 128" fill="none">
<path d="M28 90 C45 90, 50 50, 64 45 S85 70, 100 35" stroke="#4A6B40" stroke-width="10" stroke-linecap="round" fill="none"/>
<circle cx="28" cy="90" r="14" fill="#4A6B40"/>
<circle cx="64" cy="45" r="14" fill="#4A6B40"/>
<circle cx="100" cy="35" r="14" fill="#4A6B40"/>
</svg>
<div class="size-label">24px</div>
</div>
</div>
<div class="wordmark" style="margin-top: 24px;">
<svg width="32" height="28" viewBox="0 0 128 128" fill="none">
<path d="M28 90 C45 90, 50 50, 64 45 S85 70, 100 35" stroke="#4A6B40" stroke-width="6" stroke-linecap="round" fill="none"/>
<circle cx="28" cy="90" r="11" fill="#4A6B40"/>
<circle cx="64" cy="45" r="11" fill="#4A6B40"/>
<circle cx="100" cy="35" r="11" fill="#4A6B40"/>
</svg>
<span class="wordmark-text" style="font-size: 22px;"><span class="brand">trails</span><span class="tld"> .cool</span></span>
</div>
</div>
<!-- 4. ELEVATION MARK -->
<div class="concept">
<h2>4. Elevation Mark</h2>
<p>A mini elevation profile — the signature feature of the app. Not a mountain, it's data.</p>
<div class="sizes">
<div class="size-group">
<svg width="128" height="128" viewBox="0 0 128 128" fill="none">
<path d="M16 90 L30 75 L45 80 L60 50 L75 55 L90 30 L105 45 L112 40" stroke="#4A6B40" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
<path d="M16 90 L30 75 L45 80 L60 50 L75 55 L90 30 L105 45 L112 40 V100 H16 Z" fill="#4A6B40" opacity="0.1"/>
<line x1="16" y1="100" x2="112" y2="100" stroke="#4A6B40" stroke-width="2" opacity="0.3"/>
</svg>
<div class="size-label">128px</div>
</div>
<div class="size-group">
<svg width="48" height="48" viewBox="0 0 128 128" fill="none">
<path d="M16 90 L30 75 L45 80 L60 50 L75 55 L90 30 L105 45 L112 40" stroke="#4A6B40" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
<path d="M16 90 L30 75 L45 80 L60 50 L75 55 L90 30 L105 45 L112 40 V100 H16 Z" fill="#4A6B40" opacity="0.1"/>
</svg>
<div class="size-label">48px</div>
</div>
<div class="size-group">
<svg width="24" height="24" viewBox="0 0 128 128" fill="none">
<path d="M16 90 L40 60 L64 70 L90 30 L112 45" stroke="#4A6B40" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
</svg>
<div class="size-label">24px</div>
</div>
</div>
<div class="wordmark" style="margin-top: 24px;">
<svg width="36" height="24" viewBox="0 0 128 128" fill="none">
<path d="M16 90 L30 75 L45 80 L60 50 L75 55 L90 30 L105 45 L112 40" stroke="#4A6B40" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
<path d="M16 90 L30 75 L45 80 L60 50 L75 55 L90 30 L105 45 L112 40 V100 H16 Z" fill="#4A6B40" opacity="0.1"/>
</svg>
<span class="wordmark-text" style="font-size: 22px;"><span class="brand">trails</span><span class="tld"> .cool</span></span>
</div>
</div>
<!-- 5. WORDMARK ONLY -->
<div class="concept">
<h2>5. Wordmark Only</h2>
<p>No mark. The typography IS the brand. The dot in ".cool" is the visual anchor.</p>
<div class="sizes">
<div class="size-group">
<span style="font-family: 'Outfit'; font-size: 42px; letter-spacing: -0.5px;">
<span style="font-weight: 700; color: #4A6B40;">trails</span><span style="font-weight: 300; color: #9A9484;"> .cool</span>
</span>
<div class="size-label">large</div>
</div>
<div class="size-group">
<span style="font-family: 'Outfit'; font-size: 22px; letter-spacing: -0.3px;">
<span style="font-weight: 700; color: #4A6B40;">trails</span><span style="font-weight: 300; color: #9A9484;">.cool</span>
</span>
<div class="size-label">medium</div>
</div>
<div class="size-group">
<span style="font-family: 'Outfit'; font-size: 14px;">
<span style="font-weight: 700; color: #4A6B40;">t</span><span style="font-weight: 300; color: #9A9484;">.c</span>
</span>
<div class="size-label">favicon</div>
</div>
</div>
<div class="on-dark">
<span style="font-family: 'Outfit'; font-size: 22px; letter-spacing: -0.3px;">
<span style="font-weight: 700; color: #6A8B5E;">trails</span><span style="font-weight: 300; color: #9A9484;">.cool</span>
</span>
</div>
<div class="size-label" style="text-align: left; margin-top: 4px;">on dark</div>
</div>
</div>
</body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,49 @@
## Why
The current UI is functional but unstyled — default Tailwind colors, no visual
identity, no typography system. As features mature (route coloring, no-go areas,
multiplayer), the app needs a design language that matches the quality of the
interactions. Early testers find the tool powerful but visually generic.
A design exploration produced a "Trail Worn warmth + Nordic Precision lightness"
direction: warm off-whites, sage green accent, earthy overnight markers, Outfit
font, Geist Mono for stats. The reference mockup lives at
`mockup.html` (desktop + mobile views).
## What Changes
- **Design system**: CSS custom properties for colors, typography, spacing.
Tailwind config extended with project tokens. Outfit (body) + Geist Mono
(stats) fonts.
- **Topbar redesign**: Logo with mountain mark, segmented color mode toggle,
participant avatars with names, "+ Invite" button, Export GPX right-aligned
- **Sidebar redesign**: Route summary header (name, stats, duration), collapsible
day breakdown (aspirational, "SOON" badge), waypoints nested inside days,
overnight badges on stop waypoints, waypoint notes
- **Map marker styling**: Olive/dark numbered circles instead of blue, "NIGHT"
badges on overnight stops, day segment labels on route
- **Elevation chart**: Day dividers as dashed vertical lines, elevation gradient
matching route colors, km hover label, min/max elevation labels
- **Mobile responsive**: Bottom sheet pattern replacing hidden sidebar, simplified
header, swipeable tabs (Days/Waypoints/Notes)
## Capabilities
### New Capabilities
- `design-system`: Shared design tokens, typography, color palette, component
styling patterns for the Planner app
### Modified Capabilities
- `map-display`: New waypoint marker styling, overnight badges, day labels
- `planner-session`: Sidebar layout with route summary and day breakdown
## Impact
- **Tailwind config**: Extended with project color tokens and font families
- **All Planner components**: Updated styling (colors, typography, spacing)
- **New fonts**: Outfit + Geist Mono loaded via Google Fonts or self-hosted
- **No functional changes**: All existing interactions preserved, only visual
- **ElevationChart**: Canvas drawing updated for new color gradient + day dividers
- **Mobile**: New bottom sheet component for sidebar content

View file

@ -0,0 +1,61 @@
## 1. Design Tokens & Typography
- [ ] 1.1 Add CSS custom properties (`:root` vars) for colors, shadows, borders
- [ ] 1.2 Extend Tailwind config with project color tokens and font families
- [ ] 1.3 Add Outfit + Geist Mono fonts (Google Fonts or self-hosted)
- [ ] 1.4 Update base styles: body background, default text color, font-family
- [ ] 1.5 Update elevation gradient colors in ColoredRoute + ElevationChart to use tokens
## 2. Topbar Redesign
- [ ] 2.1 New logo: Waypoint Dot mark SVG (3 dots + route curve) + "trails .cool" wordmark (Outfit 700/300)
- [ ] 2.1b Generate favicon from Waypoint Dot mark (16px, 32px, 180px apple-touch)
- [ ] 2.2 Replace color mode dropdown with segmented toggle (Plain/Elevation/Surface)
- [ ] 2.3 Restyle participant avatars with name labels and Host badge
- [ ] 2.4 Add "+ Invite" button (copies session link to clipboard)
- [ ] 2.5 Restyle profile selector with bike/hike icon
- [ ] 2.6 Move Export GPX to right-aligned position
- [ ] 2.7 Apply token colors to topbar (--bg-raised, --border, etc.)
## 3. Sidebar Redesign
- [ ] 3.1 Add route summary header (route name, distance, ascent, duration)
- [ ] 3.2 Add day breakdown section with "SOON" badge (collapsible, placeholder)
- [ ] 3.3 Nest waypoints inside day sections (expandable/collapsible)
- [ ] 3.4 Style overnight stop waypoints with amber badge
- [ ] 3.5 Add waypoint note display (italic text under waypoint name, placeholder)
- [ ] 3.6 Apply token colors to sidebar (--bg-raised, --text-md, --accent, etc.)
## 4. Map Marker Styling
- [ ] 4.1 Replace blue waypoint markers with olive/dark circles (#4A6B40 accent)
- [ ] 4.2 Add overnight stop marker variant (amber-brown with "NIGHT N" badge)
- [ ] 4.3 Update ghost marker color to match accent
- [ ] 4.4 Update no-go area colors to use --nogo tokens
- [ ] 4.5 Add day segment labels on route ("Day 1 · 120 km") — placeholder/aspirational
## 5. Elevation Chart Redesign
- [ ] 5.1 Update chart gradient to use --eg-lo / --eg-mid / --eg-hi tokens
- [ ] 5.2 Add day divider vertical dashed lines with labels (aspirational)
- [ ] 5.3 Add min/max elevation labels on Y axis
- [ ] 5.4 Update hover tooltip to show km marker
- [ ] 5.5 Right-align stats display: "343 km distance ↑ 868 m ascent"
## 6. Mobile Responsive
- [ ] 6.1 Create bottom sheet component (collapsed/half/full states)
- [ ] 6.2 Move sidebar content into bottom sheet on mobile
- [ ] 6.3 Show route summary + mini elevation in collapsed state
- [ ] 6.4 Add swipeable tabs in bottom sheet (Days/Waypoints/Notes)
- [ ] 6.5 Simplify topbar on mobile (hide text labels, compact avatars)
- [ ] 6.6 Test touch interactions (map drag, waypoint tap, sheet swipe)
## 7. Polish
- [ ] 7.1 Add hover/focus states matching design tokens
- [ ] 7.2 Add transitions for sidebar collapse, bottom sheet, tab switches
- [ ] 7.3 Style loading states (connecting, computing route)
- [ ] 7.4 Style empty states (no waypoints, no route)
- [ ] 7.5 Add i18n keys for any new UI text (en + de)
- [ ] 7.6 Visual verification in cmux browser (desktop + mobile viewport)