plan: add Phase 6 responsive home page (mobile layout)
This commit is contained in:
@@ -182,6 +182,78 @@ These follow from `CONTEXT.md §5`. Direction is strongly implied but no specifi
|
||||
|
||||
---
|
||||
|
||||
## Phase 6 — Responsive home page (mobile layout)
|
||||
|
||||
The home page (`DeepDrftPublic.Client/Pages/Home.razor` + `Home.razor.css`) is built entirely on hand-rolled CSS grids with **no responsive breakpoints**. Every horizontal split is a fixed column count that holds on desktop and collapses on mobile — six genre cards in one row, four feature cards in one row, two 50/50 splits, and a `space-between` CTA banner all overflow or squash below ~960px. This phase migrates the layout to be mobile-first while preserving the wireframe-faithful visual styling.
|
||||
|
||||
**Guiding principle for the whole phase: separate *layout* from *style*.** The scoped CSS in `Home.razor.css` does two jobs — it positions columns (the part that breaks on mobile) and it paints the design (colors, fonts, padding, hover states, pseudo-element flourishes). Only the *column-positioning* job migrates. Colors, typography, padding, `::before`/`::after` decorations, and hover transitions stay in scoped CSS untouched.
|
||||
|
||||
**Two tools, used deliberately:**
|
||||
|
||||
- **`MudGrid` + `MudItem`** (with `xs`/`sm`/`md` breakpoints) for splits where MudBlazor's margin-based gutters are acceptable: hero, section-header, section-split, CTA banner. This is the house pattern already used in `DeepDrftShared.Client/Components/TracksGallery.razor` (`<MudItem xs="12" sm="6" md="4" lg="3">`). Match it. Breakpoints: xs=0, sm=600, md=960, lg=1280, xl=1920. MudGrid breakpoint attributes are CSS-only at runtime — **do not** inject `IBreakpointService` or any breakpoint-observer service into the component.
|
||||
- **CSS `@media` query on the existing scoped grid** for the two card blocks (genre grid, features grid). These two are explicitly *not* MudGrid candidates — see 6.1 for why. Adding a media query that overrides `grid-template-columns` is the minimal, correct move there.
|
||||
|
||||
**The one trap to avoid (read before touching the card grids):** the genre grid and features grid use `gap: 1px` (genre) / shared `border-right` (features) to render the cards as a single block divided by **hairline rules** — the cards touch, and the 1px gap *is* the divider line. `MudGrid`'s `Spacing` parameter produces margin-based gutters (multiples of 4px, with outer margin), which **cannot reproduce a shared hairline edge**. Porting these two grids to `MudGrid` would silently destroy the hairline-divider aesthetic. Keep them as CSS grid; only add breakpoints.
|
||||
|
||||
### 6.1 Genre grid + features grid — CSS media queries only
|
||||
|
||||
- **What:** `.genre-grid` (`repeat(6, 1fr)`) and `.features-grid` (`repeat(4, 1fr)`) get responsive column counts via `@media` overrides in `Home.razor.css`. No markup change to the grid containers themselves.
|
||||
- **Why MudGrid is wrong here:** Both grids render cards as a contiguous block separated by 1px hairline rules (`.genre-grid` via `gap: 1px` over a border-colored background; `.features-grid` via per-card `border-right`). MudGrid's `Spacing` gutters are margins, not shared edges — switching would break the visual. Pure CSS keeps the hairline intact while still going responsive.
|
||||
- **Stacking behavior:**
|
||||
- Genre grid: md+ `repeat(6, 1fr)` (current); sm `repeat(3, 1fr)`; xs `repeat(2, 1fr)`. (Six genres divide cleanly into 3 and 2 — no orphan row.)
|
||||
- Features grid: md+ `repeat(4, 1fr)` (current); sm `repeat(2, 1fr)`; xs `1fr` (single column stack).
|
||||
- **Scoped CSS that must change:** Add two `@media (max-width: 960px)` and `@media (max-width: 600px)` blocks overriding `grid-template-columns` on `.genre-grid` and `.features-grid`. For `.features-grid` at the stacked/2-col breakpoints, the per-card `border-right` produces a dangling right border on the last card in each visual row — switch the hairline strategy at those breakpoints (e.g. apply `border-bottom` on cards and drop `border-right`, or move to `gap: 1px` like the genre grid). Specify the exact rule when implementing; the constraint is "no dangling/missing hairlines at any breakpoint."
|
||||
- **Order of independence:** Fully independent. Touches only `Home.razor.css`, no markup. Can be the first slice landed and verified in isolation.
|
||||
|
||||
### 6.2 Hero — MudGrid for content, CSS for the background color split
|
||||
|
||||
- **What:** `.hero` is `grid-template-columns: 1fr 1fr` at `min-height: 100vh`, with `.hero-left` painted white and `.hero-right` painted navy — a full-viewport color split. Migrate the *content* columns to `MudGrid`; keep the *background color split* in CSS.
|
||||
- **Why split the treatment:** MudGrid rows/items do not carry per-column background colors that bleed to the full viewport height. The white/navy vertical split is a visual property of the section, not of the content columns. Wrap `DeepDrftHero` and `NowPlaying` in `<MudItem xs="12" md="6">` inside a `<MudGrid>`, but keep the white/navy backgrounds on the section via CSS.
|
||||
- **Stacking behavior:**
|
||||
- md+: 50/50 split — hero copy left (white), NowPlaying right (navy). Current desktop look preserved.
|
||||
- xs/sm: stack to single column — `DeepDrftHero` on top, `NowPlaying` below. The 100vh constraint should relax to `min-height: auto` (or a smaller min) when stacked, so the two stacked panels don't each demand a full viewport.
|
||||
- **Scoped CSS that must change:**
|
||||
- `.hero` keeps `min-height: 100vh` at md+; add `@media (max-width: 960px)` relaxing it (e.g. `min-height: auto`) and switching the background from a left/right split to a top/bottom split (or letting each `MudItem` carry its own background at the stacked breakpoint).
|
||||
- The white/navy split: at md+ this can stay a CSS background on `.hero` (e.g. a `linear-gradient(to right, white 50%, navy 50%)` on the section, or backgrounds on the two MudItems via scoped classes). At xs/sm the split becomes top/bottom. Implementer picks gradient-on-section vs. background-per-item; the gradient-on-section approach survives the MudGrid gutter cleanly (gutters show the section background, not white margins).
|
||||
- Remove `.hero`'s own `display: grid; grid-template-columns: 1fr 1fr` (MudGrid now owns column layout). Keep `overflow: hidden`.
|
||||
- **Order of independence:** Independent of all other sections. Has the most CSS nuance (the color split) — schedule it where there's time to verify the split holds at every breakpoint, including the MudGrid gutter not showing a white seam.
|
||||
- **Constraint:** `DeepDrftHero` and `NowPlaying` are child components with their own scoped CSS — **do not refactor them in this pass.** Layout is Home.razor's responsibility only.
|
||||
|
||||
### 6.3 Section header — MudGrid
|
||||
|
||||
- **What:** `.section-header` is `grid-template-columns: 1fr 2fr` (label+title left, body paragraph right) with `align-items: end`. Migrate to `MudGrid`.
|
||||
- **Stacking behavior:** md+ keep the 1fr/2fr asymmetry via `<MudItem md="4">` (title) + `<MudItem md="8">` (body). xs/sm stack to `xs="12"` each — title block on top, body paragraph below.
|
||||
- **Scoped CSS that must change:** Remove `display: grid; grid-template-columns: 1fr 2fr; gap: 4rem` from `.section-header`. The `align-items: end` baseline-alignment is a desktop nicety that's meaningless when stacked — preserve it at md+ only (MudGrid `Align.End` on the row, or a scoped rule). `.section-body`'s `align-self: end` similarly only applies in the side-by-side layout; harmless when stacked but can be dropped from the stacked breakpoint.
|
||||
- **Order of independence:** Independent. Small, low-risk — good warm-up slice.
|
||||
|
||||
### 6.4 Section split (origin + connect) — MudGrid
|
||||
|
||||
- **What:** `.section-split` is `grid-template-columns: 1fr 1fr` at `min-height: 60vh` — green "Origin" panel left, white "Connect" panel right, each a full-bleed colored column. Same shape as the hero (colored columns) but lower stakes (60vh, not full-viewport, and the colors are per-panel not a single split).
|
||||
- **Stacking behavior:** md+ 50/50. xs/sm stack — Origin (green) on top, Connect (white) below.
|
||||
- **Scoped CSS that must change:** Replace the grid container with `<MudGrid>` + two `<MudItem xs="12" md="6">`. Here the per-panel backgrounds (`.split-left` green, `.split-right` white) live on the panels themselves, so — unlike the hero — the color survives a MudGrid gutter only if the gutter is removed or the panels fill their items edge-to-edge. **Set `MudGrid Spacing="0"`** so the green and white panels meet with no white seam between them, preserving the current flush-color-block look. The `.split-left::before` decorative circle stays untouched. Relax `min-height: 60vh` to `auto` at the stacked breakpoint so each panel sizes to its content.
|
||||
- **Order of independence:** Independent. The `Spacing="0"` decision here is the same family of problem as the hero seam — landing 6.2 first will surface the seam-handling approach to reuse here.
|
||||
|
||||
### 6.5 CTA banner — MudGrid or flex-wrap
|
||||
|
||||
- **What:** `.cta-banner` is `display: flex; justify-content: space-between` — headline left, two action buttons right. `.cta-actions` is an inline flex row of two buttons.
|
||||
- **Stacking behavior:** md+ keep headline-left / actions-right. xs/sm stack — headline on top, actions below. At xs the two buttons should go full-width-stacked (or wrap) rather than sitting cramped side by side.
|
||||
- **Approach — recommend the lighter touch:** This one does **not** need MudGrid. The container is already flex; adding `flex-wrap: wrap` + a media query that flips `flex-direction: column` and `align-items: stretch` at `max-width: 600px` achieves the stack with the least churn. MudGrid is also fine (`<MudItem xs="12" md="6">` × 2) if consistency with the other sections is preferred — but flex-column is fewer moving parts for a two-element banner. **Pick flex unless the implementer wants every section uniformly on MudGrid.**
|
||||
- **Scoped CSS that must change:**
|
||||
- `.cta-banner`: add `@media (max-width: 600px)` → `flex-direction: column; align-items: flex-start; gap: 2rem`.
|
||||
- `.cta-actions`: add `flex-wrap: wrap` always; at xs, `width: 100%` with the two buttons (`.btn-white`, `.btn-outline-white`) going `flex: 1` or full-width so they don't crowd.
|
||||
- The giant `.cta-banner::before` "DRFT" watermark (22rem) will overflow badly on mobile — add a media-query rule shrinking its `font-size` at xs (e.g. `clamp` or a fixed smaller size) or hiding it, so it doesn't force horizontal scroll. **This is a hidden overflow source independent of the flex layout — do not skip it.**
|
||||
- **Order of independence:** Independent. The watermark-overflow fix is the non-obvious part; the flex stack itself is trivial.
|
||||
|
||||
### Phase 6 sequencing summary
|
||||
|
||||
All six slices are independent and touch only `Home.razor` + `Home.razor.css` (no child components, no shared CSS, no other pages). They can land in any order or in parallel. Recommended order by ascending risk: **6.3 (section header) → 6.1 (card grids) → 6.5 (CTA banner) → 6.4 (section split) → 6.2 (hero)** — warm up on the trivial MudGrid swap, get the no-MudGrid card grids done, then tackle the two color-split sections (6.4, 6.2) last since they share the gutter-seam problem and the second reuses the first's solution.
|
||||
|
||||
- **Why it matters:** The public site is the front door for a music collective whose listeners are disproportionately on phones (social-shared links, live-session discovery). A home page that overflows horizontally on mobile undercuts the entire "get the music in front of people" posture (`PLAN.md` in-flight iframe item makes the same bet). This is table-stakes polish, not a feature.
|
||||
- **Prerequisite:** None. Pure presentation work on one page.
|
||||
- **Constraint:** Do not refactor `DeepDrftHero` or `NowPlaying` (6.2 constraint). Do not touch `DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` (shared CSS) — all changes are scoped to `Home.razor.css`. Preserve every color/font/decoration; this phase changes *where columns break*, nothing about how the page looks at desktop width.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5 — Documentation backlog
|
||||
|
||||
### 5.1 Folder-level CLAUDE.md sweep
|
||||
|
||||
Reference in New Issue
Block a user