fix(theme): green hero Share/Play/Queue glyphs in dark via shared .dd-accent-icon

Fold Session/Mix hero glyphs into the reusable accent-icon treatment so they reach
the glyph (beating .mud-secondary-text) green-accent in both themes; drop the dead
wrapper white rule and the redundant dark-only hero override. Light pixel-identical.
This commit is contained in:
daniel-c-harvey
2026-06-20 02:21:11 -04:00
parent 4c56eededc
commit 2fbb1c9b95
7 changed files with 72 additions and 67 deletions
@@ -751,68 +751,70 @@ body:has(.waveform-visualizer-control-overlay) {
}
}
/* Dark-theme interactive affordances in the Cut detail header and track rows.
In dark mode, Color.Secondary resolves to off-white (#FAFAF8), making filled
and icon buttons unreadable on the light-ish dark-navy surface. Override to
green (--deepdrft-primary = green-accent in dark, --deepdrft-navy as text) to
match the "green = interactive" convention (see hero button dark rule above).
Scoped to .cut-detail-actions and .cut-detail-track-row so the hero-overlay
icons (.release-hero-play / .release-hero-share, forced white in
ReleaseHeroOverlay.razor.css) are never touched. */
/* =============================================================================
INTERACTIVE-ACCENT ICON TREATMENT (.dd-accent-icon / .dd-accent-fill)
----------------------------------------------------------------------------
The single, reusable green-accent treatment for interactive icon affordances —
replaces the per-site dark-mode overrides that previously had to fight the palette.
/* Play button (Variant.Filled, Color.Secondary) in the cut detail header */
.deepdrft-theme-dark .cut-detail-actions .mud-button-filled {
background-color: var(--deepdrft-primary);
color: var(--gradient-base);
WHY a class and not a palette colour: no MudBlazor Color enum is green in BOTH
themes (Dark.Secondary is off-white, Dark.Primary is green; Light.Secondary is
green, Light.Primary is navy), so every "green in both" affordance had to be
patched per-site. --deepdrft-green-accent (#3D7A68) is the brand constant — the
SAME value in both palettes — so a non-theme-scoped rule is correct: light already
renders these glyphs green-accent (via Color.Secondary → Light.Secondary), so this
keeps light pixel-identical while fixing dark.
WHY it reaches the glyph: MudBlazor colours a Color.Secondary icon by stamping
.mud-secondary-text on the inner .mud-icon-root <svg>, and that rule is `!important`
(color: var(--mud-palette-secondary) !important). Targeting only the .mud-icon-button
wrapper therefore never wins — the svg keeps its own !important colour. The documented
override bug. To beat an !important declaration we need our own !important AND equal-or-
higher specificity: .dd-accent-icon .mud-icon-root (0,2,0) ties .mud-icon-root.mud-
secondary-text (0,2,0) and wins on source order (deepdrft-styles.css is linked LAST in
App.razor, after MudBlazor + isolated CSS). The .mud-icon-button selector carries the
Color.Inherit affordances (lava-lamp glyph inherits the wrapper colour, no
.mud-secondary-text to fight); the spinner covers the PlayStateIcon loading state.
Apply .dd-accent-icon to a CONTAINER of the affordance(s); add .dd-accent-fill
alongside it when the container ALSO holds a filled MudButton whose Color.Secondary
fill must go green-accent in dark (a filled button is a background fill, not a glyph —
light already renders green-accent fill + white text, so .dd-accent-fill is DARK-ONLY
to keep light pixel-identical). The Session/Mix hero Share/Play glyphs use this class
too (they were already green-accent in light via Color.Secondary, so folding them in
keeps light pixel-identical and fixes dark — the over-image glyphs are not actually
theme-divergent). The one genuinely theme-divergent affordance (gas-lamp = inherited
nav text in light) does NOT use this class — it keeps a dark-only rule below.
The glyph rule targets glyphs inside an ICON button (.mud-icon-button .mud-icon-root)
only — the filled Play button is a .mud-button-filled (not .mud-icon-button), so its
StartIcon is naturally excluded and keeps its own contrast colour (white in light,
navy in dark). The bare .mud-icon-button selector carries the Color.Inherit case
(lava-lamp glyph inherits the wrapper colour); the spinner covers the loading state. */
.dd-accent-icon .mud-icon-button .mud-icon-root,
.dd-accent-icon .mud-icon-button,
.dd-accent-icon .mud-progress-circular {
color: var(--deepdrft-green-accent) !important;
}
/* Share + Queue icon buttons in the cut detail header */
.deepdrft-theme-dark .cut-detail-actions .mud-icon-button {
color: var(--deepdrft-primary);
/* Filled-button variant (DARK-ONLY): green-accent fill + navy glyph/label, matching the
play-chip language. In dark, Color.Secondary fill resolves to off-white (unreadable);
here it becomes a clear green CTA. Light is untouched (already green fill + white text). */
.deepdrft-theme-dark .dd-accent-fill .mud-button-filled {
background-color: var(--deepdrft-green-accent);
color: var(--deepdrft-navy);
}
/* Share + Queue icon buttons in each cut detail track row */
.deepdrft-theme-dark .cut-detail-track-row .mud-icon-button {
color: var(--deepdrft-primary);
.deepdrft-theme-dark .dd-accent-fill .mud-button-filled .mud-icon-root {
color: var(--deepdrft-navy) !important;
}
/* Dark-theme interactive affordances in the Session/Mix release-detail hero overlay.
The co-located ReleaseHeroOverlay.razor.css forces .release-hero-play and
.release-hero-share icons to --deepdrft-white unconditionally (correct for the
over-image light-theme contract). In dark theme the play and share glyphs adopt
green to match the "green = interactive" convention. Both the scoped ::deep rule
([b-xxx] .release-hero-play .mud-icon-button) and this global rule
(.deepdrft-theme-dark .release-hero-play .mud-icon-button) compute to specificity
(0,3,0) — a tie — so the override wins on source order: deepdrft-styles.css is
linked after DeepDrftPublic.styles.css in App.razor, making it the later rule.
No !important needed. .mud-progress-circular is included alongside .mud-icon-button
in the play slot to colour the loading spinner green as well.
Light theme: pixel-identical to before. */
.deepdrft-theme-dark .release-hero-play .mud-icon-button,
.deepdrft-theme-dark .release-hero-play .mud-progress-circular,
.deepdrft-theme-dark .release-hero-share .mud-icon-button {
color: var(--deepdrft-primary);
}
/* Dark-theme lava-lamp visualizer-settings trigger.
The MudIconButton uses Color.Secondary, which resolves to off-white in dark mode.
The .dd-lava-lamp-trigger marker div (added to WaveformVisualizerControlPopover.razor)
scopes this rule to only that trigger, preventing bleed onto other Secondary icon
buttons sharing the same host pages. Applied at all host sites (Mix, Cut, Session,
NowPlaying) since the wrapper travels with the component. Light theme: unchanged. */
.deepdrft-theme-dark .dd-lava-lamp-trigger .mud-icon-button {
color: var(--deepdrft-primary);
}
/* Dark-theme gas-lamp dark-mode toggle.
The MudIconButton uses Color.Inherit and sits inside .dd-nav-actions (the right-side
cluster of the nav bar). In dark theme it inherits the nav text colour (off-white);
green makes it consistent with the "green = interactive" convention. The selector is
scoped to .dd-nav-actions so no other icon buttons are affected. Covers both the
desktop nav and the mobile nav (which also renders its gas-lamp inside .dd-nav-actions).
Light theme: unchanged. */
/* Theme-divergent affordance — gas-lamp dark-mode toggle.
Uses Color.Inherit, so in LIGHT it inherits the nav text colour (the contract to keep).
In dark theme it goes green-accent to match the convention. Scoped to .dd-nav-actions
(covers both desktop and mobile nav, which both render the gas-lamp there); dark-only. */
.deepdrft-theme-dark .dd-nav-actions .mud-icon-button {
color: var(--deepdrft-primary);
color: var(--deepdrft-green-accent);
}
/* =============================================================================