Pulse — Mobile-First Responsive Redesign Plan
Pulse — Mobile-First Responsive Redesign Plan
Owner: Nova (Design) · Line of execution: Ace (Engineering) via A2A Priority: High · Status: Plan v1.0 — ready for implementation Stack: Nuxt 4 + Vue 3 + Tailwind CSS v4 (@tailwindcss/vite) + nuxt-auth-utils
Design lens: Every layout decision is framed as "what is the user doing, and does the interface remove friction?" Mobile is not a shrunk desktop; a 320px user gets a different information architecture, not a tighter squeeze.
1. Current State Audit — What Breaks on Mobile Today
🔴 Blocking / visibly broken
| # | Location | Issue |
|---|---|---|
| B1 | /account portfolio table | 5-column table in overflow-x-auto forces horizontal pan on 320px — no card fallback. |
| B2 | /watchlist table | 6-column table (Ticker/Price/Change/Volume/Strength/Chart) overflows; no responsive variant. |
| B3 | Dashboard brief portfolio table | Same 3-col table inside the Daily Brief card. |
| B4 | Sticky nav gap | Inline nav hidden <lg; hamburger + search crowding; SearchBox only in the hidden drawer (search is 2 taps away on mobile). |
| B5 | Podcast archive <audio> in flex row | On 320px the row is ~300px+; number/title wrap under fixed-width audio; native controls ~10-14px (below 44px). |
| B6 | Research date rail horizontal | Works (overflow-x-auto) but buttons ~30px tall (below 44px) and no edge-fade to signal scrollability. |
🟠 Degraded UX
| # | Location | Issue |
|---|---|---|
| D1 | Dashboard 2-col grid | Rail (watchlist/markets) stacks BELOW main on mobile — buried after 5 tabs of scroll. |
| D2 | Dashboard tabs | overflow-x-auto works, but small hit area, no scroll-snap, no edge-fade. |
| D3 | AI Research chat on /stock/ticker | input+Ask row can overflow 320px; input py-2 (<44px). |
| D4 | IndexStrip | Horizontal scrolls but no touch-action pan-x / edge fade — sticky on iOS. |
| D5 | /watch tiles | grid-cols-2 is good; tile tap area short. |
| D6 | Stock price hero | text-3xl wraps; label stacking un-rhythmic on 320px. |
| D7 | SearchBox | Fixed w-28/w-44 focus widths; in drawer only — not full-width on mobile. |
🟡 Missing entirely
| # | Gap |
|---|---|
| M1 | No PWA manifest — can't install/offline. |
| M2 | No service worker / offline shell (nuxt.config has no PWA module). |
| M3 | No lazy image loading / explicit route code-splitting. |
| M4 | No pull-to-refresh — feed pages have buttons but no touch gesture. |
| M5 | No focused focus-visible states — relies on default/inconsistent ring. |
| M6 | No documented breakpoint token set. |
| M7 | Chat composer not pinned above iOS keyboard (page uses h-full). |
2. Breakpoint Strategy
Tailwind v4 defaults. Mobile-first — base = mobile, sm/md/lg/xl = progressive enhancement.
| Token | Min-width | Grid / layout intent |
|---|---|---|
| base | 320px | Single column. Full-bleed cards, stacked forms/audio, mobile nav drawer, safe-area padded. |
| sm | 640px | Tables → 2-col card grids; research rail stays horizontal; hero stacked. |
| md | 768px | 2-up card grids; tables show 3-4 cols; inline audio returns. |
| lg | 1024px | THE breakpoint. Desktop inlined nav returns; 2-col page grids; hamburger disappears; search in header. |
| xl | 1280px | Content max-width; rail goes 340px; more whitespace. |
Rules: every component designed at 320px first. Use dvh not vh. Respect env(safe-area-inset-bottom) on fixed bottom elements.
3. Component-by-Component Responsive Spec
3.1 AppHeader.vue 🔴 B4
Mobile: [Pulse logo] ... [🔍 search-icon toggle] [☰ hamburger]
- Search → collapsible full-width row under header bar (1 tap to search), not only in drawer.
- Hamburger
h-11 w-11(already 44px ✔). Drawer itemsmin-h-[48px]✔ + SVG icons + active left-accent. - lg+: existing inline nav + full SearchBox + date pill + account (unchanged).
3.2 Dashboard index.vue 🔴 B3 / 🟠 D1,D2
- Mobile reorder: rail ABOVE main on mobile via CSS
order(2-col only at lg):<div class="order-2 lg:order-1">main</div> <div class="order-1 lg:order-2">rail</div> - IndexStrip pinned under header all sizes.
- Tabs: add
scroll-snap-x snap-mandatory,min-h-[44px], edge-fade mask. - Portfolio table (B3):
<sm→ stacked holding cards (ticker/price/chg% per line). Tablesm+. - News/MA50/movers: already stacked flex rows ✔ keep.
3.3 Research research.vue 🔴 B6
- Mobile: date rail ON TOP, horizontal swipe, edge-fade mask + scroll-snap.
- Date buttons
min-h-[44px] px-3.5. - Brief tables: stacked cards <sm (same as B3/B1).
- lg+: existing
lg:grid-cols-[220px_1fr]vertical rail (unchanged). Keep Show more/less.
3.4 Podcast podcast.vue 🔴 B5
- Episode row mobile-first:
flex-col gap-3 sm:flex-row sm:items-center; audiow-full sm:w-64. - Native audio too small on iOS → wrap with custom ≥44px play row, full-row tap toggles play (aria-live); native controls on
md+. - Latest episode card: same stacking (emoji + meta + full-width audio).
- Keep playbackRate=1.25 ✔.
3.5 Chat chat.vue 🔴 M7
- Root
h-[100dvh]; composersticky bottom-0+pb-[max(0.5rem,env(safe-area-inset-bottom))](above iOS keyboard + home indicator). - Textarea
py-3, send btnh-11 w-11, suggestion chipspy-3. - Bubbles
max-w-[88%](base) →sm:max-w-[78%]. - Persist draft on route change.
3.6 Account account.vue 🔴 B1
- Sidebar → horizontal segmented tab strip (<lg), vertical at lg:
<nav class="flex gap-1 overflow-x-auto lg:flex-col lg:overflow-visible">+min-h-[44px]. - Portfolio table (B1): <sm stacked cards; sm+ table.
- Sign-in modal:
max-h-[90dvh] overflow-y-autofor tiny landscape.
3.7 Watch / Watchlist 🟠 D5 / 🔴 B2
- /watch tiles:
grid-cols-2 sm:3 md:4 lg:5+min-h-[92px]. - /watchlist table (B2): <md → card stack (ticker/price/change/volume/strength/Chart→). Table
md+. - Sort tabs
min-h-[44px].
3.8 Stock ticker 🟠 D3
- AI Research input
flex-1 min-w-0+py-3; buttonpx-3 sm:px-4. - Chat panel
max-h-[50vh]mobile. - Price hero
text-2xl sm:text-3xl.
4. Tailwind Utility Classes To Use
Layout/order: grid-cols-1 grid-cols-2 sm:grid-cols-3 lg:grid-cols-[1fr_320px] lg:grid-cols-[220px_1fr] lg:grid-cols-[260px_1fr] · order-1 order-2 lg:order-1 lg:order-2 · flex flex-col sm:flex-row sm:items-center · sticky top-0 bottom-0 · h-[100dvh] min-h-[100dvh] · pb-[max(0.5rem,env(safe-area-inset-bottom))]
Touch targets: min-h-[44px] min-h-[48px] h-11 w-11 py-3 px-4
Swipe rails: overflow-x-auto scroll-snap-x snap-mandatory snap-start · [-webkit-mask-image:linear-gradient(to_right,black,black_90%,transparent)] · touch-pan-x overscroll-x-contain
Focus/a11y: focus-visible:outline focus-visible:outline-2 focus-visible:outline-brand-500/60 · aria-selected:bg-brand-600/15 aria-selected:text-brand-300 · scroll-mt-24
Tables→cards pattern: grid grid-cols-1 gap-2 md:hidden (cards) + hidden md:table (table)
5. Migration Steps (Phased, Non-Breaking)
| Phase | Scope | Ship signal |
|---|---|---|
| P0 | PWA manifest + offline shell (@vite-pwa/nuxt); focus-visible + safe-area CSS foundation | build passes; /site.webmanifest; Lighthouse PWA ≥90 |
| P1 | Header mobile search + SVG icons + drawer polish; chat 100dvh + keyboard-safe composer; bump send/textarea | search 1 tap at 320px; composer above keyboard |
| P2 | Table→card sweep (Dashboard, Account, Watchlist, Research) via shared components | no horizontal pan on 320px in those spots |
| P3 | Research rail abovetrail order + edge fade + tap targets; channel rails scroll-snap; Podcast audio full-width + play rows | clean vertical 320px flow on all 6 pages |
| P4 | Dashboard rail-above order; min-44px sweep; focus-visible; WCAG contrast review | Lighthouse a11y ≥95; tab through site |
| P5 | Route code-split audit; lazy images; pull-to-refresh on /, /watch, /news | Lighthouse Performance ≥85 mobile |
Each phase is an isolated commit → git revert <phase> for rollback.
6. Testing Checklist
Devices
320px (SE/fold), 390px (iPhone Pro, portrait+landscape), 360px (Android), 600-820px (tablet), 1280/1920 (desktop).
Interaction
- All tap targets ≥44px
- Swipe date rail/index strip/tabs: fade + snap work
- Pull-to-refresh on /, /watch, /news
- Chat composer above iOS keyboard + home indicator
- Hamburger→drawer→Esc/backdrop closes cleanly
- Mobile search: 1 tap→expands→focused→navigates
Browsers
Safari/iOS 16+, Chrome/Android, Samsung Int; Chrome/Firefox/Safari/Edge desktop; audio playback on iOS Safari + Android Chrome (autoplay restrictions).
A11y (WCAG AA)
- focus-visible on all interactives
- Screen reader: nav landmark, drawer aria-expanded, audio labelled, tables caption/scope
- Color contrast muted on surface ≥4.5:1
- prefers-reduced-motion respected
- axe + manual touch-target audit
Performance (Lighthouse, mobile 4G)
- LCP <2.5s · code-split routes · PWA installable + offline · non-blocking hydration
7. Risk & Reversibility
| Decision | Alternatives | Trade-off | Chosen | Reversible |
|---|---|---|---|---|
| Table→card <md | keep horizontal scroll all sizes | simplest vs best UX | shared component dual render | Easy |
| Rail-above on mobile | keep current bottom rail | change vs buries watchlist | CSS order only | Easy |
| PWA now vs later | later | additive/unblocks install | now (P0) | Easy |
| Pull-to-refresh | skip/custom | custom must not fight scroll | Phase 5 feed pages only | Medium |
Cost: CSS/component only — NO API/server/data changes.
8. Handoff to Ace
Dispatch per phase: "Implement per designs/responsive-redesign.md section {n}. Nuxt 4 + Tailwind v4, additive + revertible. Verify npm run build + 320px iOS emulation sweep. Commit feat(pulse): {summary}. Report diff + Lighthouse."
9. Design Tokens (locked, no change)
surface #09090b · card #101014 · card2 #16161c · muted #a1a1aa · foreground #e4e4e7 · brand mint scale · Inter · square radius (2026-08-13 lock)
Reviewed end-to-end against live codebase. Design rationale: single-column mobile flows, thumb-reachable primaries, swipe-native lists; desktop stays dense + untouched. — Nova
Pulse V2 — Design Spec (Nova)
Companion to: PULSE-V2-SPEC.md (product spec, Min) · Status: v1.0 design layer Scope: wireframes, component tree, design tokens, interaction & feedback patterns, a11y Constraint honored: V1 tokens unchanged (dark #09090b, mint #16A34A) — V2 is a layout/data upgrade, not a rebrand.
Spaceship Study — Competitive Analysis for Pulse
Date: 2026-08-31 · Author: Min · Source: spaceship.com.au (home, US Investing, Learn) Young's directive: "Pulse is offering service similar to Spaceship, study more from them."

