feat(ui): port Direction B layout shell (Phase 1)

Implements the layout-shell phase of the Direction B redesign from the
Anthropic Design handoff bundle.

Visual layer:
- Geist font + new --gd-* CSS token palette (panel/border/text scales,
  green/amber/blue/purple accents alongside the red).
- Top bar with brand chip, origin/destination inputs, chat composer
  with chip-based refinements, vehicle selector chip, Export/Share.
- Body split: map-left flex-1, stops rail 540px right (replaces the
  prior chat-sidebar + bottom-timeline layout).
- Stops rail: trip summary header (stops · days · km · drive · charge),
  sticky day headers with date label + per-day km/drive/charge totals,
  icon-led stop cards with colored type-icon tile (charge/sleep/hotel/
  attraction/cafe/viewpoint colour-coded), combo pill, description,
  charge/arrive meta inline.
- Leg row between cards (km · drive time), still computed from real
  OSRM routes.
- Click stop to expand: 4-stat grid (Charge/Arrive/Leave/Cost),
  amenity chip cloud, alternative-swap list (preserving the existing
  delta swap mechanic), Customise/Remove actions.
- Map ↔ rail bridge: clicking a card flies the map to that pin,
  hovering either highlights the other. Pins are custom Leaflet
  divIcons coloured per stop type with active/hover scaling.
- Empty state + quick-prompt buttons in the rail.

Not in Phase 1 (deferred):
- Variant strip (Fastest/Scenic/Cheapest) — needs backend prompt work.
- While-here food/do/see tabs — needs backend nearby[] data.
- Customise / Add-detour / GPX modals.
- Vehicle selector trim panel (still a native select for now).
- Drag-to-reorder, in-trip/compare/shared screens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 11:37:48 +01:00
parent 225cd250a3
commit ece882ea29
2 changed files with 875 additions and 503 deletions
File diff suppressed because it is too large Load Diff
+56 -26
View File
@@ -1,51 +1,81 @@
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500&display=swap');
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
:root { :root {
--tesla-red: #E82127; /* Direction B palette */
--bg: #0a0a0a; --gd-bg: #0a0a0c;
--bg-elevated: #111111; --gd-bg-2: #111114;
--bg-card: #1a1f2b; --gd-panel: #15151a;
--border: rgba(255, 255, 255, 0.08); --gd-panel-2: #1c1c22;
--gd-border: rgba(255, 255, 255, 0.08);
--gd-border-2: rgba(255, 255, 255, 0.14);
--gd-text: #f5f5f7;
--gd-text-2: #a8a8b0;
--gd-text-3: #6c6c75;
--gd-red: #e31937;
--gd-red-soft: rgba(227, 25, 55, 0.14);
--gd-red-line: rgba(227, 25, 55, 0.32);
--gd-green: #4ade80;
--gd-amber: #fbbf24;
--gd-blue: #60a5fa;
--gd-purple: #c084fc;
/* Legacy aliases (still referenced in a few places) */
--tesla-red: var(--gd-red);
--bg: var(--gd-bg);
--bg-elevated: var(--gd-bg-2);
--bg-card: var(--gd-panel);
--border: var(--gd-border);
} }
body { html, body, #root {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; margin: 0;
background-color: var(--bg); padding: 0;
color: white; height: 100%;
background: var(--gd-bg);
color: var(--gd-text);
font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
letter-spacing: -0.01em;
-webkit-font-smoothing: antialiased;
} }
/* Tesla-inspired scrollbar */ .mono { font-family: 'Geist Mono', ui-monospace, monospace; }
.num { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum'; }
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 6px; width: 6px;
height: 6px; height: 6px;
} }
::-webkit-scrollbar-track { ::-webkit-scrollbar-track { background: transparent; }
background: #1a1a1a;
}
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
background: #3a3a3a; background: rgba(255, 255, 255, 0.12);
border-radius: 3px; border-radius: 3px;
} }
::-webkit-scrollbar-thumb:hover { ::-webkit-scrollbar-thumb:hover {
background: #E82127; background: rgba(255, 255, 255, 0.22);
} }
/* Map container */
.leaflet-container { .leaflet-container {
background: #0a0f1a !important; background: #0a0f1a !important;
font-family: inherit;
} }
/* Chat bubbles */ /* Override Leaflet popup styling to match Direction B */
.chat-bubble-user { .leaflet-popup-content-wrapper {
background: #E82127; background: rgba(20, 20, 24, 0.95);
color: white; color: var(--gd-text);
border-bottom-right-radius: 4px; border: 1px solid var(--gd-border-2);
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
} }
.leaflet-popup-tip {
.chat-bubble-assistant { background: rgba(20, 20, 24, 0.95);
background: #1f242e; }
border: 1px solid rgba(255,255,255,0.08); .leaflet-popup-content {
border-bottom-left-radius: 4px; margin: 10px 12px;
font-size: 12px;
line-height: 1.5;
} }