# Mix Detail — Hero + MetaContent overlay rework (mirror the Sessions hero) — Design Spec

Status: **shipped on dev** (2026-06-16). Author: product-designer. Date: 2026-06-16.

## 0. Goal

Rework the **Mix detail** Hero + MetaContent so the **cover art becomes a background image** with **all
metadata laid out on top of it**, inside a **max-medium square cover-art region** — mirroring the
already-shipped **Session detail** hero-overlay composition. This consolidates the masthead + cover +
meta into one overlaid block, frees vertical room for the lava-lamp visualizer behind the content, and
cleans up the aesthetic so the Mix page reads as a member of the same design family as Sessions.

The Mix visualizer + eight-knob controls layout landed in the Phase 10 reframe (`TopRowCenter` slot,
in-flow controls container between the back link and the lava-lamp) **must be preserved unchanged** —
this rework touches only what sits *below* that top row.

---

## 1. What is actually shipped today (confirmed from live source, not spec)

Read of the live tree on 2026-06-16:

**Session detail** (`Pages/SessionDetail.razor` + `.razor.css`) — the target aesthetic, **already shipped**:

- **Does NOT use `ReleaseDetailScaffold`.** It composes its own hero overlay directly inside a
  `MudContainer MaxWidth="Large"`, and wires `PlayTrack` in its own `@code` block (the scaffold's
  play-toggle logic is duplicated here deliberately — see `SessionDetail.razor` lines 131–145).
- Structure: a `.session-hero` positioning context (`position: relative; aspect-ratio: 16/10;
  max-height: 70vh; min-height: 420px; overflow: hidden; border-radius: 8px`) holding:
  - `.session-hero-img` — a `MudPaper` whose `background-image` is the hero/cover image
    (`background-size: cover`), or a `.session-hero-placeholder` when none.
  - `.session-hero-shim` — a plain `<div>` darkening gradient (stronger top + bottom) for overlay legibility.
  - `.session-hero-top` — absolutely-positioned overlay row: genre chip + release-date + `SharePopover`.
  - `.session-hero-bottom` — absolutely-positioned overlay row: optional cover thumbnail + title/artist +
    `PlayStateIcon`.
- The back link (`.deepdrft-track-detail-back`) sits **above** the hero, in normal flow.
- CSS uses `::deep` on every class that lands on a MudBlazor child component's native output
  (`.session-hero-img` on `MudPaper`, `.session-overlay-chip.mud-chip` on `MudChip`,
  `.session-hero-bottom-row` on `MudStack`, the play/share icon-color overrides on `MudIconButton`).

**Mix detail** (`Pages/MixDetail.razor` + `.razor.css`) — the page to rework, **uses the scaffold**:

- `<MixWaveformVisualizer>` paints a fixed full-viewport backdrop (`z-index: 0`); a
  `.mix-detail-foreground` wrapper (`z-index: 1`) lifts the content above it; inside a
  `MudContainer MaxWidth="Large"` (class `mix-detail-container`) sits a `<ReleaseDetailScaffold>`.
- The scaffold's **`TopRowCenter`** slot holds `<MixVisualizerControls>`; **`TopRightAction`** holds the
  lava-lamp `MudIconButton` (the Phase 10 reframe layout — **do not touch**).
- The scaffold's **`Hero`** slot today is a `.mix-detail-cover` (square, `max-width: 220px`, centered)
  holding a `MudPaper` cover-art / placeholder. The **`MetaContent`** slot holds genre chip + release
  date. The masthead (title + artist) is rendered by the scaffold's **default header region** above the
  hero. The `BodyContent` slot holds the share row.

**The scaffold** (`Controls/ReleaseDetailScaffold.razor` + `.razor.cs`) — the shared chrome:

- Vertical order: top row (back | `TopRowCenter` | `TopRightAction`) → `TopContent` → header
  (masthead + play, or a custom `Header`) → `Hero` → divider + `MetaContent` (gated by `ShowMeta`) →
  `BodyContent` → default track-keyed share row (gated by `ShowShareRow`).
- Owns the back link and the play-toggle wiring. Cut and Track also consume it; Session does **not**.

**Render boundary (both detail pages are identical here — confirmed):** both `SessionDetail` and
`MixDetail` derive from `ReleaseDetailBase`, run under `InteractiveAuto`, and bridge the prerendered
release+track across the prerender→WASM seam via `PersistentComponentState` (keyed `session-detail` /
`mix-detail`). The release DTO (title, artist, genre, release date, `ImagePath`) is **available at first
render in both passes** — there is no render-mode divergence to design around. The image is served from
`api/image/{EscapeDataString(key)}` in both pages. **Conclusion: the data read at render time is the
same shape and same timing for both; the overlay rework is purely presentational.**

