SPIKE-010 was a UX-only spike to produce the information architecture, user flows, wireframes, readiness score specification, and visual design direction for the Data Hub dashboard. No implementation code was written. The spike focused entirely on defining the user experience layer that will guide future development.
The team of five (UX Researcher, UI Designer, Product Owner, Business Analyst, Scrum Master) worked from established inputs: a pastel-on-charcoal visual direction, progressive disclosure as the core navigation model (Glance to Domain to Detail), and the readiness score as the hero element. Data sources include Strava activities, Google Fit heart rate and sleep, Garmin Index S2 body composition, estimated nutrition logs, and Ozempic timeline tracking.
Six documentation artefacts were produced covering the full UX surface: site map and navigation, core user flows, wireframes for all page types, a readiness score UX specification, pastel design direction tokens, and acceptance criteria for the UX MVP.
| ID | Title | Effort | Status | Owner |
|---|---|---|---|---|
| D-01 | Information architecture map (site map + navigation model) | M | Complete | UX Researcher |
| D-02 | Core user flows (morning check, post-ride review, weekly review, log meal, log meds) | M | Complete | UX Researcher |
| D-03 | Wireframes: Glance page | L | Complete | UI Designer |
| D-04 | Wireframes: Domain pages (Training, Recovery, Body, Nutrition, Timeline) | L | Complete | UI Designer |
| D-05 | Wireframes: Detail drilldowns (Sleep, HR, CTL/ATL/TSB, Weight, Ride) | L | Complete | UI Designer |
| D-06 | Readiness score UX spec (score, factors, confidence, empty states) | M | Complete | UX Researcher |
| D-07 | Pastel design direction notes (tokens at UX level) | S | Complete | UI Designer |
| D-08 | Acceptance criteria for UX MVP | M | Complete | Product Owner |
| D-09 | Final report HTML | M | Complete | Business Analyst |
| D-10 | Reports index update card | S | Complete | Business Analyst |
| D-11 | Backlog update SPIKE-010 | S | Complete | Scrum Master |
All artefacts are located in docs/spike-ux-dashboard/:
ia.md: Information architecture map with site map and navigation modelflows.md: Core user flows with step-by-step interaction sequenceswireframes.md: ASCII wireframes for Glance, Domain, and Detail pagesreadiness-spec.md: Readiness score UX specification covering score display, factor breakdown, confidence levels, and empty statespastel-direction.md: Pastel design direction tokens at the UX level, including colour palette, typography scale, and spacingux-acceptance-criteria.md: Acceptance criteria for the UX MVP, defining the minimum bar for each page and flowThis spike produced no implementation code. All outputs are design documentation intended to guide future development sprints.
This section embeds the UX artefacts produced in this spike for easy reading.
**Spike:** SPIKE-010, UX Dashboard Wireframes
**Author:** UX Researcher
**Date:** 2026-02-22
**Status:** Complete
---
The dashboard uses a three-layer progressive disclosure model. Each layer serves a different user intent and time commitment.
| Layer | Name | Intent | Time Budget |
|-------|------|--------|-------------|
| L1 | Glance | "How am I doing right now?" | Under 10 seconds |
| L2 | Domain | "Tell me more about this area." | 1 to 3 minutes |
| L3 | Detail | "I want to explore this deeply." | Open-ended |
**Layer transitions:**
---
Dashboard (Glance) [L1]
├── Training [L2]
│ ├── Ride Detail (per activity) [L3]
│ ├── CTL / ATL / TSB (Fitness & Form) [L3]
│ └── Weekly Volume History [L3]
├── Recovery [L2]
│ ├── Sleep Detail (per night) [L3]
│ ├── HR Detail (resting HR trend) [L3]
│ └── Readiness History [L3]
├── Body [L2]
│ ├── Weight Detail (trend + history) [L3]
│ └── Body Comp Detail (future) [L3]
├── Nutrition [L2]
│ ├── Meal Detail (per entry) [L3]
│ └── Daily Summary [L3]
└── Timeline [L2]
├── Ozempic Compliance Grid [L3]
└── Event Detail (per log entry) [L3]
---
The single entry point. Displays a curated set of hero cards that answer "how am I doing today?" at a glance.
**Hero element:** Readiness Score card, prominently placed at the top of the page. Large score number (0 to 100), color-coded ring, top contributing factor, and a single-line insight.
**Supporting cards (below the hero):**
| Card | Data Source | Purpose |
|------|------------|---------|
| Race Countdown | Static config | Days until Race to the Sun (30 May 2026) |
| Today Snapshot | Google Fit | Steps, resting HR, sleep summary |
| Latest Activity | Strava | Most recent ride or workout |
| Fitness / Form Chart | Strava (computed) | CTL, ATL, TSB sparkline |
| Weight Trend | Garmin Index S2 / Google Fit | Current weight, 7-day direction |
| Weekly Volume | Strava | Total hours and km this week vs. last |
**Card interaction:** Each card links to its parent domain page (L2). The Latest Activity card links directly to the Ride Detail page (L3) for that specific activity.
Each domain page expands one area with richer data, charts, and recent history.
Each detail page provides deep exploration of a single metric or event.
| Detail Page | Parent Domain | Content |
|------------|---------------|---------|
| Ride Detail | Training | Full activity stats, map, HR/power charts, lap splits, segment efforts |
| CTL/ATL/TSB Detail | Training | Extended fitness/form chart, date range picker, trend analysis |
| Weekly Volume History | Training | Week-over-week comparison, volume targets |
| Sleep Detail | Recovery | Per-night sleep stage chart, duration trend, consistency score |
| HR Detail | Recovery | Resting HR 30-day trend, morning vs. evening readings, anomaly highlights |
| Readiness History | Recovery | Daily readiness scores over time, factor contribution trends |
| Weight Detail | Body | Full weight history chart, rate of change, annotations for milestones |
| Body Comp Detail | Body | Body fat %, muscle mass trends (future, when Garmin data available) |
| Meal Detail | Nutrition | Single meal entry: foods, macros, notes |
| Daily Summary | Nutrition | Full day nutrition totals, macro breakdown chart |
| Ozempic Compliance Grid | Timeline | Calendar heatmap of doses, streak tracking, dose history |
| Event Detail | Timeline | Single event record with all metadata |
---
The sidebar is always visible on screens wider than 768px.
┌─────────────────────────────────────────────┐
│ [Logo/Title] │ │
│ │ │
│ ● Dashboard (Glance) │ Page Content │
│ │ │
│ ○ Training │ │
│ ○ Recovery │ │
│ ○ Body │ │
│ ○ Nutrition │ │
│ ○ Timeline │ │
│ │ │
│ ───────────── │ │
│ [Race Countdown Mini] │ │
└─────────────────────────────────────────────┘
**Sidebar behaviour:**
On screens narrower than 768px, navigation moves to a fixed bottom bar.
┌───────────────────────────┐
│ Page Content │
│ │
│ │
│ │
├───────────────────────────┤
│ Home Train Recov Body │
│ Nutr Time │
└───────────────────────────┘
**Bottom bar behaviour:**
When the user drills into a detail page (L3), the navigation context changes:
---
All routes use a flat, readable pattern.
| Page | URL | Layer |
|------|-----|-------|
| Glance (Dashboard) | / | L1 |
| Training | /training | L2 |
| Recovery | /recovery | L2 |
| Body | /body | L2 |
| Nutrition | /nutrition | L2 |
| Timeline | /timeline | L2 |
| Ride Detail | /training/rides/:id | L3 |
| CTL/ATL/TSB Detail | /training/fitness-form | L3 |
| Weekly Volume History | /training/volume | L3 |
| Sleep Detail | /recovery/sleep/:date | L3 |
| HR Detail | /recovery/heart-rate | L3 |
| Readiness History | /recovery/readiness | L3 |
| Weight Detail | /body/weight | L3 |
| Body Comp Detail | /body/composition | L3 |
| Meal Detail | /nutrition/meals/:id | L3 |
| Daily Summary | /nutrition/day/:date | L3 |
| Ozempic Compliance | /timeline/ozempic | L3 |
| Event Detail | /timeline/events/:id | L3 |
**Conventions:**
:id (activity ID) or :date (ISO date, YYYY-MM-DD)---
Breadcrumbs provide orientation, especially when deep-linking into detail pages.
**Format:** Domain > Page Title
**Examples:**
| Page | Breadcrumb |
|------|------------|
| Ride Detail | Training > Morning Ride (21 Feb) |
| Sleep Detail | Recovery > Sleep (21 Feb) |
| Weight Detail | Body > Weight Trend |
| CTL/ATL/TSB | Training > Fitness and Form |
| Meal Detail | Nutrition > Lunch (21 Feb) |
| Ozempic Compliance | Timeline > Ozempic Log |
**Behaviour:**
---
The readiness score is the single most prominent element on the Glance page.
**Position:** First card, top of the content area, spanning the full width on mobile and occupying the primary column on desktop.
**Why hero placement:**
**Navigation from readiness:**
---
| Layer | Cards/Sections | Charts | Data Points | Actions |
|-------|---------------|--------|-------------|---------|
| L1 Glance | 6 hero cards | 2 sparklines (fitness, weight) | Under 20 visible numbers | Tap to drill down |
| L2 Domain | 3 to 5 sections | 2 to 3 full charts | 20 to 50 visible data points | Tap rows, filter date range |
| L3 Detail | 1 focused view | 1 to 2 detailed charts | 50+ data points | Zoom, pan, date picker, export |
---
Each page must handle missing data gracefully.
| Scenario | Behaviour |
|----------|-----------|
| No Strava data | Training cards show "Connect Strava" prompt |
| No sleep data | Recovery page shows readiness with reduced confidence; sleep card shows "No sleep data recorded" |
| No weight data | Body page shows "Log your first weigh-in" prompt |
| No meals logged | Nutrition page shows quick-add CTA prominently |
| No Ozempic logs | Timeline shows empty compliance grid with "Log your first dose" prompt |
| Partial data (some sources fresh, some stale) | Stale data cards show a subtle "last updated X ago" label; readiness confidence indicator adjusts |
---
The information architecture follows a clean three-layer model. The Glance page is the hub, domain pages are the spokes, and detail pages are the leaves. Readiness sits at the top of the hierarchy as the hero element. Navigation is persistent (sidebar on desktop, bottom bar on mobile) so the user always knows where they are and can switch context without going "back." Breadcrumbs provide orientation on detail pages only, keeping the interface uncluttered at higher layers.
**Spike:** SPIKE-010, UX Dashboard Wireframes
**Author:** UX Researcher
**Date:** 2026-02-22
**Status:** Complete
---
**Goal:** Answer "How am I doing today? Should I train hard or take it easy?"
**Time budget:** Under 60 seconds for the full flow, under 10 seconds for the glance.
1. **Open app** (or navigate to dashboard URL)
2. **Glance at readiness score**
3. **Review factor pills**
4. **Tap readiness card** (optional drill-down)
5. **Tap sleep factor** (optional deeper drill-down)
6. **Return to Glance**
---
**Goal:** Review the ride just completed, understand its impact on fitness/form.
**Time budget:** 2 to 5 minutes.
1. **Open app after a ride**
2. **Tap the Latest Activity card**
3. **Review stats grid**
4. **Scroll to HR chart**
5. **Scroll to power chart** (if power meter used)
6. **Check PR badges** (if any set)
7. **Tap back to Training domain** (via breadcrumb: Training > Morning Ride)
8. **Review training load chart**
---
**Goal:** Assess the week's progress across all domains, plan adjustments.
**Time budget:** 3 to 10 minutes.
1. **Open app (Sunday evening or Monday morning)**
2. **Review weekly volume**
3. **Navigate to Training domain** (tap sidebar or bottom bar)
4. **Navigate to Recovery domain**
5. **Navigate to Body domain**
6. **Navigate to Nutrition domain**
7. **Navigate to Timeline domain**
8. **Return to Glance**
---
**Goal:** Record a meal with estimated calories and macros.
**Time budget:** Under 30 seconds.
1. **Navigate to Nutrition domain**
2. **Tap "Log Meal" button**
3. **Enter meal details**
4. **Confirm entry**
5. **Return to previous view**
---
**Goal:** Record an Ozempic dose.
**Time budget:** Under 15 seconds.
1. **Navigate to Timeline domain**
2. **Tap "Log Meds" button**
3. **Confirm dose details**
4. **Tap "Log" to confirm**
5. **Visual confirmation**
---
| Flow | Entry Point | Primary Layer | Deepest Layer | Key Action |
|------|------------|---------------|---------------|------------|
| Morning Check | Glance (L1) | L1 | L3 (Sleep Detail) | Check readiness, plan day |
| Post-Ride Review | Glance (L1) | L3 (Ride Detail) | L3 | Review ride, check fitness impact |
| Weekly Review | Glance (L1) | L2 (all domains) | L3 (optional) | Assess week, plan adjustments |
| Log Meal | Nutrition (L2) | L2 | L2 (form overlay) | Record meal, update daily totals |
| Log Meds | Timeline (L2) | L2 | L2 (form overlay) | Record Ozempic dose, update compliance |
---
All flows assume the user can switch between any domain at any time using the persistent navigation (sidebar or bottom bar). No flow requires going "back to home first" to reach another domain. This is a key benefit of the persistent navigation model.
Quick actions available from multiple entry points:
Goal: user sees today’s plan, understands why, and sees plan vs actual progress.
1. Open dashboard
2. See Readiness and Today’s Plan card
3. Optional: tap Plan vs Actual strip to open Training or Body domain
4. If plan is acceptable: start day, no interaction
5. If plan needs change: tap Adjust Plan
6. Tap Why to open Plan rationale
7. Later: mark Ride and Strength as done
Success criteria:
SPIKE-010 deliverable. Text wireframes for every page in the three-layer progressive disclosure model: Glance, Domain, and Detail.
All wireframes assume a 12-column CSS Grid at 1200px max width, dark mode with pastel accents on deep charcoal.
Notation:
[ ... ] = interactive element (button, link, control)+--+ | +--+ = box-drawing for cards and containers(( ... )) = chart or visualization area< ... > = navigation element{ ... } = dynamic/computed value=== = section dividerc1-c12 for grid placement// ... = annotation or responsive note---
The primary view. Everything above the fold answers "How am I doing right now?" in under 10 seconds. The readiness score is the hero element.
+---------------------------------------------------------------------+
| TOP BAR (64px) c1-c12 |
| |
| Data Hub < << 22 Feb 2026 >> > [ 97 days to race ] |
| (wordmark) (date navigator) (countdown chip) |
+---------------------------------------------------------------------+
// Date nav: tap arrows to shift day. Tap date for calendar picker.
// Countdown chip: pastel accent bg, days until Race to the Sun.
// On mobile: wordmark collapses to icon, countdown moves below date.
==========================================================================
+---------------------------------------------------------------------+
| READINESS SCORE HERO CARD (160px) c1-c12 |
| |
| +--------------------------------------------------------------+ |
| | | |
| | .--------. | |
| | / \ Ready to Train | |
| | | 72 | "Solid recovery overnight. | |
| | | /100 | CTL trending up." | |
| | \ / | |
| | '--------' {status label} | |
| | (color ring, {one-line insight} | |
| | gradient fill | |
| | based on score) | |
| | | |
| | Factors: Sleep 8/10 | HRV 7/10 | Form +4 | Rest 1d | |
| | (mini factor pills, pastel tinted) | |
| | | |
| +--------------------------------------------------------------+ |
| |
+---------------------------------------------------------------------+
// Readiness ring: circular progress, gradient from red (0-30) to
// yellow (30-60) to green (60-100), all pastel muted tones.
// Score number: --text-3xl (32px), extra bold.
// Status label: "Ready to Train" / "Take It Easy" / "Recovery Day".
// Factor pills: small rounded badges with pastel bg tints.
// On mobile: ring above text, stacked vertically. Full width card.
==========================================================================
+---------------------------------------------------------------------+
| DAILY SNAPSHOT ROW (120px) c1-c12 |
| |
| +--------+ +--------+ +--------+ +--------+ +--------+ |
| | Weight | |Body Fat| | Steps | | RHR | | Form | |
| | 83.2 | | 22.1% | | 8,421 | | 58 | | +4 | |
| | -0.3kg | | -0.2% | | .... | | .... | | Fresh | |
| | v | | v | |(spark) | |(spark) | |(badge) | |
| +--------+ +--------+ +--------+ +--------+ +--------+ |
| c1-c2 c3-c4 c5-c7 c8-c9 c10-c12 |
+---------------------------------------------------------------------+
// Each card: metric label (--text-sm, secondary color),
// value (--text-xl, bold), delta or sparkline, trend arrow.
// Delta colors: green = improving, red = declining, neutral = stable.
// Cards are clickable, drill down to respective Domain page.
// On mobile: 2-column grid, Form card spans full width below.
==========================================================================
+---------------------------------------------------------------------+
| TRAINING LOAD CHART (280px) c1-c12 |
| |
| Fitness and Form [ 1W 1M 3M 6M 1Y All ] |
| CTL 62 | ATL 58 | TSB +4 (time range segmented control) |
| |
| (( )) |
| (( .-------. : RACE )) |
| (( / CTL \-----------. . : DAY )) |
| ((/ (area) \ / \ \------ : )) |
| (( \-------/ : )) |
| (( : )) |
| (( ---- ATL (line, dashed) ---- : )) |
| (( : )) |
| (( #### TSB (diverging area, +green / -red) #### : )) |
| (( : )) |
| (( Jan Feb Mar Apr May : )) |
| (( )) |
| |
+---------------------------------------------------------------------+
// Time range control: top-right, 6 presets. Active uses --accent bg.
// On mobile: chart height shrinks to 200px, fewer x-axis labels.
==========================================================================
+---------------------------------------------------------------------+
| ACTIVITY FEED (variable height) c1-c12 |
| |
| Recent Activities [ View All > ] |
| |
| +----------------------------------------------------------------+ |
| | Morning Ride 22 Feb, 07:30 | |
| | 42.3 km | 1:45:00 | 187W avg | 142 bpm | SS 78 | |
| +----------------------------------------------------------------+ |
| +----------------------------------------------------------------+ |
| | Recovery Spin 21 Feb, 17:00 | |
| | 18.1 km | 0:45:00 | 112W avg | 118 bpm | SS 32 | |
| +----------------------------------------------------------------+ |
| +----------------------------------------------------------------+ |
| | Strength: Quad Rehab 21 Feb, 09:00 | |
| | 0:35:00 | Leg extensions, step-ups, wall sits | |
| +----------------------------------------------------------------+ |
| |
+---------------------------------------------------------------------+
// Cards are clickable, drill to Ride Detail.
// Show 3 most recent on Glance. Full list on Training domain.
==========================================================================
+----------------------------------+-----------------------------------+
| BODY COMPOSITION (c1-c6) | SLEEP (c7-c12) |
| | |
| Weight Trend | Last Night |
| 83.2 kg (-0.3 this wk) | 7h 42m Quality: 82/100 |
| | |
| (( )) | +-----------------------------+ |
| (( \ )) | | Deep #### 1h 20m | |
| (( \ )) | | Light ###### 3h | |
| (( \___/ \___ )) | | REM ##### 2h | |
| (( \-- )) | | Awake ## 0h 22m | |
| (( goal ............ )) | +-----------------------------+ |
| (( )) | |
| (( Jan Feb Mar )) | 7-Day Trend |
| | (( ....###.. )) |
| Body Fat: 22.1% | (( M T W T F S S )) |
| [View Details >] | [View Details >] |
| | |
+----------------------------------+-----------------------------------+
// On mobile: stacked vertically, full width each.
==========================================================================
+----------------------------------+-----------------------------------+
| HEART RATE (c1-c6) | NUTRITION (c7-c12) |
| | |
| Today's HR | Today's Food |
| RHR: 58 bpm | 1,840 / 2,200 kcal |
| | [360 remaining] |
| | |
| (( )) | +-----------------------------+ |
| (( HR timeline )) | | Breakfast 520 kcal | |
| (( zone-colored area )) | | Lunch 680 kcal | |
| (( 06 09 12 15 18 )) | | Snack 240 kcal | |
| (( )) | | Dinner 400 kcal | |
| | +-----------------------------+ |
| Zone Distribution | |
| [Z1 ============= 45%] | Macros |
| [Z2 ========= 28%] | (( P 32% C 45% F 23% )) |
| [Z3 ====== 18%] | |
| [Z4 == 6%] | Ozempic: 0.5mg (today) |
| [Z5 = 3%] | [Log Meal] [Log Meds] |
| [View Details >] | [View Details >] |
| | |
+----------------------------------+-----------------------------------+
// On mobile: stacked vertically, full width each.
==========================================================================
+---------------------------------------------------------------------+
| WEEKLY SUMMARY HEATMAP (80px) c1-c12 |
| |
| This Week |
| +------+------+------+------+------+------+------+ |
| | Mon | Tue | Wed | Thu | Fri | Sat | Sun | |
| | Ride | Str | Rest | Ride | Str | Ride | Rest | |
| | 42km | Rehab| | 35km | Rehab| 65km | | |
| | ### | ## | .. | ## | ## | ### | .. | |
| +------+------+------+------+------+------+------+ |
| |
| Total: 142 km | 4h 30m | 3 rides | 2 strength |
| |
+---------------------------------------------------------------------+
// On mobile: 7 narrow columns, icons only, no text labels.
---
+---------------------------------------------------------------------+
| TRAINING HEADER c3-c12 |
| Training Overview [ 1W 1M 3M 6M 1Y All] |
| CTL {62} ATL {58} TSB {+4} Phase: Build |
+---------------------------------------------------------------------+
+---------------------------------------------------------------------+
| FITNESS AND FORM CHART (360px) c3-c12 |
| (( Full CTL/ATL/TSB chart with phase markers and race line )) |
| (( Crosshair synced with activity list below )) |
+---------------------------------------------------------------------+
+----------------------------------+-----------------------------------+
| WEEKLY VOLUME BARS (c3-c7) | GOALS PROGRESS (c8-c12) |
| (( Stacked bars: hours, km )) | CTL: 62 / 75 target [====...83%] |
| (( W1 W2 W3 W4 W5 W6 W7 )) | Consistency: 4/5 sessions [80%] |
+----------------------------------+-----------------------------------+
+---------------------------------------------------------------------+
| ACTIVITY LIST c3-c12 |
| | Date | Activity | Dist | Time | Power | SS | |
| | 22 Feb | Morning Ride | 42 km | 1:45 | 187W | 78 | |
| | 21 Feb | Recovery Spin | 18 km | 0:45 | 112W | 32 | |
| | 21 Feb | Quad Rehab | -- | 0:35 | -- | -- | |
| [ Load More ] |
+---------------------------------------------------------------------+
+---------------------------------------------------------------------+
| RECOVERY HEADER c3-c12 |
| Recovery Score: {82/100} Sleep: {7h 42m} RHR: {58} |
+---------------------------------------------------------------------+
+---------------------------------------------------------------------+
| SLEEP DURATION CHART (280px) c3-c12 |
| (( Stacked bars: Deep / Light / REM / Awake, 7-day )) |
| (( Goal line: 7h 30m )) |
+---------------------------------------------------------------------+
+----------------------------------+-----------------------------------+
| LAST NIGHT (c3-c7) | HR TREND (c8-c12) |
| 7h 42m, Quality 82/100 | Resting HR: 58 bpm |
| Hypnogram (stepped area) | (( 30-day trend line )) |
| Bed: 22:15 Wake: 06:02 | 7-day avg: 57 30-day avg: 59 |
+----------------------------------+-----------------------------------+
+---------------------------------------------------------------------+
| RECOVERY SCORE BREAKDOWN c3-c12 |
| | Sleep 8/10 | HRV 7/10 | RHR 8/10 | Rest 6/10 | Training 7/10 | |
| (each factor: small ring gauge, label, score) |
+---------------------------------------------------------------------+
+---------------------------------------------------------------------+
| BODY HEADER c3-c12 |
| Weight: {83.2 kg} Body Fat: {22.1%} Goal: {80 kg} |
+---------------------------------------------------------------------+
+---------------------------------------------------------------------+
| WEIGHT TREND CHART (320px) c3-c12 |
| (( Weight line, goal line (dashed), Ozempic dose markers )) |
+---------------------------------------------------------------------+
+----------------------------------+-----------------------------------+
| BODY COMP BREAKDOWN (c3-c7) | WEEKLY DELTA (c8-c12) |
| Muscle 38.2kg, Fat 18.4kg | Weight -0.3kg, BF -0.2% |
| Bone 3.2kg, Water 23.4kg | Rate: -0.4 kg/week |
| BMI: 25.8 | Projected goal: 22 Apr |
+----------------------------------+-----------------------------------+
+---------------------------------------------------------------------+
| ADHERENCE TRACKER (28-day grid: logged vs missed) c3-c12 |
| 24/28 days (86%) |
+---------------------------------------------------------------------+
+---------------------------------------------------------------------+
| NUTRITION HEADER c3-c12 |
| Today: {1,840 / 2,200 kcal} Protein: {128g} Streak: {5 days} |
+---------------------------------------------------------------------+
+----------------------------------+-----------------------------------+
| DAILY FOOD LOG (c3-c7) | MACRO CHARTS (c8-c12) |
| Breakfast 520 kcal | (( Donut: P 32% C 45% F 23% )) |
| Lunch 680 kcal | Protein 128/140g [=====.] |
| Snack 240 kcal | Carbs 208/250g [=====.] |
| Dinner 400 kcal | Fat 47/60g [====..] |
| [ Log Meal ] | |
+----------------------------------+-----------------------------------+
+---------------------------------------------------------------------+
| CALORIE TREND (daily bars vs target line) c3-c12 |
+---------------------------------------------------------------------+
+---------------------------------------------------------------------+
| Ozempic Grid + Logging Streak | [ Log Meds ] c3-c12 |
+---------------------------------------------------------------------+
+---------------------------------------------------------------------+
| TIMELINE HEADER c3-c12 |
| Annotated view of all events, doses, and correlations |
+---------------------------------------------------------------------+
+---------------------------------------------------------------------+
| ANNOTATED TIMELINE (scrollable) c3-c12 |
| 22 Feb -- Ride: Morning Ride (42 km, SS 78) |
| 21 Feb -- Recovery Spin, Quad Rehab, Scale: 83.2 kg |
| 20 Feb -- Tempo Intervals, Ozempic 0.5 mg, Food: 2,180 kcal |
| 19 Feb -- Rest Day, Scale: 83.5 kg |
| ... [ Load More ] |
+---------------------------------------------------------------------+
+----------------------------------+-----------------------------------+
| OZEMPIC DOSE HISTORY (c3-c7) | CORRELATIONS (c8-c12) |
| (( Dot plot over months )) | Ozempic vs Weight r=-0.82 |
| Total: 18 doses, 0.5mg now | Training vs Sleep r=+0.64 |
+----------------------------------+-----------------------------------+
---
Detail views open as slide-over panels (400px) on desktop, full page on mobile.
+--------------------------------------+
| [ <- Recovery ] [ x Close ] |
| Sleep Detail, 22 Feb 2026 |
| |
| Duration: 7h 42m Quality: 82/100 |
| Bed: 22:15 Wake: 06:02 |
| |
| HYPNOGRAM |
| (( Awake/REM/Light/Deep stages )) |
| (( 22:30 00:00 02:00 04:00 )) |
| |
| STAGES: Deep 1h20m (17%) |
| Light 3h (39%), REM 2h (26%) |
| Awake 22m (5%) |
| |
| VS AVERAGE: Duration +27m, |
| Deep +15m, Quality +6 |
+--------------------------------------+
+--------------------------------------+
| [ <- Recovery ] [ x Close ] |
| Heart Rate, 22 Feb 2026 |
| |
| RHR: 58 Max: 178 Avg: 72 |
| |
| DAILY HR TIMELINE |
| (( Zone-colored area chart )) |
| |
| ZONES: Z1 68%, Z2 18%, Z3 8% |
| Z4 4%, Z5 2% |
| |
| RHR TREND (30 days) |
| (( Line chart )) |
+--------------------------------------+
+--------------------------------------+
| [ <- Training ] [ x Close ] |
| Fitness and Form |
| |
| CTL: 62 ATL: 58 TSB: +4 |
| |
| FULL CHART with phase markers |
| (( Interactive CTL/ATL/TSB )) |
| |
| PHASES: Base > Build > Peak > Race |
| PROJECTION: CTL at race: 71 |
| Target: 75 Gap: -4 |
+--------------------------------------+
+--------------------------------------+
| [ <- Body ] [ x Close ] |
| Weight Detail |
| |
| Current: 83.2 Goal: 80.0 |
| To Go: 3.2 kg BMI: 25.8 |
| |
| WEIGHT HISTORY |
| (( Full trend + goal + Ozempic )) |
| |
| BODY COMP TRENDS |
| (( Muscle, fat, water lines )) |
| |
| RATE: -0.4 kg/week |
| Projected goal: 22 Apr 2026 |
+--------------------------------------+
+--------------------------------------+
| [ <- Training ] [ x Close ] |
| Morning Ride, 22 Feb 07:30 |
| |
| MAP PLACEHOLDER |
| (( Route on dark tiles )) |
| |
| STATS: 42.3km 1:45 520m elev |
| 187W avg 142bpm SS 78 |
| |
| HR OVER TIME |
| (( Zone-colored area )) |
| |
| POWER OVER TIME |
| (( Line with NP overlay )) |
| |
| PR BADGES (if any) |
+--------------------------------------+
---
| Breakpoint | Layout | Nav | Detail View | Chart Height |
|------------|--------|-----|-------------|-------------|
| Desktop 1024px+ | 12-column grid | Sidebar | 400px slide-over | 280-360px |
| Tablet 480-768px | 2-column | Top tabs | 320px slide-over | 240px |
| Phone <480px | Single column | Bottom tabs (56px) | Full page | 200px |
Universal: 16px card gap, 24px section gap, 44px touch targets, readiness hero always above fold.
This section adds the missing coach surfaces for "what should I do today" and "plan vs actual".
Layout intent: a single, actionable card that prescribes today’s ride and strength or mobility.
┌────────────────────────────────────────────────────────────┐
│ TODAY’S PLAN Readiness 74 │
├────────────────────────────────────────────────────────────┤
│ Ride: Z2 Endurance 60 to 90 min │
│ Target: easy steady, conversational pace │
│ Why: Sleep ok, Fatigue high, keep consistency │
│ │
│ Strength: Mobility only 12 to 15 min │
│ Knee note: avoid kneeling, stairs slow and controlled │
│ │
│ [Mark Ride Done] [Mark Strength Done] [Adjust Plan] │
└────────────────────────────────────────────────────────────┘
Adjust Plan opens a modal:
Show forecast as a band, not a single line.
┌──────────────────────────┐ ┌──────────────────────────┐
│ WEIGHT: PLAN vs ACTUAL │ │ FITNESS (CTL): PLAN vs ACT│
│ target band ┈┈┈┈┈┈┈┈┈┈ │ │ target band ┈┈┈┈┈┈┈┈┈┈ │
│ actual line ━━━●━━●━━ │ │ actual line ━━━╸━━╸━━ │
│ Δ 7d: -0.6 kg on track │ │ Δ 7d: +2.1 on track │
└──────────────────────────┘ └──────────────────────────┘
┌──────────────────────────┐ ┌──────────────────────────┐
│ FATIGUE (ATL): PLAN vs ACT│ │ FORM (TSB): PLAN vs ACT │
│ target band ┈┈┈┈┈┈┈┈┈┈ │ │ target band ┈┈┈┈┈┈┈┈┈┈ │
│ actual line ━━━╸━━╸━━ │ │ actual line ━━━╸━━╸━━ │
│ risk: elevated fatigue │ │ taper readiness: building │
└──────────────────────────┘ └──────────────────────────┘
Rules:
┌────────────────────────────────────────────────────────────┐
│ WHY THIS PLAN TODAY │
├────────────────────────────────────────────────────────────┤
│ Readiness: 74 (High confidence) │
│ Factors: Sleep 7.7h, HR trend stable, Fatigue elevated │
│ │
│ Applied rules: │
│ 1) If Fatigue high and Sleep ok, prescribe Z2 not intervals │
│ 2) If knee pain > 3, replace strength with mobility │
│ │
│ Expected outcomes (forecast): │
│ - CTL trend within band by end of week │
│ - ATL returns into safe band within 48h │
│ - Weight trend stays within band │
└────────────────────────────────────────────────────────────┘
**Spike:** SPIKE-010, UX Dashboard Wireframes
**Author:** UX Researcher
**Date:** 2026-02-22
**Status:** Complete
---
The readiness score is a daily computed value from 0 to 100 that answers: "Should I train hard today or take it easy?" It is the first-class hero element on the Glance page, the single most prominent piece of information in the entire dashboard.
The score synthesises multiple data sources into one actionable number. It is not a medical metric. It is a personal heuristic that improves as more data flows in.
---
| Range | Label | Colour | Guidance |
|-------|-------|--------|----------|
| 80 to 100 | Excellent | Pastel green (#A8E6CF) | Full intensity training. Body is well recovered. |
| 60 to 79 | Good | Pastel teal (#88D8B0) | Normal training. Proceed as planned. |
| 40 to 59 | Moderate | Pastel amber (#FFD3B6) | Reduce intensity. Consider an easy day or active recovery. |
| 20 to 39 | Low | Pastel coral (#FF8B94) | Rest or very light activity only. Check contributing factors. |
| 0 to 19 | Very Low | Pastel red (#FFAAA5) | Rest strongly recommended. Something significant is off. |
The colour applies to:
---
Four primary factors contribute to the readiness score. Each factor produces a sub-score from 0 to 10.
**Inputs:**
**Scoring logic:**
**Data source:** Google Fit sleep sessions and segments
**Inputs:**
**Scoring logic:**
**Data source:** Google Fit HR samples (overnight/morning window)
**Inputs:**
**Scoring logic:**
**Data source:** Strava activities (suffer score, TSS), computed CTL/ATL
**Inputs:**
**Scoring logic:**
**Data source:** Strava activity history, training plan (if configured)
---
The overall readiness score is a weighted sum of the four factor sub-scores, scaled to 0 to 100:
readiness = (sleep * 0.30 + rhr * 0.25 + strain * 0.25 + consistency * 0.20) * 10
Each factor sub-score ranges from 0 to 10. The weighted sum ranges from 0 to 10, then multiplied by 10 to produce the 0 to 100 scale.
---
Factors appear as compact pills below the score:
Factors: Sleep 8/10 | RHR 7/10 | Strain 6/10 | Consistency 9/10
Each pill:
Each factor gets a card with:
---
Readiness confidence depends on data completeness. Not all sources may be available.
| Sources Available | Confidence | Display |
|-------------------|------------|---------|
| All 4 factors have fresh data (under 24h) | High | Score shown normally. No indicator needed. |
| 3 of 4 factors have data | Medium | Score shown with "Based on 3 of 4 inputs" label below. Missing factor named. |
| 2 of 4 factors have data | Low | Score shown with "Limited data" label. Colour intensity reduced (50% opacity ring). Missing factors named. |
| 1 or 0 factors have data | Insufficient | Score not computed. Empty state shown instead (see section 7). |
---
Displayed when fewer than 2 factors have data.
+--------------------------------------------------------------+
| |
| .--------. |
| / \ |
| | -- | Readiness score needs data |
| | | |
| \ / Connect at least two of these: |
| '--------' [ ] Sleep data (Google Fit) |
| (empty ring, [ ] Heart rate (Google Fit) |
| dashed border) [ ] Activities (Strava) |
| [ ] Training plan |
| |
+--------------------------------------------------------------+
Elements:
When sleep data specifically is missing but other factors are available:
---
The readiness hero card is the largest and most prominent element on the dashboard.
+---------------------------------------------------------------------+
| |
| +--[Ring]--+ Ready to Train |
| | | |
| | 72 | "Solid recovery overnight. CTL trending up." |
| | /100 | |
| +----------+ Sleep 8/10 | RHR 7/10 | Strain 6/10 | ... |
| |
+---------------------------------------------------------------------+
+----------------------------------+
| |
| .--------. |
| | 72 | |
| | /100 | |
| '--------' |
| |
| Ready to Train |
| "Solid recovery overnight." |
| |
| Sleep 8 RHR 7 Strain 6 C 9 |
| |
+----------------------------------+
---
When the user taps the readiness hero card, they navigate to the Recovery domain page. The readiness breakdown is the first section.
+---------------------------------------------------------------------+
| Readiness Score: 72/100 22 Feb 2026 |
| |
| +----------+----------+----------+----------+ |
| | Sleep | RHR | Strain | Consist. | |
| | 8/10 | 7/10 | 6/10 | 9/10 | |
| | (ring) | (ring) | (ring) | (ring) | |
| | 7h 42m | 58 bpm | SS 78 | Rest 1d | |
| | Deep 18% | vs 57avg | ACWR 1.1 | 4/5 sess | |
| +----------+----------+----------+----------+ |
| |
| Trend: Readiness improving over 7 days (avg 68 -> 72) |
| Confidence: High (all sources fresh) |
| |
+---------------------------------------------------------------------+
Each factor card:
Below the breakdown, a readiness history chart:
---
The readiness card includes a single-line insight that surfaces the most important factor driving today's score.
1. Identify the factor with the lowest sub-score
2. If that factor is 3+ points below the next lowest, it is "the big thing"
3. If all factors are within 2 points of each other, use the overall trend instead
| Scenario | Insight |
|----------|---------|
| Sleep factor is 3/10, all others above 7 | "Poor sleep is pulling your score down. Prioritise rest tonight." |
| RHR 4 bpm above average | "Resting heart rate is elevated. Take it easy today." |
| Hard ride yesterday, strain factor is 2/10 | "Yesterday's hard ride increased fatigue. An easy day would help recovery." |
| All factors above 7 | "Solid recovery across the board. Ready for a quality session." |
| CTL rising, form positive | "Fitness is building well. CTL trending up towards race target." |
| All factors above 8, near race | "Peak form. Trust the taper and stay sharp for race day." |
The insight is generated from templates, not free-form AI text. This keeps it predictable and trustworthy.
---
Readiness must be shown alongside forecast progress to make it actionable.
Display rules:
SPIKE-010 deliverable. UX-level design tokens for the pastel theme. Dark mode only. Muted pastels on deep charcoal.
---
The Data Hub dashboard uses muted pastels layered onto deep charcoal surfaces. The goal is a calm, data-forward aesthetic that feels warm and personal, not clinical or corporate. Every color choice serves a purpose: either communicating data category, indicating status, or providing visual hierarchy.
Guiding principles:
---
Extending the existing Data Hub four-level surface system with pastel tint states for interactive elements.
| Token | Value | Usage |
|----------------|-----------|------------------------------------|
| --bg | #0f0f0f | Page background |
| --surface | #1a1a1a | Card surfaces, primary containers |
| --surface2 | #242424 | Elevated elements, inputs, popups |
| --surface3 | #2e2e2e | Hover states, active elements |
For interactive states that need to hint at a domain color without overwhelming the dark base.
| Token | Value | Usage |
|-------------------------|----------------------------|--------------------------------------|
| --surface-hover | #2e2e2e | Default hover on neutral cards |
| --surface-active | #333333 | Default active/pressed state |
| --surface-selected | rgba(108,99,255,0.08) | Selected card/row (accent tint) |
| --surface-training | rgba(129,140,248,0.06) | Training domain card hover |
| --surface-recovery | rgba(196,181,253,0.06) | Recovery domain card hover |
| --surface-body | rgba(251,191,178,0.06) | Body domain card hover |
| --surface-nutrition | rgba(167,223,186,0.06) | Nutrition domain card hover |
| --surface-meds | rgba(216,191,255,0.06) | Meds domain card hover |
| Token | Value | Usage |
|-----------------|--------------------------|--------------------------------|
| --border | #333333 | Default card borders |
| --border2 | #444444 | Emphasized borders |
| --border-focus | rgba(108,99,255,0.5) | Focus ring color |
---
| Token | Value | Contrast on --surface | Usage |
|-----------------|-----------|-----------------------|---------------------------------|
| --text | #e8e8e8 | 12.4:1 | Primary text, headings, values |
| --text2 | #a0a0a0 | 6.4:1 | Secondary text, labels, captions|
| --text3 | #6b6b6b | 3.2:1 | Tertiary text, hints, disabled |
| --text-disabled| #4a4a4a| 2.0:1 | Disabled controls, placeholders |
Notes:
--text3 passes WCAG AA for large text (>18px) only. Use at 14px+ with caution.--text-disabled is intentionally below AA. Disabled elements should not draw attention.--text for maximum readability.--text2.---
Pastel variants of the SPIKE-007 accent colors. Each has a base, muted, and tint variant.
| Token | Value | Usage |
|--------------------|--------------------------|------------------------------|
| --accent | #818cf8 | Primary actions, active nav |
| --accent-hover | #93a0ff | Hover on accent elements |
| --accent-muted | rgba(129,140,248,0.12) | Accent backgrounds, pills |
| --accent-subtle | rgba(129,140,248,0.06) | Selected row, faint highlight|
| Token | Value | Usage |
|--------------------|--------------------------|------------------------------|
| --green | #6ee7b7 | Positive trends, on track |
| --green-hover | #86efcb | Hover on green elements |
| --green-muted | rgba(110,231,183,0.12) | Green backgrounds, badges |
| Token | Value | Usage |
|--------------------|--------------------------|------------------------------|
| --yellow | #fde68a | Warnings, caution, behind |
| --yellow-hover | #fef0ad | Hover on yellow elements |
| --yellow-muted | rgba(253,230,138,0.12) | Yellow backgrounds, badges |
| Token | Value | Usage |
|--------------------|--------------------------|------------------------------|
| --red | #fca5a5 | Errors, at risk, declining |
| --red-hover | #fdb8b8 | Hover on red elements |
| --red-muted | rgba(252,165,165,0.12) | Red backgrounds, badges |
| Color | SPIKE-007 (neon) | SPIKE-010 (pastel) | Change |
|---------|-------------------|--------------------|---------------------------|
| Accent | #6C63FF | #818cf8 | Lighter, less saturated |
| Green | #4ECDC4 | #6ee7b7 | Shifted warmer, softer |
| Yellow | #FFE66D | #fde68a | Slightly muted |
| Red | #FF6B6B | #fca5a5 | Significantly softened |
The pastel variants maintain the same hue families but reduce saturation and increase lightness. On the deep charcoal background, they appear gentle yet readable.
---
Status and feedback colors derived from the accent palette.
| Token | Value | Usage |
|--------------------|--------------------------|------------------------------|
| --success | #6ee7b7 | Success states, confirmations|
| --success-muted | rgba(110,231,183,0.12) | Success backgrounds |
| --warning | #fde68a | Warnings, needs attention |
| --warning-muted | rgba(253,230,138,0.12) | Warning backgrounds |
| --error | #fca5a5 | Errors, failures |
| --error-muted | rgba(252,165,165,0.12) | Error backgrounds |
| --info | #818cf8 | Informational, neutral tips |
| --info-muted | rgba(129,140,248,0.12) | Info backgrounds |
Rules for semantic color usage:
--error for neutral data (e.g. a low step count is not an error).--text or --text2, not semantic colors.---
Each data domain has a dedicated color family for charts. Colors are chosen to be distinguishable from each other when viewed side by side.
| Token | Value | Usage |
|------------------------|-----------|---------------------------------|
| --chart-ctl | #818cf8 | CTL (Fitness) area fill |
| --chart-ctl-line | #a5b4fc | CTL line stroke |
| --chart-atl | #fca5a5 | ATL (Fatigue) line |
| --chart-atl-dash | #fca5a5 | ATL dashed stroke |
| --chart-tsb-pos | #6ee7b7 | TSB positive area (above zero) |
| --chart-tsb-neg | #fca5a5 | TSB negative area (below zero) |
| --chart-power | #818cf8 | Power line in ride charts |
| --chart-suffer | #fca5a5 | Suffer score bar fill |
| Token | Value | Usage |
|------------------------|-----------|---------------------------------|
| --chart-sleep | #c4b5fd | Sleep duration bars |
| --chart-deep | #6366f1 | Deep sleep stage |
| --chart-light | #a5b4fc | Light sleep stage |
| --chart-rem | #c4b5fd | REM sleep stage |
| --chart-awake | #fde68a | Awake periods |
| --chart-rhr | #c4b5fd | Resting heart rate trend |
| --chart-recovery | #a78bfa | Recovery score ring/gauge |
| Token | Value | Usage |
|------------------------|-----------|---------------------------------|
| --chart-weight | #fbbfb2 | Weight trend line |
| --chart-bodyfat | #fdba74 | Body fat percentage line |
| --chart-muscle | #6ee7b7 | Muscle mass line |
| --chart-bone | #a0a0a0 | Bone mass (neutral) |
| --chart-water | #7dd3fc | Body water percentage |
| --chart-bmi | #fbbfb2 | BMI line (same family as weight)|
| Token | Value | Usage |
|------------------------|-----------|---------------------------------|
| --chart-calories | #fde68a | Calorie bars |
| --chart-protein | #6ee7b7 | Protein in macro donut |
| --chart-carbs | #fde68a | Carbohydrates in macro donut |
| --chart-fat | #fbbfb2 | Fat in macro donut |
| --chart-fibre | #a7dfba | Fibre target bar |
| --chart-target-line | #6b6b6b | Calorie/macro target lines |
| Token | Value | Usage |
|------------------------|-----------|---------------------------------|
| --chart-ozempic | #d8bfff | Ozempic dose markers/timeline |
| --chart-ozempic-bg | rgba(216,191,255,0.12) | Dose marker backgrounds|
| --chart-dose-low | #c4b5fd | Low dose (0.25 mg) marker |
| --chart-dose-high | #a78bfa | Higher dose (0.5 mg+) marker |
| Token | Value | Zone |
|----------------|-----------|--------------------|
| --zone-1 | #7dd3fc | Recovery (Z1) |
| --zone-2 | #6ee7b7 | Endurance (Z2) |
| --zone-3 | #fde68a | Tempo (Z3) |
| --zone-4 | #fdba74 | Threshold (Z4) |
| --zone-5 | #fca5a5 | Max effort (Z5) |
Zone colors graduate from cool (blue) through warm (coral). Each is readable on --surface backgrounds.
---
The readiness score uses a continuous gradient mapped to three zones. All values are pastel.
| Range | Color | Label | Token |
|---------|-----------|----------------|----------------------|
| 0-30 | #fca5a5 | Poor | --readiness-low |
| 31-60 | #fde68a | Moderate | --readiness-mid |
| 61-100 | #6ee7b7 | Good | --readiness-high |
The readiness ring uses a CSS conic gradient with smooth transitions:
--readiness-gradient: conic-gradient(
from 0deg,
var(--readiness-low) 0%,
var(--readiness-mid) 40%,
var(--readiness-high) 70%,
var(--readiness-high) 100%
);
Each readiness factor gets a pastel background tint:
| Factor | Background | Text Color |
|-----------|--------------------------------|------------|
| Sleep | rgba(196,181,253,0.15) | #c4b5fd |
| HRV | rgba(129,140,248,0.15) | #818cf8 |
| Form | rgba(110,231,183,0.15) | #6ee7b7 |
| Rest | rgba(253,230,138,0.15) | #fde68a |
| Training | rgba(129,140,248,0.15) | #818cf8 |
---
Extending the SPIKE-007 type scale. System font stack, Major Third ratio (1.25).
--font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
--font-mono: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
| Token | Value | Usage |
|--------------------|-------|--------------------------------------|
| --font-regular | 400 | Body text, descriptions |
| --font-medium | 500 | Labels, secondary headings |
| --font-semibold | 600 | Card titles, table headers |
| --font-bold | 700 | Section headings, emphasis |
| --font-extrabold | 800 | Hero numbers, page titles |
| Token | Size | Line Height | Usage |
|----------------|-------|-------------|--------------------------------|
| --text-3xl | 32px | 1.1 | Hero score number, page titles |
| --text-2xl | 26px | 1.2 | Section headers |
| --text-xl | 20px | 1.3 | Card values, stat numbers |
| --text-lg | 16px | 1.5 | Body text, descriptions |
| --text-md | 14px | 1.5 | Secondary text, form labels |
| --text-sm | 12px | 1.4 | Captions, badges, metadata |
| --text-xs | 11px | 1.3 | Chart axis labels, timestamps |
All metric values use tabular numerals for alignment:
--numeric: font-variant-numeric: tabular-nums;
Delta values (e.g. -0.3 kg) use --text-md at --font-medium with semantic color.
---
Base unit: 4px. All spacing is a multiple of the base unit.
| Token | Value | Usage |
|-------------|-------|------------------------------------------|
| --space-1 | 4px | Tight gaps, icon padding |
| --space-2 | 8px | Inline spacing, badge padding |
| --space-3 | 12px | Card inner padding (compact) |
| --space-4 | 16px | Card gap, standard padding |
| --space-5 | 20px | Card inner padding (standard) |
| --space-6 | 24px | Section gap, section padding |
| --space-8 | 32px | Large section gap |
| --space-10| 40px | Page-level padding |
| --space-12| 48px | Hero element vertical padding |
| --space-16| 64px | Top bar height, major section spacing |
--space-5 (20px)--space-4 (16px)--space-6 (24px)--space-3 (12px)--space-1 horizontal, --space-2 vertical--space-16 (64px)---
No box shadows. Depth is communicated entirely through surface color levels and 1px borders.
| Token | Value | Usage |
|---------------------|--------------------------|-----------------------------|
| --border-default | 1px solid #333333 | Card borders, separators |
| --border-emphasis | 1px solid #444444 | Emphasized sections, tables |
| --border-focus | 2px solid rgba(129,140,248,0.5) | Focus rings |
| --border-accent | 1px solid rgba(129,140,248,0.3) | Active nav indicator|
| Token | Value | Usage |
|------------------|-------|------------------------------------|
| --radius-sm | 4px | Small badges, code blocks |
| --radius-md | 8px | Cards, inputs, buttons |
| --radius-lg | 12px | Large cards, modal panels |
| --radius-full | 9999px| Pills, circular badges, rings |
No shadows. Hierarchy is expressed through four surface levels:
1. --bg (#0f0f0f): page canvas
2. --surface (#1a1a1a): primary cards
3. --surface2 (#242424): elevated overlays (tooltips, dropdowns)
4. --surface3 (#2e2e2e): active/pressed states within overlays
Each level is ~10 lightness units apart, creating subtle but perceptible depth.
---
All interactive elements follow a consistent state model using pastel tones.
| State | Background | Border | Text |
|-----------|------------------|-----------------|----------|
| Default | --surface | --border | --text |
| Hover | --surface3 | --border2 | --text |
| Active | #333333 | --border2 | --text |
| Focus | --surface | --border-focus| --text |
| Disabled | --surface | --border | --text-disabled |
| State | Background | Text |
|-----------|------------------|------------------|
| Default | --accent | #ffffff |
| Hover | --accent-hover | #ffffff |
| Active | #6c77e0 | #ffffff |
| Focus | --accent + focus ring | #ffffff |
| Disabled | --accent-muted | --text3 |
| State | Background | Text |
|-----------|--------------------|---------------|
| Default | transparent | --accent |
| Hover | --accent-muted | --accent |
| Active | rgba(129,140,248,0.18) | --accent |
| Focus | transparent + focus ring | --accent |
| Disabled | transparent | --text3 |
| State | Indicator | Label Color |
|-----------|------------------------|---------------|
| Default | none | --text2 |
| Hover | --surface3 bg | --text |
| Active | --accent left bar (3px) | --text |
| Disabled | none | --text-disabled |
| Element | Default | Hover/Active |
|----------------|--------------------|----------------------|
| Data point | 6px radius, line color | 8px radius, brighter |
| Crosshair line | --border2 (1px) | --text3 (1px) |
| Tooltip bg | --surface2 | n/a |
| Tooltip border | --border | n/a |
| Time range pill| --surface2 | --accent-muted bg |
| Active range | --accent-muted bg| --accent text |
--border-focus.outline-offset).:focus-visible).--transition-fast: 100ms ease-out; /* hover states, tooltips */
--transition-base: 200ms ease-out; /* panel slides, fades */
--transition-slow: 300ms ease-out; /* page transitions */
All transitions respect prefers-reduced-motion: reduce by collapsing to 0ms.
---
:root {
/* Surfaces */
--bg: #0f0f0f;
--surface: #1a1a1a;
--surface2: #242424;
--surface3: #2e2e2e;
--surface-hover: #2e2e2e;
--surface-active: #333333;
--surface-selected: rgba(108,99,255,0.08);
/* Text */
--text: #e8e8e8;
--text2: #a0a0a0;
--text3: #6b6b6b;
--text-disabled: #4a4a4a;
/* Accents (pastel) */
--accent: #818cf8;
--accent-hover: #93a0ff;
--accent-muted: rgba(129,140,248,0.12);
--accent-subtle: rgba(129,140,248,0.06);
--green: #6ee7b7;
--green-hover: #86efcb;
--green-muted: rgba(110,231,183,0.12);
--yellow: #fde68a;
--yellow-hover: #fef0ad;
--yellow-muted: rgba(253,230,138,0.12);
--red: #fca5a5;
--red-hover: #fdb8b8;
--red-muted: rgba(252,165,165,0.12);
/* Semantic */
--success: #6ee7b7;
--warning: #fde68a;
--error: #fca5a5;
--info: #818cf8;
/* Borders */
--border: #333333;
--border2: #444444;
--border-focus: rgba(129,140,248,0.5);
/* Readiness */
--readiness-low: #fca5a5;
--readiness-mid: #fde68a;
--readiness-high: #6ee7b7;
/* Chart: Training */
--chart-ctl: #818cf8;
--chart-atl: #fca5a5;
--chart-tsb-pos: #6ee7b7;
--chart-tsb-neg: #fca5a5;
/* Chart: Recovery */
--chart-sleep: #c4b5fd;
--chart-deep: #6366f1;
--chart-light: #a5b4fc;
--chart-rem: #c4b5fd;
--chart-awake: #fde68a;
/* Chart: Body */
--chart-weight: #fbbfb2;
--chart-bodyfat: #fdba74;
--chart-muscle: #6ee7b7;
/* Chart: Nutrition */
--chart-calories: #fde68a;
--chart-protein: #6ee7b7;
--chart-carbs: #fde68a;
--chart-fat: #fbbfb2;
/* Chart: Meds */
--chart-ozempic: #d8bfff;
/* HR Zones */
--zone-1: #7dd3fc;
--zone-2: #6ee7b7;
--zone-3: #fde68a;
--zone-4: #fdba74;
--zone-5: #fca5a5;
/* Radius */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-full: 9999px;
/* Spacing */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
--space-16: 64px;
/* Typography */
--font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
--font-mono: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
--font-regular: 400;
--font-medium: 500;
--font-semibold: 600;
--font-bold: 700;
--font-extrabold: 800;
/* Transitions */
--transition-fast: 100ms ease-out;
--transition-base: 200ms ease-out;
--transition-slow: 300ms ease-out;
}
**Spike:** SPIKE-010
**Owner:** Product Owner
**Reviewer:** Scrum Master
**Status:** Complete
**Last updated:** 2026-02-22
All criteria are UX-level, not implementation-level. Each criterion describes observable user experience, not technical behaviour. Criteria use the format AC-XXX with declarative or Given/When/Then statements.
---
**AC-001:** The readiness score card is the most visually prominent element on the Glance page, positioned at the top of the content area.
**AC-002:** The readiness score displays as a number from 0 to 100 with a clear label ("Readiness" or equivalent).
**AC-003:** The readiness score card uses colour coding to communicate state at a glance: green for good (70 to 100), amber for moderate (40 to 69), red for poor (0 to 39).
**AC-004:** Tapping or clicking the readiness score card navigates to a readiness detail view showing the full factor breakdown.
**AC-005:** A race countdown element is visible on the Glance page showing the number of days remaining until Race to the Sun (30 May 2026).
**AC-006:** The race countdown includes the race name and target date alongside the day count.
**AC-007:** Given the race date has passed, the countdown displays "Race day" or a post-race label instead of a negative number.
**AC-008:** A daily snapshot row displays exactly five KPIs: Weight, Body Fat %, Steps, Resting Heart Rate, and Form (TSB).
**AC-009:** Each KPI in the snapshot row shows its current value, unit, and a directional indicator (up, down, or stable compared to previous day or 7-day average).
**AC-010:** Each KPI card in the snapshot row is tappable, navigating to its respective domain page.
**AC-011:** Given a KPI has no data for today, the card displays a placeholder value (e.g. "--") rather than disappearing from the row.
**AC-012:** A training load chart (CTL/ATL/TSB or equivalent visualisation) is visible on the Glance page without scrolling on desktop viewports (1024px and above).
**AC-013:** The training load chart shows at minimum the last 6 weeks of data by default.
**AC-014:** Tapping or clicking the training load chart navigates to the Training domain page.
**AC-015:** Every data card on the Glance page is interactive. Tapping or clicking navigates to the relevant domain page or detail view.
**AC-016:** Interactive cards provide a visual hover state on desktop and a pressed state on touch devices to confirm interactivity.
**AC-017:** Every data card on the Glance page includes a freshness indicator showing the time of the last data update.
**AC-018:** Given data is older than 48 hours, the freshness indicator is visually distinct (amber or warning colour) to flag staleness.
---
**AC-019:** The readiness score is displayed as a prominent numeric value (0 to 100) with a circular or arc gauge visualisation.
**AC-020:** The score uses a three-tier colour system: green (70 to 100), amber (40 to 69), red (0 to 39).
**AC-021:** A short text label accompanies the score describing the state in plain language (e.g. "Good to go", "Take it easy", "Rest day recommended").
**AC-022:** Below the score, a factor breakdown section lists each contributing factor: Sleep Quality, Resting Heart Rate, Training Strain, Consistency.
**AC-023:** Each factor shows its individual contribution as a bar, percentage, or similar proportional indicator.
**AC-024:** Each factor row is tappable, navigating to the relevant domain detail for that metric.
**AC-025:** When one or more contributing data sources are missing or stale, the readiness score displays a confidence indicator (e.g. "Based on 3 of 4 inputs").
**AC-026:** The confidence indicator clearly names which data sources are missing so the user understands the gap.
**AC-027:** Given no contributing data sources have data for today, the readiness score area displays a friendly empty state explaining what data is needed to generate a score.
**AC-028:** The empty state includes guidance on which data sources to connect or sync to enable the score.
---
**AC-029:** The Training page displays a CTL/ATL/TSB chart as its primary visualisation.
**AC-030:** The CTL/ATL/TSB chart supports time range controls: 4 weeks, 8 weeks, 12 weeks, 6 months, or 1 year.
**AC-031:** The chart highlights the Race to the Sun date (30 May 2026) as a vertical marker with a label.
**AC-032:** Below the chart, a list of recent activities shows date, type, duration, distance, and suffer score for each.
**AC-033:** Each activity in the list is tappable, navigating to the ride detail drilldown.
**AC-034:** Summary metrics at the top include: weekly volume, current CTL, current ATL, current TSB.
**AC-035:** The Recovery page displays a sleep summary card showing last night's total sleep, sleep score, and bed/wake times.
**AC-036:** The sleep summary card is tappable, navigating to the sleep detail drilldown with full hypnogram.
**AC-037:** A resting heart rate trend chart shows at minimum the last 30 days of RHR data.
**AC-038:** Recovery signals are displayed as a summary section including: average RHR trend direction, sleep consistency, and HRV if available.
**AC-039:** Given sleep data is unavailable, the Recovery page shows an empty state for the sleep card while still displaying HR data if available.
**AC-040:** The Body page displays a weight trend chart showing at minimum 30 days of data by default.
**AC-041:** Body composition metrics are displayed alongside weight: body fat %, muscle mass, bone mass, body water %.
**AC-042:** A weekly delta section shows weight change over the last 7 days and rate of change (kg per week).
**AC-043:** The weight chart supports time range controls: 1 month, 3 months, 6 months, 1 year.
**AC-044:** Given Ozempic doses are logged, the weight chart overlays dose markers on the timeline.
**AC-045:** The Nutrition page displays a food log list showing today's entries with estimated calories and macro breakdown.
**AC-046:** A daily calorie and macro summary is visible at the top of the page.
**AC-047:** A calorie chart shows daily totals for the last 7 days as a bar chart.
**AC-048:** A weekly pattern view shows average calorie intake by day of week over the last 4 weeks.
**AC-049:** Given no food entries exist for today, the Nutrition page displays an empty state with a prompt to log a meal.
**AC-050:** The Timeline page displays a chronological annotated timeline of events spanning all data sources.
**AC-051:** Ozempic dose entries are displayed with date, dose amount (mg), and a distinct visual marker.
**AC-052:** Key events include: activities, weight milestones, medication changes, and user annotations.
**AC-053:** The timeline supports filtering by event type via toggle controls.
**AC-054:** Correlation overlays allow viewing two metrics together on the timeline.
---
**AC-055:** Given the user is on the Glance page, tapping any card navigates to the relevant Domain page.
**AC-056:** Given the user is on a Domain page, tapping a chart, metric, or list item navigates to the relevant Detail drilldown.
**AC-057:** Given the user is on a Detail view, tapping back returns to the Domain page, not the Glance page.
**AC-058:** A breadcrumb trail is visible on Detail pages showing the navigation path.
**AC-059:** Each breadcrumb segment is clickable, allowing the user to jump to any ancestor level.
**AC-060:** A back button or arrow is always visible on Detail pages.
**AC-061:** The current page is visually highlighted in the navigation element (sidebar on desktop, active tab on mobile).
**AC-062:** The page title updates to reflect the current view.
**AC-063:** Each Glance, Domain, and Detail view has a unique URL that can be bookmarked.
**AC-064:** Given a user navigates directly to a bookmarked URL, the page loads correctly with full context.
**AC-065:** On desktop (1024px+), navigation is a persistent sidebar with labelled domain links.
**AC-066:** On mobile (below 768px), navigation is a bottom tab bar with domain icons.
**AC-067:** On tablet (768px to 1023px), navigation adapts appropriately per orientation.
---
**AC-068:** Displays a full hypnogram showing sleep stages (REM, light, deep, awake) across the night.
**AC-069:** Sleep stage totals shown as breakdown with duration and percentage for each stage.
**AC-070:** A sleep quality score is displayed if available from the data source.
**AC-071:** Bed time and wake time are displayed with total time in bed and total sleep time.
**AC-072:** Displays a daily heart rate timeline showing all recorded HR samples.
**AC-073:** HR zones are visualised as a summary showing time spent in each zone.
**AC-074:** A resting heart rate trend line covers at minimum the last 30 days.
**AC-075:** Given an activity occurred during the day, the HR timeline highlights the activity period.
**AC-076:** Displays the full CTL/ATL/TSB chart with all available historical data.
**AC-077:** Training phase markers are displayed on the chart if phases are defined.
**AC-078:** The Race to the Sun target date is marked on the chart.
**AC-079:** Hovering or tapping a point shows a tooltip with exact CTL, ATL, and TSB values.
**AC-080:** Displays the full weight history chart with all available data points.
**AC-081:** Body composition data is displayed alongside or below the weight chart.
**AC-082:** Given Ozempic doses are logged, an Ozempic overlay shows dose dates and amounts.
**AC-083:** Weight milestones or targets are displayed on the chart if defined.
**AC-084:** Displays a stats grid: distance, duration, elevation gain, average speed, average HR, average power, suffer score.
**AC-085:** A heart rate chart for the ride is displayed showing HR over the duration.
**AC-086:** Given power data is available, a power chart or zones summary is displayed alongside HR.
**AC-087:** The ride title, date, and route name are displayed at the top.
---
**AC-088:** All views are fully functional at phone widths (320px to 479px).
**AC-089:** All views are fully functional at tablet widths (480px to 1023px).
**AC-090:** All views use their full layout at desktop widths (1024px and above).
**AC-091:** All interactive elements have a minimum touch target of 44x44px on viewports below 768px.
**AC-092:** Charts resize fluidly without horizontal scrolling.
**AC-093:** Given orientation changes, charts re-render within 1 second.
---
**AC-094:** Given a data source has never been connected, relevant cards display a friendly empty state.
**AC-095:** Given data is older than 48 hours, a freshness warning is displayed.
**AC-096:** Given a data fetch fails, the affected section shows an error state with retry action.
**AC-097:** Errors are isolated per section; other sections continue to display normally.
**AC-098:** Loading states use skeleton placeholders that match the loaded content layout.
---
**AC-099:** All text meets WCAG AA contrast ratios (4.5:1 body text, 3:1 large text) on the dark background.
**AC-100:** Colour is never the sole means of communicating information. Labels supplement all colour coding.
**AC-101:** All charts include a text summary or description for screen reader users.
**AC-102:** All interactive elements are reachable via keyboard (Tab, Enter, Space, Arrow keys).
**AC-103:** Focus indicators are visible on all interactive elements when focused via keyboard.
**AC-104:** Heading hierarchy is logical and sequential with no skipped levels.
---
| Area | Criteria Range | Count |
|------|---------------|-------|
| Glance Page | AC-001 to AC-018 | 18 |
| Readiness Score | AC-019 to AC-028 | 10 |
| Domain Pages | AC-029 to AC-054 | 26 |
| Navigation and Disclosure | AC-055 to AC-067 | 13 |
| Detail Drilldowns | AC-068 to AC-087 | 20 |
| Responsive Behaviour | AC-088 to AC-093 | 6 |
| Empty and Error States | AC-094 to AC-098 | 5 |
| Accessibility | AC-099 to AC-104 | 6 |
| **Total** | | **104** |