Import Stitch UI export: Rippr Minimalist Activity Tracker
Pulled via the Stitch MCP from project 8187200995279352789: the design system spec (neon-HUD dark theme -- Sora/Inter/JetBrains Mono, electric green primary, cyan secondary) plus HTML/screenshot for Map HUD, Plan Screen, Route Planning, and Rides History (all Dark Mode), and the project's own export summary.
Raw reference material only, not yet wired into the app. Flags a real discrepancy in README.md: the export summary describes a different ('Modern Professional Dark', blue) design system than the one actually attached to the project and used by every screen fetched -- treat design-system.md as current, export-summary.md as stale.
This commit is contained in:
48
docs/design/stitch-export/README.md
Normal file
48
docs/design/stitch-export/README.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# Stitch export — Rippr Minimalist Activity Tracker
|
||||||
|
|
||||||
|
Pulled from [stitch.withgoogle.com](https://stitch.withgoogle.com) project
|
||||||
|
`8187200995279352789` via the Stitch MCP server on 2026-08-23.
|
||||||
|
|
||||||
|
## Contents
|
||||||
|
|
||||||
|
| File | Stitch screen | What it is |
|
||||||
|
|---|---|---|
|
||||||
|
| `design-system.md` | Design System | Full design-system spec: color tokens, typography, spacing, elevation, shape, and component rules. This is the current, authoritative design system for the project (see note below). |
|
||||||
|
| `screens/export-summary.md` | Rippr Project Export Summary | Stitch's own generated overview of the project and screen inventory. |
|
||||||
|
| `screens/map-hud-dark.html` + `.png` | Map HUD - Dark Mode | Active-recording map screen: floating telemetry cards (speed, avg speed, distance, time), Pause/Stop controls. |
|
||||||
|
| `screens/plan-screen-dark.html` + `.png` | Plan Screen - Dark Mode | Empty-state route planner: map with a "Tap to drop a pin" prompt. |
|
||||||
|
| `screens/route-planning-dark.html` + `.png` | Route Planning - Dark Mode | Route planner with pins dropped: distance/time/pin-count header, dotted route line, Start Route button. |
|
||||||
|
| `screens/rides-history-dark.html` + `.png` | Rides History - Dark Mode | Ride list: search bar, distance-unit toggle, cards with a mini-map thumbnail, date, distance, time, avg speed. |
|
||||||
|
|
||||||
|
Each `.html` is Stitch's generated markup (Tailwind CSS, vanilla JS) for that screen — a
|
||||||
|
reference for structure and interaction, not something to drop into the Flutter app
|
||||||
|
as-is.
|
||||||
|
|
||||||
|
## A discrepancy worth flagging
|
||||||
|
|
||||||
|
`screens/export-summary.md` describes a **different** design system than
|
||||||
|
`design-system.md` — it names "Modern Professional Dark" (#1978e5 blue, Inter,
|
||||||
|
8px roundness), while the design system actually attached to the project (and to every
|
||||||
|
screen fetched above) is the **HUD / Minimalist-Technical** one: near-black
|
||||||
|
(`#0A0A0B`-ish surfaces), electric-neon-green primary (`#00FF41`/`#00E639`), cyan
|
||||||
|
secondary telemetry accent (`#00E0FF`), Sora/Inter/JetBrains Mono typography, and 4px
|
||||||
|
roundness. The screenshots above all use the neon/HUD system, not the blue one the
|
||||||
|
summary describes — the export summary looks like it's describing an earlier or
|
||||||
|
different iteration of the project. Treat `design-system.md` as the current source of
|
||||||
|
truth; `export-summary.md` is kept here for reference but its "Design System" section is
|
||||||
|
stale.
|
||||||
|
|
||||||
|
## Not pulled
|
||||||
|
|
||||||
|
The "Design System" screen instance in the project
|
||||||
|
(`assets_e73325c5365a4a56b93823236777e95a`) is a design-system asset, not a regular
|
||||||
|
screen — Stitch's `get_screen` call is for screens, not asset instances. Its content is
|
||||||
|
what's captured in `design-system.md` (fetched via `get_project`'s `designTheme`), so
|
||||||
|
nothing is missing, just fetched through a different call.
|
||||||
|
|
||||||
|
## Next step
|
||||||
|
|
||||||
|
This is raw material, not yet applied to the app. `lib/src/ui/theme.dart`'s current
|
||||||
|
palette (safety-orange accent, warm near-black ground — see V3-16) is a different
|
||||||
|
direction from this neon-HUD system. Reconciling the two, or replacing one with the
|
||||||
|
other, is a decision for whoever picks up the actual UI work on this branch.
|
||||||
171
docs/design/stitch-export/design-system.md
Normal file
171
docs/design/stitch-export/design-system.md
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
---
|
||||||
|
name: Rippr
|
||||||
|
colors:
|
||||||
|
surface: '#131314'
|
||||||
|
surface-dim: '#131314'
|
||||||
|
surface-bright: '#3a393a'
|
||||||
|
surface-container-lowest: '#0e0e0f'
|
||||||
|
surface-container-low: '#1c1b1c'
|
||||||
|
surface-container: '#201f20'
|
||||||
|
surface-container-high: '#2a2a2b'
|
||||||
|
surface-container-highest: '#353436'
|
||||||
|
on-surface: '#e5e2e3'
|
||||||
|
on-surface-variant: '#b9ccb2'
|
||||||
|
inverse-surface: '#e5e2e3'
|
||||||
|
inverse-on-surface: '#313031'
|
||||||
|
outline: '#84967e'
|
||||||
|
outline-variant: '#3b4b37'
|
||||||
|
surface-tint: '#00e639'
|
||||||
|
primary: '#ebffe2'
|
||||||
|
on-primary: '#003907'
|
||||||
|
primary-container: '#00ff41'
|
||||||
|
on-primary-container: '#007117'
|
||||||
|
inverse-primary: '#006e16'
|
||||||
|
secondary: '#b9f1ff'
|
||||||
|
on-secondary: '#00363f'
|
||||||
|
secondary-container: '#00e0ff'
|
||||||
|
on-secondary-container: '#005f6d'
|
||||||
|
tertiary: '#fff8f4'
|
||||||
|
on-tertiary: '#442b10'
|
||||||
|
tertiary-container: '#ffd5ae'
|
||||||
|
on-tertiary-container: '#7a5b3c'
|
||||||
|
error: '#ffb4ab'
|
||||||
|
on-error: '#690005'
|
||||||
|
error-container: '#93000a'
|
||||||
|
on-error-container: '#ffdad6'
|
||||||
|
primary-fixed: '#72ff70'
|
||||||
|
primary-fixed-dim: '#00e639'
|
||||||
|
on-primary-fixed: '#002203'
|
||||||
|
on-primary-fixed-variant: '#00530e'
|
||||||
|
secondary-fixed: '#a5eeff'
|
||||||
|
secondary-fixed-dim: '#00daf8'
|
||||||
|
on-secondary-fixed: '#001f25'
|
||||||
|
on-secondary-fixed-variant: '#004e5a'
|
||||||
|
tertiary-fixed: '#ffdcbd'
|
||||||
|
tertiary-fixed-dim: '#e7bf99'
|
||||||
|
on-tertiary-fixed: '#2c1701'
|
||||||
|
on-tertiary-fixed-variant: '#5d4124'
|
||||||
|
background: '#131314'
|
||||||
|
on-background: '#e5e2e3'
|
||||||
|
surface-variant: '#353436'
|
||||||
|
typography:
|
||||||
|
display-telemetry:
|
||||||
|
fontFamily: JetBrains Mono
|
||||||
|
fontSize: 64px
|
||||||
|
fontWeight: '700'
|
||||||
|
lineHeight: 64px
|
||||||
|
letterSpacing: -0.04em
|
||||||
|
headline-lg:
|
||||||
|
fontFamily: Sora
|
||||||
|
fontSize: 32px
|
||||||
|
fontWeight: '600'
|
||||||
|
lineHeight: 40px
|
||||||
|
headline-md:
|
||||||
|
fontFamily: Sora
|
||||||
|
fontSize: 24px
|
||||||
|
fontWeight: '600'
|
||||||
|
lineHeight: 32px
|
||||||
|
body-lg:
|
||||||
|
fontFamily: Inter
|
||||||
|
fontSize: 18px
|
||||||
|
fontWeight: '400'
|
||||||
|
lineHeight: 28px
|
||||||
|
body-md:
|
||||||
|
fontFamily: Inter
|
||||||
|
fontSize: 16px
|
||||||
|
fontWeight: '400'
|
||||||
|
lineHeight: 24px
|
||||||
|
label-caps:
|
||||||
|
fontFamily: JetBrains Mono
|
||||||
|
fontSize: 12px
|
||||||
|
fontWeight: '500'
|
||||||
|
lineHeight: 16px
|
||||||
|
letterSpacing: 0.1em
|
||||||
|
display-telemetry-mobile:
|
||||||
|
fontFamily: JetBrains Mono
|
||||||
|
fontSize: 48px
|
||||||
|
fontWeight: '700'
|
||||||
|
lineHeight: 48px
|
||||||
|
rounded:
|
||||||
|
sm: 0.125rem
|
||||||
|
DEFAULT: 0.25rem
|
||||||
|
md: 0.375rem
|
||||||
|
lg: 0.5rem
|
||||||
|
xl: 0.75rem
|
||||||
|
full: 9999px
|
||||||
|
spacing:
|
||||||
|
unit: 4px
|
||||||
|
container-margin: 20px
|
||||||
|
gutter: 12px
|
||||||
|
stack-sm: 8px
|
||||||
|
stack-md: 24px
|
||||||
|
stack-lg: 48px
|
||||||
|
---
|
||||||
|
|
||||||
|
## Brand & Style
|
||||||
|
The design system centers on a high-performance, dark-mode aesthetic tailored for real-time activity tracking. The brand personality is kinetic, precise, and undistracted. It utilizes a **Minimalist-Technical** style, stripping away non-essential chrome to focus entirely on telemetry and movement.
|
||||||
|
|
||||||
|
The visual narrative is driven by a "HUD" (Heads-Up Display) concept: information is layered over the user's environment or activity maps using subtle glassmorphism and high-contrast data points. The emotional response should be one of focus and momentum, making the user feel like a precision instrument.
|
||||||
|
|
||||||
|
## Colors
|
||||||
|
The palette is dominated by **Pitch Black (#0A0A0B)** to preserve OLED battery life and minimize ocular strain during night activities.
|
||||||
|
|
||||||
|
- **Primary (Electric Neon):** Used exclusively for active states, completion goals, and primary "Go" actions.
|
||||||
|
- **Secondary (Cyan Telemetry):** Reserved for secondary data streams, such as cadence or heart rate, to provide visual separation from primary distance/time metrics.
|
||||||
|
- **Surface Strategy:** Backgrounds use deep charcoal. Overlays use a semi-transparent version of the surface color with a 20px background blur to create the HUD effect.
|
||||||
|
|
||||||
|
## Typography
|
||||||
|
The typography system uses a functional split: **Sora** for UI headers and brand moments, **Inter** for standard interface text, and **JetBrains Mono** for all numerical data and telemetry.
|
||||||
|
|
||||||
|
- **Data Legibility:** All numeric values must use the monospaced font to prevent "jumping" layouts during real-time updates.
|
||||||
|
- **Visual Hierarchy:** Use `label-caps` for units (e.g., KM/H, BPM) placed immediately adjacent to large telemetry displays.
|
||||||
|
- **Scale:** On mobile devices, telemetry data should prioritize width; if values exceed 5 digits, scale the font size down dynamically to fit the viewport width minus margins.
|
||||||
|
|
||||||
|
## Layout & Spacing
|
||||||
|
This design system employs a **Fluid HUD Grid**. Elements are anchored to the corners of the screen to keep the center clear for maps or camera feeds.
|
||||||
|
|
||||||
|
- **Grid Model:** A 6-column grid for mobile, 12-column for desktop.
|
||||||
|
- **Padding:** Use a generous 20px "Safe Zone" margin on all edges of the screen to ensure interactive elements are reachable and not clipped by hardware notches or rounded device corners.
|
||||||
|
- **Density:** High density for data readouts (8px spacing between related metrics) and low density for navigation/settings (24px+ spacing) to prevent accidental taps during motion.
|
||||||
|
|
||||||
|
## Elevation & Depth
|
||||||
|
Depth is expressed through **translucency** rather than shadows.
|
||||||
|
|
||||||
|
1. **Level 0 (Base):** Pure black (#0A0A0B).
|
||||||
|
2. **Level 1 (Substrate):** Dark charcoal (#161618) with 0% transparency.
|
||||||
|
3. **Level 2 (HUD Panels):** Surface color at 60% opacity with a `backdrop-filter: blur(20px)`.
|
||||||
|
4. **Level 3 (Modals):** Surface color at 80% opacity with a subtle 1px inner border in a low-opacity white (10%) to define the edge against dark backgrounds.
|
||||||
|
|
||||||
|
Shadows should be avoided entirely to maintain the "lightweight" digital feel.
|
||||||
|
|
||||||
|
## Shapes
|
||||||
|
The shape language is **Technical-Precision**.
|
||||||
|
|
||||||
|
- **Corners:** Use 0.25rem (4px) as the base radius for all containers to maintain a sharp, engineered appearance.
|
||||||
|
- **Interactive Elements:** Buttons and inputs follow the same 4px rule.
|
||||||
|
- **Progress Indicators:** Use sharp, non-rounded ends for progress bars to emphasize a "segmental" or "digital" look.
|
||||||
|
- **Iconography:** Use 2px stroke weights with squared-off ends to match the monospaced typographic theme.
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
### Buttons
|
||||||
|
- **Primary:** Solid Electric Neon background with Black text. No rounding beyond the base 4px.
|
||||||
|
- **Ghost:** 1px Neon border with transparent background. Text matches border color.
|
||||||
|
- **Telemetry Toggle:** Small, square buttons using monospaced labels.
|
||||||
|
|
||||||
|
### Cards & HUD Panels
|
||||||
|
- All cards use the Level 2 Elevation (Glassmorphism).
|
||||||
|
- Remove all drop shadows. Use a 1px stroke of #FFFFFF at 10% opacity for definition.
|
||||||
|
|
||||||
|
### Data Inputs
|
||||||
|
- Underlined style only (no bounding box) for a lighter footprint.
|
||||||
|
- Active state changes the underline to the Primary Neon color.
|
||||||
|
- Use JetBrains Mono for all numeric input fields.
|
||||||
|
|
||||||
|
### Progress & Gauges
|
||||||
|
- **Circular Gauges:** Use thin 4px strokes. The "track" should be 5% opacity white; the "fill" should be the Primary Neon.
|
||||||
|
- **Pulse:** Active heart rate or GPS signals should use a "scanning" animation—a vertical line moving across the element—rather than a standard fade.
|
||||||
|
|
||||||
|
### Navigation
|
||||||
|
- A bottom-anchored, floating "Dock" with a glassmorphic background.
|
||||||
|
- Active icons are highlighted with a single Neon pixel-dot underneath.
|
||||||
50
docs/design/stitch-export/screens/export-summary.md
Normal file
50
docs/design/stitch-export/screens/export-summary.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# Rippr Project Export
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
Rippr is a minimalist activity tracker designed for cyclists and runners, featuring an immersive map-centric interface, real-time telemetry, and streamlined route planning.
|
||||||
|
|
||||||
|
## Design System: Modern Professional Dark
|
||||||
|
**ID:** {{DATA:DESIGN_SYSTEM:DESIGN_SYSTEM_3}}
|
||||||
|
|
||||||
|
### Theme Tokens
|
||||||
|
- **Color Mode:** Dark
|
||||||
|
- **Primary Color:** #1978e5 (Professional Blue)
|
||||||
|
- **Typography:** Inter
|
||||||
|
- **Roundness:** 8px (Round Eight)
|
||||||
|
|
||||||
|
### Core Components
|
||||||
|
- **TopAppBar:** Minimalist, often hidden for immersive map views.
|
||||||
|
- **BottomNavBar:** 4-icon layout (Map, History, Plan, Settings) with a signature active indicator dot.
|
||||||
|
- **Telemetry Cards:** Floating, semi-transparent modules (`bg-surface/60`) with `backdrop-blur-xl` and `white/10` borders.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Screen Inventory
|
||||||
|
|
||||||
|
### 1. Map HUD (Active Navigation)
|
||||||
|
- **ID:** {{DATA:SCREEN:SCREEN_8}}
|
||||||
|
- **Description:** Fullscreen map interface with floating telemetry cards at the top showing Speed, Avg Speed, Distance, and Time. Units are integrated inline (e.g., "24.5 km/h").
|
||||||
|
- **Controls:** Detached Pause (Yellow) and Stop (Red) buttons positioned above the bottom navigation.
|
||||||
|
|
||||||
|
### 2. Plan Screen (Ready state)
|
||||||
|
- **ID:** {{DATA:SCREEN:SCREEN_7}}
|
||||||
|
- **Description:** Clean map interface identical to the HUD but without telemetry or ride controls. Features a subtle floating tooltip: "Tap to drop a pin".
|
||||||
|
|
||||||
|
### 3. Route Planning (Active Pins)
|
||||||
|
- **ID:** {{DATA:SCREEN:SCREEN_5}}
|
||||||
|
- **Description:** Secondary state of the Plan screen showing 5 dropped pins connected by a blue dotted line. A floating header displays total distance, estimated time, and pin count.
|
||||||
|
|
||||||
|
### 4. Rides History
|
||||||
|
- **ID:** {{DATA:SCREEN:SCREEN_6}}
|
||||||
|
- **Description:** List of previous routes displayed as cards over a blurred live map background. Each card shows a mini-map preview, date, distance, time, and average speed.
|
||||||
|
|
||||||
|
### 5. Settings / Profile
|
||||||
|
- **ID:** {{DATA:SCREEN:SCREEN_4}}
|
||||||
|
- **Description:** Structured list of user preferences, account details, and cloud sync options. Designed with clean hierarchy and professional dark mode styling.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technical Specifications
|
||||||
|
- **Framework:** HTML5 / CSS3 (Tailwind CSS)
|
||||||
|
- **Interactivity:** Vanilla JavaScript for map state and telemetry updates.
|
||||||
|
- **Visual Effects:** Backdrop filters for UI depth and high-contrast vector paths for route visualization.
|
||||||
317
docs/design/stitch-export/screens/map-hud-dark.html
Normal file
317
docs/design/stitch-export/screens/map-hud-dark.html
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html class="dark" lang="en" style=""><head></head><body class="antialiased selection:bg-primary-container selection:text-on-primary-container flex flex-col h-screen relative text-on-surface bg-surface"><svg aria-hidden="true" class="inline-defs-container" style="position:absolute;width:0;height:0;overflow:hidden"></svg>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
|
<title>RIPPR - Record Activity</title>
|
||||||
|
<link href="https://fonts.googleapis.com" rel="preconnect"/>
|
||||||
|
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&family=Sora:wght@400;600;700&display=swap" rel="stylesheet"/>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
|
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||||||
|
<script id="tailwind-config">
|
||||||
|
tailwind.config = {
|
||||||
|
darkMode: "class",
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
"colors": {
|
||||||
|
"secondary-fixed-dim": "#aec7f6",
|
||||||
|
"primary-fixed": "#d6e3ff",
|
||||||
|
"tertiary-fixed-dim": "#ffb68c",
|
||||||
|
"inverse-surface": "#e5e2e1",
|
||||||
|
"on-surface-muted": "#9ca3af",
|
||||||
|
"error": "#ffb4ab",
|
||||||
|
"inverse-primary": "#005db8",
|
||||||
|
"on-primary-fixed-variant": "#00458d",
|
||||||
|
"secondary": "#aec7f6",
|
||||||
|
"primary-fixed-dim": "#aac7ff",
|
||||||
|
"surface-container": "#201f1f",
|
||||||
|
"primary": "#aac7ff",
|
||||||
|
"tertiary-container": "#e3711f",
|
||||||
|
"surface-variant": "#353534",
|
||||||
|
"on-background": "#e5e2e1",
|
||||||
|
"on-secondary-fixed-variant": "#2e476f",
|
||||||
|
"primary-container": "#4090fe",
|
||||||
|
"outline-variant": "#414753",
|
||||||
|
"background": "#131313",
|
||||||
|
"surface": "#131313",
|
||||||
|
"on-tertiary": "#532200",
|
||||||
|
"on-tertiary-fixed": "#321200",
|
||||||
|
"on-surface": "#e5e2e1",
|
||||||
|
"surface-container-low": "#1c1b1b",
|
||||||
|
"on-primary-container": "#002958",
|
||||||
|
"secondary-fixed": "#d6e3ff",
|
||||||
|
"accent-error": "#ffb4ab",
|
||||||
|
"on-primary-fixed": "#001b3e",
|
||||||
|
"surface-container-lowest": "#0e0e0e",
|
||||||
|
"surface-tint": "#aac7ff",
|
||||||
|
"error-container": "#93000a",
|
||||||
|
"secondary-container": "#2e476f",
|
||||||
|
"surface-main": "#0a0a0c",
|
||||||
|
"tertiary-fixed": "#ffdbc9",
|
||||||
|
"surface-container-high": "#2a2a2a",
|
||||||
|
"on-primary": "#002f64",
|
||||||
|
"on-surface-bright": "#ffffff",
|
||||||
|
"on-tertiary-container": "#481d00",
|
||||||
|
"on-error": "#690005",
|
||||||
|
"surface-card": "#16161a",
|
||||||
|
"surface-container-highest": "#353534",
|
||||||
|
"surface-bright": "#393939",
|
||||||
|
"on-secondary-container": "#9db6e4",
|
||||||
|
"on-tertiary-fixed-variant": "#763400",
|
||||||
|
"on-error-container": "#ffdad6",
|
||||||
|
"on-secondary-fixed": "#001b3d",
|
||||||
|
"tertiary": "#ffb68c",
|
||||||
|
"outline": "#8b919f",
|
||||||
|
"surface-dim": "#131313",
|
||||||
|
"on-secondary": "#143057",
|
||||||
|
"inverse-on-surface": "#313030",
|
||||||
|
"on-surface-variant": "#c1c6d5"
|
||||||
|
},
|
||||||
|
"borderRadius": {
|
||||||
|
"DEFAULT": "0.25rem",
|
||||||
|
"lg": "0.5rem",
|
||||||
|
"xl": "0.75rem",
|
||||||
|
"full": "9999px"
|
||||||
|
},
|
||||||
|
"spacing": {
|
||||||
|
"margin-mobile": "16px",
|
||||||
|
"gutter": "24px",
|
||||||
|
"margin-desktop": "32px",
|
||||||
|
"base": "4px",
|
||||||
|
"max-width": "1280px"
|
||||||
|
},
|
||||||
|
"fontFamily": {
|
||||||
|
"headline-md": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"label-sm": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"body-lg": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"body-md": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"headline-sm": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"headline-lg": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"headline-lg-mobile": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"label-md": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"display-telemetry": ["Inter"],
|
||||||
|
"label-caps": ["Inter"]
|
||||||
|
},
|
||||||
|
"fontSize": {
|
||||||
|
"headline-md": [
|
||||||
|
"24px",
|
||||||
|
{
|
||||||
|
"lineHeight": "32px",
|
||||||
|
"fontWeight": "600"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label-sm": [
|
||||||
|
"11px",
|
||||||
|
{
|
||||||
|
"lineHeight": "16px",
|
||||||
|
"letterSpacing": "0.5px",
|
||||||
|
"fontWeight": "500"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body-lg": [
|
||||||
|
"16px",
|
||||||
|
{
|
||||||
|
"lineHeight": "24px",
|
||||||
|
"fontWeight": "400"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body-md": [
|
||||||
|
"14px",
|
||||||
|
{
|
||||||
|
"lineHeight": "20px",
|
||||||
|
"fontWeight": "400"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"headline-sm": [
|
||||||
|
"20px",
|
||||||
|
{
|
||||||
|
"lineHeight": "28px",
|
||||||
|
"fontWeight": "600"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"headline-lg": [
|
||||||
|
"32px",
|
||||||
|
{
|
||||||
|
"lineHeight": "40px",
|
||||||
|
"letterSpacing": "-0.02em",
|
||||||
|
"fontWeight": "700"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"headline-lg-mobile": [
|
||||||
|
"28px",
|
||||||
|
{
|
||||||
|
"lineHeight": "36px",
|
||||||
|
"letterSpacing": "-0.01em",
|
||||||
|
"fontWeight": "700"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label-md": [
|
||||||
|
"12px",
|
||||||
|
{
|
||||||
|
"lineHeight": "16px",
|
||||||
|
"letterSpacing": "0.5px",
|
||||||
|
"fontWeight": "500"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"display-telemetry": ["64px", { "lineHeight": "64px", "letterSpacing": "-0.04em", "fontWeight": "700" }],
|
||||||
|
"label-caps": ["12px", { "lineHeight": "16px", "letterSpacing": "0.1em", "fontWeight": "500" }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
body { margin: 0; overflow: hidden; background-color: #131313; color: #e5e2e1; min-height: max(884px, 100dvh); }
|
||||||
|
.hud-panel { background: rgba(32, 31, 31, 0.8); backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.1); }
|
||||||
|
.glass-btn { background: rgba(32, 31, 31, 0.9); backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.1); }
|
||||||
|
</style>
|
||||||
|
<!-- Background Map Placeholder -->
|
||||||
|
<div class="absolute inset-0 z-0 bg-surface">
|
||||||
|
<div class="w-full h-full bg-cover bg-center opacity-40 mix-blend-luminosity" data-alt="A light mode stylized city map view for a fitness tracking application. Minimalist aesthetic with high contrast blue routes highlighting paths against light gray blocks representing buildings and terrain. The map appears like a clean interface overlay." data-location="Tokyo" style="background-image: url('https://lh3.googleusercontent.com/aida-public/AB6AXuDr5_s-KgoDdw3V0jHBFYtHVB3aikGStl0j7TM7kPJnauzs3U1eRnVMaMh4ywSZTMLAo_LxEZnu9rTzBPq-EGev_TiD3t0VY9osDcW0xKKUZxL2rx7TPn0qh2lor7H-TT1FWRur2eVHGsIsu-YT3ht-zwG1VrgIArB7Dxx5IgNThsHCroZ6oFbBB_Uo1Y8rIjPn8NPkxuUVxmKjpNze6RAmNCuYj9V3ivWdnkUNS_Z6ybPWERqbvRA4')"></div>
|
||||||
|
<!-- Routes and Location Overlay -->
|
||||||
|
<svg class="absolute inset-0 w-full h-full pointer-events-none" preserveaspectratio="xMidYMid slice" viewbox="0 0 400 800">
|
||||||
|
<defs>
|
||||||
|
<lineargradient id="speedGradient" x1="10%" x2="50%" y1="90%" y2="50%">
|
||||||
|
<stop offset="0%" stop-color="#4090fe"></stop>
|
||||||
|
<stop offset="40%" stop-color="#aac7ff"></stop>
|
||||||
|
<stop offset="70%" stop-color="#ffb4ab"></stop>
|
||||||
|
<stop offset="100%" stop-color="#ffb4ab"></stop>
|
||||||
|
</lineargradient>
|
||||||
|
</defs>
|
||||||
|
<!-- Planned Route -->
|
||||||
|
<path d="M 200 400 C 250 250, 150 150, 300 50" fill="none" opacity="0.8" stroke="#8b919f" stroke-dasharray="10 10" stroke-linecap="round" stroke-linejoin="round" stroke-width="6"></path>
|
||||||
|
<!-- Completed Route -->
|
||||||
|
<path d="M 100 750 C 150 600, 100 500, 200 400" fill="none" stroke="url(#speedGradient)" stroke-linecap="round" stroke-linejoin="round" stroke-width="6"></path>
|
||||||
|
<!-- Pulsing Location Dot -->
|
||||||
|
<circle cx="200" cy="400" fill="#4090fe" r="8"></circle>
|
||||||
|
<circle cx="200" cy="400" fill="none" r="8" stroke="#4090fe" stroke-width="2">
|
||||||
|
<animate attributename="r" dur="1.5s" from="8" repeatcount="indefinite" to="24"></animate>
|
||||||
|
<animate attributename="opacity" dur="1.5s" from="1" repeatcount="indefinite" to="0"></animate>
|
||||||
|
</circle>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<!-- TopAppBar JSON Component -->
|
||||||
|
<!-- Main Content Canvas (HUD Layout) -->
|
||||||
|
<main class="flex-1 relative z-10 flex flex-col pb-40 px-2 md:px-margin-desktop w-full max-w-7xl mx-auto md:ml-24 md:w-[calc(100%-6rem)] p-2">
|
||||||
|
<!-- Compact Telemetry Row -->
|
||||||
|
<div class="flex flex-row gap-1 w-full" id="telemetry-container">
|
||||||
|
<div class="metric-card flex-1 hud-panel p-2 rounded-lg flex flex-col items-center justify-center cursor-pointer transition-all duration-300 overflow-hidden min-w-0">
|
||||||
|
<span class="metric-title font-label-caps text-[9px] sm:text-[10px] text-on-surface-variant uppercase whitespace-nowrap truncate w-full text-center">Speed</span>
|
||||||
|
<div class="metric-value font-display-telemetry text-base text-primary mt-1 transition-all duration-300 whitespace-nowrap">24.5 km/h</div>
|
||||||
|
</div>
|
||||||
|
<div class="metric-card flex-1 hud-panel p-2 rounded-lg flex flex-col items-center justify-center cursor-pointer transition-all duration-300 overflow-hidden min-w-0">
|
||||||
|
<span class="metric-title font-label-caps text-[9px] sm:text-[10px] text-on-surface-variant uppercase whitespace-nowrap truncate w-full text-center">Avg Speed</span>
|
||||||
|
<div class="metric-value font-display-telemetry text-lg text-on-surface mt-1 transition-all duration-300">22.1</div>
|
||||||
|
</div>
|
||||||
|
<div class="metric-card flex-1 hud-panel p-2 rounded-lg flex flex-col items-center justify-center cursor-pointer transition-all duration-300 overflow-hidden min-w-0">
|
||||||
|
<span class="metric-title font-label-caps text-[9px] sm:text-[10px] text-on-surface-variant uppercase whitespace-nowrap truncate w-full text-center">Dist</span>
|
||||||
|
<div class="metric-value font-display-telemetry text-base text-secondary mt-1 transition-all duration-300 whitespace-nowrap">12.4 km</div>
|
||||||
|
</div>
|
||||||
|
<div class="metric-card flex-1 hud-panel p-2 rounded-lg flex flex-col items-center justify-center cursor-pointer transition-all duration-300 overflow-hidden min-w-0">
|
||||||
|
<span class="metric-title font-label-caps text-[9px] sm:text-[10px] text-on-surface-variant uppercase whitespace-nowrap truncate w-full text-center">Time</span>
|
||||||
|
<div class="metric-value font-display-telemetry text-lg text-on-surface mt-1 transition-all duration-300">45:12</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<!-- Full Width Recording Control Bar -->
|
||||||
|
<div class="fixed bottom-[80px] md:bottom-0 md:left-24 w-full md:w-[calc(100%-6rem)] z-40">
|
||||||
|
<div class="flex flex-row w-full h-16 shadow-[0_-4px_6px_-1px_rgba(0,0,0,0.5)]">
|
||||||
|
<button class="flex-1 bg-tertiary-container text-on-tertiary-container font-headline-md flex items-center justify-center transition-colors duration-300 border-r border-white/10"><span class="material-symbols-outlined text-[32px]" style='font-variation-settings: "FILL" 1;'>pause</span></button>
|
||||||
|
<button class="flex-1 bg-error-container text-on-error-container font-headline-md flex items-center justify-center transition-colors duration-300"><span class="material-symbols-outlined text-[32px]" style='font-variation-settings: "FILL" 1;'>stop</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- BottomNavBar JSON Component -->
|
||||||
|
<nav class="bg-surface/80 backdrop-blur-xl fixed bottom-0 w-full z-50 pb-safe border-t border-white/10 md:hidden">
|
||||||
|
<div class="flex justify-around items-center h-20 px-margin-mobile font-label-caps text-label-caps font-display-telemetry"><button class="flex flex-col items-center justify-center text-primary relative after:content-[''] after:absolute after:-bottom-1 after:w-1 after:h-1 after:bg-primary after:rounded-full hover:text-primary/80 transition-transform duration-150 scale-95">
|
||||||
|
<span class="material-symbols-outlined" style='font-variation-settings: "FILL" 1;'>map</span>
|
||||||
|
</button>
|
||||||
|
<button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary/80 transition-transform duration-150"><span class="material-symbols-outlined" style='font-variation-settings: "FILL" 0;'>book</span></button>
|
||||||
|
<button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary/80 transition-transform duration-150">
|
||||||
|
<span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 0;">route</span>
|
||||||
|
</button>
|
||||||
|
<button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary/80 transition-transform duration-150">
|
||||||
|
<span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 0;">settings</span>
|
||||||
|
</button></div>
|
||||||
|
</nav>
|
||||||
|
<!-- Desktop Side Nav (Visible only on md+) -->
|
||||||
|
<aside class="hidden md:flex flex-col fixed left-0 top-16 bottom-0 w-24 bg-surface/80 backdrop-blur-xl border-r border-white/10 z-40 items-center py-8 gap-12">
|
||||||
|
<button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary/80 transition-colors w-full py-4 font-label-caps text-label-caps">
|
||||||
|
<span class="material-symbols-outlined mb-2 text-2xl">map</span>
|
||||||
|
Map
|
||||||
|
</button>
|
||||||
|
<button class="flex flex-col items-center justify-center text-primary relative after:content-[''] after:absolute after:left-0 after:top-1/2 after:-translate-y-1/2 after:w-1 after:h-8 after:bg-primary after:rounded-r-full hover:text-primary/80 transition-colors w-full py-4 font-label-caps text-label-caps bg-white/5">
|
||||||
|
<span class="material-symbols-outlined mb-2 text-2xl" style="font-variation-settings: 'FILL' 1;">directions_bike</span>
|
||||||
|
Rides
|
||||||
|
</button>
|
||||||
|
<button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary/80 transition-colors w-full py-4 font-label-caps text-label-caps">
|
||||||
|
<span class="material-symbols-outlined mb-2 text-2xl">route</span>
|
||||||
|
Plan
|
||||||
|
</button>
|
||||||
|
</aside>
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// Recording Toggle Logic
|
||||||
|
const toggleBtn = document.getElementById('recordingToggle');
|
||||||
|
const toggleIcon = document.getElementById('toggleIcon');
|
||||||
|
const toggleText = document.getElementById('toggleText');
|
||||||
|
let isRecording = true;
|
||||||
|
|
||||||
|
toggleBtn?.addEventListener('click', () => {
|
||||||
|
isRecording = !isRecording;
|
||||||
|
if(isRecording) {
|
||||||
|
toggleBtn.classList.remove('bg-error-container', 'text-on-error-container');
|
||||||
|
toggleBtn.classList.add('bg-primary-container', 'text-on-primary-container');
|
||||||
|
toggleIcon.textContent = 'stop_circle';
|
||||||
|
toggleText.textContent = 'Stop Recording';
|
||||||
|
} else {
|
||||||
|
toggleBtn.classList.remove('bg-primary-container', 'text-on-primary-container');
|
||||||
|
toggleBtn.classList.add('bg-error-container', 'text-on-error-container');
|
||||||
|
toggleIcon.textContent = 'play_arrow';
|
||||||
|
toggleText.textContent = 'Start Recording';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Telemetry Expansion Logic
|
||||||
|
const metrics = document.querySelectorAll('.metric-card');
|
||||||
|
|
||||||
|
metrics.forEach(metric => {
|
||||||
|
metric.addEventListener('click', () => {
|
||||||
|
const isExpanded = metric.classList.contains('flex-[2.5]');
|
||||||
|
|
||||||
|
// Reset all
|
||||||
|
metrics.forEach(m => {
|
||||||
|
m.classList.remove('flex-[2.5]', 'bg-surface-container-highest');
|
||||||
|
m.classList.add('flex-1');
|
||||||
|
m.querySelector('.metric-value').classList.remove('text-2xl', 'md:text-3xl');
|
||||||
|
m.querySelector('.metric-value').classList.add('text-lg');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Expand if it wasn't already expanded
|
||||||
|
if (!isExpanded) {
|
||||||
|
metric.classList.remove('flex-1');
|
||||||
|
metric.classList.add('flex-[2.5]', 'bg-surface-container-highest');
|
||||||
|
metric.querySelector('.metric-value').classList.remove('text-lg');
|
||||||
|
metric.querySelector('.metric-value').classList.add('text-2xl', 'md:text-3xl');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body></html>
|
||||||
BIN
docs/design/stitch-export/screens/map-hud-dark.png
Normal file
BIN
docs/design/stitch-export/screens/map-hud-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 89 KiB |
336
docs/design/stitch-export/screens/plan-screen-dark.html
Normal file
336
docs/design/stitch-export/screens/plan-screen-dark.html
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en"><head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||||
|
<title>RIPPR - Plan Route</title>
|
||||||
|
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500;700&family=Sora:wght@600;700&display=swap" rel="stylesheet"/>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
|
<script id="tailwind-config">
|
||||||
|
tailwind.config = {
|
||||||
|
darkMode: "class",
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
"colors": {
|
||||||
|
"secondary-fixed-dim": "#aec7f6",
|
||||||
|
"primary-fixed": "#d6e3ff",
|
||||||
|
"tertiary-fixed-dim": "#ffb68c",
|
||||||
|
"inverse-surface": "#e5e2e1",
|
||||||
|
"on-surface-muted": "#9ca3af",
|
||||||
|
"error": "#ffb4ab",
|
||||||
|
"inverse-primary": "#005db8",
|
||||||
|
"on-primary-fixed-variant": "#00458d",
|
||||||
|
"secondary": "#aec7f6",
|
||||||
|
"primary-fixed-dim": "#aac7ff",
|
||||||
|
"surface-container": "#201f1f",
|
||||||
|
"primary": "#aac7ff",
|
||||||
|
"tertiary-container": "#e3711f",
|
||||||
|
"surface-variant": "#353534",
|
||||||
|
"on-background": "#e5e2e1",
|
||||||
|
"on-secondary-fixed-variant": "#2e476f",
|
||||||
|
"primary-container": "#4090fe",
|
||||||
|
"outline-variant": "#414753",
|
||||||
|
"background": "#131313",
|
||||||
|
"surface": "#131313",
|
||||||
|
"on-tertiary": "#532200",
|
||||||
|
"on-tertiary-fixed": "#321200",
|
||||||
|
"on-surface": "#e5e2e1",
|
||||||
|
"surface-container-low": "#1c1b1b",
|
||||||
|
"on-primary-container": "#002958",
|
||||||
|
"secondary-fixed": "#d6e3ff",
|
||||||
|
"accent-error": "#ffb4ab",
|
||||||
|
"on-primary-fixed": "#001b3e",
|
||||||
|
"surface-container-lowest": "#0e0e0e",
|
||||||
|
"surface-tint": "#aac7ff",
|
||||||
|
"error-container": "#93000a",
|
||||||
|
"secondary-container": "#2e476f",
|
||||||
|
"surface-main": "#0a0a0c",
|
||||||
|
"tertiary-fixed": "#ffdbc9",
|
||||||
|
"surface-container-high": "#2a2a2a",
|
||||||
|
"on-primary": "#002f64",
|
||||||
|
"on-surface-bright": "#ffffff",
|
||||||
|
"on-tertiary-container": "#481d00",
|
||||||
|
"on-error": "#690005",
|
||||||
|
"surface-card": "#16161a",
|
||||||
|
"surface-container-highest": "#353534",
|
||||||
|
"surface-bright": "#393939",
|
||||||
|
"on-secondary-container": "#9db6e4",
|
||||||
|
"on-tertiary-fixed-variant": "#763400",
|
||||||
|
"on-error-container": "#ffdad6",
|
||||||
|
"on-secondary-fixed": "#001b3d",
|
||||||
|
"tertiary": "#ffb68c",
|
||||||
|
"outline": "#8b919f",
|
||||||
|
"surface-dim": "#131313",
|
||||||
|
"on-secondary": "#143057",
|
||||||
|
"inverse-on-surface": "#313030",
|
||||||
|
"on-surface-variant": "#c1c6d5"
|
||||||
|
},
|
||||||
|
"borderRadius": {
|
||||||
|
"DEFAULT": "0.25rem",
|
||||||
|
"lg": "0.5rem",
|
||||||
|
"xl": "0.75rem",
|
||||||
|
"full": "9999px"
|
||||||
|
},
|
||||||
|
"spacing": {
|
||||||
|
"margin-mobile": "16px",
|
||||||
|
"gutter": "24px",
|
||||||
|
"margin-desktop": "32px",
|
||||||
|
"base": "4px",
|
||||||
|
"max-width": "1280px",
|
||||||
|
"unit": "4px",
|
||||||
|
"stack-sm": "8px",
|
||||||
|
"stack-lg": "48px",
|
||||||
|
"stack-md": "24px",
|
||||||
|
"container-margin": "20px"
|
||||||
|
},
|
||||||
|
"fontFamily": {
|
||||||
|
"headline-md": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"label-sm": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"body-lg": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"body-md": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"headline-sm": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"headline-lg": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"headline-lg-mobile": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"label-md": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"label-caps": ["JetBrains Mono"],
|
||||||
|
"display-telemetry-mobile": ["JetBrains Mono"],
|
||||||
|
"display-telemetry": ["JetBrains Mono"]
|
||||||
|
},
|
||||||
|
"fontSize": {
|
||||||
|
"headline-md": [
|
||||||
|
"24px",
|
||||||
|
{
|
||||||
|
"lineHeight": "32px",
|
||||||
|
"fontWeight": "600"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label-sm": [
|
||||||
|
"11px",
|
||||||
|
{
|
||||||
|
"lineHeight": "16px",
|
||||||
|
"letterSpacing": "0.5px",
|
||||||
|
"fontWeight": "500"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body-lg": [
|
||||||
|
"16px",
|
||||||
|
{
|
||||||
|
"lineHeight": "24px",
|
||||||
|
"fontWeight": "400"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body-md": [
|
||||||
|
"14px",
|
||||||
|
{
|
||||||
|
"lineHeight": "20px",
|
||||||
|
"fontWeight": "400"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"headline-sm": [
|
||||||
|
"20px",
|
||||||
|
{
|
||||||
|
"lineHeight": "28px",
|
||||||
|
"fontWeight": "600"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"headline-lg": [
|
||||||
|
"32px",
|
||||||
|
{
|
||||||
|
"lineHeight": "40px",
|
||||||
|
"letterSpacing": "-0.02em",
|
||||||
|
"fontWeight": "700"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"headline-lg-mobile": [
|
||||||
|
"28px",
|
||||||
|
{
|
||||||
|
"lineHeight": "36px",
|
||||||
|
"letterSpacing": "-0.01em",
|
||||||
|
"fontWeight": "700"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label-md": [
|
||||||
|
"12px",
|
||||||
|
{
|
||||||
|
"lineHeight": "16px",
|
||||||
|
"letterSpacing": "0.5px",
|
||||||
|
"fontWeight": "500"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label-caps": ["12px", { "lineHeight": "16px", "letterSpacing": "0.1em", "fontWeight": "500" }],
|
||||||
|
"display-telemetry-mobile": ["48px", { "lineHeight": "48px", "fontWeight": "700" }],
|
||||||
|
"display-telemetry": ["64px", { "lineHeight": "64px", "letterSpacing": "-0.04em", "fontWeight": "700" }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.map-grid-overlay {
|
||||||
|
background-image:
|
||||||
|
linear-gradient(to right, rgba(255,255,255,0.03) 1px, transparent 1px),
|
||||||
|
linear-gradient(to bottom, rgba(255,255,255,0.03) 1px, transparent 1px);
|
||||||
|
background-size: 40px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulse-ring {
|
||||||
|
animation: pulse-ring 2s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-ring {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.8);
|
||||||
|
opacity: 0.8;
|
||||||
|
box-shadow: 0 0 0 0 rgba(170, 199, 255, 0.7);
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 0;
|
||||||
|
box-shadow: 0 0 0 20px rgba(170, 199, 255, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(0.8);
|
||||||
|
opacity: 0;
|
||||||
|
box-shadow: 0 0 0 0 rgba(170, 199, 255, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-line {
|
||||||
|
stroke-dasharray: 10, 10;
|
||||||
|
animation: dash 20s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes dash {
|
||||||
|
to {
|
||||||
|
stroke-dashoffset: -1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-float {
|
||||||
|
animation: float 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes float {
|
||||||
|
0% { transform: translateY(0px); }
|
||||||
|
50% { transform: translateY(-8px); }
|
||||||
|
100% { transform: translateY(0px); }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
min-height: max(884px, 100dvh);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="bg-background text-on-surface h-screen w-full overflow-hidden relative selection:bg-primary-container selection:text-on-primary-container antialiased flex flex-col dark">
|
||||||
|
<!-- Fullscreen Map Canvas -->
|
||||||
|
<main class="flex-grow relative h-full w-full z-0 overflow-hidden">
|
||||||
|
<!-- Base Map Layer -->
|
||||||
|
<div class="absolute inset-0 z-0 bg-surface-container-lowest">
|
||||||
|
<img class="w-full h-full object-cover opacity-60 mix-blend-screen invert" data-alt="A dark mode digital map showing a top-down view of city streets and terrain. The map is rendered in dark grey and black tones with subtle lighter outlines for roads." data-location="San Francisco, CA" src="https://lh3.googleusercontent.com/aida-public/AB6AXuA-oqjvzL6bUKZVJD2vvMu-0LPsY-GmGnGrfOmA0Pv5d3jBrTEuOXQ2lhZUXb9SvIGOnr2Wz64OSx0LGVbxce3zkTseW9Q62p9djWl96s-LaFizAtCBJ7okbDdDDBZVyS8RutWkvabaIwEi_lE9yq26OZuanhZ7NS6Ny4AZx69Sah-DvoE1nzwD2AEEpWJXbfX_KRFa3iGbCUa02sKaAUWzoirpWg5yU6Gk6u2OWNRefC6YtASxYmBq"/>
|
||||||
|
</div>
|
||||||
|
<!-- Technical Grid Overlay -->
|
||||||
|
<div class="absolute inset-0 map-grid-overlay z-10 pointer-events-none"></div>
|
||||||
|
<!-- Planned Route Overlay (SVG) -->
|
||||||
|
<svg class="absolute inset-0 w-full h-full z-20 pointer-events-none" preserveaspectratio="xMidYMid slice" viewbox="0 0 1000 1000">
|
||||||
|
<!-- Path connecting dropped pins - Primary Blue -->
|
||||||
|
<path class="route-line opacity-80" d="M 300 700 Q 400 650 450 500 T 700 300" fill="none" stroke="#aac7ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="6"></path>
|
||||||
|
<!-- Waypoint 1 (Dropped Pin) -->
|
||||||
|
<circle cx="450" cy="500" fill="#aac7ff" r="6" stroke="#131313" stroke-width="2"></circle>
|
||||||
|
<!-- Waypoint 2 (Destination) -->
|
||||||
|
<circle cx="700" cy="300" fill="#131313" r="8" stroke="#aac7ff" stroke-width="3"></circle>
|
||||||
|
</svg>
|
||||||
|
<!-- User Location Marker (Pulsing) -->
|
||||||
|
<div class="absolute top-[70%] left-[30%] z-30 transform -translate-x-1/2 -translate-y-1/2 flex items-center justify-center pointer-events-none">
|
||||||
|
<div class="absolute w-4 h-4 bg-primary rounded-full opacity-30"></div>
|
||||||
|
<div class="absolute w-3 h-3 bg-primary rounded-full pulse-ring"></div>
|
||||||
|
<div class="w-2 h-2 bg-primary rounded-full relative z-10 shadow-[0_0_10px_rgba(170,199,255,0.8)]"></div>
|
||||||
|
<!-- Vision cone indicator -->
|
||||||
|
<div class="absolute -top-12 left-1/2 -translate-x-1/2 w-0 h-0 border-l-[20px] border-l-transparent border-r-[20px] border-r-transparent border-t-[40px] border-t-primary/20 origin-bottom transform rotate-45"></div>
|
||||||
|
</div>
|
||||||
|
<!-- Interactive Map Canvas Layer (Invisible, captures clicks for dropping pins) -->
|
||||||
|
<div class="absolute inset-0 z-40 cursor-crosshair" id="map-interaction-layer"></div>
|
||||||
|
</main>
|
||||||
|
<!-- Floating HUD Elements Layer -->
|
||||||
|
<div class="absolute inset-0 z-50 pointer-events-none flex flex-col justify-end">
|
||||||
|
<!-- Tooltip -->
|
||||||
|
<div class="w-full flex justify-center mb-stack-md pointer-events-none px-container-margin">
|
||||||
|
<div class="tooltip-float bg-surface-container-high/90 backdrop-blur-xl border border-outline-variant/30 rounded-full px-6 py-3 flex items-center gap-2 shadow-sm">
|
||||||
|
<span class="material-symbols-outlined text-primary text-xl" style="font-variation-settings: 'FILL' 1;">location_on</span>
|
||||||
|
<span class="font-label-caps text-label-caps text-on-surface">Tap to drop a pin</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Bottom Navigation Bar -->
|
||||||
|
<nav class="bg-surface-container/90 backdrop-blur-xl border-t border-outline-variant/20 w-full pb-safe flex justify-around items-center h-20 px-container-margin pointer-events-auto shrink-0 relative shadow-[0_-4px_20px_rgba(0,0,0,0.5)]">
|
||||||
|
<!-- Map (Inactive) -->
|
||||||
|
<button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary transition-colors duration-200 w-16 h-full gap-1 group">
|
||||||
|
<span class="material-symbols-outlined text-2xl group-active:scale-95 transition-transform duration-150">map</span>
|
||||||
|
<span class="font-label-caps text-[10px] uppercase tracking-widest">Map</span>
|
||||||
|
</button>
|
||||||
|
<!-- Rides (Inactive) -->
|
||||||
|
<button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary transition-colors duration-200 w-16 h-full gap-1 group">
|
||||||
|
<span class="material-symbols-outlined text-2xl group-active:scale-95 transition-transform duration-150">directions_bike</span>
|
||||||
|
<span class="font-label-caps text-[10px] uppercase tracking-widest">Rides</span>
|
||||||
|
</button>
|
||||||
|
<!-- Plan (Active) -->
|
||||||
|
<button class="flex flex-col items-center justify-center text-primary relative after:content-[''] after:absolute after:bottom-2 after:w-1 after:h-1 after:bg-primary after:rounded-full hover:text-primary transition-colors duration-200 w-16 h-full gap-1 group">
|
||||||
|
<span class="material-symbols-outlined text-2xl group-active:scale-95 transition-transform duration-150" style="font-variation-settings: 'FILL' 1;">route</span>
|
||||||
|
<span class="font-label-caps text-[10px] uppercase tracking-widest text-primary">Plan</span>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<!-- Micro-interaction Script for Pin Dropping Simulation -->
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const mapLayer = document.getElementById('map-interaction-layer');
|
||||||
|
const svgLayer = document.querySelector('svg');
|
||||||
|
let pinCount = 0;
|
||||||
|
|
||||||
|
mapLayer.addEventListener('click', (e) => {
|
||||||
|
const rect = mapLayer.getBoundingClientRect();
|
||||||
|
const x = e.clientX - rect.left;
|
||||||
|
const y = e.clientY - rect.top;
|
||||||
|
|
||||||
|
// Visual feedback of drop
|
||||||
|
const ripple = document.createElement('div');
|
||||||
|
ripple.className = 'absolute rounded-full border-2 border-primary bg-primary/20 pointer-events-none transform -translate-x-1/2 -translate-y-1/2';
|
||||||
|
ripple.style.left = `${x}px`;
|
||||||
|
ripple.style.top = `${y}px`;
|
||||||
|
ripple.style.width = '0px';
|
||||||
|
ripple.style.height = '0px';
|
||||||
|
ripple.style.opacity = '1';
|
||||||
|
ripple.style.transition = 'all 0.5s cubic-bezier(0.165, 0.84, 0.44, 1)';
|
||||||
|
|
||||||
|
mapLayer.parentElement.appendChild(ripple);
|
||||||
|
|
||||||
|
// Trigger animation
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
ripple.style.width = '60px';
|
||||||
|
ripple.style.height = '60px';
|
||||||
|
ripple.style.opacity = '0';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clean up ripple
|
||||||
|
setTimeout(() => ripple.remove(), 500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body></html>
|
||||||
BIN
docs/design/stitch-export/screens/plan-screen-dark.png
Normal file
BIN
docs/design/stitch-export/screens/plan-screen-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 138 KiB |
307
docs/design/stitch-export/screens/rides-history-dark.html
Normal file
307
docs/design/stitch-export/screens/rides-history-dark.html
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html class="dark" lang="en" style=""><head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||||
|
<title>RIPPR - Rides</title>
|
||||||
|
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&family=Sora:wght@400;600;700&display=swap" rel="stylesheet"/>
|
||||||
|
<script id="tailwind-config">
|
||||||
|
tailwind.config = {
|
||||||
|
darkMode: "class",
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
"colors": {
|
||||||
|
"secondary-fixed-dim": "#aec7f6",
|
||||||
|
"primary-fixed": "#d6e3ff",
|
||||||
|
"tertiary-fixed-dim": "#ffb68c",
|
||||||
|
"inverse-surface": "#e5e2e1",
|
||||||
|
"on-surface-muted": "#9ca3af",
|
||||||
|
"error": "#ffb4ab",
|
||||||
|
"inverse-primary": "#005db8",
|
||||||
|
"on-primary-fixed-variant": "#00458d",
|
||||||
|
"secondary": "#aec7f6",
|
||||||
|
"primary-fixed-dim": "#aac7ff",
|
||||||
|
"surface-container": "#201f1f",
|
||||||
|
"primary": "#aac7ff",
|
||||||
|
"tertiary-container": "#e3711f",
|
||||||
|
"surface-variant": "#353534",
|
||||||
|
"on-background": "#e5e2e1",
|
||||||
|
"on-secondary-fixed-variant": "#2e476f",
|
||||||
|
"primary-container": "#4090fe",
|
||||||
|
"outline-variant": "#414753",
|
||||||
|
"background": "#131313",
|
||||||
|
"surface": "#131313",
|
||||||
|
"on-tertiary": "#532200",
|
||||||
|
"on-tertiary-fixed": "#321200",
|
||||||
|
"on-surface": "#e5e2e1",
|
||||||
|
"surface-container-low": "#1c1b1b",
|
||||||
|
"on-primary-container": "#002958",
|
||||||
|
"secondary-fixed": "#d6e3ff",
|
||||||
|
"accent-error": "#ffb4ab",
|
||||||
|
"on-primary-fixed": "#001b3e",
|
||||||
|
"surface-container-lowest": "#0e0e0e",
|
||||||
|
"surface-tint": "#aac7ff",
|
||||||
|
"error-container": "#93000a",
|
||||||
|
"secondary-container": "#2e476f",
|
||||||
|
"surface-main": "#0a0a0c",
|
||||||
|
"tertiary-fixed": "#ffdbc9",
|
||||||
|
"surface-container-high": "#2a2a2a",
|
||||||
|
"on-primary": "#002f64",
|
||||||
|
"on-surface-bright": "#ffffff",
|
||||||
|
"on-tertiary-container": "#481d00",
|
||||||
|
"on-error": "#690005",
|
||||||
|
"surface-card": "#16161a",
|
||||||
|
"surface-container-highest": "#353534",
|
||||||
|
"surface-bright": "#393939",
|
||||||
|
"on-secondary-container": "#9db6e4",
|
||||||
|
"on-tertiary-fixed-variant": "#763400",
|
||||||
|
"on-error-container": "#ffdad6",
|
||||||
|
"on-secondary-fixed": "#001b3d",
|
||||||
|
"tertiary": "#ffb68c",
|
||||||
|
"outline": "#8b919f",
|
||||||
|
"surface-dim": "#131313",
|
||||||
|
"on-secondary": "#143057",
|
||||||
|
"inverse-on-surface": "#313030",
|
||||||
|
"on-surface-variant": "#c1c6d5"
|
||||||
|
},
|
||||||
|
"borderRadius": {
|
||||||
|
"DEFAULT": "0.25rem",
|
||||||
|
"lg": "0.5rem",
|
||||||
|
"xl": "0.75rem",
|
||||||
|
"full": "9999px"
|
||||||
|
},
|
||||||
|
"spacing": {
|
||||||
|
"margin-mobile": "16px",
|
||||||
|
"gutter": "24px",
|
||||||
|
"margin-desktop": "32px",
|
||||||
|
"base": "4px",
|
||||||
|
"max-width": "1280px"
|
||||||
|
},
|
||||||
|
"fontFamily": {
|
||||||
|
"headline-md": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"label-sm": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"body-lg": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"body-md": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"headline-sm": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"headline-lg": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"headline-lg-mobile": [
|
||||||
|
"Inter"
|
||||||
|
],
|
||||||
|
"label-md": [
|
||||||
|
"Inter"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fontSize": {
|
||||||
|
"headline-md": [
|
||||||
|
"24px",
|
||||||
|
{
|
||||||
|
"lineHeight": "32px",
|
||||||
|
"fontWeight": "600"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label-sm": [
|
||||||
|
"11px",
|
||||||
|
{
|
||||||
|
"lineHeight": "16px",
|
||||||
|
"letterSpacing": "0.5px",
|
||||||
|
"fontWeight": "500"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body-lg": [
|
||||||
|
"16px",
|
||||||
|
{
|
||||||
|
"lineHeight": "24px",
|
||||||
|
"fontWeight": "400"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body-md": [
|
||||||
|
"14px",
|
||||||
|
{
|
||||||
|
"lineHeight": "20px",
|
||||||
|
"fontWeight": "400"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"headline-sm": [
|
||||||
|
"20px",
|
||||||
|
{
|
||||||
|
"lineHeight": "28px",
|
||||||
|
"fontWeight": "600"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"headline-lg": [
|
||||||
|
"32px",
|
||||||
|
{
|
||||||
|
"lineHeight": "40px",
|
||||||
|
"letterSpacing": "-0.02em",
|
||||||
|
"fontWeight": "700"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"headline-lg-mobile": [
|
||||||
|
"28px",
|
||||||
|
{
|
||||||
|
"lineHeight": "36px",
|
||||||
|
"letterSpacing": "-0.01em",
|
||||||
|
"fontWeight": "700"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label-md": [
|
||||||
|
"12px",
|
||||||
|
{
|
||||||
|
"lineHeight": "16px",
|
||||||
|
"letterSpacing": "0.5px",
|
||||||
|
"fontWeight": "500"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style type="text/tailwindcss">
|
||||||
|
@layer utilities {
|
||||||
|
.glass-panel {
|
||||||
|
@apply bg-surface/80 backdrop-blur-[20px] border border-outline-variant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="bg-background text-on-surface min-h-screen pb-[100px]"><div class="fixed inset-0 z-0 bg-surface"><div class="w-full h-full bg-cover bg-center opacity-30 backdrop-blur-md backdrop-blur-xl" data-alt="A light mode stylized city map view for a fitness tracking application." data-location="Tokyo" style='background-image: url("https://lh3.googleusercontent.com/aida-public/AB6AXuDr5_s-KgoDdw3V0jHBFYtHVB3aikGStl0j7TM7kPJnauzs3U1eRnVMaMh4ywSZTMLAo_LxEZnu9rTzBPq-EGev_TiD3t0VY9osDcW0xKKUZxL2rx7TPn0qh2lor7H-TT1FWRur2eVHGsIsu-YT3ht-zwG1VrgIArB7Dxx5IgNThsHCroZ6oFbBB_Uo1Y8rIjPn8NPkxuUVxmKjpNze6RAmNCuYj9V3ivWdnkUNS_Z6ybPWERqbvRA4");'></div><svg class="absolute inset-0 w-full h-full pointer-events-none" preserveaspectratio="xMidYMid slice" viewbox="0 0 400 800"><path d="M 200 400 C 250 250, 150 150, 300 50" fill="none" opacity="0.3" stroke="#aac7ff" stroke-dasharray="10 10" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"></path></svg></div>
|
||||||
|
<!-- TopAppBar -->
|
||||||
|
<!-- Main Content -->
|
||||||
|
<main class="px-margin-mobile max-w-4xl mx-auto flex flex-col gap-6 pt-2 relative z-10">
|
||||||
|
<!-- Search & Filter -->
|
||||||
|
<div class="flex gap-gutter items-center p-2 rounded-lg border border-outline-variant bg-surface-container-lowest shadow-sm">
|
||||||
|
<div class="flex-1 relative">
|
||||||
|
<span class="material-symbols-outlined absolute left-3 top-1/2 -translate-y-1/2 text-on-surface-variant">search</span>
|
||||||
|
<input class="w-full bg-surface-container-lowest border-b border-outline-variant focus:border-primary text-on-surface pl-10 pr-4 py-2 font-body-md text-body-md outline-none transition-colors placeholder:text-on-surface-variant/70" placeholder="Search rides..." type="text"/>
|
||||||
|
</div>
|
||||||
|
<button class="w-10 h-10 flex items-center justify-center rounded hover:bg-surface-container-highest transition-colors text-primary border border-outline-variant shadow-sm bg-surface-container-lowest">
|
||||||
|
<span class="material-symbols-outlined">tune</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<!-- Summary Stats -->
|
||||||
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-gutter mb-2 z-10">
|
||||||
|
<div class="p-4 rounded-lg flex flex-col gap-1 bg-surface-container-lowest border border-outline-variant shadow-sm"><span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant uppercase">Total Dist</span><span class="font-headline-md text-headline-md text-primary">482<span class="text-label-sm tracking-wider ml-1 text-on-surface-variant">KM</span></span></div>
|
||||||
|
<div class="p-4 rounded-lg flex flex-col gap-1 bg-surface-container-lowest border border-outline-variant shadow-sm"><span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant uppercase">Total Dist</span><span class="font-headline-md text-headline-md text-primary">482<span class="text-label-sm tracking-wider ml-1 text-on-surface-variant">KM</span></span></div>
|
||||||
|
<div class="p-4 rounded-lg flex flex-col gap-1 bg-surface-container-lowest border border-outline-variant shadow-sm"><span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant uppercase">Total Dist</span><span class="font-headline-md text-headline-md text-primary">482<span class="text-label-sm tracking-wider ml-1 text-on-surface-variant">KM</span></span></div>
|
||||||
|
<div class="p-4 rounded-lg flex flex-col gap-1 bg-surface-container-lowest border border-outline-variant shadow-sm"><span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant uppercase">Total Dist</span><span class="font-headline-md text-headline-md text-primary">482<span class="text-label-sm tracking-wider ml-1 text-on-surface-variant">KM</span></span></div>
|
||||||
|
</div>
|
||||||
|
<!-- Rides List -->
|
||||||
|
<div class="flex flex-col gap-gutter">
|
||||||
|
<!-- Ride Item 1 -->
|
||||||
|
<div class="rounded-lg flex flex-col md:flex-row overflow-hidden group cursor-pointer hover:border-primary/50 transition-colors bg-surface-container-lowest border border-outline-variant shadow-sm">
|
||||||
|
<div class="h-32 md:h-auto md:w-48 bg-surface-container-highest relative">
|
||||||
|
<img class="w-full h-full object-cover opacity-90 group-hover:opacity-100 transition-opacity" data-alt="A dark mode minimalist map view showing a neon green GPS route line traversing through city blocks. High contrast, technical aesthetic, muted dark charcoal background." data-location="San Francisco" src="https://lh3.googleusercontent.com/aida-public/AB6AXuAx1uDTgkMgXUBwI-JLBmH1_3Mw1sk91ovk-19wP19I5wktrsuJ9nM757sCThvGGNFlWi88pEzXj9cB_wlHAhQoTdkoXYp1csaGHd6e_iulV84cPEhZNlj6_M-EWzoEdv7CT-q9BJLlkOBPq9D5IaX6mQk1nqZQDfeR0k535iIYJ2rXJFCyAAgCEF0gKEYyumLsUopkQMD2ig13W01XANoAJPCP--li-S1iln0VfzpqY-vmyHLZsO9H"/>
|
||||||
|
<div class="absolute inset-0 bg-gradient-to-t from-surface/80 to-transparent md:hidden"></div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 flex flex-col justify-between flex-1 gap-4">
|
||||||
|
<div>
|
||||||
|
<h3 class="font-headline-sm text-headline-sm text-on-surface mb-1">Morning Circuit</h3>
|
||||||
|
<p class="font-body-md text-body-md text-on-surface-variant">Oct 24, 06:30 AM</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-6">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant mb-1 uppercase">DISTANCE</span>
|
||||||
|
<span class="font-headline-sm text-headline-sm text-primary">42.5 KM</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant mb-1 uppercase">TIME</span>
|
||||||
|
<span class="font-headline-sm text-headline-sm text-primary">1:45:22</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant mb-1 uppercase">AVG SPD</span>
|
||||||
|
<span class="font-headline-sm text-headline-sm text-primary">24.2 KPH</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Ride Item 2 -->
|
||||||
|
<div class="rounded-lg flex flex-col md:flex-row overflow-hidden group cursor-pointer hover:border-primary/50 transition-colors bg-surface-container-lowest border border-outline-variant shadow-sm">
|
||||||
|
<div class="h-32 md:h-auto md:w-48 bg-surface-container-highest relative">
|
||||||
|
<img class="w-full h-full object-cover opacity-90 group-hover:opacity-100 transition-opacity" data-alt="A dark mode minimalist map view showing a neon green GPS route line winding through a mountainous region. High contrast, technical aesthetic, deep black background." data-location="Marin Headlands" src="https://lh3.googleusercontent.com/aida-public/AB6AXuA8dTKlnX4_8dnTgJ0UQpocYH5zvSgIxrAirD88D7z-dcBw6SziTL2p8niEuvn-Q-z1M3AwecI2VoHbFXE70wCOQEymO_yZatnGuP5BkKz-orUNu3Lpmy3ZnXrxYVUOF77CdUnY6WWo098sJre88SDaK82aid7U4mo6vcV5DtxUqQ-H9D0N6RvTzWc0gmev36tcOCKDZqlUsRiHMarZOD6QHiPfL7HzGu_KN1gdDF1n-7G0vLs6CzmA"/>
|
||||||
|
<div class="absolute inset-0 bg-gradient-to-t from-surface/80 to-transparent md:hidden"></div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 flex flex-col justify-between flex-1 gap-4">
|
||||||
|
<div>
|
||||||
|
<h3 class="font-headline-sm text-headline-sm text-on-surface mb-1">Hill Repeats</h3>
|
||||||
|
<p class="font-body-md text-body-md text-on-surface-variant">Oct 22, 17:15 PM</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-6">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant mb-1 uppercase">DISTANCE</span>
|
||||||
|
<span class="font-headline-sm text-headline-sm text-primary">28.1 KM</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant mb-1 uppercase">TIME</span>
|
||||||
|
<span class="font-headline-sm text-headline-sm text-primary">1:12:05</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant mb-1 uppercase">AVG SPD</span>
|
||||||
|
<span class="font-headline-sm text-headline-sm text-primary">23.4 KPH</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Ride Item 3 -->
|
||||||
|
<div class="rounded-lg flex flex-col md:flex-row overflow-hidden group cursor-pointer hover:border-primary/50 transition-colors opacity-75 bg-surface-container-lowest border border-outline-variant shadow-sm">
|
||||||
|
<div class="h-32 md:h-auto md:w-48 bg-surface-container-highest relative">
|
||||||
|
<img class="w-full h-full object-cover opacity-90 group-hover:opacity-100 transition-opacity grayscale group-hover:grayscale-0" data-alt="A dark mode minimalist map view showing a neon green GPS route line along a coastal highway. High contrast, technical aesthetic, muted dark charcoal background." data-location="Highway 1" src="https://lh3.googleusercontent.com/aida-public/AB6AXuAr-gumM8Tc0ayTzCw3s39Z1j0cydRKq7oGECkbJNXERMpAQaP4xrvoVkTVHzGe7mG83pDzxMMZGy9SpTk19uSKlnM5Vjoz3zurdx6AbWLUisqVcuB6CjXS4wt_hJlUK4TfOICbZdPN2UzCkVYUHClJ1jwfeRwA0SFVxWC2gfneSIXny-aaJMfddGQCFtCB7Xjh6hoFigOGUZB-2yjvcHcgwh_u3hZXLDETlfCtPZmyedY1zuZJ9Lft"/>
|
||||||
|
<div class="absolute inset-0 bg-gradient-to-t from-surface/80 to-transparent md:hidden"></div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 flex flex-col justify-between flex-1 gap-4">
|
||||||
|
<div>
|
||||||
|
<h3 class="font-headline-sm text-headline-sm text-on-surface mb-1">Coastal Cruise</h3>
|
||||||
|
<p class="font-body-md text-body-md text-on-surface-variant">Oct 18, 08:00 AM</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-6">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant mb-1 uppercase">DISTANCE</span>
|
||||||
|
<span class="font-headline-sm text-headline-sm text-primary">85.4 KM</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant mb-1 uppercase">TIME</span>
|
||||||
|
<span class="font-headline-sm text-headline-sm text-primary">3:24:10</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="font-label-sm text-label-sm tracking-wider text-on-surface-variant mb-1 uppercase">AVG SPD</span>
|
||||||
|
<span class="font-headline-sm text-headline-sm text-primary">25.1 KPH</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<!-- BottomNavBar -->
|
||||||
|
<nav class="fixed bottom-0 w-full z-50 pb-safe bg-surface-container-lowest/80 backdrop-blur-xl border-t border-outline-variant flex justify-around items-center h-20 px-margin-mobile md:hidden"><button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary/80 transition-transform duration-150"><span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 0;">map</span></button><button class="flex flex-col items-center justify-center text-primary relative after:content-[''] after:absolute after:-bottom-1 after:w-1 after:h-1 after:bg-primary after:rounded-full hover:text-primary/80 transition-transform duration-150 scale-95"><span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 1;">book</span></button><button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary/80 transition-transform duration-150"><span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 0;">route</span></button><button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary/80 transition-transform duration-150"><span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 0;">settings</span></button></nav>
|
||||||
|
<!-- Desktop Side Nav Overlay (Hidden on Mobile, replaces Bottom Nav visually in a real app, keeping it simple here) -->
|
||||||
|
<nav class="hidden md:flex fixed left-0 top-16 bottom-0 w-24 bg-surface-container-lowest/80 backdrop-blur-md border-r border-outline-variant flex-col items-center py-6 gap-6 z-40">
|
||||||
|
<button class="w-12 h-12 flex items-center justify-center rounded hover:bg-surface-container-highest text-on-surface-variant transition-colors group relative">
|
||||||
|
<span class="material-symbols-outlined">map</span>
|
||||||
|
<span class="absolute left-14 bg-surface-container px-2 py-1 rounded font-label-sm text-label-sm tracking-wider text-on-surface opacity-0 group-hover:opacity-100 pointer-events-none transition-opacity">Map</span>
|
||||||
|
</button>
|
||||||
|
<button class="w-12 h-12 flex items-center justify-center rounded bg-primary-container/50 text-primary transition-colors group relative border border-primary/20"><span class="material-symbols-outlined" style='font-variation-settings: "FILL" 1;'>book</span><span class="absolute left-14 bg-surface-container px-2 py-1 rounded font-label-sm text-label-sm tracking-wider text-on-surface opacity-0 group-hover:opacity-100 pointer-events-none transition-opacity">Journal</span></button>
|
||||||
|
<button class="w-12 h-12 flex items-center justify-center rounded hover:bg-surface-container-highest text-on-surface-variant transition-colors group relative">
|
||||||
|
<span class="material-symbols-outlined">route</span>
|
||||||
|
<span class="absolute left-14 bg-surface-container px-2 py-1 rounded font-label-sm text-label-sm tracking-wider text-on-surface opacity-0 group-hover:opacity-100 pointer-events-none transition-opacity">Plan</span>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
<style>
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
body { padding-left: 96px; pb: 0; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body></html>
|
||||||
BIN
docs/design/stitch-export/screens/rides-history-dark.png
Normal file
BIN
docs/design/stitch-export/screens/rides-history-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
275
docs/design/stitch-export/screens/route-planning-dark.html
Normal file
275
docs/design/stitch-export/screens/route-planning-dark.html
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html class="dark" lang="en" style=""><head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||||
|
<title>RIPPR - Plan Route</title>
|
||||||
|
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500;700&family=Sora:wght@600;700&display=swap" rel="stylesheet"/>
|
||||||
|
<script id="tailwind-config">
|
||||||
|
tailwind.config = {
|
||||||
|
darkMode: "class",
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
"colors": {
|
||||||
|
"secondary-fixed-dim": "#aec7f6",
|
||||||
|
"primary-fixed": "#d6e3ff",
|
||||||
|
"tertiary-fixed-dim": "#ffb68c",
|
||||||
|
"inverse-surface": "#e5e2e1",
|
||||||
|
"on-surface-muted": "#9ca3af",
|
||||||
|
"error": "#ffb4ab",
|
||||||
|
"inverse-primary": "#005db8",
|
||||||
|
"on-primary-fixed-variant": "#00458d",
|
||||||
|
"secondary": "#aec7f6",
|
||||||
|
"primary-fixed-dim": "#aac7ff",
|
||||||
|
"surface-container": "#201f1f",
|
||||||
|
"primary": "#aac7ff",
|
||||||
|
"tertiary-container": "#e3711f",
|
||||||
|
"surface-variant": "#353534",
|
||||||
|
"on-background": "#e5e2e1",
|
||||||
|
"on-secondary-fixed-variant": "#2e476f",
|
||||||
|
"primary-container": "#4090fe",
|
||||||
|
"outline-variant": "#414753",
|
||||||
|
"background": "#131313",
|
||||||
|
"surface": "#131313",
|
||||||
|
"on-tertiary": "#532200",
|
||||||
|
"on-tertiary-fixed": "#321200",
|
||||||
|
"on-surface": "#e5e2e1",
|
||||||
|
"surface-container-low": "#1c1b1b",
|
||||||
|
"on-primary-container": "#002958",
|
||||||
|
"secondary-fixed": "#d6e3ff",
|
||||||
|
"accent-error": "#ffb4ab",
|
||||||
|
"on-primary-fixed": "#001b3e",
|
||||||
|
"surface-container-lowest": "#0e0e0e",
|
||||||
|
"surface-tint": "#aac7ff",
|
||||||
|
"error-container": "#93000a",
|
||||||
|
"secondary-container": "#2e476f",
|
||||||
|
"surface-main": "#0a0a0c",
|
||||||
|
"tertiary-fixed": "#ffdbc9",
|
||||||
|
"surface-container-high": "#2a2a2a",
|
||||||
|
"on-primary": "#002f64",
|
||||||
|
"on-surface-bright": "#ffffff",
|
||||||
|
"on-tertiary-container": "#481d00",
|
||||||
|
"on-error": "#690005",
|
||||||
|
"surface-card": "#16161a",
|
||||||
|
"surface-container-highest": "#353534",
|
||||||
|
"surface-bright": "#393939",
|
||||||
|
"on-secondary-container": "#9db6e4",
|
||||||
|
"on-tertiary-fixed-variant": "#763400",
|
||||||
|
"on-error-container": "#ffdad6",
|
||||||
|
"on-secondary-fixed": "#001b3d",
|
||||||
|
"tertiary": "#ffb68c",
|
||||||
|
"outline": "#8b919f",
|
||||||
|
"surface-dim": "#131313",
|
||||||
|
"on-secondary": "#143057",
|
||||||
|
"inverse-on-surface": "#313030",
|
||||||
|
"on-surface-variant": "#c1c6d5"
|
||||||
|
},
|
||||||
|
"borderRadius": {
|
||||||
|
"DEFAULT": "0.25rem",
|
||||||
|
"lg": "0.5rem",
|
||||||
|
"xl": "0.75rem",
|
||||||
|
"full": "9999px"
|
||||||
|
},
|
||||||
|
"spacing": {
|
||||||
|
"margin-mobile": "16px",
|
||||||
|
"gutter": "24px",
|
||||||
|
"margin-desktop": "32px",
|
||||||
|
"base": "4px",
|
||||||
|
"max-width": "1280px",
|
||||||
|
"unit": "4px",
|
||||||
|
"stack-sm": "8px",
|
||||||
|
"stack-lg": "48px",
|
||||||
|
"stack-md": "24px",
|
||||||
|
"container-margin": "20px"
|
||||||
|
},
|
||||||
|
"fontFamily": {
|
||||||
|
"headline-md": ["Inter"],
|
||||||
|
"label-sm": ["Inter"],
|
||||||
|
"body-lg": ["Inter"],
|
||||||
|
"body-md": ["Inter"],
|
||||||
|
"headline-sm": ["Inter"],
|
||||||
|
"headline-lg": ["Inter"],
|
||||||
|
"headline-lg-mobile": ["Inter"],
|
||||||
|
"label-md": ["Inter"],
|
||||||
|
"label-caps": ["JetBrains Mono"]
|
||||||
|
},
|
||||||
|
"fontSize": {
|
||||||
|
"headline-md": ["24px", { "lineHeight": "32px", "fontWeight": "600" }],
|
||||||
|
"label-sm": ["11px", { "lineHeight": "16px", "letterSpacing": "0.5px", "fontWeight": "500" }],
|
||||||
|
"body-lg": ["16px", { "lineHeight": "24px", "fontWeight": "400" }],
|
||||||
|
"body-md": ["14px", { "lineHeight": "20px", "fontWeight": "400" }],
|
||||||
|
"headline-sm": ["20px", { "lineHeight": "28px", "fontWeight": "600" }],
|
||||||
|
"headline-lg": ["32px", { "lineHeight": "40px", "letterSpacing": "-0.02em", "fontWeight": "700" }],
|
||||||
|
"headline-lg-mobile": ["28px", { "lineHeight": "36px", "letterSpacing": "-0.01em", "fontWeight": "700" }],
|
||||||
|
"label-md": ["12px", { "lineHeight": "16px", "letterSpacing": "0.5px", "fontWeight": "500" }],
|
||||||
|
"label-caps": ["12px", { "lineHeight": "16px", "letterSpacing": "0.1em", "fontWeight": "500" }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.map-grid-overlay {
|
||||||
|
background-image:
|
||||||
|
linear-gradient(to right, rgba(255,255,255,0.05) 1px, transparent 1px),
|
||||||
|
linear-gradient(to bottom, rgba(255,255,255,0.05) 1px, transparent 1px);
|
||||||
|
background-size: 40px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulse-ring {
|
||||||
|
animation: pulse-ring 2s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-ring {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.8);
|
||||||
|
opacity: 0.8;
|
||||||
|
box-shadow: 0 0 0 0 rgba(170, 199, 255, 0.5);
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 0;
|
||||||
|
box-shadow: 0 0 0 20px rgba(170, 199, 255, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(0.8);
|
||||||
|
opacity: 0;
|
||||||
|
box-shadow: 0 0 0 0 rgba(170, 199, 255, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-line {
|
||||||
|
stroke-dasharray: 10, 10;
|
||||||
|
animation: dash 20s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes dash {
|
||||||
|
to {
|
||||||
|
stroke-dashoffset: -1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-float {
|
||||||
|
animation: float 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes float {
|
||||||
|
0% { transform: translateY(0px); }
|
||||||
|
50% { transform: translateY(-8px); }
|
||||||
|
100% { transform: translateY(0px); }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
min-height: max(884px, 100dvh);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="bg-background text-on-surface h-screen w-full overflow-hidden relative selection:bg-primary-container selection:text-on-primary-container antialiased flex flex-col">
|
||||||
|
<!-- Fullscreen Map Canvas -->
|
||||||
|
<main class="flex-grow relative h-full w-full z-0 overflow-hidden">
|
||||||
|
<div class="absolute top-4 left-1/2 -translate-x-1/2 z-50 w-auto px-container-margin pointer-events-none mt-4">
|
||||||
|
<div class="bg-surface/90 backdrop-blur-xl border border-outline-variant/30 rounded-full px-8 py-4 flex items-center gap-8 shadow-sm pointer-events-auto">
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<span class="text-on-surface-variant font-headline-md text-[10px] uppercase tracking-widest mb-1">Distance</span>
|
||||||
|
<span class="font-headline-md text-primary-container">12.4<span class="text-sm ml-1">km</span></span>
|
||||||
|
</div>
|
||||||
|
<div class="w-px h-8 bg-outline-variant/30"></div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<span class="text-on-surface-variant font-headline-md text-[10px] uppercase tracking-widest mb-1">Est. Time</span>
|
||||||
|
<span class="font-headline-md text-primary-container">45<span class="text-sm ml-1">m</span></span>
|
||||||
|
</div>
|
||||||
|
<div class="w-px h-8 bg-outline-variant/30"></div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<span class="text-on-surface-variant font-headline-md text-[10px] uppercase tracking-widest mb-1">Pins</span>
|
||||||
|
<span class="font-headline-md text-primary-container">5</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Base Map Layer -->
|
||||||
|
<div class="absolute inset-0 z-0 bg-surface-container">
|
||||||
|
<img class="w-full h-full object-cover opacity-30 mix-blend-screen" data-alt="A digital map showing a top-down view of city streets and terrain." data-location="San Francisco, CA" src="https://lh3.googleusercontent.com/aida-public/AB6AXuDtux0iJ6r19x5fCEWn0L1Ai3ziybnKhwYCd-8xyKm8ebAQHTJPdulojF6Pi_31mtsUlhqpI5ejusGg8Rk7y9c20eWK9sqj3uubky70kqSRiHsd37IJzOiRUTYdHCyOg2g7K5uADAg-39nR48gfWmfotW13eKGb1I9OMrc8MJBtj6lD9rtqapC2DG8kLoTz50c_QCt_AVShQyLrft6yW1SShV4mZXP2kwhf4AZsh3bvkzeCQzfIB43E"/>
|
||||||
|
</div>
|
||||||
|
<!-- Technical Grid Overlay -->
|
||||||
|
<div class="absolute inset-0 map-grid-overlay z-10 pointer-events-none"></div>
|
||||||
|
<!-- Planned Route Overlay (SVG) -->
|
||||||
|
<svg class="absolute inset-0 w-full h-full z-20 pointer-events-none" preserveaspectratio="xMidYMid slice" viewbox="0 0 1000 1000">
|
||||||
|
<path class="route-line opacity-80" d="M 400 400 L 450 420 L 500 380 L 550 430 L 600 400" fill="none" stroke="#4090fe" stroke-dasharray="10, 10" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"></path>
|
||||||
|
<circle cx="400" cy="400" fill="#4090fe" r="6" stroke="#131313" stroke-width="2"></circle>
|
||||||
|
<circle cx="450" cy="420" fill="#4090fe" r="6" stroke="#131313" stroke-width="2"></circle>
|
||||||
|
<circle cx="500" cy="380" fill="#4090fe" r="6" stroke="#131313" stroke-width="2"></circle>
|
||||||
|
<circle cx="550" cy="430" fill="#4090fe" r="6" stroke="#131313" stroke-width="2"></circle>
|
||||||
|
<circle cx="600" cy="400" fill="#4090fe" r="6" stroke="#131313" stroke-width="2"></circle>
|
||||||
|
</svg>
|
||||||
|
<!-- User Location Marker (Pulsing) -->
|
||||||
|
<div class="absolute top-[70%] left-[30%] z-30 transform -translate-x-1/2 -translate-y-1/2 flex items-center justify-center pointer-events-none">
|
||||||
|
<div class="absolute w-4 h-4 bg-primary-container rounded-full opacity-30"></div>
|
||||||
|
<div class="absolute w-3 h-3 bg-primary-container rounded-full pulse-ring"></div>
|
||||||
|
<div class="w-2 h-2 bg-primary-container rounded-full relative z-10 shadow-[0_0_10px_rgba(64,144,254,0.5)]"></div>
|
||||||
|
<!-- Vision cone indicator -->
|
||||||
|
<div class="absolute -top-12 left-1/2 -translate-x-1/2 w-0 h-0 border-l-[20px] border-l-transparent border-r-[20px] border-r-transparent border-t-[40px] border-t-primary-container/20 origin-bottom transform rotate-45"></div>
|
||||||
|
</div>
|
||||||
|
<!-- Interactive Map Canvas Layer (Invisible, captures clicks for dropping pins) -->
|
||||||
|
<div class="absolute inset-0 z-40 cursor-crosshair" id="map-interaction-layer"></div>
|
||||||
|
</main>
|
||||||
|
<!-- Floating HUD Elements Layer -->
|
||||||
|
<div class="absolute inset-0 z-50 pointer-events-none flex flex-col justify-end">
|
||||||
|
<!-- Tooltip -->
|
||||||
|
<div class="w-full flex justify-center mb-stack-md pointer-events-none px-container-margin">
|
||||||
|
<button class="pointer-events-auto bg-primary-container text-on-primary-container font-headline-md text-label-caps px-12 py-4 rounded-xl shadow-md uppercase tracking-widest hover:brightness-110 active:scale-95 transition-all">Start Route</button>
|
||||||
|
</div>
|
||||||
|
<!-- Bottom Navigation Bar (Generated from JSON) -->
|
||||||
|
<nav class="bg-surface border-t border-outline-variant/30 w-full pb-safe flex justify-around items-center h-20 px-container-margin pointer-events-auto shrink-0 relative shadow-[0_-4px_20px_rgba(0,0,0,0.2)]">
|
||||||
|
<button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary-container transition-colors duration-150">
|
||||||
|
<span class="material-symbols-outlined mb-1" style="font-variation-settings: 'FILL' 0;">map</span>
|
||||||
|
</button>
|
||||||
|
<button class="flex flex-col items-center justify-center text-primary-container relative after:content-[''] after:absolute after:-bottom-1 after:w-1 after:h-1 after:bg-primary-container after:rounded-full hover:text-primary-container transition-colors duration-150 scale-95">
|
||||||
|
<span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 1;">book</span>
|
||||||
|
</button>
|
||||||
|
<button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary-container transition-colors duration-150">
|
||||||
|
<span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 0;">route</span>
|
||||||
|
</button>
|
||||||
|
<button class="flex flex-col items-center justify-center text-on-surface-variant hover:text-primary-container transition-colors duration-150">
|
||||||
|
<span class="material-symbols-outlined mb-1" style="font-variation-settings: 'FILL' 0;">settings</span>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<!-- Micro-interaction Script for Pin Dropping Simulation -->
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const mapLayer = document.getElementById('map-interaction-layer');
|
||||||
|
const svgLayer = document.querySelector('svg');
|
||||||
|
let pinCount = 0;
|
||||||
|
|
||||||
|
mapLayer.addEventListener('click', (e) => {
|
||||||
|
const rect = mapLayer.getBoundingClientRect();
|
||||||
|
const x = e.clientX - rect.left;
|
||||||
|
const y = e.clientY - rect.top;
|
||||||
|
|
||||||
|
// Visual feedback of drop
|
||||||
|
const ripple = document.createElement('div');
|
||||||
|
ripple.className = 'absolute rounded-full border-2 border-primary-container bg-primary-container/20 pointer-events-none transform -translate-x-1/2 -translate-y-1/2';
|
||||||
|
ripple.style.left = `${x}px`;
|
||||||
|
ripple.style.top = `${y}px`;
|
||||||
|
ripple.style.width = '0px';
|
||||||
|
ripple.style.height = '0px';
|
||||||
|
ripple.style.opacity = '1';
|
||||||
|
ripple.style.transition = 'all 0.5s cubic-bezier(0.165, 0.84, 0.44, 1)';
|
||||||
|
|
||||||
|
mapLayer.parentElement.appendChild(ripple);
|
||||||
|
|
||||||
|
// Trigger animation
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
ripple.style.width = '60px';
|
||||||
|
ripple.style.height = '60px';
|
||||||
|
ripple.style.opacity = '0';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clean up ripple
|
||||||
|
setTimeout(() => ripple.remove(), 500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body></html>
|
||||||
BIN
docs/design/stitch-export/screens/route-planning-dark.png
Normal file
BIN
docs/design/stitch-export/screens/route-planning-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 83 KiB |
Reference in New Issue
Block a user