---

## 2. The DRY/SOLID question — where is the source of truth?

This is the load-bearing decision. The brief asks: extract a shared hero-overlay shell that both Sessions
and Mixes consume, or per-page duplication?

### The honest finding: the two pages are structurally divergent *by design today*

Sessions **deliberately does not use the scaffold** — it forks the whole chrome to get the overlay
composition. Mixes **does use the scaffold**, and the scaffold's `Hero`/`MetaContent`/masthead are
*separate stacked regions*, which is the opposite of "everything overlaid on the cover." So the two
pages do not share a hero today, and the scaffold's stacked-region model is not the overlay model.

Three meaningfully different directions, in shape:

**Direction A — Per-page copy.** Inline the `.session-hero` overlay structure into `MixDetail.razor`,
copy the `.session-*` CSS into `MixDetail.razor.css` (renamed `.mix-hero-*`), tune the square/medium
sizing. No shared component.
- *Pro:* fastest; zero risk to Sessions; Mix can diverge freely (it has a visualizer behind it that
  Sessions does not).
- *Con:* **two copies of the overlay cascade to keep in sync** — exactly the drift the `track-view-css-
  consolidation` note spent a pass undoing. The shim gradient, the overlay-label typography, the
  `::deep` icon-color overrides, the responsive wrap rules all get duplicated. A future overlay tweak
  has to land twice. Violates the "one source, multiple views" instinct (Daniel's standing preference).

**Direction B — Extract a shared `ReleaseHeroOverlay` component, both pages consume it.** Pull the
`.session-hero` overlay (image/placeholder + shim + top overlay + bottom overlay) into a new
`Controls/ReleaseHeroOverlay.razor` that takes the release data (+ optional play affordance + optional
share slot + optional cover-thumb) and renders the overlaid hero. Sessions swaps its inline hero for the
component; Mix renders the component inside its `.mix-detail-foreground`, **bypassing the scaffold's
`Hero`/`MetaContent`/masthead regions** (Mix stops using the scaffold for the hero, same as Sessions
already does).
- *Pro:* **one source of truth for the overlay** — the headline DRY win. Honors "same data shape,
  different rendering": both pages feed the same release DTO into one overlay VM/parameter set, the
  divergence (visualizer backdrop, square-vs-wide aspect) rides parameters/CSS, not a second copy.
  SOLID: the overlay is a single-responsibility presentational component; the pages compose it.
- *Con:* touches the **already-shipped Sessions page** (regression surface on a working view) and means
  Mix no longer routes its hero through the scaffold — Mix keeps the scaffold only for the back/controls
  top row, or drops the scaffold entirely (see §4 sub-decision). More upfront work; a real refactor.

**Direction C — Teach the scaffold an overlay mode.** Add an overlay-hero capability to
`ReleaseDetailScaffold` so it can render its `Hero`/masthead/`MetaContent` as one overlaid block when a
flag/slot says so; migrate Sessions onto the scaffold in overlay mode and switch Mix to overlay mode.
- *Pro:* one component owns *all* detail chrome including the overlay; Sessions finally joins the scaffold.
- *Con:* **largest blast radius and worst SOLID.** It bloats the scaffold with a second layout
  personality (stacked-regions *and* overlaid-hero) gated by a flag — exactly the "variance rides a
  flag" anti-pattern the scaffold's own convention forbids (Phase 9 §5.3: "layout variance rides a
  slot, never a boolean"). It also drags the working Sessions page through a chrome migration for no
  user-visible gain. Over-engineered for a two-consumer overlay.

### Recommendation: **Direction B — extract `ReleaseHeroOverlay`, both pages consume it.**

Rationale, with the trade-off stated plainly:

- **The source of truth should be one overlay component, not the scaffold and not a copy.** Sessions
  already proved the overlay wants to live *outside* the scaffold's stacked-region model — forcing it
  back into the scaffold (Direction C) fights that and bloats shared chrome. Copying it (Direction A)
  reintroduces the exact cascade-duplication this codebase already paid down once.
- **It satisfies "one source, multiple views" directly:** one overlay fed the same release DTO,
  rendering differences (Mix's visualizer backdrop, the square medium cover vs. Sessions' wide hero)
  expressed as component parameters + a CSS class, never as a forked structure.
- **The cost is real and must be owned:** Direction B edits the shipped Sessions page. That is a
  regression surface on a working view. Mitigation: extract by *moving* Sessions' exact current markup +
  CSS into the component first (a behavior-preserving lift — Sessions should look pixel-identical after),
  then point Mix at it. The Sessions migration is the risky step; treat it as its own wave with a
  before/after visual check (§7 acceptance).

**If Daniel wants to minimize risk to Sessions and ship Mix fast, Direction A is the acceptable
fallback** — but it takes on the duplication debt knowingly, and a later consolidation pass (like the
track-card one) becomes likely. Recommended only if the Sessions page is considered too load-bearing to
touch right now. **Flagging this as the one open decision for Daniel (§8, Q1).**

---

## 3. The shared component — `ReleaseHeroOverlay` (Direction B shape)

A new plain-shell presentational component: `DeepDrftPublic.Client/Controls/ReleaseHeroOverlay.razor`
(+ `.razor.css` carrying the overlay cascade, moved from `SessionDetail.razor.css`).

**Responsibility (single):** given a release's display data, render the background-image hero with the
metadata overlaid (top row: genre/date + share slot; bottom row: optional cover thumb + title/artist +
optional play affordance). It owns no data fetch, no player wiring beyond invoking a passed-in callback,
no JS interop.

**Parameters (the "same data shape" contract):**

| Parameter | Type | Purpose |
|-----------|------|---------|
| `HeroImageKey` | `string?` | The background image entry key (Sessions: hero-then-cover precedence; Mix: cover). Null → placeholder. |
| `PlaceholderIcon` | `string` | Material icon for the no-image placeholder (Sessions: `Piano`; Mix: `Album`). |
| `CoverThumbKey` | `string?` | Optional small cover thumbnail shown in the bottom row (Sessions shows it only when it differs from the hero image; Mix likely null — see §4). |
| `Title` / `Artist` | `string` / `string?` | Overlaid title + artist. |
| `Genre` | `string?` | Genre chip (top overlay) when present. |
| `ReleaseDate` | `DateOnly?` | Release date (top overlay) when present. |
| `ShareContent` | `RenderFragment?` | The share affordance (each page passes its `SharePopover` with the right release params). |
| `PlayContent` | `RenderFragment?` | The play affordance (each page passes its `PlayStateIcon` wired to its own toggle). |
| `Class` | `string?` | Extra class for per-page aspect/sizing variance (`mix-hero` vs default wide). |

Play/share ride as **slots**, not as wired-in player logic, so the component stays presentational and
each page keeps owning its own play-toggle (Sessions already does; the scaffold does for Mix today —
this preserves that ownership without the component reaching for the cascaded player).

**House constraint — plain-div shell.** The overlay shell (`.release-hero`, `.release-hero-shim`,
`.release-hero-top`, `.release-hero-bottom`) is **plain `<div>`s with project CSS classes**, exactly as
Sessions does today. The **background-image surface stays a `MudPaper`** *only because Sessions already
uses one there* — but note it carries no card affordances; if staff-engineer prefers, it can become a
plain `<div class="release-hero-img">` with the same `background-image` style, which is *more* aligned
with the plain-shell rule. **Recommendation: make it a plain `<div>`** and drop the `MudPaper` — there
is no MudPaper behavior being used (Elevation=0, Square=true), so the Mud wrapper is dead weight. This is
a small improvement over the shipped Sessions code; flag it to Daniel as an incidental cleanup
(§8, Q2). Chips/icons remain Mud components (they carry real behavior) and keep their `::deep` overrides.

---

## 4. Mix-specific composition + the square medium cover

Daniel's ask: "metadata laid out on top of a **max-medium square cover-art region**." Two design notes
specific to Mix that differ from Sessions:

### 4a. Aspect ratio — square medium, not Sessions' wide hero

Sessions uses `aspect-ratio: 16/10; max-height: 70vh; min-height: 420px` (a wide, tall hero). Daniel
wants Mix to use a **square** region at a **max-medium** size. The current Mix cover is `max-width:
220px` (small). "Max-medium square" reads as: a centered `aspect-ratio: 1/1` block, capped at a medium
width — recommend **`max-width: 420–480px`** (medium: bigger than the 360px track cover, smaller than
the Large container) — so the overlaid metadata has room to sit on the cover without crowding, while the
lava-lamp visualizer keeps the surrounding canvas. This rides the `Class` parameter (`mix-hero`) + a Mix
CSS rule, not a forked component.

- *Why square, not wide:* the Mix cover art is square album art; a 16/10 crop would letterbox or
  distort it, and the point is to free room for the visualizer, which a smaller square does better than a
  full-bleed wide hero.
- *Open sub-question (§8, Q3):* on a square overlay, the **top overlay row (genre/date/share) + bottom
  overlay row (title/artist/play) over a 480px square** may feel cramped versus Sessions' tall hero.
  Acceptable mitigation: keep the same two-overlay structure but let the shim carry more darkening, or
  drop the cover thumbnail (4b). Daniel tunes on screen per his standing preference.

### 4b. No cover thumbnail in the bottom row (recommended)

Sessions shows a small cover thumb in the bottom overlay *only when the hero image differs from the
cover* (it has a dedicated hero image distinct from the cover). **Mix has no separate hero image — the
cover art *is* the background.** So a cover thumbnail would duplicate the background. **Recommend Mix
passes `CoverThumbKey = null`** — the bottom overlay is just title/artist + play. This falls out of the
shared component's existing `showCover` logic for free.

### 4c. Mix keeps the scaffold for the top row only — or drops it

With the hero now a self-composed overlay (not the scaffold's `Hero`/`MetaContent`/masthead regions),
Mix has a sub-decision:

- **Option (i) — keep `ReleaseDetailScaffold` for the back/controls top row only.** Mix keeps supplying
  `TopRowCenter` (controls) + `TopRightAction` (lava-lamp) to the scaffold, but stops supplying `Hero` /
  `MetaContent` / the default masthead, and instead renders `<ReleaseHeroOverlay>` in `BodyContent` (or a
  new slot). **Problem:** the scaffold's default header region renders the masthead (title+artist) *and*
  a second `PlayStateIcon` — which would now duplicate the overlay's title/artist/play. Suppressing the
  scaffold's masthead requires the `Header` slot to render *nothing*, which is awkward (the slot exists to
  *replace* the masthead, and an empty `Header` is a smell).
- **Option (ii) — Mix drops the scaffold, composes directly like Sessions does.** Mix renders the back
  link + the controls top row + the lava-lamp + `<ReleaseHeroOverlay>` itself inside
  `.mix-detail-foreground`, mirroring how Sessions composes directly. **But** this loses the scaffold's
  ownership of the back link and the three-zone top-row structure that the Phase 10 reframe specifically
  built into the scaffold (`TopRowCenter`), and would duplicate that row.

**Recommendation: Option (i), with the scaffold's masthead suppressed by passing an empty-but-present
`Header` fragment** — *or*, cleaner, **the overlay renders inside the scaffold's existing `Hero` slot and
Mix passes a `Header` fragment that renders nothing** so the scaffold contributes only the top row +
hero. The least-smelly realization: **keep the scaffold (it owns the Phase 10 top row — the constraint we
must preserve), put `<ReleaseHeroOverlay>` in the `Hero` slot, leave `MetaContent` null (metadata now
lives in the overlay), and pass a no-op `Header` fragment to suppress the duplicate masthead/play.**
This preserves the visualizer/controls layout exactly (§5) while moving the hero+meta into the overlay.

> **Flag for staff-engineer:** an empty `Header` fragment to suppress the masthead is slightly awkward
> but is the lowest-risk way to keep the Phase 10 top row intact. If it reads badly in code, the
> alternative is a small scaffold change (a `ShowHeader` gate mirroring `ShowMeta`/`ShowShareRow`) — that
> is a *minimal, slot-consistent* scaffold edit (a gate, not a layout flag), acceptable under the Phase 9
> §5.3 convention because it suppresses an optional region rather than switching layouts. **Recommend the
> `ShowHeader` gate over the empty-fragment hack** if staff-engineer touches the scaffold anyway. Noted
> as §8 Q4.

---

## 5. Preserving the Phase 10 visualizer + controls layout (hard constraint)

The Phase 10 reframe put the controls in the scaffold's **`TopRowCenter`** slot and the lava-lamp in
**`TopRightAction`**, with the in-flow grow/collapse behavior and the `flex-wrap` responsive drop. This
rework **must not disturb any of that.** Concretely:

- **Keep the scaffold and its three-zone top row.** Mix continues supplying `TopRowCenter`
  (`<MixVisualizerControls>`) and `TopRightAction` (the lava-lamp `MudIconButton`) unchanged. The
  `_controlsExpanded` flag, `ToggleSettings`, and the filled/outline lamp glyph are untouched.
- **The overlay goes *below* the top row**, in the `Hero` slot — it occupies the space the old
  `.mix-detail-cover` + masthead + `MetaContent` occupied. Net effect: the region below the controls row
  gets *shorter* (one overlaid block instead of masthead + 220px cover + meta divider + meta row),
  which **frees more canvas for the lava-lamp visualizer** — exactly Daniel's stated goal.
- **`MixWaveformVisualizer` is unchanged.** It is a fixed full-viewport backdrop at `z-index: 0`; the
  overlay rides inside `.mix-detail-foreground` (`z-index: 1`) like the current cover does. The footer
  clip / lava-rest-line work (Phase 10 §2c) is independent of this and unaffected.
- **`MetaContent` becomes null** (metadata moves into the overlay), so the scaffold's divider +
  `.deepdrft-track-detail-meta` row no longer renders for Mix. The share row moves into the overlay's
  `ShareContent` slot (matching Sessions, which overlays share top-right).

**Acceptance tie-in:** after the rework, expanding the controls still grows the in-flow container between
back and lamp, still wraps on narrow widths, and the lava-lamp still toggles it — no change to that
interaction (§7).

---

## 6. CSS approach

- **The overlay cascade moves into `ReleaseHeroOverlay.razor.css`** (Direction B), renamed from
  `.session-*` to neutral `.release-hero-*`. Sessions' `SessionDetail.razor.css` keeps only what is
  page-specific (the `.session-detail-page` padding, the per-page aspect overrides if any); Mix's
  `MixDetail.razor.css` keeps only the `.mix-detail-foreground` z-index lift + the `mix-hero` square/
  medium sizing override.
- **`::deep` is required** wherever a class lands on a MudBlazor child component's native output — this
  is unchanged from Sessions today and must carry into the shared component's scoped CSS:
  - the background-image surface **if it stays `MudPaper`** (`::deep .release-hero-img`) — *avoidable by
    making it a plain `<div>`, §3, which removes the `::deep` need for that element entirely*;
  - the genre chip on `MudChip` (`::deep .release-overlay-chip.mud-chip`);
  - the bottom-row `MudStack` wrap (`::deep .release-hero-bottom-row`);
  - the play/share icon-color overrides on `MudIconButton`/`MudProgressCircular`
    (`::deep .release-hero-play .mud-icon-button`, etc.).
- **The square/medium aspect for Mix** is a single override scoped to the `mix-hero` class
  (`aspect-ratio: 1/1; max-width: ~480px; margin-inline: auto`) — it overrides the component's default
  wide aspect. This is the "divergence rides CSS, not structure" realization of the one-source rule.
- **No `MudCard`/`MudPaper` shell for the overlay container** (house rule). The `.release-hero`
  positioning context, the shim, and both overlay rows are plain `<div>`s — as Sessions already does.
  The only Mud wrappers that remain are the chip, the icon buttons, and (optionally) the image surface —
  each carrying real component behavior, none acting as a layout shell. **If staff-engineer reaches for a
  Mud wrapper as a layout shell, stop and flag it** (per the standing constraint).

---

## 7. Acceptance criteria (observable)

1. **Cover-as-background.** On a Mix detail page with a cover image, the cover renders as a
   background-image hero (`background-size: cover`), not as a bordered thumbnail; metadata sits overlaid
   on top of it.
2. **Square medium region.** The hero is a centered square (`aspect-ratio: 1/1`) capped at a medium
   width (~480px), visibly larger than the old 220px cover, with the surrounding canvas left to the
   visualizer.
3. **All metadata overlaid.** Title, artist, genre (when present), release date (when present), and the
   share affordance all render *over* the cover image — no separate masthead block, no separate meta
   divider/row below the cover.
4. **Placeholder path.** A Mix with no cover image shows the placeholder treatment (Album icon over the
   soft-secondary gradient) with metadata still legibly overlaid.
5. **Legibility.** The darkening shim keeps overlaid text readable over light and dark cover art, in both
   light and dark theme.
6. **Visualizer/controls preserved.** The lava-lamp toggle still opens the in-flow eight-knob controls
   container between the back link and the lamp; it still grows in place, still wraps on narrow widths,
   and the lava-lamp glyph still swaps filled/outline. No regression to the Phase 10 layout.
7. **More canvas for the visualizer.** The content block below the controls row is shorter than before
   (one overlaid hero vs. masthead + cover + meta), leaving more visible visualizer area.
8. **Sessions unchanged (Direction B).** After the shared-component extraction, the Session detail page
   renders pixel-identically to before (before/after visual check on a session with a dedicated hero
   image, a session with cover-only, and a session with no image).
9. **One source of truth (Direction B).** The overlay markup + cascade exists in exactly one component;
   grepping for `.session-hero` / `.release-hero` finds no duplicate structure across the two pages.
10. **No Mud layout shell.** The overlay container, shim, and overlay rows are plain `<div>`s; no
    `MudCard`/`MudPaper` acts as a layout wrapper (image surface excepted only if kept as `MudPaper`).

---

## 8. Open questions for Daniel

1. **DRY decision (the load-bearing one).** Recommended **Direction B** — extract a shared
   `ReleaseHeroOverlay` both pages consume (one source of truth; edits the shipped Sessions page).
   Fallback **Direction A** — per-page copy in Mix (fast, zero Sessions risk, takes on duplication debt).
   **Which do you want?** (B is the "one source, multiple views" call; A is the play-it-safe-on-Sessions
   call.)
2. **Drop the `MudPaper` on the image surface** for a plain `<div class="release-hero-img">` while we're
   in here? It carries no Mud behavior (Elevation=0/Square=true), so it is dead weight and a plain div is
   more on-spec with the plain-shell rule. Incidental cleanup — yes/no?
3. **Square hero size.** Recommended ~**480px max-width** square. Crowded vs. roomy is a feel call you'll
   tune on screen — is ~480px the right starting point, or do you want it bigger (closer to the Sessions
   hero scale) / smaller (more visualizer room)?
4. **Suppressing the duplicate masthead.** Mix's hero now carries title/artist/play, so the scaffold's
   default masthead must be suppressed. Recommended: add a small **`ShowHeader` gate** to the scaffold
   (slot-consistent with `ShowMeta`/`ShowShareRow`), vs. the hackier empty-`Header`-fragment. OK to add
   the `ShowHeader` gate?
5. **Square overlay crowding (deferrable).** If the genre/date/share top row + title/artist/play bottom
   row feel cramped on a 480px square, are you fine tuning shim/spacing on screen, or do you want a
   different overlay arrangement for the square (e.g. a single bottom-stacked overlay) speced now?

---

## 9. File-change inventory (for staff-engineer, Direction B)

**New:**
- `DeepDrftPublic.Client/Controls/ReleaseHeroOverlay.razor` (+ `.razor.css`) — the shared overlay,
  lifted from Sessions' current hero markup + CSS, parameterized per §3.

**Edited:**
- `DeepDrftPublic.Client/Pages/SessionDetail.razor` — replace the inline `.session-hero` block with
  `<ReleaseHeroOverlay ... />`, passing its hero/cover precedence, share, and play slots. Behavior-
  preserving (must render identically).
- `DeepDrftPublic.Client/Pages/SessionDetail.razor.css` — remove the overlay cascade now living in the
  component; keep only page-specific rules.
- `DeepDrftPublic.Client/Pages/MixDetail.razor` — replace the `.mix-detail-cover` `Hero` slot with
  `<ReleaseHeroOverlay Class="mix-hero" ... CoverThumbKey="null" />`; drop `MetaContent`; move the share
  row into the overlay's `ShareContent` slot; suppress the scaffold masthead (per Q4). **`TopRowCenter` /
  `TopRightAction` / the visualizer / `_controlsExpanded` wiring untouched.**
- `DeepDrftPublic.Client/Pages/MixDetail.razor.css` — keep `.mix-detail-foreground`; add the `mix-hero`
  square/medium sizing override; remove `.mix-detail-cover`.
- `DeepDrftPublic.Client/Controls/ReleaseDetailScaffold.razor[.cs]` — **only if Q4 = ShowHeader gate:**
  add a `bool ShowHeader = true` gate around the default header region.
- `DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` — no change required; `.deepdrft-track-detail-
  cover*` stays (Track detail still uses it). The `.mix-detail-container .deepdrft-track-detail-
  container` width override stays (the scaffold still hosts the top row).

**For Direction A (fallback):** no new component; the overlay markup is inlined into `MixDetail.razor`
and the `.session-*` cascade is copied + renamed into `MixDetail.razor.css`. Sessions untouched.
