deckhearth/.convoys/redesign-v2-from-mockups.md
varutasu f701c4ac89
docs(convoys): mark redesign-v2-from-mockups epic shipped (8/8 sub-convoys merged) (#108)
All 8 sub-convoys from the redesign-v2 epic landed across 5 PRs
(#102#107). Updates the umbrella convoy with:

- frontmatter status: open → shipped, shipped: 2026-06-04
- § 9: table mapping each sub-convoy to its PR + squash commit
  + brief one-liner so the next agent reading .convoys/ has a
  complete audit trail
- § 9: 9 queued follow-up convoys explicitly captured (Daily
  Ember backend, rarity aggregation, wishlist feature, user
  activity feed, market data + chart library decision, featured
  collection filters, federated command palette, page-header-
  glass CSS cleanup, top-bar user dropdown). Each names the
  upstream call site (component / hook / TODO comment) so the
  follow-up author has a starting line.

Zero code changes. Lint clean. No tests touched (docs-only).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 11:24:34 -05:00

23 KiB
Raw Permalink Blame History

name classification success_metric skip status created shipped
redesign-v2-from-mockups epic When a logged-in user opens deckhearth.com/dashboard, the screen they see is recognizably the visual language of the operator's two reference mockups (saved 2026-06-04 in /Users/rstillw/.cursor/projects/Users-rstillw-Documents-Personal-Coding-Projects-tcg-vault/assets/image-d1fca5e0-cdde-4a5a-99a3-2e008408b19e.png and image-dea39822-cea5-4c33-8e58-12b43095468d.png): visible warm ember pools in the viewport corners (both themes), a bold gradient active-pill in the sidebar, a "Deck|Hearth" gradient wordmark with flame logomark, four stat cards with colored gradient icon tiles, a prominent top search bar (Cmd+K hint), a Daily Ember progress widget at the bottom of the sidebar, and a content-card grid with warm outer-glow border treatment. All eight gates green (lint, vitest, build, smoke, screenshot diff, the three forbidden-* grep gates, Vercel preview).
shipped 2026-06-04 2026-06-04

Redesign v2 — from operator mockups

Umbrella convoy that completes the Liquid Glass redesign by aligning the actual look-and-feel with the operator's two reference mockups (2026-06-04). The prior liquid-glass-redesign umbrella (PRs #95-#101, 8 sub-convoys completed) shipped the architectural foundation — design tokens, primitives, .glass-panel + .page-header-glass utilities, the layered hearth gradient, the <GlassSurface> / <Modal> / <Button> / <Input> / <SearchBar> JSX primitives. But when the operator opened the deployed product they reported "I am not seeing very many changes with the new look" and shared the two mockups linked in success_metric above. This convoy reads those mockups as the actual aesthetic spec and ships the missing pieces.

This convoy is planning-only. No source files are touched here. Each numbered sub-convoy below is its own gated PR.


1. The gap, honestly

The prior epic ships architecturally-correct CSS but visually-timid output:

Mockup shows Prior epic delivered
Bright ember pools glowing at viewport corners (both themes) 28% alpha radials that read as faint warmth, not embers
Bold gradient active-pill in sidebar with ember-orange fill + soft outer glow Thin 1px ember border-left indicator on a nearly-transparent rect
"Deck | Hearth" wordmark with flame logomark on the left "DH" monogram badge + plain text "Deck Hearth"
Stat cards with colored gradient icon tiles (gold / purple / blue / red rounded squares with white icon) Plain icon next to text inside a glass-panel
Top search bar stretched across the top with Cmd+K hint, notif bell with badge, mail icon, avatar+name+level chip Page-header-strip (.page-header-glass) with title + action button
Daily Ember progress widget at the bottom of the sidebar (flame icon, "16 / 20", progress bar, helper text) Nothing — never built
Card grid items with warm outer glow Card thumbnails sit on solid bg with default shadow
Dark theme with deep navy + visible ember corner glow + rich card chrome Dark theme exists but corner gradient is even more subtle than light
Right-rail Card Spotlight with metadata table + price chart + watchlist Not part of current dashboard at all

The operator is right. The prior epic was a foundation; this convoy is the actual visual identity layer on top of it.


2. What this convoy is NOT

  • NOT a rewrite from zero. The prior epic's tokens (--glass-surface-*, --rim-light-*, --elevation-*) and JSX primitives (<GlassSurface>, <Modal>, <Button>) are correct and reused. The .glass-panel utility stays. What changes is how those pieces compose, the gradient intensity (boost), and the addition of new primitives (<StatCard>, <DailyEmberWidget>, <TopSearchBar>, <SidebarPill>).
  • NOT a TypeScript migration. Files stay .js per Gotcha #9.
  • NOT a new dependency. No icon library, no chart library yet — if the right-rail spotlight ships in this convoy, charts come via SVG or a single recharts install gated by a separate convoy.
  • NOT a card-detail page redesign. Sub-convoy 8 ("right-rail") only sketches the layout. A full Card Spotlight rail with real price data is a downstream convoy.
  • NOT changing the canonical product features. Existing dashboard routes, queries, and content survive. This convoy re-skins the presentation; it does not rebuild the data model.

3. Hard scoping rules (inherited from liquid-glass-redesign § 3)

  • Tailwind + CSS variables only; no new CSS framework.
  • Theme tokens, not hex. Every new color reads from a :root var (or its [data-theme="dark"] override).
  • Both themes ship together per sub-convoy.
  • prefers-reduced-motion honored; new animations opt-in via .motion-essential only when functionally required.
  • AA contrast measured at the new gradient corner intensities — the ember pool MUST NOT drag bg contrast below 4.5:1 against --text-primary in the affected viewport region.
  • backdrop-filter followed the rules from PR #99's maintainer comment: literal values inside blur(), no -webkit- duplicate in source (let Lightning CSS autoprefix).
  • One sub-convoy per PR; visual diff baseline updated only when necessary and only in a Linux container (per seed-visual-baselines-on-linux queued convoy guidance — see .convoys/ship-readiness.md).

4. Dependency graph

   ┌──────────────────────────────────────────────┐
   │ 1. hearth-bg-corner-embers                   │
   │    boost gradient intensity to mockup level; │
   │    light theme: visible warm-amber corners;  │
   │    dark theme: deep navy + ember-red pools   │
   └────────────────────────┬─────────────────────┘
                            │
       ┌────────────────────┼────────────────────┐
       │                    │                    │
       ▼                    ▼                    ▼
 ┌────────────┐    ┌────────────────┐   ┌────────────────┐
 │ 2. sidebar │    │ 3. top-search- │   │ 4. stat-card-  │
 │    active- │    │    bar         │   │    primitive   │
 │    pill +  │    │    (replaces   │   │    <StatCard>  │
 │    logo    │    │    page-       │   │                │
 │            │    │    header-     │   │                │
 │            │    │    strip on    │   │                │
 │            │    │    dashboard)  │   │                │
 └─────┬──────┘    └────────┬───────┘   └────────┬───────┘
       │                    │                    │
       │                    │                    │
       └────────┬───────────┴─────────┬──────────┘
                │                     │
                ▼                     ▼
       ┌────────────────┐    ┌────────────────┐
       │ 5. daily-ember │    │ 6. card-grid   │
       │    widget      │    │    outer-glow  │
       │    (sidebar    │    │    (CardItem   │
       │    footer)     │    │    chrome)     │
       └────────┬───────┘    └────────┬───────┘
                │                     │
                └──────────┬──────────┘
                           ▼
                ┌────────────────────┐
                │ 7. dashboard-      │
                │    rebuild         │
                │    (assemble the   │
                │    above into the  │
                │    mockup layout)  │
                └─────────┬──────────┘
                          │
                          ▼
                ┌────────────────────┐
                │ 8. right-rail-     │ ← optional (scope guard)
                │    spotlight       │
                │    (Card Spotlight │
                │    sketch — no     │
                │    new deps)       │
                └────────────────────┘

Strict blockers:

  • #1 must merge before #2-7 — they all live against the new gradient.
  • #2, #3, #4 are independent and can run in parallel (multitask candidate; disjoint files).
  • #5 is independent of #2-4 but visually relies on #1; merges any time after #1.
  • #6 is independent; can run in parallel.
  • #7 is the integrator and merges last in the foundation phase.
  • #8 is gated by operator approval after #7 lands — it touches layout structure non-trivially.

5. Sub-convoys (seed brief — one paragraph each)

1. hearth-bg-corner-embers

Raise the body-gradient intensity in styles/globals.css from the current 28%/18%/16% alpha radials to mockup-level visibility. Two themes ship together. Light: amber pool ~40% alpha bottom-left, secondary amber ~25% bottom-right, gold ~20% top-right, vertical warm wash ramps from cool top to warm bottom. Dark: deep navy (#0d0a18-ish) base + ember-red pool ~55% bottom-left, secondary ember ~35% bottom-right, purple-magenta accent ~18% top-right. Add --bg-primary dark-theme value adjustment to match the mockup's deep-navy base. Acceptance: side-by-side screenshot against the mockups shows recognizably the same corner-ember treatment in both themes. Lint + vitest + build + smoke + screenshot-diff green; visual diff baseline re-seeded ONLY for the public landing page (tests/visual/homepage.spec.ts) since that's the only currently baselined surface.

2. sidebar-active-pill-and-wordmark

Replace Layout.js's current sidebar active-state (thin 1px border indicator) with a bold rounded-pill that has an ember-orange gradient fill, white icon + label, and a soft outer ember glow. Inactive items remain transparent / hover-only. Replace the "DH" monogram + "Deck Hearth" text header with: gradient flame logomark (SVG, ember gradient) on the left + "Deck" + "Hearth" wordmark where "Hearth" uses the gradient-text-flame utility so the two-tone word reads like the mockup. Acceptance: sidebar visually matches the mockup's active-pill + wordmark treatment in both themes; the existing 5 Layout regression-lock vitest assertions still pass (Sign-in CTA when null user, no maintainer email leak, etc.).

Add a new <TopSearchBar> component that renders a full-width horizontal bar with: (a) prominent search input with magnifier icon and Cmd+K hint pill on the right, (b) notification bell with red badge (number from user.unreadNotifications or static "3" for demo until the real query lands), (c) mail icon, (d) avatar + name

  • level chip + dropdown caret. On /dashboard only, replace the current <header> (lines 824-855 of Layout.js with the search box when showSearch=true) with this primitive. Keep .page-header-glass for non-dashboard pages — the two patterns coexist. Acceptance: dashboard top edge matches mockup (search bar dominant, right side has the three icons + avatar block).

4. stat-card-primitive

Add components/ui/StatCard.js exporting <StatCard> that renders: glass-panel container, a 48×48 rounded-2xl tile on the left with a gradient background (prop: accent="gold" | "purple" | "blue" | "red"), a white icon (children or icon prop), large number, label, and an optional delta indicator (delta="+12.5%" or delta="-2.1%") with up/down arrow + color. Used by sub-convoy #7 on the dashboard (4 cards in a row). Acceptance: new component test in test/components/StatCard.test.js covering: renders all 4 accent gradients, renders delta in green when positive and red when negative, renders without delta when prop omitted, escapes label as text not HTML. The 4 accent colors get new :root tokens (--stat-accent-gold, --stat-accent-purple, --stat-accent-blue, --stat-accent-red) so dark/light variants are clean.

5. daily-ember-widget

Add components/DailyEmberWidget.js exporting <DailyEmberWidget>: glass-panel container, flame icon top-left, "Daily Ember" label, "N / M" current/max display, ember-gradient horizontal progress bar, "Collect 20 embers for bonus XP!" helper text below. Wired to a new (mocked-for-now) hook useDailyEmber() in lib/use-daily-ember.js that returns { current, max, multiplier }. Real backend wiring is out of scope; the hook returns hardcoded { current: 16, max: 20 } matching the mockup until a separate convoy adds the API. Used by sub-convoy #7 (mounted in the Layout sidebar above the user menu/footer block). Acceptance: visually matches mockup, vitest covers the hook returning a valid object shape and the component rendering with hook data.

6. card-grid-outer-glow

Adjust components/CardItem.js's outer container to add a warm soft outer glow that matches the mockup's card treatment (the cards in the Featured Collection grid appear to "glow" gently from a warm light source). Implementation: box-shadow: 0 0 24px -4px rgba(255, 128, 0, 0.18) on the card root, intensified on hover. Must NOT touch the rarity-color glow logic (existing gradient-text-gold etc.). Per the prior epic's hard scoping rule ("card grids may NOT use glass on every card"), the glow stays as a single cheap box-shadow per card. Acceptance: visual matches mockup, no scroll-jank on long card grids.

7. dashboard-rebuild

Rewrite pages/dashboard.js to assemble the new primitives into the mockup layout. Structure:

  • Layout shell unchanged
  • Replace <header>/.page-header-glass with <TopSearchBar>
  • Row 1: 4× <StatCard> (Total Cards, Rare Cards, Decks Built, Wishlist Items — the metric names from mockup)
  • Row 2: <FeaturedCollectionGrid> (new component, used only by dashboard, internally is a 4×2 <CardItem> grid with the mockup's title bar + filters)
  • Row 3: <RecentActivityFeed> (new component, list with avatar
    • text + timestamp rows — wire-mocked from existing /api/collections/recent or static if no endpoint yet)
  • The right-rail Card Spotlight is OUT OF SCOPE for this sub-convoy (it's #8)
  • Layout's sidebar gets <DailyEmberWidget> mounted above the user-menu footer Existing dashboard logic (router, auth, data fetching) is preserved; only the JSX structure and component composition changes. Acceptance: deckhearth.com/dashboard side-by-side with the mockup is "recognizably the same product" (operator gate, not a CI gate).

8. right-rail-spotlight (optional follow-up)

Sketch the right-rail Card Spotlight panel from the mockup: selected card image, metadata table (Rarity, Set, Collector #, Condition), market value + delta, two charts (price trend line + market overview area). Charts via inline SVG until a charting library convoy lands. Watchlist below charts. This is a SCOPE GUARD: the data wiring (real market-value API, real watchlist) is out of scope; component ships with hardcoded demo data and a clearly-marked TODO comment. Acceptance gate: operator explicit "ship #8" approval before kicking off — easy to defer to a follow-up convoy if turn budget runs short.


6. What gets rewritten / replaced from the prior epic

Honest list of regressions from PRs #95-#101 this convoy reverses or significantly modifies:

  • .page-header-glass utility (PR #100) — used by /my-cards, /cards, /collections, /community/collections, /collection/[id], NOT by dashboard after #3 lands. The class stays; dashboard.js stops using it.
  • Dashboard's current "stat cards" (PR #97) — replaced by <StatCard> primitive in #4 → #7. The current dashboard surfaces (.glass-panel rounded-2xl p-6) become old-shape after #7 merges. No CSS removal; just call-site replacement.
  • Body hearth gradient values (PR #101) — boosted to mockup intensity in #1. The composition (3 radials + linear wash) stays; the alphas roughly double.
  • Sidebar active-state border-left + DH monogram (Layout.js) — replaced wholesale by #2's gradient pill + wordmark.
  • Top header <header> block when showSearch=true (Layout.js lines 824-855) — replaced by <TopSearchBar> on dashboard. Other pages keep the existing header (or fall through to no header).
  • pages/dashboard.js JSX structure — rewritten in #7. Data hooks (useAuth, query for owned cards count, etc.) preserved.

CI grep gate updates needed:

  • None expected. The forbidden-modal-shell-without-primitive and forbidden-deprecated-color-aliases gates from #96 remain. No new gate added; the mockup-matching is operator-judged, not CI-judged.

7. Operator decisions (locked 2026-06-04)

  1. Stat card metrics: Total Cards / Rare Cards / Collection Value / Wishlist Items. Use real product data where available; placeholders (0 / N/A) where the concept doesn't yet exist (Wishlist Items has no schema today — show as 0 with a small "coming soon" subtitle until the wishlist feature ships).
  2. Cmd+K shortcut: wired in this convoy. <TopSearchBar> ships with a global keyboard handler that opens a search modal. The modal is the minimum viable — input + 3-5 recent searches + Enter to submit. Full federated search across cards / decks / lists is a downstream convoy.
  3. Top search bar scope: sweep to ALL authenticated pages in this convoy. Consistent top-bar everywhere: /dashboard, /my-cards, /cards, /collections, /community/collections, /collection/[id], /scanner, /settings. The .page-header-glass utility stays in styles/globals.css (it's used by other potential future pages) but no call site references it after this convoy.
  4. Default theme: flip to dark in this convoy. The mockup's dark variant is the visually-defining read. Light theme stays fully supported (the toggle in the sidebar still works), but a first-time visitor lands on dark by default. Set [data-theme="dark"] as the initial DOM attribute in lib/theme-context.js's initial-load logic (currently defaults to system preference; change to dark unless the user has an explicit stored preference).
  5. <FeaturedCollectionGrid> data: show the user's most-recent 8 owned cards (from the existing user_cards query). If the user has <8, fill with a clear "Add cards to populate this grid" CTA in the empty slots. Hardcoded demos are NOT shipped (the operator wants real data, not fake polish).
  6. Right-rail #8: in scope. Ship the sketch with hardcoded demo data and a clearly-marked TODO comment for the real market-value API. Charts via inline SVG.

8. Roles invoked

  • role-conductor (this file)
  • role-design-system-auditor — sub-convoy #1 (gradient values, contrast check at higher intensities) + #2 (active-pill contrast/glow tuning) + #4 (stat card accent token palette)
  • role-architect — every sub-convoy
  • role-implementer — every sub-convoy
  • role-reviewer — every sub-convoy (multitask candidate after implementer ships draft)
  • role-a11y-auditor — sub-convoys #1 (corner contrast), #2 (active-pill focus ring), #3 (top-bar tab order)
  • role-ux-reviewer — sub-convoys #2, #3, #5, #7 (interaction patterns)

9. Status

Shipped 2026-06-04. All 8 sub-convoys merged to main in five PRs:

Sub-convoy PR Squash commit Notes
#1 hearth-bg-corner-embers + dark default #102 dd5ddce Boosted gradient ~50%; dark base shifted #1a0f0a → #0d0e1a
#2 sidebar pill + wordmark #103 ceb041b Bundled with #5
#5 Daily Ember widget #103 ceb041b Mocked hook; backend in follow-up
#4 StatCard primitive #104 3d11ef1 4 accent gradients; dashboard 4-up wired
#3 TopSearchBar + Cmd+K + sweep #105 e6e7780 6 page-header-glass call sites swept
#6 card-grid outer-glow #106 ea21b01 Single-axis shadow per perf budget
#7 dashboard rebuild #107 7acee45 Bundled with #8
#8 right-rail Card Spotlight #107 7acee45 Sketch tier; demo data + inline SVG charts

Follow-up convoys queued (out of scope for this epic, tracked here so the next agent doesn't re-discover them):

  1. daily-ember-backend — wire useDailyEmber() to a real /api/user/daily-ember endpoint that derives the current/max from collection_activity + scan_activity day-bucketed sums.
  2. rarity-aggregation — populate the StatCard "Rare Cards" tile with a real count (currently 0 + "Coming soon"). Requires user_cards.rarity column to be populated by the import jobs.
  3. wishlist-feature — populate the StatCard "Wishlist Items" tile. Requires a new wishlist table + API.
  4. user-activity-feed — replace <DashboardRecentActivity>'s demo rows with rows from a new /api/user/activity endpoint (aggregates across collection_activity + scan_activity + trade_activity).
  5. market-data — replace <DashboardCardSpotlight>'s static demo with real market-value + price-history + watchlist APIs. Decide whether to add a charting library at that time (current sketch uses inline SVG per umbrella § 2 "No new dependency").
  6. featured-collection-filters — wire the "All Sets" filter dropdown + grid/list toggle in <DashboardFeaturedCollection>.
  7. command-palette-federated-search — extend <CommandPaletteModal> from input-then-submit to live federated results across cards / decks / lists / users. The current "Quick actions" pattern is the minimum viable.
  8. page-header-glass-css-cleanup.page-header-glass utility in styles/globals.css has zero call sites after sub-convoy #3 (umbrella § 7.3 contract). Remove the rule itself in a small housekeeping convoy.
  9. topbar-user-menu-dropdown — the user-menu chip in <TopSearchBar> currently routes to /settings on click. A follow-up can add a real dropdown (Settings, Profile, Theme Toggle, Sign Out) if the operator wants the full pattern.