Same shape as docs/v3/: Goal/Context/Design/Implementation/Acceptance/Tests/Risks/Out-of-scope, written before implementing. UI-01: persistent 4-tab shell (StatefulShellRoute) replacing the current push/pop stack rooted at Record, with a single shared background map dimmed behind every tab and no header anywhere. UI-02: animated skeleton map for the no-cache/no-network case, since the map is now a permanent background presence rather than opt-in per screen. UI-03: shared GlassPanel/FloatingPill/PulsingLocationMarker component kit. UI-04: draggable, resizable HUD telemetry widgets with a Settings visibility toggle -- split out from the screen redesign itself since it's a genuinely separate piece of engineering (a small widget-layout system, not a reskin). UI-05: Map HUD/Record screen redesign -- the design north star every other screen ticket restyles toward. UI-06: Plan & Route Planning -- correct in principle, explicitly restyled toward UI-05 rather than copying the Stitch export's drifted styling. UI-07: Rides History -- live dimmed map background (not the mockup's static image), search/filter, real per-ride map thumbnails, and real distinct summary stats (fixing the export's 4-identical-cards generation artifact). UI-08: theme migration to Modern Professional Dark, superseding V3-16's safety-orange direction. README documents the dependency order, and two categories worth keeping separate: what was named explicitly by the person commissioning this (map-on-every-tab, no header, offline skeleton, customizable HUD) versus what the mockups themselves got inconsistent (nav icon count, duplicate summary cards, wrong active-tab highlight) and should not be copied as intentional.
5.6 KiB
UI-08 — Theme migration to Modern Professional Dark
Depends on nothing · Size S · Status Not started
Goal
Replace theme.dart's current safety-orange palette with "Modern Professional Dark" —
the design system actually backing every fetched Stitch screen — so every screen ticket
in this set has one settled palette to build against instead of guessing or patching
colors per screen.
Context
V3-16 (last shipped) deliberately kept and refined the original safety-orange-on-warm-
charcoal identity, with an instrument-blue tertiary for reference readings. That work is
good and tested, but it is not the palette the Stitch mockups use — confirmed by
hex-matching every color in the four fetched screens' HTML against all three design
systems in the Stitch project (docs/design/stitch-export/README.md). If this redesign
ships, V3-16's direction is superseded, not extended.
Full spec: docs/design/stitch-export/design-system-modern-professional-dark.md.
Design
- Ground: deep dark gray
#0a0a0c(not pure black — "a true premium feel without the harshness of pure black," per the design system's own doc), stepped up through#131313(surface) and#16161a(cards) for elevation. - Primary: Professional Blue — rendered as
#4090fe(container) /#aac7ff(on-dark-surface primary) /#002f64(on-primary text). This replaces safety-orange as the accent everywhere: live telemetry, active nav indicator, primary buttons, the user's own location dot. - Secondary/tertiary: muted slate-blue (
#aec7f6/#2e476f) and a warm orange (#ffb68c/#e3711f) reserved for tertiary accents (the design system's own spec doesn't define a strict "reference vs. live" split the way V3-16's tertiary did — decide during implementation whether to keep that instinct using this palette's secondary color, or drop it; either is defensible, but pick one and apply it consistently rather than leaving it ambiguous per screen). - Typography: Inter, exclusively, for every role (headline/body/label) — this drops
the multi-font split V3-16 and the original theme used (monospace for numbers via
monoDigitsis a separate, orthogonal decision from V3-16 worth keeping regardless of which color palette wins, since "digits must not jitter" is a real constraint, not a branding choice — retainmonoDigitslayered under Inter-family theming). - Shape: 8px rounding (
ROUND_EIGHT), up from the current 4px. - Depth: tonal layering + a soft blue glow on elevated/active elements, no shadows — matches V3-16's existing "no shadows, translucency for depth" instinct, just with a different accent color for the glow.
- Contrast: the design system's own doc claims AAA-level contrast for functional
text against the dark backdrop — verify this the same way V3-16 did (a
contrastRatio()helper and real assertions), don't take the claim on faith.
Implementation
- Update
theme.dart'sripprColors/ColorSchemeto the Modern Professional Dark values (ground, surface, cards, primary/secondary/tertiary, outline). - Update
bodyFont/headlineFont/labelFontto Inter throughout; keepmonoDigitsas a distinct style applied specifically to numeric displays, unchanged in spirit from today. - Update
roundnessusage (button/card corner radii) from 4px to 8px. - Re-run V3-16's
contrastRatio()assertions against the new palette; adjust any color that fails AA before shipping, exactly as V3-16 did for the palette it replaces. - Decide and document the reference-vs-live color convention (see Design) rather than leaving V3-16's tertiary-for-reference-readings instinct undecided under the new palette.
- Mounted mode (V3-05) needs its own pass, not an automatic inheritance — it's a separate high-contrast daylight theme with its own palette, tuned against a real sunlight/visor constraint. Confirm it still holds up in spirit (still legible, still AA-compliant) under the new brand direction; V3-13's real-ride verification is still the only way to confirm the actual sunlight legibility claim, same caveat V3-16 already recorded.
Acceptance criteria
ripprColorsmatches Modern Professional Dark's token values- Every screen using
Theme.of(context).colorSchemepicks up the new palette with no per-screen hardcoded color left over from the old theme contrastRatio()assertions pass against the new palette (AA normal/large, same thresholds V3-16 established)monoDigitsstill applies to every numeric display- Mounted mode re-verified against the new brand direction
Tests
- All of V3-16's
theme_test.dartcontrast assertions, re-pointed at the new color values, still pass - The existing black-on-black regression guard (
text is legible against the dark ground) still passes - Widget: a representative sample of screens render with the new palette (no leftover hardcoded orange/old-tertiary-blue literals)
Risks
- Regressing the black-on-black guard is the named risk V3-16 itself called out —
this ticket touches the same
textTheme/bodyColor/displayColorwiring that bug came from originally. Do not remove the explicit color-naming discipline while restyling. - Grep for hardcoded hex literals from the old palette (
0xFFFF5722and friends) across the UI layer before considering this done — a few call sites (e.g.RideMap's speed gradient) reference specific hex values directly rather than through the theme, and those need a deliberate decision, not an accidental miss.
Out of scope
Any screen-specific redesign (UI-05/06/07) — this ticket only changes the token layer those screens then build against.