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:
parent
28d6d02858
commit
36b9b6b382
6 changed files with 2072 additions and 0 deletions
2
openspec/changes/visual-redesign/.openspec.yaml
Normal file
2
openspec/changes/visual-redesign/.openspec.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
schema: spec-driven
|
||||
created: 2026-03-28
|
||||
179
openspec/changes/visual-redesign/design.md
Normal file
179
openspec/changes/visual-redesign/design.md
Normal 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.
|
||||
231
openspec/changes/visual-redesign/logo-concepts.html
Normal file
231
openspec/changes/visual-redesign/logo-concepts.html
Normal 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>
|
||||
1550
openspec/changes/visual-redesign/mockup.html
Normal file
1550
openspec/changes/visual-redesign/mockup.html
Normal file
File diff suppressed because it is too large
Load diff
49
openspec/changes/visual-redesign/proposal.md
Normal file
49
openspec/changes/visual-redesign/proposal.md
Normal 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
|
||||
61
openspec/changes/visual-redesign/tasks.md
Normal file
61
openspec/changes/visual-redesign/tasks.md
Normal 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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue