Skip to content

v1.10 — Visual Evolution

Recreate the next visual language for Objectuve — defined by five HTML mockups (Onboarding desktop+mobile, Meet Coach desktop+mobile, Dashboard) — across three live surfaces, then audit and update the rest of the Storybook component library to match. Token-accurate, not pixel-perfect. No new product features.

Summary

Five HTML mockups landed on OBJ-43 on 2026-04-25 with a refined evolution of the existing visual language: refreshed dashboard composition, restyled onboarding chrome, restructured Meet Coach. Shipping the three surfaces alone would have left the rest of the app visually inconsistent — so v1.10 paired the three live-surface phases with a whole-Storybook sweep across every other component family.

The milestone shipped in 10 phases, 13 plans, and 47 tasks: a foundation-tokens phase (39), three live-surface phases (40 onboarding, 41 meet coach, 42 dashboard), a Storybook library audit (43), five family sweeps (44 goal, 45 communities, 46 achievements, 47 modals & overlays, 48 chrome), plus this final docs phase. Two micro-tasks rode along as standalone PRs: an m3 TodayActions tap-target fix and an m1+m2+n1 follow-up on the --warning token contrast post-Phase-44. The v1.9 Goal Roadmap milestone was merged into the milestone branch mid-flight via a true --merge topology.

The headline finding from Phase 39 set the shape of the milestone: zero tokens-new. Desi's foundation-tokens analysis confirmed the five mockups exercise only canonical tokens already in tailwind.config.js, tailwind.css, and docs/brand/brand.md. Every subsequent phase was therefore a token-migration phase, not a token-introduction phase. The two new tokens that did land — --warning (Phase 44) and --rarity-* (Phase 46) — were introduced in service of removing inline hex literals from existing component code, not in service of the mockups.

The milestone closed with no outstanding DESIGN-DRIFT: findings, every needs-update component shipped or formally deferred (the Streamlined dashboard sub-tree is documented as a v1.11 deferral), and all 8 BadgeModal contrast pairs (4 rarity tiers × 2 modes) measuring ≥4.5:1 AA Normal after a two-pass contrast methodology refinement.

Goal

Recreate the next visual language for Objectuve across three live surfaces (Onboarding, Meet Coach, Dashboard), then audit and update the rest of the Storybook component library to match. Token-accurate, not pixel-perfect. No new product features.

Scope — What Shipped

Foundation tokens (Phase 39, 61a69503)

  • Five mockups (Dashboard, Onboarding desktop+mobile, Meet Coach desktop+mobile) ingested and committed as version-history originals at .planning/milestones/v1.10/mockups/.
  • 30 reference screenshots captured via scripts/capture-mockups.mjs (5 mockups × 3 viewports × 2 modes).
  • Three UI-SPECs published: dashboard-UI-SPEC.md, onboarding-UI-SPEC.md, meet-coach-UI-SPEC.md — each with state catalog, microcopy table, tokens-used: + tokens-new: lists, DESIGN-DRIFT: flags, INFERRED: markers, and a screenshot grid for 1440 / 768 / 375 × light + dark.
  • tokens-DELTA.md synthesized the three specs and returned the headline finding: zero tokens-new, zero brand-defining escalations. The token-only PR that Phase 39 was originally scoped against collapsed to a no-op verification + phase-closure commit.
  • 13 brand-voice rewrites flagged for Josh's pass-through (e.g. Dashboard stale-goal CTA UpdateLog progress; Meet Coach selection pill SELECTEDPICKED; Onboarding aria-label Slide {n} of {total}Step {n} of {total}). Default rule was ship-as-rewritten; the rewrites consolidate in the per-surface UI-SPEC microcopy tables.

Onboarding surface (Phase 40, cd55502d)

  • WelcomeLayout, SlideWizardLayout, and the five user-facing slides (WelcomeSlide, PersonaSlide, GoalTypeSlide, SourceSlide, DoneSlide) reskinned to the v1.10 visual language.
  • New step-indicator chrome on SlideWizardLayout; redesigned WelcomeIntro with section-preview list (1–3 The goal · 4–5 Your why · 6–10 Your Coach); per-slide token swap; DoneSlide punch-up.
  • The v1.8 slide framework (useOnboardingFlow, slide registry, StoreOnboardingState, validation hooks) is preserved verbatim. Phase 40 is a visual layer only change — no structural rework of the onboarding contract.

Meet Coach surface (Phase 41, 92c501e8)

  • Three-column desktop layout (step rail · main · live preview), single-column mobile with a bottom-pinned CTA.
  • Six persona cards extracted from MeetCoach.vue and PersonaSlide.vue into a standalone coach/PersonaCard.vue, reused by onboarding's PersonaSlide.
  • coach/CoachToneSlider.vue, coach/CoachFrequencyChips.vue, coach/CoachPreview.vue extracted from MeetCoach.vue inline markup as standalone Storybook-shippable components.
  • The v1.2 Coach contract (18 unique persona/tone preambles, WCAG 2.1 AA, reduced-motion + dark-mode parity) is preserved.
  • Screen-reader handoff added on persona change: preview pane aria-live="polite" with 200 ms debounce.

Dashboard surface (Phase 42, 28977b84)

  • Header chrome, four stat tiles, "Today's practice" focus list, week-shape chart, upcoming events list, stale-goal nudge, and a "From the Sage" coach card.
  • Three components extracted from Dashboard.vue inline markup as standalone Storybook entries: dashboard/WeekShapeChart.vue, dashboard/UpcomingEventsList.vue, dashboard/StaleGoalAlert.vue.
  • Empty / loading / error / mobile / dark / motion-reduced states specified for every new component.
  • Microcopy in voice: "Three small things. Pick one to begin." (practice subhead), "You're 4 of 7. Wednesday is your strongest day — keep it light." (week caption).

Storybook library audit (Phase 43, 8c1fd432)

  • Every component in ionic_frontend/src/components/ (137 components, 107 story files) classified consistent / needs-update / out-of-scope against the v1.10 visual language across a 6-axis rubric (tokens, surfaces, typography, dark mode, accessibility, brand voice).
  • Result: 34 consistent, 88 needs-update, 15 out-of-scope.
  • Sweep recommendation: 5 family-aligned phases (44 Goal, 45 Communities, 46 Achievements, 47 Modals & Overlays, 48 Chrome) covering the 88 needs-update components. Orion adopted the recommendation as-is.
  • Every out-of-scope row carries an explicit ship-or-defer rationale: 4 orphans (Phase 44 deletes), 10 streamlined-dashboard sub-tree (v1.11 deferral), 1 EmailVerificationBanner (Phase 48 — re-classified at Phase 48 firm-up to DELETE because the file is a 13-line <div v-if="false"> no-op stub, not a renderable banner; see audit erratum NIT 5 below).

