docs: mark track-card plain-shell refactor completed
This commit is contained in:
@@ -0,0 +1,446 @@
|
||||
# Track Card CSS Architecture — eliminate `!important` from section 8
|
||||
|
||||
Status: completed. Author: product-designer. Date: 2026-06-05. Implementer: daniel-c-harvey. Landed: 2026-06-05.
|
||||
|
||||
Predecessor: [`track-card-theming.md`](track-card-theming.md) (completed 2026-06-05) landed the
|
||||
navy-glass + moss-green treatment and, in doing so, introduced the two `!important` rules this
|
||||
spec exists to remove. That note is the *what it should look like*; this note is the *how the
|
||||
CSS should be structured so it looks like that without `!important`*. Nothing here changes the
|
||||
visual design — only the mechanism.
|
||||
|
||||
---
|
||||
|
||||
## §1. Root cause analysis — why MudCard/MudPaper fight our CSS
|
||||
|
||||
### 1.1 The two `!important` rules in question
|
||||
|
||||
`DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` section 8:
|
||||
|
||||
```css
|
||||
.deepdrft-track-card-container { ... background: transparent !important; } /* line 222 */
|
||||
.deepdrft-track-card-fallback { ... background: var(--deepdrft-navy-mid, #162437) !important; } /* line 268 */
|
||||
.deepdrft-theme-dark .deepdrft-track-card-fallback { ... !important; } /* line 273 */
|
||||
.deepdrft-theme-light .deepdrft-track-card-fallback { ... !important; } /* line 280 */
|
||||
```
|
||||
|
||||
Four `!important` declarations, all on `background`, all on elements rendered by MudBlazor
|
||||
(`MudCard` → container, `MudPaper` → fallback).
|
||||
|
||||
### 1.2 What MudBlazor paints and with what selector
|
||||
|
||||
MudBlazor ships a single global `<style>` block (injected by `MudThemeProvider`, served as
|
||||
`_content/MudBlazor/MudBlazor.min.css`). The relevant rules are roughly:
|
||||
|
||||
```css
|
||||
.mud-paper {
|
||||
background-color: var(--mud-palette-surface); /* the conflict */
|
||||
color: var(--mud-palette-text-primary);
|
||||
...
|
||||
}
|
||||
.mud-card { /* composes .mud-paper */ }
|
||||
```
|
||||
|
||||
`MudCard` and `MudPaper` both render a root element carrying the `.mud-paper` class, and
|
||||
`--mud-palette-surface` resolves to `DeepDrftPalettes.Surface` — `#162437` (navy-mid) in dark,
|
||||
`#FAFAF8` (off-white) in light. So **every** track card root gets a painted surface color we do
|
||||
not want, because we layer our own album-art div / fallback glass / scrim underneath the content.
|
||||
|
||||
### 1.3 Why our scoped CSS can't reach it and `!important` was the escape hatch
|
||||
|
||||
Two compounding facts:
|
||||
|
||||
1. **Specificity / source-order.** `.mud-paper { background-color: ... }` is a single class
|
||||
selector (specificity `0,1,0`). Our `.deepdrft-track-card-container { background: ... }` is
|
||||
*also* a single class selector (`0,1,0`). When specificity ties, **source order wins** — and
|
||||
MudBlazor's stylesheet load order relative to `deepdrft-styles.css` is not something section 8
|
||||
controls reliably (framework CSS, theme-injected CSS, and our sheet are separate links). To
|
||||
guarantee we win regardless of order, the author reached for `!important`. That is the smell:
|
||||
`!important` is being used to paper over an *ordering/specificity* uncertainty, not a genuine
|
||||
need.
|
||||
|
||||
2. **CSS isolation cannot help here.** This is the deeper structural reason. Blazor scoped CSS
|
||||
(`*.razor.css`) works by stamping a `b-<hash>` attribute onto elements *that Blazor renders*
|
||||
and rewriting the scoped selector to `.foo[b-<hash>]` (specificity `0,2,0` — would beat
|
||||
`.mud-paper`). But `MudCard`/`MudPaper` render their **own** inner HTML; Blazor never stamps
|
||||
the scope attribute onto MudBlazor's internal elements. So a `TrackCard.razor.css` rule
|
||||
targeting `.mud-paper` would compile to `.mud-paper[b-<hash>]` and match **nothing**. (This is
|
||||
also why no `TrackCard.razor.css` exists today — it would be inert against the very elements
|
||||
that need overriding.) The team correctly fell back to global rules in section 8 — but global
|
||||
single-class rules don't beat MudBlazor without either higher specificity or `!important`.
|
||||
|
||||
**The fundamental mismatch:** we are using MudBlazor surface components (`MudCard`, `MudPaper`)
|
||||
as *layout shells* while wanting to own their backgrounds entirely. MudBlazor's whole contract is
|
||||
"I paint the surface from the palette." We are fighting the component's purpose. Every option
|
||||
below is a different way to stop fighting it.
|
||||
|
||||
### 1.4 What we actually need from these two elements
|
||||
|
||||
Stripped to first principles, the container and fallback need:
|
||||
- **Container:** a `position: relative`, fixed-size, `overflow: hidden` box. A *transparent*
|
||||
stacking context so the album-art div, fallback glass, and content scrim layer correctly.
|
||||
No surface paint, no Material elevation (already `Elevation="0"`), no ripple.
|
||||
- **Fallback:** an absolutely-positioned full-bleed panel painted with our navy-glass (dark) or
|
||||
navy-tint (light) treatment, with a border + `backdrop-filter`.
|
||||
|
||||
Neither needs anything MudBlazor's surface model provides. That observation drives the
|
||||
recommendation.
|
||||
|
||||
---
|
||||
|
||||
## §2. Option A — Replace container + fallback with plain `<div>`
|
||||
|
||||
Drop `MudCard` → `<div class="deepdrft-track-card-container">` and the fallback `MudPaper` →
|
||||
`<div class="deepdrft-track-card-fallback">`. Keep `MudCardContent`, `MudText`, `MudChip`,
|
||||
`MudFab` (none of these own a competing background once the card root is a plain div — and the
|
||||
text/chip/fab already work today).
|
||||
|
||||
**Note:** `MudCardContent` technically expects a `MudCard` ancestor, but it only emits a
|
||||
`<div class="mud-card-content">` with padding — no background, no JS, no required parent context.
|
||||
It renders fine inside a plain div. If we want zero MudBlazor coupling in the shell, it can also
|
||||
become a plain `<div class="deepdrft-track-card-content">` (the class already carries all the
|
||||
real styling — padding, flex, z-index, scrim). Recommend replacing it too, for consistency.
|
||||
|
||||
### Pros
|
||||
- **Removes the conflict at the source.** No `.mud-paper` background means no `!important`
|
||||
anywhere. Section 8 backgrounds become plain single-class rules that win by default.
|
||||
- **Re-enables CSS isolation as an option.** With plain divs, a future `TrackCard.razor.css`
|
||||
*would* work (Blazor stamps the scope attribute on divs it renders). We are not required to use
|
||||
it — section 8's public-only scoping is still convenient per the predecessor note — but the door
|
||||
reopens. This satisfies the "design the seam" instinct: we are not just fixing today, we are
|
||||
removing a structural block.
|
||||
- **Precedent already exists in this codebase.** `NowPlayingCard.razor` is built entirely from
|
||||
plain `<div>`s with a `.razor.css` and achieves the *exact aesthetic these cards are imitating*.
|
||||
This option makes TrackCard structurally consistent with the component it was told to match.
|
||||
The two should be siblings in construction, not one Material and one hand-rolled.
|
||||
- **Lighter DOM + less CSS the browser must override.** Removes `.mud-card` / `.mud-paper`
|
||||
rulesets from applying to these nodes entirely.
|
||||
|
||||
### Cons — what MudBlazor functionality is lost
|
||||
- **Elevation shadow:** already `Elevation="0"` on both elements (current Razor). Nothing lost —
|
||||
the design explicitly moved to flat-glass (predecessor §3d). A plain div is the honest
|
||||
expression of `Elevation="0"`.
|
||||
- **Ripple:** `MudCard`/`MudPaper` do **not** ripple (ripple is a `MudButton`/`MudFab`/`MudIconButton`
|
||||
behavior). The card is not clickable as a whole — the only interactive element is the `MudFab`,
|
||||
which stays and keeps its ripple. Nothing lost.
|
||||
- **ARIA / semantics:** `MudCard` renders a plain `<div>` with no implicit role — it adds no ARIA
|
||||
semantics a plain div lacks. The card conveys meaning through its text content and the labeled
|
||||
FAB, not through a container role. Nothing lost. (If anything, a future enhancement could add an
|
||||
explicit `role`/`aria-label` to the div — easier on a plain element than fighting MudBlazor's.)
|
||||
- **Theme reactivity of the surface color:** we *want* to lose this — the whole problem is that
|
||||
MudBlazor repaints the surface from the palette. Our section-8 rules are already theme-aware via
|
||||
`.deepdrft-theme-dark` / `-light` wrappers, so theme switching still works.
|
||||
- **Migration cost:** ~6 lines of Razor changed. Trivial.
|
||||
|
||||
**Assessment:** acceptable in full. There is no MudBlazor capability the track-card shell actually
|
||||
uses. This is the option that resolves the root cause rather than the symptom.
|
||||
|
||||
---
|
||||
|
||||
## §3. Option B — Inline `Style="background: transparent"` on MudCard/MudPaper
|
||||
|
||||
Keep the MudBlazor components; pass an inline style to clear their background:
|
||||
|
||||
```razor
|
||||
<MudCard Class="deepdrft-track-card-container" Elevation="0" Style="background: transparent;">
|
||||
<MudPaper Class="deepdrft-track-card-fallback" Elevation="0" Style="background: transparent;">
|
||||
```
|
||||
|
||||
Inline styles have specificity above any selector (and above `!important` from a stylesheet, for
|
||||
non-`!important` inline declarations the inline wins over normal stylesheet rules; MudBlazor's
|
||||
`.mud-paper` background is *not* `!important`, so inline transparent beats it cleanly).
|
||||
|
||||
But note: the fallback's *real* navy-glass paint then has to come from **somewhere**. If we set
|
||||
the MudPaper transparent inline and paint via `.deepdrft-track-card-fallback` in CSS, we are
|
||||
back to a CSS class trying to beat `.mud-paper` — except now `.mud-paper` is already transparent
|
||||
(inline), so our class wins without `!important`. That works. The container is simpler: it just
|
||||
wants transparent, which the inline gives directly.
|
||||
|
||||
### Pros
|
||||
- No `!important`. Inline transparent neutralizes `.mud-paper`, then our classes paint normally.
|
||||
- Smaller change than Option A (no element swap), keeps MudBlazor components if there's a reason
|
||||
to (there isn't a strong one here).
|
||||
- No risk of `MudCardContent`-without-`MudCard` edge cases.
|
||||
|
||||
### Cons
|
||||
- **Scatters styling concern into Razor.** The whole point of section 8 is centralized,
|
||||
theme-aware card styling. An inline `Style` on the component is a second place card appearance
|
||||
is decided — exactly the maintenance split the team should avoid. Next person editing the card
|
||||
background looks in section 8, doesn't find the override, and is confused.
|
||||
- **Doesn't address the root mismatch.** We're still using a surface component as a layout shell
|
||||
and then telling it "don't be a surface." It reads as an apology for the wrong component choice.
|
||||
- **CSS isolation stays blocked** — MudBlazor still renders the inner HTML, so a `.razor.css`
|
||||
still can't reach it. The seam stays closed.
|
||||
- **Inline `transparent` is itself a quiet "magic override."** It's `!important` by another name —
|
||||
a higher-specificity hammer applied at the element. Marginally cleaner than `!important` in a
|
||||
sheet, but the same category of move: beating MudBlazor by force rather than not inviting the
|
||||
fight.
|
||||
|
||||
**Assessment:** cleaner than `!important` strictly speaking, but trades one smell (sheet
|
||||
`!important`) for a milder one (scattered inline overrides) and leaves the structural mismatch and
|
||||
the blocked isolation seam intact. A lateral move, not a fix.
|
||||
|
||||
---
|
||||
|
||||
## §4. Option C — Override `--mud-palette-surface` locally on the container
|
||||
|
||||
Scope a CSS custom-property override to the card so MudBlazor's own
|
||||
`background-color: var(--mud-palette-surface)` resolves to transparent inside the card subtree:
|
||||
|
||||
```css
|
||||
.deepdrft-track-card-container {
|
||||
--mud-palette-surface: transparent;
|
||||
}
|
||||
```
|
||||
|
||||
Because `.mud-paper` reads `var(--mud-palette-surface)` and custom properties inherit, both the
|
||||
container's own paint and the nested `MudPaper` fallback would inherit the transparent value — no
|
||||
`!important` needed (we're changing the *input* to MudBlazor's rule, not overriding the rule).
|
||||
|
||||
### Pros
|
||||
- No `!important`, no inline styles, no element swap. One declaration.
|
||||
- Works *with* MudBlazor's mechanism instead of against it — arguably the most "correct" CSS-vars
|
||||
approach. We feed the palette variable the value we want for this subtree.
|
||||
- Centralized in section 8.
|
||||
|
||||
### Cons
|
||||
- **Blast radius is the whole subtree.** `--mud-palette-surface` is read by *many* MudBlazor
|
||||
components, not just paper. Any MudBlazor component nested in the card that relies on
|
||||
`--mud-palette-surface` (now or in future) silently renders transparent. Today the card nests
|
||||
`MudChip` and `MudFab` — both read other palette vars (`--mud-palette-primary` etc.), but a
|
||||
future addition (a `MudMenu`, a `MudTooltip` surface, a `MudPaper` accent) would inherit the
|
||||
transparent surface and break subtly. This is a **spooky-action-at-a-distance** override: it
|
||||
works today but plants a trap.
|
||||
- **Fragile against MudBlazor internals.** It depends on `.mud-paper` continuing to read exactly
|
||||
`--mud-palette-surface` for its background. If a MudBlazor version computes the surface
|
||||
differently (e.g. a derived var, or `color-mix`), the override misses. Coupling our fix to a
|
||||
framework implementation detail is a maintenance liability — the kind of thing that breaks on a
|
||||
minor version bump with no compile error.
|
||||
- **Still doesn't reopen CSS isolation.** Same as B — MudBlazor renders the HTML.
|
||||
- **Obscure.** The next maintainer sees a card rendering transparent and has no obvious thread to
|
||||
pull — the cause is a custom-property override three rules up, not a `background` declaration.
|
||||
Low discoverability.
|
||||
|
||||
**Assessment:** the most elegant-looking, the most dangerous. It's a clever override that depends
|
||||
on framework internals and leaks into every descendant. Reject for the trap it sets, despite the
|
||||
aesthetics.
|
||||
|
||||
---
|
||||
|
||||
## §5. Option D — Keep `!important` with a clear comment
|
||||
|
||||
Leave the four `!important`s, add a comment explaining the MudBlazor specificity conflict, accept
|
||||
it as documented technical debt.
|
||||
|
||||
### Pros
|
||||
- Zero change, zero risk. The cards render correctly today.
|
||||
- A good comment turns a mystery smell into a known, explained trade-off — which is genuinely
|
||||
better than an *unexplained* `!important`.
|
||||
|
||||
### Cons
|
||||
- **Doesn't meet the stated goal.** The task is explicitly to *eliminate* `!important` from
|
||||
section 8. Documenting it is not eliminating it.
|
||||
- **`!important` is contagious.** Once the card backgrounds are `!important`, any future rule that
|
||||
needs to legitimately override them (a "now playing" highlight state on a card, a selected
|
||||
state, a hover treatment) must *also* be `!important`, escalating the war. The predecessor note
|
||||
already floats a genre-chip treatment and skeleton tints — feature growth on this card is
|
||||
expected, and each new state inherits the `!important` tax.
|
||||
- **Leaves the structural mismatch and blocked isolation seam in place** — same as B and C.
|
||||
|
||||
**Assessment:** honest, but it's the do-nothing option dressed as a decision. Acceptable only if
|
||||
all other options were blocked, which they are not. The comment is worth keeping *as a fallback*
|
||||
if Option A is somehow rejected.
|
||||
|
||||
---
|
||||
|
||||
## §6. Recommendation — Option A (plain `<div>` shell)
|
||||
|
||||
**Replace `MudCard` and the fallback `MudPaper` with plain `<div>`s. Replace `MudCardContent` with
|
||||
a plain `<div>` too (it carries no behavior). Keep `MudText`, `MudChip`, `MudFab`.** This removes
|
||||
all four `!important` declarations, preserves the glass-card aesthetic exactly (the section-8 paint
|
||||
rules are unchanged except for dropping `!important`), is the most maintainable, and aligns
|
||||
TrackCard structurally with `NowPlayingCard` — the very component it was designed to imitate.
|
||||
|
||||
Why A over the others, in one line each:
|
||||
- **Over B (inline transparent):** A fixes the root mismatch and reopens the isolation seam; B
|
||||
scatters overrides and leaves both problems.
|
||||
- **Over C (palette-var override):** A has no blast radius and no coupling to MudBlazor internals;
|
||||
C plants a transparent-surface trap for every future nested component.
|
||||
- **Over D (keep `!important`):** A meets the stated goal; D doesn't.
|
||||
|
||||
Trade-off being accepted with A: TrackCard's shell stops being a MudBlazor component. That is a
|
||||
*feature* here (the card never used MudBlazor's surface behavior), but it does mean the shell no
|
||||
longer auto-reacts to a future palette change to `Surface` — which is exactly what we want, since
|
||||
our theme-aware section-8 rules own the card's appearance. No real cost.
|
||||
|
||||
---
|
||||
|
||||
### 6.1 Exact Razor changes — `DeepDrftShared.Client/Components/TrackCard.razor`
|
||||
|
||||
Replace the current file body with the following. Only the three shell elements change
|
||||
(`MudCard`→`div`, `MudPaper`→`div`, `MudCardContent`→`div`); all class hooks, `MudText`,
|
||||
`MudChip`, and `MudFab` are preserved verbatim from the current file.
|
||||
|
||||
```razor
|
||||
<div class="deepdrft-track-card-container">
|
||||
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.ImagePath))
|
||||
{
|
||||
<div class="deepdrft-track-card-bg" style="background-image: url('@TrackModel.ImagePath');">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="deepdrft-track-card-fallback"></div>
|
||||
}
|
||||
|
||||
<div class="deepdrft-track-card-content">
|
||||
|
||||
<div class="deepdrft-track-info-top">
|
||||
<MudText Typo="Typo.subtitle1"
|
||||
Class="deepdrft-track-title text-truncate mb-1">
|
||||
@TrackModel?.TrackName
|
||||
</MudText>
|
||||
|
||||
<MudText Typo="Typo.caption"
|
||||
Class="deepdrft-track-artist text-truncate mb-2">
|
||||
@TrackModel?.Artist
|
||||
</MudText>
|
||||
</div>
|
||||
|
||||
<div class="deepdrft-track-info-middle">
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Album))
|
||||
{
|
||||
<MudText Typo="Typo.caption"
|
||||
Class="deepdrft-track-meta text-truncate">
|
||||
@TrackModel.Album
|
||||
</MudText>
|
||||
}
|
||||
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Genre))
|
||||
{
|
||||
<MudChip T="string"
|
||||
Size="Size.Small"
|
||||
Variant="Variant.Filled"
|
||||
Color="Color.Primary"
|
||||
Class="deepdrft-genre-chip">
|
||||
@TrackModel.Genre
|
||||
</MudChip>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="deepdrft-track-info-bottom">
|
||||
@if (TrackModel?.ReleaseDate.HasValue == true)
|
||||
{
|
||||
<MudText Typo="Typo.caption"
|
||||
Class="deepdrft-track-meta">
|
||||
@TrackModel.ReleaseDate.Value.Year
|
||||
</MudText>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div></div>
|
||||
}
|
||||
|
||||
<MudFab Color="Color.Primary"
|
||||
Size="Size.Medium"
|
||||
StartIcon="@PlayPauseIcon"
|
||||
OnClick="@PlayClick"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
Changes, precisely:
|
||||
- Line 1–2: `<MudCard Class="deepdrft-track-card-container" Elevation="0">` →
|
||||
`<div class="deepdrft-track-card-container">`. (Drop `Elevation="0"` — meaningless on a div; the
|
||||
flat look is the default.)
|
||||
- Line 11–13: `<MudPaper Class="deepdrft-track-card-fallback" Elevation="0"></MudPaper>` →
|
||||
`<div class="deepdrft-track-card-fallback"></div>`.
|
||||
- Line 16: `<MudCardContent Class="deepdrft-track-card-content">` →
|
||||
`<div class="deepdrft-track-card-content">`.
|
||||
- Line 72 (`</MudCard>`) → `</div>`; the `</MudCardContent>` close (line 70) → `</div>`.
|
||||
|
||||
No change to `TrackCard.razor.cs` — it references no MudBlazor card types (only `Icons`,
|
||||
`TrackDto`, `EventCallback`). The `using MudBlazor;` stays (still used by `Icons.Material`).
|
||||
|
||||
### 6.2 Exact CSS changes — `DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` section 8
|
||||
|
||||
Remove `!important` from all four declarations. No other change — the colors, layout, and
|
||||
theme-aware scoping all stay exactly as they are.
|
||||
|
||||
**Line 216–223** — container:
|
||||
```css
|
||||
.deepdrft-track-card-container {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
min-width: 250px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: transparent; /* was: transparent !important */
|
||||
}
|
||||
```
|
||||
|
||||
**Line 262–269** — fallback base:
|
||||
```css
|
||||
.deepdrft-track-card-fallback {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--deepdrft-navy-mid, #162437); /* was: ... !important */
|
||||
}
|
||||
```
|
||||
|
||||
**Line 272–276** — fallback dark:
|
||||
```css
|
||||
.deepdrft-theme-dark .deepdrft-track-card-fallback {
|
||||
background: color-mix(in srgb, var(--deepdrft-navy) 55%, transparent); /* was: ... !important */
|
||||
border: 1px solid rgba(250, 250, 248, 0.12);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
```
|
||||
|
||||
**Line 279–282** — fallback light:
|
||||
```css
|
||||
.deepdrft-theme-light .deepdrft-track-card-fallback {
|
||||
background: color-mix(in srgb, var(--deepdrft-navy) 8%, var(--deepdrft-white)); /* was: ... !important */
|
||||
border: 1px solid var(--deepdrft-border);
|
||||
}
|
||||
```
|
||||
|
||||
After this change, the four backgrounds are plain single-class (and class-under-theme-wrapper)
|
||||
rules painting plain `<div>`s. Nothing competes; nothing needs `!important`. The
|
||||
`.deepdrft-theme-dark .deepdrft-track-card-fallback` selector is `0,2,0` and the base is `0,1,0`,
|
||||
so the theme override correctly beats the base — the normal cascade, working as intended.
|
||||
|
||||
### 6.3 Verification checklist for the implementer
|
||||
- Dark public site: card with album art shows art + scrim + green/off-white text; card without
|
||||
art shows navy-glass fallback. No grey/teal surface flash on hydration (the base
|
||||
`--deepdrft-navy-mid` fallback rule still covers the no-wrapper-class window).
|
||||
- Light public site: fallback shows the navy-tint-on-white panel; text legible.
|
||||
- Toggle dark/light: card repaints correctly (theme-wrapper-scoped rules still drive it).
|
||||
- Confirm no other component references `.deepdrft-track-card-container` / `-fallback` expecting a
|
||||
`.mud-paper` ancestor (grep — `TracksGallery.razor` wraps cards but only positions them via
|
||||
`.deepdrft-track-gallery-item-center`).
|
||||
- Confirm the rendered card root is now a plain `<div>` (devtools) with **no** `.mud-paper` /
|
||||
`.mud-card` class, and that no `background ... !important` remains anywhere in section 8.
|
||||
|
||||
### 6.4 What this unblocks (not in scope, noted for the seam)
|
||||
With a plain-div shell, the deferred polish items from the predecessor note become cleaner to
|
||||
implement and could, if desired, migrate to a real `TrackCard.razor.css` (now functional):
|
||||
genre-chip distinct treatment (predecessor §3a), skeleton tints (§3c), card hover/selected/now-
|
||||
playing states. None are required by this spec; flagged so a future pass knows the seam is open.
|
||||
|
||||
---
|
||||
|
||||
## §7. Fallback position
|
||||
|
||||
If Option A is rejected for a reason not surfaced here (e.g. a policy that shell components must
|
||||
remain MudBlazor for consistency with other cards), the next-best is **Option D with comments** —
|
||||
not B or C. B scatters the override and C couples to framework internals; a *documented*
|
||||
`!important` is more honest and more maintainable than either clever hack. But A has no real cost
|
||||
identified, so this fallback should not be needed.
|
||||
```
|
||||
Reference in New Issue
Block a user