# 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 `monoDigits` is 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 — retain `monoDigits` layered 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 1. Update `theme.dart`'s `ripprColors`/`ColorScheme` to the Modern Professional Dark values (ground, surface, cards, primary/secondary/tertiary, outline). 2. Update `bodyFont`/`headlineFont`/`labelFont` to Inter throughout; keep `monoDigits` as a distinct style applied specifically to numeric displays, unchanged in spirit from today. 3. Update `roundness` usage (button/card corner radii) from 4px to 8px. 4. 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. 5. 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. 6. **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 - [ ] `ripprColors` matches Modern Professional Dark's token values - [ ] Every screen using `Theme.of(context).colorScheme` picks 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) - [ ] `monoDigits` still applies to every numeric display - [ ] Mounted mode re-verified against the new brand direction ## Tests - All of V3-16's `theme_test.dart` contrast 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`/`displayColor` wiring that bug came from originally. Do not remove the explicit color-naming discipline while restyling. - Grep for hardcoded hex literals from the old palette (`0xFFFF5722` and 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.