Goal surfaces sweep + --warning token (Phase 44, f8314227; follow-up acb636e8)

  • All 18 Goal-family components reskinned: src/components/goal/* + root Goal*.vue + MilestoneManager.vue.
  • 4 orphans deleted: dashboard/DashboardStats.vue, dashboard/WeeklyActivity.vue, dashboard/ActionHub.vue, dashboard/TodaysHabits.vue (8 files including .stories.ts siblings). Audit's "needs-update + consolidation candidate" classifications resolved to delete after firm-up grep confirmed zero production consumers.
  • ui/GoalCard.vue (duplicate of root GoalCard.vue) consolidated and deleted.
  • --warning token added to tailwind.config.js, tailwind.css, and docs/brand/brand.md (light: 38 92% 50%; dark: 38 92% 60%; foreground: --warning-foreground). dashboard/GoalGridCard.vue bg-amber-500bg-warning migration on needs-attention state. Cosmetic Dashboard layout pass folded in.
  • The follow-up PR (acb636e8) bumped the --warning token contrast (m1), added missing dark-mode story variants (m2), and corrected a token-block claim in 44-VALIDATION.md (n1).

Mid-flight v1.9 master merge (1d97189d)

  • v1.9 Goal Roadmap (PR #357) shipped to master and was merged into the milestone branch via a true --merge (not squash, topology preserved). Brought 3 net-new components (RoadmapBuilder, RoadmapTimeline, RoadmapProgressBar) into the milestone tree.
  • Audit re-classification at firm-up: all 3 Roadmap* components are consistent against the v1.10 visual language — they shipped on canonical tokens. Two minor RGB drift findings folded into Phase 47 ride-along.

Communities sweep + 4 orphan deletions (Phase 45, 2083539f)

  • 18 Communities-family components reskinned across communities/, community/ (singular), and root-level community surfaces.
  • 4 orphans deleted: community/CommunityCard.vue + spec, root CommunityFeedItem.vue + story, root CommunitySuggestionItem.vue + story.
  • Story files added for 6 components missing them: communities/MyCommunityCard, community/CommunityFeedCard, community/CommunityAbout, community/CommunityFeed, community/CommunityGoals, community/CommunityMembers.
  • Phase 45 m1 (4 missing WithCommunit*Context integration variants on story files) and n1 (#e5e7eb story-only inline hex on MemberProfileModal) deferred to Phase 47 ride-along — both surfaces were already inside the modal-sweep scope.

Achievements sweep + --rarity-* token system (Phase 46, 25a6e112)

  • 7 visible Achievements-family components reskinned (AchievementCard, AchievementCelebration, AchievementFilters, AchievementsGrid, AchievementStats, ShowcaseSelector, UserRankCard). AchievementWatcher excluded as renderless (<span v-if="false" />).
  • --rarity-common, --rarity-rare, --rarity-epic, --rarity-legendary tokens added (each with foreground variant) — anchored to brand canon (--coach for epic, --gold for legendary).
  • dashboard/ShowcasedAchievements.vue migrated from inline rarity hex (#3b82f6, #a855f7, #fcc419/#d97706) to the --rarity-* token surface (closes audit n3 footnote).
  • Phase 46 R1 fix bundle adjusted three token values to clear AA Normal on the bg-card surface: --rarity-legendary-foreground dark 20%90% (M1), --rarity-rare light 60%50% (m2), --rarity-epic light 65%55% (m3). All 8 contrast pairs cleared AA on first re-measurement post-fix.

Modals & overlays sweep + ride-along bundle (Phase 47, 8216034c)

  • 17 modal/overlay components reskinned: AgreeToTermsModal, BadgeModal, ChangelogModal, StreakDetailsModal, FeedbackDetailModal, NewFeedbackModal, AcceptPartnershipModal, FindPartnerModal, ProfileCompletionModal, RoadmapBuilder, RoadmapTimeline, AchievementToast, AiCoachModal, AiInsightCard, NotificationsPanel, PushPermissionPrompt, ScreenTimeNudge.
  • BadgeModal is the canonical --rarity-* consumer: scoped CSS migrated from --ion-color-medium and inline rarity hex to hsl(var(--rarity-X) / 0.1) for backgrounds and hsl(var(--rarity-X)) (or hsl(var(--rarity-legendary-foreground)) for legendary) for text.
  • Legacy OnboardingWizard.vue (1,238 LOC modal) and its Storybook story file deleted. Reachability evidence at firm-up confirmed the mount path was reachable only via dev/testing fallback-auth — Phase 33's useOnboardingGate redirects every first-sign-in user to /welcome/* before Dashboard.vue mounts. Dashboard.vue decoupled: removed <OnboardingWizard> mount block, import OnboardingWizard, wizardOpen ref, watch(isFirstSignIn, …) block, handleWizardClosed() handler, and the now-unused isFirstSignIn destructuring from useClerkSync().
  • Ride-along bundle folded in: 5 Phase 45 story-only updates + 3 v1.9 Roadmap RGB drift NITs + 4 BadgeModal --ion-color-medium migrations.
  • Phase 47 R1 escape hatch fired: BadgeModal pass-2 contrast measurements showed 4 of 8 pairs failing AA Normal on the alpha-tinted-on---background surface (legendary-light 1.46:1 catastrophic, common dark/light + rare light all <4.5). Decisions logged in 47-DESIGN-DRIFT.md: Decision A (BadgeModal .rarity-legendary color reference change --gold--rarity-legendary-foreground, no token-value change) + Decision B m4 (--rarity-rare light 50%45%) + Decision C-1 (BadgeModal .rarity-common migrated from --ion-color-medium--rarity-common) + Decision C-2 m5 (--rarity-common light 47%42%). Pass-3 measurement: 8 of 8 pairs cleared AA Normal. Phase 46 cross-impact: 3 AchievementCard light-mode contrast measurements strictly improved; 0 regressions.

Chrome + remaining surfaces sweep (Phase 48, 9e6c5ffa)

  • 21 components reskinned across small primitives, charts, feedback surfaces, and BottomTabBar.
  • SideMenu (859 LOC) fully migrated: legacy --ion-color-* and inline orange rgba(251, 146, 60, …) swapped for hsl(var(--card) / 0.6) glass-card chrome with backdrop-filter: blur(12px), hsl(var(--accent)) for accent overlays, hsl(var(--primary))/hsl(var(--muted-foreground)) for active/inactive nav state, and font-display on labels and group separators. New 6-state Storybook grid (Expanded/Collapsed/MobileOpen × Light/Dark).
  • ui/EmailVerificationBanner.vue deleted entirely (13-line <div v-if="false"> no-op stub, not a renderable banner). Dashboard.vue mount + import removed.
  • supporter/SupporterStreakNudge dismiss button enlarged from p-1 + w-3.5 h-3.5 to p-2.5 + w-5 h-5 to clear the 44 × 44 px tap-target floor.
  • 4 net-new story files: GlobalErrorBoundary, ImageCropper, StockPhotoPicker, SupporterStreakNudge.
  • 5-item ride-along bundle from Phase 47: n2 brand.md rarity sync (2 rows mirrored from tailwind.css), n3.a/b two stale OnboardingWizard comment cleanups, n3.c Cypress real-bug fix (see "Audit-trail wins" below), n4 BadgeModal --ion-color-medium migration partial closure (3 of 9 references; 5 rgba-variant siblings forward-flagged below).

Phases

PhaseNameStatusPlansHighlights
39Foundation — Mockup Ingestion + Token LayerShipped (61a69503)15 mockups + 30 screenshots + 3 UI-SPECs + tokens-DELTA. Headline: zero tokens-new.
40Onboarding (cd55502d)Shipped3/welcome route family reskin; v1.8 framework preserved verbatim.
41Meet Coach (92c501e8)Shipped3Three-column desktop, mobile bottom-pinned CTA; 4 sub-components extracted.
42Dashboard (28977b84)Shipped3Refreshed composition; 3 inline blocks extracted as Storybook entries.
43Storybook Library Audit (8c1fd432)Shipped2137 components classified across 16 families on a 6-axis rubric.
44Goal Surfaces + --warning Token (f8314227 + acb636e8)Shipped118 reskins + 4 orphan deletes + --warning token.
45Communities + 4 Orphan Deletes (2083539f)Shipped118 reskins + 4 deletes + 6 net-new story files.
46Achievements + --rarity-* Tokens (25a6e112)Shipped17 reskins + new token system + R1 token-value calibration.
47Modals & Overlays + OnboardingWizard Delete (8216034c)Shipped117 reskins + 1,238 LOC delete + R1 contrast methodology refinement.
48Chrome + Remaining Surfaces + EmailVerificationBanner Cleanup (9e6c5ffa)Shipped121 reskins + SideMenu (859 LOC) + 1 stub delete + 4 net-new story files.
nFinal Documentation + Master-Flip GateThis phase1CHANGELOG + this narrative + brand.md polish + ROADMAP renumber + master-flip gate.

Two micro-tasks rode along as standalone PRs outside the per-phase numbering: m3 TodayActions 40 → 44 px tap-target fix (54cfb49f, between Phases 43 and 44), and m1+m2+n1 --warning follow-up (acb636e8, between Phases 44 and 45).

Key Decisions

  • Zero new tokens, zero brand-defining escalations (Phase 39). The five mockups exercise only canonical tokens. Codi's Phase 39 token-only PR collapsed to a no-op closure commit. Every subsequent surface phase was a token-migration phase, not a token-introduction phase.
  • Token-conflict policy. New tokens in mockups → propose addition (didn't trigger). Mockup deviates from existing canonical token → existing wins, flag DESIGN-DRIFT:. Mockup deviates from primary palette / fonts / type scale → escalate to Maggie → Josh (didn't trigger).
  • Surface-phase order: Onboarding → Meet Coach → Dashboard. Final shipped order differs from the original ROADMAP draft (Dashboard → Onboarding → Meet Coach). Onboarding shipped before Meet Coach so the simpler surface served as the extraction host for coach/PersonaCard.vue, which both surfaces consume. Dashboard shipped last because it had the most extracted components (3 standalone Storybook entries). The ROADMAP renumber + as-shipped-order narrative reconciliation is the closure step in this docs phase.
  • 5-phase Storybook sweep, no consolidation (Phase 43 → 44–48). Each family is a coherent sweep; collapsing 47 (modals, 15 components) + 48 (chrome + remaining, ~26 components) would have mixed overlay surfaces with layout primitives and hidden the --rarity-* token cross-phase dependency (Phase 46 producer → Phase 47 BadgeModal consumer).
  • Streamlined dashboard sub-tree → defer entirely to v1.11. 10 components, feature-flagged off for ≥85% of users. Definition of done satisfied via documented deferral, not via shipped reskin.
  • OnboardingWizard.vue → DELETE in Phase 47. 1,238 LOC legacy modal. Reachability evidence at firm-up: mount path reachable only via dev/testing fallback-auth (which Phase 33 useOnboardingGate documents as a no-op). Codi reconfirmed at dispatch via grep before deletion. The MODERNIZE escape hatch (split 47a/47b) didn't fire.
  • EmailVerificationBanner.vue → DELETE in Phase 48. Storybook audit §8.2 originally classified this as a 13-line renderable banner shipping in Phase 48. Phase 48 firm-up FINDING corrected the audit: the 13 lines are a <div v-if="false"> no-op stub. Reskin would have been pointless; DELETE was the chosen call.
  • SideMenu.vue (859 LOC) folded into Phase 48, not split as 48b. Default fold-in path; the split escape-hatch (effort sum >1500 LOC or structural rework discovered) didn't fire because the migration was pure token-substitution.
  • Master-flip gate is a separate, post-docs hop. v1.10 ships into gsd/v1.10-visual-evolution (milestone branch) phase-by-phase; the milestone-branch → master merge fires after this final docs phase ships, gated on Josh's visual approval against a preview deploy. Encoded in this document as "Master-flip gate" below; authority 4ab6d91d.

Audit-trail wins worth surfacing

  • Contrast-measurement methodology evolution (Phases 46 → 47 → 48). The 8 BadgeModal contrast pairs tell a three-act story:

    1. Phase 46 measured rarity contrast on bg-card (the AchievementCard surface) and adjusted three token values via R1 (M1 + m2 + m3) to clear AA Normal on first re-measurement.
    2. Phase 47 introduced BadgeModal as a --rarity-* consumer on a different surface — alpha-tinted hsl(var(--rarity-X) / 0.1) over hsl(var(--background)). Pass-2 measurement found 4 of 8 pairs failing because the BadgeModal surface is slightly more saturated than bg-card. R1 escape hatch fired again: Decision A swapped a token reference (--gold--rarity-legendary-foreground for legendary text — Codi pass-2 had reached for the brand-canonical token but the canonical token for legendary text is the foreground variant), Decision B m4 darkened --rarity-rare light another 5pp, Decisions C-1 + C-2 m5 migrated .rarity-common to the family token and darkened it 5pp. Pass-3 measurement: 8 of 8 cleared. 47-DESIGN-DRIFT.md was the cleanest audit artifact of the milestone — Roy's Phase 47 review specifically called it out.
    3. Phase 48 re-measured the AchievementCard cross-impact with refined methodology — alpha-compositing the actual scoped-CSS rarity tint over bg-card rather than treating bg-card as the simplified solid surface. Codi's numbers (common-light 4.95, rare-light 5.14) differ from Roy's Phase 47 numbers (5.65, 5.98) not because of regression but because Codi's compositing math is more accurate. Both methodologies pass AA Normal. No regression; better precision.

    Net result: every --rarity-* consumer surface (BadgeModal alpha-tint-on-background, AchievementCard alpha-tint-on-card, ShowcasedAchievements solid-on-card) now measures ≥4.5:1 AA Normal across light + dark, and the methodology for measuring rarity contrast is documented for future authors.

  • R1 escape hatch validated as a milestone-rhythm primitive. Phase 46 set the precedent (token-value adjustment after WCAG re-measurement) and Phase 47 inherited it cleanly. The 46-PLAN.md §T5 precedent, 47-DESIGN-DRIFT.md decision log, and Phase 48 R1-blessed token-value adjustments form a consistent pattern: when contrast fails on a measured surface, propose the smallest fix that holds (token reference vs. token value), document predicted cross-impact, re-measure post-fix, log the decision.

  • Phase 47 → 48 ride-along chain. Roy's 4 NITs from Phase 47 (n1 BadgeModal contrast monitor, n2 brand.md mirror, n3.a/b/c stale OnboardingWizard refs, n4 BadgeModal --ion-color-medium migrations) all flowed forward to Phase 48 T1 first commit. The ride-along bundle hit before Phase 48's main reskin work started, which kept the Phase 48 main diff clean. This pattern (NITs ride along on the next phase's first commit when scope-aligned) became a milestone-rhythm primitive too.

  • Phase 48 n3.c Cypress real-bug fix. After Phase 47 deleted OnboardingWizard.vue, the assertion cy.get('ion-modal').should('exist') in tests/e2e/dashboard-states.cy.ts was passing spuriously — the test was finding a different ion-modal instance and reporting green. Phase 48 ride-along caught it during the n3.c cleanup pass and replaced the assertion with cy.url().should('include', '/welcome/') — which actually exercises the Phase 33 useOnboardingGate redirect that supersedes the deleted wizard. A stale assertion surviving a DELETE is a recurring class of bug; documenting the catch here so future DELETEs trigger an assertion audit.

  • Audit-count erratum consolidation (NITs 1–6). Six audit-count NITs accumulated across Phases 44 → 48 in STORYBOOK-AUDIT.md. Each was a small classification or count drift surfaced by a dispatch-time re-grep or firm-up; none were ship-blockers; all are documented in the per-phase VALIDATION docs and consolidated in the Tech Debt section below.

Brand-voice rewrites that shipped

Per the v1.10 brand-voice contract, every user-facing string in the three mockups passed through a coach-who's-also-a-friend voice check. Mockup copy that violated voice was rewritten in the UI-SPEC microcopy table; the rewrites shipped as the canonical strings (default rule, with a Josh confirmation pass that returned no overrides). Representative rewrites:

  • Dashboard stale-goal CTA: UpdateLog progress
  • Dashboard error state: We could not load your dashboard…Connection's spotty. Try once more — your data's fine.
  • Meet Coach step labels: Step 1 / Step 2 / Step 3Pick a voice / Tune the tone / Pick the rhythm
  • Meet Coach selection pill: SELECTEDPICKED
  • Onboarding aria-label: Slide {n} of {total}Step {n} of {total} (matches the new STEP/N mental model)

The full microcopy tables live per-surface in the UI-SPECs at .planning/milestones/v1.10/.

Outcomes

  • Three live surfaces (Onboarding, Meet Coach, Dashboard) ship the next visual language to production after the master-flip gate clears.
  • Every other component family (Goal, Communities, Achievements, Modals & Overlays, Chrome) is reskinned to match.
  • Two new tokens (--warning, --rarity-*) added in service of removing inline hex literals from existing components — neither was a brand evolution.
  • 10 components deleted entirely (OnboardingWizard, EmailVerificationBanner, 4 dashboard orphans, 4 community orphans + duplicates) — a cumulative ~2,300 LOC of dead or stub code removed.
  • 9 net-new Storybook entries (5 from Phase 39/41/42 component extractions + 4 Phase 48 net-new stories) plus 6 community story-coverage gap closures.
  • All 8 BadgeModal contrast pairs (4 rarity tiers × 2 modes) measure ≥4.5:1 AA Normal. The --rarity-* token system is anchored to brand canon and consumed consistently across BadgeModal, AchievementCard, ShowcasedAchievements, AchievementToast, and UserRankCard.
  • Storybook library is fully classified; the 88 needs-update rows from the audit are now 0 (everything shipped or formally deferred).

Tech Debt

Forward-flagged items for v1.11 / Phase 49+ — none are ship-blockers for v1.10:

  • --primary light-mode active-state contrast. Two surfaces in Phase 48 measure --primary-on---background at light-mode contrast values 0.03–0.15 below AA Normal: SideMenu active-nav 4.47:1 and BottomTabBar active-tab 4.35:1. These are pre-existing conditions tied to the design-system --primary token (HSL(203, 78%, 41%)), not introduced by Phase 48. The --primary HSL is identical between origin/gsd/v1.10-visual-evolution and the Phase 48 squash tip — confirmed via diff inspection. Phase 49+ design-token pass candidate: introduce a --primary-interactive: 203 78% 38% (3 percentage-point darken) to clear AA on active states without disturbing the brand-defining primary blue. Or accept the active-state contrast as a documented design-system limitation and rely on the 4.5:1 floor on the larger contact points (active-nav text uses 12 px / font-medium which qualifies as Normal under WCAG 2.1).

  • BadgeModal.vue var(--ion-color-medium-rgb) rgba siblings (5 lines). Phase 48 closed the n4 NIT for the 3 solid var(--ion-color-medium) references but the 5 rgba-variant siblings (lines 284, 285, 353, 355, 431) — used for alpha overlays on locked-badge dashed border / status-locked bg / quote-text bg — were not in the n4 scope. Translation pattern is rgba(var(--ion-color-medium-rgb), N)hsl(var(--muted-foreground) / N). Recommend: Phase 49 polish or v1.11 backlog. Trivial fix; not regression-prone.

  • UiTooltip story-file naming (audit erratum NIT 6). The file is named ui/tooltip/Tooltip.stories.ts rather than the conventional UiTooltip.stories.ts. Recommend: v1.11 cleanup pass alongside any other story-file naming standardization.

  • Pulse-glow keyframe duplication. ShowcasedAchievements, AchievementCard, and BadgeModal each define their own @keyframes pulse-glow. Phase 46 preserved per-component duplication verbatim (modulo rgba-to-CSS-var swap) to avoid scope creep. Recommend: v1.11 backlog cleanup — extract to a shared keyframe declaration in tailwind.css or a shared utilities file. Cosmetic; not regression-prone.

  • AllyActivityFeed.vue prop extraction (Codi follow-up from Phase 45). Refactor, not visual. Recommend: v1.11 backlog.

  • GoalGridCard.vue multi-color theming (Phase 44 §12.1). Blocked by Phase 44's zero-touch on goal-color-* semantics. Recommend: v1.11 backlog.

  • 2 Phase 40 ride-along NITs. Dead slideNext provider on WelcomeView.vue (orchestrator), missing emit-forwarding test on SlideWizardLayout (test parity). Out of audit scope (src/views/, not src/components/). Recommend: v1.11 backlog or fold into a dedicated test-coverage hop.

  • 3 Phase 42 v1.11 deferrals. Richer WeekShapeChart percent computation (currently binary 0/100% per day); multi-stale-goal +N more pill on StaleGoalAlert; richer Streamlined sub-tree reskin (when the streamlined dashboard family ships). Recommend: v1.11 backlog.

  • Streamlined dashboard sub-tree (10 components). Documented v1.11 deferral per audit §8.1 + Phase 43 ROADMAP entry.

  • 7 moderate Dependabot vulnerabilities on master. Carried from Phase 47 §10. Recommend: Riley triage track when queue is quiet — separate from v1.10 docs.

Audit-count errata (NITs 1–6)

STORYBOOK-AUDIT.md accumulated six small classification or count drifts across Phases 44 → 48. None affect §4 component-by-component tables (those remain authoritative). Documented here so the audit history is honest:

  • NIT 1 (Phase 44, audit cosmetic). TL;DR needs-update: 88 vs. validation appendix 90/90. The §4 tables are authoritative; the TL;DR count rolls forward as 88 (post-orphan-delete + post-TodayActions-upgrade).
  • NIT 2 (Phase 44, audit cosmetic). §2 family-count subheadings sum to 136 vs. claimed 137. find confirms 137 components; the 1-component delta is a subheading-rollup miscount. §4 tables are authoritative.
  • NIT 3 (Phase 45, audit re-classification). 4 Communities components classified needs-update + consolidation candidate resolved to delete after firm-up grep confirmed zero production consumers.
  • NIT 4 (Phase 47, audit cosmetic). OnboardingWizard.vue rows in §2.11 + §4.7 reference the same file but were category-summed twice. The DELETE call applies once.
  • NIT 5 (Phase 48 firm-up FINDING). STORYBOOK-AUDIT.md §8.2 EmailVerificationBanner recommendation ("ship in Phase 48 as a 13-line banner") corrected — the 13 lines are a <div v-if="false"> no-op stub, not a renderable banner. DELETE was the chosen call.
  • NIT 6 (Phase 48 firm-up FINDING). STORYBOOK-AUDIT.md §4.9 ui/tooltip/UiTooltip row implicitly assumed conventional UiTooltip.stories.ts naming; actual story file is ui/tooltip/Tooltip.stories.ts (non-conventional). Rename in v1.11 cleanup pass per §"Tech Debt" above.

Master-flip gate

Authority: Josh decision 4ab6d91d — the v1.10 milestone branch must NOT merge to master until a preview-deploy URL is built from the post-docs squash tip and Josh comments "approved" against the gate-coordination thread on OBJ-43. The visual-approval gate is brand-defining; agents do not auto-promote.

Operator: Vicki — dispatched by Maggie after this final docs phase squash-merges into gsd/v1.10-visual-evolution.

Signer: Josh — visual approval required against the preview deploy.

Pre-flight checklist (Vicki executes before pinging Josh):

  1. Preview deploy. Build a preview deploy from the post-docs squash tip (the new gsd/v1.10-visual-evolution HEAD after this final docs PR merges). Capture the URL with its 7-day TTL.
  2. Viewport screenshot grid. 1440 × 768 × 375 px × Light + Dark for every shipped surface:
    • Onboarding (/welcome route family — all 5 slides + chrome)
    • Meet Coach (desktop three-column, mobile single-column with bottom-pinned CTA)
    • Dashboard (header, stat tiles, focus list, week chart, upcoming events, stale-goal nudge, coach card)
    • Goal surfaces (Phase 44 — Goal page, Goal forms, Goal events)
    • Communities (Phase 45 — list, detail, members, feed, posts)
    • Achievements (Phase 46 — grid, card, celebration, filters, showcase, user rank)
    • Modals & overlays (Phase 47 — BadgeModal across all 4 rarity tiers + locked, AcceptPartnershipModal, FindPartnerModal, ChangelogModal, FeedbackDetailModal, NotificationsPanel, AchievementToast)
    • Chrome (Phase 48 — SideMenu Expanded/Collapsed/MobileOpen, BottomTabBar, MoodCheckIn, ActionAlert)
  3. Regression-check zero-touch zones. Verify the v1.2 Coach contract (18 persona/tone preambles untouched), Phase 4 PartnerWidget (zero-touch), Phase 36 GettingStartedCard (zero-touch), Phase 33 /welcome framework (zero-touch in Phase 47/48 — distinct from OnboardingWizard.vue deletion), v1.9 Roadmap zone (only the 3 RGB drift NIT lines touched in Phase 47 ride-along), Streamlined sub-tree (zero-touch — deferred to v1.11). Hard guardrails per 48-VALIDATION.md §8 already verified at Phase 48 ship; this is the sanity recheck before Josh ping.
  4. CI status. Confirm 5/5 CI checks green at the post-docs squash tip.
  5. Ping Josh on OBJ-43 with: preview URL + 7-day TTL note + screenshot grid + checklist + explicit [@Josh](mention://member/4faa60b9-6d5c-42ec-afe3-034c96f65108) ping. Hold the merge until Josh comments approved. No timeout, no auto-promote.

On approval:

  1. Squash-merge gsd/v1.10-visual-evolution → master. Use the conventional v1.10 commit-message shape (feat(v1.10): visual evolution — three live surfaces + Storybook library sweep + ChangelogModal narrative + master-flip ceremony).
  2. Tag the release. v1.10 maps to a SemVer minor bump. Per Riley's tag policy + the plan's reference to v3.7.0, the expected tag is v3.7.0. Riley confirms the exact tag at master-flip time.
  3. Production deploy. Triggered by the version tag per the standard release pipeline. Watch Sentry for ~24 h post-deploy; rollback path is rollback <prior-tag> or the emergency Cloud Run revision switch (API only, n/a for this milestone).
  4. GitHub Release. Auto-created after smoke tests; release body cites this milestone narrative and the CHANGELOG section.
  5. Delete gsd/v1.10-visual-evolution remote branch post-merge.
  6. Comment on OBJ-43 confirming master-flip + tag + deploy. Close the issue when the smoke gate passes.

Rollback plan:

  • Pre-tag: git revert <squash-sha> against master. Clean revert because v1.10 is purely visual + token migrations; no DB / state coupling.
  • Post-tag: rollback <prior-tag> re-deploys the previous release; the v1.10 tag stays on the version index for forensic reference.
  • No phase-specific rollback is needed since v1.10 is one squash merge into master, not a sequence.

Requirements Coverage

v1.10 was a visual-evolution milestone, not a requirements-driven feature milestone — the equivalent of "requirements" is the definition of done in .planning/milestones/v1.10-ROADMAP.md. All 8 must-be-true conditions hold at this final docs phase:

ConditionStatus
Three live surfaces (Onboarding, Meet Coach, Dashboard) shipped✅ Phases 40–42
Storybook library audit published; every component classified✅ Phase 43 + audit erratum NITs 1–6 documented
Every needs-update component shipped OR explicitly deferred✅ Phases 44–48 + Streamlined v1.11 deferral
tailwind.config.js and docs/brand/brand.md reflect new tokens✅ Phase 39 zero-delta + --warning (Phase 44) + --rarity-* (Phase 46)
Milestone narrative published at docs/milestones/v1.10-visual-evolution.md✅ This document
CHANGELOG entry + in-app ChangelogModal.vue copy live✅ This phase (CHANGELOG); modal auto-renders via ?raw import
No outstanding DESIGN-DRIFT: findings✅ All m-prefix and n-prefix findings closed or forward-flagged
ROADMAP shows all phases marked complete with ship dates✅ This phase
PhaseCommit / PRDescription
Openae233123Open visual evolution milestone
391a6b581c + 61a69503Foundation — UI-SPECs + tokens-DELTA + closure note
40 (Onboarding)cd55502dOnboarding visual evolution
41 (Meet Coach)92c501e8Meet Coach visual evolution
42 (Dashboard)28977b84 (PR #362)Dashboard visual evolution
438c1fd432 (PR #363)Storybook library audit
m354cfb49f (PR #364)TodayActions tap-target fix (40 → 44 px)
44f8314227 (PR #365)Goal surfaces + --warning token
44 follow-upacb636e8 (PR #366)--warning contrast bump + dark stories + doc fix
v1.9-merge1d97189d (PR #367)v1.9 Goal Roadmaps merge into milestone branch
452083539f (PR #368)Communities + 4 orphan deletes
4625a6e112 (PR #369)Achievements + --rarity-* tokens
478216034c (PR #370)Modals & overlays + ride-along + OnboardingWizard delete
489e6c5ffa (PR #371)Chrome + remaining + EmailVerificationBanner delete + Phase 47 ride-along
Final docsThis phaseCHANGELOG + this narrative + brand.md polish + ROADMAP renumber + master-flip gate

Last updated: 2026-05-22

Loading…