diff --git a/COMPLETED.md b/COMPLETED.md index 1957530..5be3fc4 100644 --- a/COMPLETED.md +++ b/COMPLETED.md @@ -8,6 +8,36 @@ Newest entries at the top. Group by phase/wave header (mirroring `PLAN.md` / `CM ## Phase 2 — Product surface: player and theming +**Status:** Track card glass theming landed on 2026-06-05. AudioPlayerBar responsive unification and SpectrumVisualizer fix landed on 2026-06-05. + +### Track Card Glass Theming + +**Landed 2026-06-05.** + +Aligned `TrackCard` component visual language with the `NowPlayingCard` aesthetic via glass background + text hierarchy. Two coordinated changes: + +**Razor changes (`DeepDrftShared.Client/Components/TrackCard.razor`):** +- Removed `mud-theme-secondary` class and `Color="Color.Surface"` attributes from all four `MudText` elements, handing color control to CSS. +- Added semantic class hooks: `deepdrft-track-title` (track name), `deepdrft-track-artist` (artist), `deepdrft-track-meta` (album and release year). +- Changed MudCard `Elevation="4"` → `Elevation="0"` to align with glass-panel vocabulary (no drop shadow). + +**CSS changes (`DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` §8):** +- Dark theme: navy-glass fallback panel (`color-mix(in srgb, var(--deepdrft-navy) 55%, transparent)` + `backdrop-filter: blur(8px)` + translucent border), matching `NowPlayingCard` glass vocabulary. +- Text hierarchy (dark): title in off-white, artist in moss-green accent, meta in muted off-white — mirrors the `NowPlayingCard` hierarchy. +- Content scrim behind text (dark): dark navy gradient to guarantee legibility over both glass fallback and album art. +- Light theme: subtle navy-tint fallback on off-white, light text inherits body colour for legibility. +- Glass border on card container (dark): `1px solid rgba(250, 250, 248, 0.12)` for aesthetic consistency. + +**Scope:** +- `TrackCard` component in shared `DeepDrftShared.Client` consumed by both public site and CMS. +- CSS in `DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` (public site only, not loaded by CMS). +- Build clean: 0 errors, 0 new warnings. + +**Notes for future work:** +- Genre chip text still uses `Color.Primary` (moss-green); it now sits alongside moss-green artist text. Consider a distinct genre-chip treatment (3a) in future polish work. + +--- + **Status:** AudioPlayerBar responsive unification and SpectrumVisualizer fix landed on 2026-06-05. ### AudioPlayerBar Responsive Unification diff --git a/product-notes/track-card-theming.md b/product-notes/track-card-theming.md new file mode 100644 index 0000000..b14b5af --- /dev/null +++ b/product-notes/track-card-theming.md @@ -0,0 +1,328 @@ +# Track Card Theming — align fallback + text with NowPlayingCard + +Status: completed. Author: product-designer. Date: 2026-06-05. Implementer: maintenance-engineer. Landed 2026-06-05. + +## Goal + +Make the public tracks-page track cards match the NowPlayingCard's established visual +language: + +- **Fallback background (no album art)** → navy-blue glassy look (translucent + blur), + as used by `.now-playing`. +- **Card text** → moss-green accent (`--deepdrft-green-accent` = `#3D7A68`) for the + label-grade text, matching `.np-label` / waveform bars. + +## Scope constraint (read before implementing) + +`TrackCard.razor` lives in **`DeepDrftShared.Client`**, which is consumed by **both** the +public site (light + dark) **and** the CMS host (`DeepDrftManager`, light-only). Any change +to TrackCard's defaults is inherited by the CMS. The NowPlayingCard aesthetic is a +*dark-on-dark* treatment; applying it unconditionally would break legibility on the CMS's +off-white surfaces. + +**Therefore the fix must be theme-aware**, not a flat recolor. The dark/navy-glass + +moss-green treatment applies under `.deepdrft-theme-dark`; light/CMS keeps a legible +on-light treatment. The hooks below are written so a single CSS file carries both. + +The card CSS lives in `DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` section 8. That +stylesheet is served by the public host and (per its own header comment) is shared across +server and client of the public app. **It is not loaded by the CMS host.** This is +actually convenient: putting the navy-glass treatment in section 8 means it only reaches +the public site. The CMS gets TrackCard with no `.deepdrft-track-card-*` styling beyond +whatever MudBlazor defaults apply. Confirm during implementation that the CMS still +renders TrackCard legibly (it currently relies on the same classes; if the CMS does not +link this stylesheet, the fallback `mud-theme-secondary` is the only thing styling it). +If the CMS does not actually use TrackCard in any live page, this concern is moot — verify +before spending effort on the light path. + +--- + +## 1. Current problems + +### 1a. Fallback background resolves to white + +`TrackCard.razor` line 11: + +```razor + +``` + +`mud-theme-secondary` paints the element with the theme's **Secondary** palette color. +In the dark palette (`DeepDrftPalettes.Dark`), `Secondary = "#FAFAF8"` (off-white). So a +track with no album art renders as a **white card** on the navy page — the opposite of the +intended navy-glass look, and it makes the white-intended text invisible-by-collision. + +(In the light/CMS palette, Secondary = `#1A3C34` deep green — a dark card on a light page, +also not the intended look but at least legible. Either way `mud-theme-secondary` is the +wrong abstraction here.) + +### 1b. All card text resolves to near-invisible navy + +Every `MudText` in TrackCard uses `Color="Color.Surface"` (lines 20, 26, 36, 57). MudBlazor's +`Color.Surface` maps to the palette **Surface** color. In the dark palette, +`Surface = "#162437"` (navy-mid). So all text is navy-mid: + +- On the *current buggy* white fallback: barely legible (low contrast dark-on-white, but + the white itself is wrong). +- On the *intended* navy-glass fallback: **near-invisible** (navy-mid text on a + navy-translucent ground — contrast well below WCAG AA). +- On a real album-art background (`.deepdrft-track-card-bg`, `brightness(0.7)`): unreliable, + depends entirely on the artwork. + +`Color.Surface` is semantically "the color of a surface," never intended as a text color. +This is the root mistake. + +### 1c. No per-component scoped CSS exists + +There is **no** `TrackCard.razor.css`. All TrackCard styling is global in section 8 of +`deepdrft-styles.css` plus MudBlazor utility classes applied inline. The fix can stay in +section 8 (preferred — keeps the public-only scoping described above) rather than +introducing a scoped file. + +--- + +## 2. Proposed changes + +Two coordinated edits: (A) remove the wrong MudBlazor color utilities from the Razor so +CSS can own the colors, (B) add navy-glass + moss-green rules to section 8. + +### 2a. Razor changes — `DeepDrftShared.Client/Components/TrackCard.razor` + +Goal: stop hard-binding to palette Secondary/Surface; hand color control to CSS via stable +class hooks. + +**Fallback `MudPaper` (line 11):** remove `mud-theme-secondary`. Replace the class list with +a single semantic hook: + +```razor + +``` + +The navy-glass background moves into the `.deepdrft-track-card-fallback` CSS rule (2b). + +**Text elements (lines 19–23, 25–29, 35–39, 57–60):** remove the `Color="Color.Surface"` +attribute from each `MudText`. Add class hooks so CSS can assign the moss-green / hierarchy +colors. Suggested hooks (match the NowPlayingCard's title/label/sub hierarchy): + +- Track name (line 19, `Typo.subtitle1`) → add `deepdrft-track-title` to its `Class`. + Currently `Class="text-truncate mb-1"` → `Class="deepdrft-track-title text-truncate mb-1"`. +- Artist (line 25, `Typo.caption`) → add `deepdrft-track-artist`. + `Class="text-truncate mb-2"` → `Class="deepdrft-track-artist text-truncate mb-2"`. +- Album (line 35, `Typo.caption`) → add `deepdrft-track-meta`. + `Class="text-truncate"` → `Class="deepdrft-track-meta text-truncate"`. +- Release year (line 57, `Typo.caption`) → add `deepdrft-track-meta`. + Has no `Class` today → add `Class="deepdrft-track-meta"`. + +Do **not** add inline `Style` or MudBlazor `Color` values; all color lives in CSS so the +theme-aware split works. + +### 2b. CSS changes — `DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` section 8 + +Reference values from NowPlayingCard (`NowPlayingCard.razor.css`): + +- glass background: `rgba(250, 250, 248, 0.06)` +- glass border: `1px solid rgba(250, 250, 248, 0.12)` +- blur: `backdrop-filter: blur(8px)` +- label/accent text: `var(--deepdrft-green-accent)` (`#3D7A68`) +- title text: `var(--deepdrft-white)` (`#FAFAF8`) +- sub text: `rgba(250, 250, 248, 0.45)` + +**Note:** NowPlayingCard's glass is a *light-tinted* translucency (`rgba(250,250,248,…)`) +over the navy page, which reads as navy-glass because the navy page shows through. To make +the fallback unambiguously "navy-blue glassy" even where the page behind it is not pure +navy (e.g. over a gradient), tint with navy explicitly. Use the navy token at low alpha +plus the same light border/blur. Both options below are acceptable; **Option A** matches +NowPlayingCard literally, **Option B** is more robustly navy. Recommend **Option B** for +the fallback since the card is a discrete object on a varied page, where NowPlayingCard +sits in a known navy context. + +Replace the existing `.deepdrft-track-card-fallback` rule (currently only position/size) +and add the text rules. Proposed block (dark-mode treatment scoped under +`.deepdrft-theme-dark`; base rule keeps layout only): + +```css +/* Fallback panel — layout (theme-agnostic) */ +.deepdrft-track-card-fallback { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +/* Fallback panel — navy-glass treatment, dark theme only. + Mirrors NowPlayingCard's .now-playing glass. */ +.deepdrft-theme-dark .deepdrft-track-card-fallback { + /* Option A (literal NowPlayingCard match): + background: rgba(250, 250, 248, 0.06); */ + /* Option B (recommended — explicit navy tint): */ + background: color-mix(in srgb, var(--deepdrft-navy) 55%, transparent); + border: 1px solid rgba(250, 250, 248, 0.12); + backdrop-filter: blur(8px); +} + +/* Card text — dark theme. Moss-green for label-grade text, off-white title. */ +.deepdrft-theme-dark .deepdrft-track-title { + color: var(--deepdrft-white); +} +.deepdrft-theme-dark .deepdrft-track-artist { + color: var(--deepdrft-green-accent); +} +.deepdrft-theme-dark .deepdrft-track-meta { + color: rgba(250, 250, 248, 0.55); +} +``` + +**Decision needed (1 of these):** the user said "track card text → the moss-green color." +Two readings: + +1. **Title in moss-green, supporting text muted** — strongest match to "card text is the + moss green," puts the green on the most prominent line. Use: + `.deepdrft-track-title { color: var(--deepdrft-green-accent); }` and demote the artist + to off-white or muted. +2. **NowPlayingCard hierarchy** (title off-white `#FAFAF8`, accent green on the *label*, + sub muted) — the block above. This is the literal NowPlayingCard mapping: green is the + accent/label color, not the title color. + +The block above implements a hybrid (artist line in green). **Recommend reading 1** — it +most directly satisfies "card text → moss green" and reads well on the navy-glass ground: +title in moss-green, artist + meta in muted off-white. If the user wants the literal +NowPlayingCard hierarchy instead, swap to reading 2. Flag this back to the user if +ambiguous; otherwise default to reading 1: + +```css +/* Reading 1 (recommended default) */ +.deepdrft-theme-dark .deepdrft-track-title { color: var(--deepdrft-green-accent); } +.deepdrft-theme-dark .deepdrft-track-artist { color: rgba(250, 250, 248, 0.70); } +.deepdrft-theme-dark .deepdrft-track-meta { color: rgba(250, 250, 248, 0.55); } +``` + +### 2c. Text legibility over real album art + +When album art *is* present (`.deepdrft-track-card-bg`), the same text classes now apply. +Moss-green/off-white over arbitrary artwork at `brightness(0.7)` can still be low-contrast. +NowPlayingCard never sits over artwork, so it gives no precedent. Recommend a scrim behind +the content to guarantee contrast in both art and fallback cases: + +```css +.deepdrft-track-card-content { + /* existing rules unchanged; add: */ + background: linear-gradient(to top, + rgba(13, 27, 42, 0.75) 0%, + rgba(13, 27, 42, 0.35) 45%, + rgba(13, 27, 42, 0.0) 100%); +} +``` + +This is optional but recommended — it makes the green/off-white text legible over both the +fallback glass and any album art, and reinforces the navy identity. If the user prefers the +fallback glass to read cleaner without a scrim, gate the scrim to art-only by moving it to +`.deepdrft-track-card-bg` as an `::after` overlay instead. **Recommend the content-level +scrim** for uniformity. Confirm with the user if the glassy fallback should stay scrim-free. + +### 2d. Light / CMS path + +With the dark treatment scoped under `.deepdrft-theme-dark`, light mode currently gets **no** +explicit text color (the removed `Color.Surface`) and **no** fallback background beyond the +base layout rule. That means: + +- Light fallback card → transparent (shows the page behind it). Likely undesirable. +- Light text → inherits MudBlazor body text (navy `#0D1B2A`), which is legible on a light + ground. Acceptable. + +Add a minimal light treatment so the public site's light mode and the CMS don't regress to +a transparent fallback: + +```css +.deepdrft-theme-light .deepdrft-track-card-fallback { + background: color-mix(in srgb, var(--deepdrft-navy) 8%, var(--deepdrft-white)); + border: 1px solid var(--deepdrft-border); +} +``` + +Text in light mode can be left to inherit (navy on light reads fine) or, for consistency +with the green identity, set the title to `--deepdrft-green-accent` in light too — the +accent green has adequate contrast on a near-white card. Recommend leaving light text to +inherit unless the user wants the green identity carried into light mode. + +**CMS caveat:** the CMS host does not link `deepdrft-styles.css` (it is in `DeepDrftPublic/wwwroot`). +If the CMS renders TrackCard, none of these rules reach it and the fallback will be +unstyled. Verify whether the CMS uses TrackCard at all before investing in the CMS path; if +it does, the light-mode rules need to live in the shared token/style layer the CMS *does* +load, not in `deepdrft-styles.css`. **This is the one open structural question** — resolve +it before implementing the light path. + +--- + +## 3. Other theming issues spotted on the tracks page + +Beyond the two the user called out: + +### 3a. Genre chip uses `Color.Primary` — green-on-navy collision (dark) + +`TrackCard.razor` line 48: ``. In the dark palette +`Primary = "#3D7A68"` (the same moss-green we're about to use for text). A green chip sitting +next to green text on a navy-glass card flattens the hierarchy — everything is one green. +Recommend giving the chip its own treatment: filled navy-mid with green text/border, or a +subtle outlined variant, so it reads as a distinct tag rather than blending into the text. +Suggested: `Variant="Variant.Outlined"` with a `.deepdrft-genre-chip` color override to +`--deepdrft-green-accent` border + text on transparent. Low priority; raise with user. + +### 3b. Play FAB uses `Color.Primary` — same green, but here it's correct + +Line 67: ``. Green FAB on navy is the intended interactive +accent (matches the dark palette's "green-accent is the primary interactive color" note in +`DeepDrftPalettes.Dark`). **No change** — this is the one place the green-as-primary mapping +is right. Noting it so the implementer doesn't "fix" it while touching the chip. + +### 3c. Loading skeletons are theme-default gray + +`TracksView.razor` lines 30, 37 use bare `MudSkeleton`. MudBlazor skeletons render in a +neutral gray that does not match the navy-glass language — on the navy dark page they'll be +light-gray rectangles, a jarring pre-load flash before the navy cards appear. Recommend +tinting skeletons toward the navy-glass treatment (`rgba(250,250,248,0.06)` pulse) so the +loading state previews the real cards. Low priority, but it's the most visible remaining +mismatch with the NowPlayingCard aesthetic on this page. Defer unless the user wants polish. + +### 3d. Card container has no border / elevation language matching the glass + +`.deepdrft-track-card-container` (section 8) sets size + `overflow: hidden` and relies on +MudCard `Elevation="4"` (a drop shadow). NowPlayingCard uses a **1px translucent border + no +shadow** for its flat-glass look. The track cards' Material drop-shadow is a different visual +vocabulary. For full alignment, consider `Elevation="0"` on the MudCard plus a +`1px solid rgba(250,250,248,0.12)` border on the container (dark) to match the glass edge. +Medium priority — this is what most distinguishes "Material card" from "NowPlayingCard glass +panel." Worth doing if the goal is genuine aesthetic match, not just color. + +### 3e. `--deepdrft-green-accent` is not defined inside `.deepdrft-theme-dark` + +The token block (`deepdrft-tokens.css`) defines `--deepdrft-green-accent: #3D7A68` only in +`:root`. The `.deepdrft-theme-dark` block re-declares the *alias* layer but inherits the raw +`--deepdrft-*` wireframe tokens from `:root`. NowPlayingCard already uses +`var(--deepdrft-green-accent)` successfully under dark, so the cascade resolves fine — **no +action needed**, just confirming the token is in scope for the new rules. Noting it so the +implementer doesn't worry the var is undefined in dark. + +--- + +## 4. Summary of edits for the implementer + +| File | Change | Priority | +|------|--------|----------| +| `DeepDrftShared.Client/Components/TrackCard.razor` | Drop `mud-theme-secondary` from fallback; drop `Color="Color.Surface"` from all 4 MudText; add class hooks `deepdrft-track-title` / `-artist` / `-meta` | required | +| `DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` §8 | Navy-glass fallback (dark), moss-green/off-white text (dark), light fallback fallback-bg, optional content scrim | required | +| same §8 / §9 | Genre chip distinct treatment (3a) | optional | +| `DeepDrftShared.Client/Components/TrackCard.razor` | MudCard `Elevation="0"` + glass border on container (3d) | recommended for true match | +| `TracksView.razor` skeleton tint (3c) | polish | defer | + +## 5. Open questions to resolve before / during implementation + +1. **Green on title vs. green on label** (§2b reading 1 vs 2). Default to reading 1 (title + in moss-green) unless the user says otherwise. +2. **Does the CMS host render TrackCard, and does it link `deepdrft-styles.css`?** Determines + whether the light-mode rules belong in `deepdrft-styles.css` or the shared token layer. + This is the only blocker for the light path; the dark path (what the user actually asked + for) is unblocked. +3. **Scrim or no scrim** over album art (§2c). Recommend yes; confirm. +4. **Match the glass edge** (Elevation 0 + border, §3d) — confirm the user wants full + aesthetic match vs. color-only.