/* DeepDrft Global Styles - Simplified & Maintainable Note: the palette / token layer (--deepdrft-*, --theme-*, --gradient-*, and the .deepdrft-theme-dark override block) lives in DeepDrftShared.Client and is served at _content/DeepDrftShared.Client/styles/deepdrft-tokens.css. Link that file BEFORE this one in App.razor — every rule below depends on those tokens. */ /* ============================================================================= 1. PAGE BASELINE ============================================================================= */ /* Base page colours — use MudBlazor's theme-injected variables so they switch automatically when IsDarkMode toggles. The --mud-palette-background and --mud-palette-text-primary variables are injected by MudThemeProvider and update in both light and dark modes. */ html, body { background-color: var(--mud-palette-background); color: var(--mud-palette-text-primary); } /* Main-content clearance for the fixed frosted-glass nav (.dd-nav). The nav is position:fixed (so content scrolls under its backdrop blur) and thus out of flow; in MainLayout's flex column the content would otherwise start at the top and slide under the bar. Pad the top by the shared --deepdrft-nav-height token so the clearance tracks the bar exactly across breakpoints. Replaces the old hardcoded MudBlazor pt-16. */ .dd-main-content { padding-top: var(--deepdrft-nav-height, 88px); } /* Ensure the theme wrapper fills the full viewport so no background gap shows. */ .deepdrft-theme-dark, .deepdrft-theme-light { min-height: 100vh; } /* ============================================================================= 2. GRADIENTS ============================================================================= */ .deepdrft-gradient-primary, .deepdrft-gradient-hero { background: linear-gradient(135deg, var(--gradient-base) 0%, color-mix(in srgb, var(--gradient-base) 90%, var(--gradient-accent) 10%) 50%, color-mix(in srgb, var(--gradient-base) 80%, var(--gradient-accent) 20%) 100%); } .deepdrft-gradient-soft-primary { background: linear-gradient(45deg, color-mix(in srgb, var(--gradient-accent) 4%, transparent) 0%, color-mix(in srgb, var(--gradient-warm) 6%, transparent) 100%); } .deepdrft-gradient-soft-secondary { background: linear-gradient(45deg, color-mix(in srgb, var(--gradient-light) 6%, transparent) 0%, color-mix(in srgb, var(--gradient-accent) 4%, transparent) 100%); } .deepdrft-gradient-soft-accent { background: linear-gradient(135deg, color-mix(in srgb, var(--gradient-accent) 3%, transparent) 0%, color-mix(in srgb, var(--gradient-light) 5%, transparent) 100%); } .deepdrft-gradient-soft-tertiary { background: linear-gradient(135deg, color-mix(in srgb, var(--gradient-warm) 5%, transparent) 0%, color-mix(in srgb, var(--gradient-accent) 3%, transparent) 100%); } .deepdrft-gradient-features { background: linear-gradient(to right, color-mix(in srgb, var(--gradient-accent) 2%, transparent) 0%, color-mix(in srgb, var(--gradient-warm) 3%, transparent) 100%); } /* ============================================================================= 3. TYPOGRAPHY ============================================================================= */ /* Hero text */ h1, .deepdrft-text-hero { font-family: var(--deepdrft-font-display); font-weight: bold; text-shadow: 2px 2px 4px rgba(0,0,0,0.5); } /* Suppress the browser focus ring that FocusOnNavigate triggers on h1 after navigation. */ h1:focus-visible { outline: none; } /* Headers */ h2, h3, h4, h5, h6, .deepdrft-text-subtitle { font-family: var(--deepdrft-font-display); } .deepdrft-text-subtitle { font-weight: 300; text-shadow: 1px 1px 2px rgba(0,0,0,0.3); } /* Body */ .deepdrft-text-description, .deepdrft-text-readable { font-family: var(--deepdrft-font-body); } .deepdrft-text-description { font-weight: 400; opacity: 0.9; } .deepdrft-text-bold { font-weight: bold; } .deepdrft-text-readable { line-height: 1.6; } /* MudBlazor font overrides */ .mud-typography-h1, .mud-typography-h2, .mud-typography-h3, .mud-typography-h4, .mud-typography-h5, .mud-typography-h6, .mud-navlink-text, .mud-appbar-content { font-family: var(--deepdrft-font-display) !important; } .mud-button-text, .mud-typography-caption, .mud-typography-overline { font-family: var(--deepdrft-font-mono) !important; } .mud-typography-body1, .mud-typography-body2, .mud-input-text, .mud-select-text, .mud-form-label { font-family: var(--deepdrft-font-body) !important; } /* ============================================================================= 4. HERO SECTION ============================================================================= */ .deepdrft-hero-container { min-height: 60vh; display: flex; flex-direction: column; justify-content: center; } .deepdrft-hero-text-container { max-width: 600px; } /* Light mode hero text */ .deepdrft-theme-light .deepdrft-hero-title { color: var(--deepdrft-primary); } .deepdrft-theme-light .deepdrft-hero-subtitle { color: var(--deepdrft-secondary); } .deepdrft-theme-light .deepdrft-hero-description { color: var(--theme-surface-soft); } /* Dark mode hero text */ .deepdrft-theme-dark .deepdrft-hero-title { color: var(--theme-surface); } .deepdrft-theme-dark .deepdrft-hero-subtitle { color: var(--deepdrft-tertiary); } .deepdrft-theme-dark .deepdrft-hero-description { color: var(--theme-surface-soft); } /* Hero buttons - Light */ .deepdrft-theme-light .deepdrft-hero-button-filled.mud-button-filled { background-color: var(--deepdrft-primary); color: var(--gradient-base); } .deepdrft-theme-light .deepdrft-hero-button-outlined.mud-button-outlined { border-color: var(--deepdrft-primary); color: var(--deepdrft-primary); } /* Hero buttons - Dark */ .deepdrft-theme-dark .deepdrft-hero-button-filled.mud-button-filled { background-color: var(--deepdrft-primary); color: var(--gradient-base); } .deepdrft-theme-dark .deepdrft-hero-button-outlined.mud-button-outlined { border-color: var(--theme-surface); color: var(--theme-surface); } /* ============================================================================= 5. APPBAR ============================================================================= */ .deepdrft-theme-light .mud-appbar, .deepdrft-theme-light .mud-appbar *, .deepdrft-theme-light .mud-appbar .mud-icon-button { color: var(--gradient-base); } .deepdrft-theme-dark .mud-appbar, .deepdrft-theme-dark .mud-appbar *, .deepdrft-theme-dark .mud-appbar .mud-icon-button { color: var(--theme-surface); } /* ============================================================================= 6. BORDERS (Only used variants) ============================================================================= */ .deepdrft-border-left-secondary { border-left: 4px solid var(--theme-secondary); } .deepdrft-border-left-tertiary { border-left: 4px solid var(--theme-tertiary); } .deepdrft-border-top-quaternary { border-top: 4px solid var(--theme-quaternary); } .deepdrft-border-top-senary { border-top: 4px solid var(--theme-senary); } /* ============================================================================= 7. CARDS & TINTS (Only used variants) ============================================================================= */ .deepdrft-feature-card, .deepdrft-about-card { height: 100%; } .deepdrft-feature-icon-container { text-align: center; } /* Card tints - using theme variables */ .deepdrft-card-purple-tint { background: color-mix(in srgb, var(--deepdrft-secondary) 10%, transparent); } .deepdrft-card-pink-tint { background: color-mix(in srgb, var(--gradient-warm) 10%, transparent); } .deepdrft-card-indigo-tint { background: color-mix(in srgb, var(--gradient-accent) 8%, transparent); } .deepdrft-card-lavender-tint { background: color-mix(in srgb, var(--theme-quinary) 10%, transparent); } /* ============================================================================= 8. (moved to TrackCard.razor.css and TracksGallery.razor.css) ============================================================================= */ /* ============================================================================= 9. CHIPS & BUTTONS ============================================================================= */ .deepdrft-chip-spacing { margin: 2px; } .deepdrft-genre-chip { opacity: 0.9; margin-top: 4px; } .deepdrft-button-spaced { margin: 8px; } /* Extended palette chips */ .mud-chip.deepdrft-chip-quaternary { background-color: var(--theme-quaternary); color: white; } .mud-chip.deepdrft-chip-quinary { background-color: var(--theme-quinary); color: white; } .mud-chip.deepdrft-chip-senary { background-color: var(--theme-senary); color: white; } /* ============================================================================= 10. EXTENDED PALETTE TEXT COLORS (Only used variants) ============================================================================= */ .deepdrft-text-quaternary { color: var(--theme-quaternary); } .deepdrft-text-quinary { color: var(--theme-quinary); } .deepdrft-text-senary { color: var(--theme-senary); } /* ============================================================================= 11. CTA SECTION ============================================================================= */ .deepdrft-cta-container { border-radius: 16px; text-align: center; } .deepdrft-cta-buttons { margin-bottom: 16px; } /* ============================================================================= 12. ICONS & UTILITIES ============================================================================= */ .deepdrft-icon-large { font-size: 3rem; } /* ============================================================================= 13. RESPONSIVE ============================================================================= */ @media (max-width: 768px) { .deepdrft-hero-text { font-size: clamp(1.5rem, 6vw, 3rem) !important; } .deepdrft-cta-buttons .mud-button { margin: 4px !important; width: 100%; } } /* ============================================================================= 14. TRACK DETAIL PAGE ============================================================================= */ .deepdrft-track-detail-container { max-width: 760px; margin: 0 auto; padding: 3rem 1.5rem 4rem; } /* Mix detail widens its body to the Sessions detail width (MudContainer Large, ~1280px) by hosting the scaffold inside a MudContainer Large and neutralizing the scaffold's own 760px cap for that instance. Both classes are global, so a plain descendant selector reaches the scaffold div without ::deep. The horizontal gutter is dropped here because the wrapping MudContainer supplies its own. Mix-scoped, so Track detail (which also uses .deepdrft-track-detail-container) stays at 760px. */ .mix-detail-container .deepdrft-track-detail-container { max-width: none; padding-left: 0; padding-right: 0; } .deepdrft-track-detail-back { display: inline-flex; align-items: center; gap: 4px; margin-bottom: 1.5rem; opacity: 0.65; transition: opacity 0.15s ease; } .deepdrft-track-detail-back:hover { opacity: 1; } /* Square cover frame — the placeholder MudPaper fills it. */ .deepdrft-track-detail-cover { aspect-ratio: 1 / 1; max-width: 360px; margin: 0 auto 2rem; overflow: hidden; box-shadow: 0 8px 28px color-mix(in srgb, var(--mud-palette-text-secondary) 18%, transparent); } /* Stat-card parallel: elevated surface with a soft secondary wash, album icon centered. */ .deepdrft-track-detail-cover-placeholder { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; background-color: var(--mud-palette-surface); } .deepdrft-track-detail-cover-placeholder .mud-icon-root { font-size: 72px; } /* Album art fills the square frame; background-size:cover handles any aspect ratio. */ .deepdrft-track-detail-cover-art { height: 100%; background-size: cover; background-position: center; background-repeat: no-repeat; } .deepdrft-track-detail-masthead { display: flex; flex-direction: column; gap: 0.5rem; } .deepdrft-track-detail-meta { display: flex; flex-direction: row; align-items: center; justify-content: space-around; gap: 2rem; margin-top: 1.5rem; } /* Small-caps mono labels match the caption/overline typography override. */ .deepdrft-track-detail-meta .mud-typography-overline { font-variant: small-caps; opacity: 0.6; font-family: var(--deepdrft-font-mono) !important; } /* Default MudBlazor popover surface (Phase 18, T4 — symptom #1). Selects, menus, and the share-popover body render inside .mud-popover. (Tooltips are NOT covered here — MudBlazor tooltips paint from --mud-palette-text, not the popover surface.) Their visible surface is the inner .mud-paper, which paints background-color: var(--mud-palette-surface). Inspection settled the root cause: the "too dark" is NOT --deepdrft-panel-ground leakage (the bespoke dark-glass panels are MudOverlay .mud-overlay-content surfaces and never match .mud-popover) — it is simply that the popover surface tracks --mud-palette-surface with no desaturated-navy treatment. So re-point --mud-palette-surface to the theme-aware --deepdrft-popover-surface *within the popover scope only*: a soft desaturated-navy wash in light, the existing panel-ground charcoal in dark. Scoping the variable (not a flat background) means any inner .mud-paper, .mud-list, or menu picks it up for free, while the global surface used elsewhere on the page is unaffected. */ .mud-popover { --mud-palette-surface: var(--deepdrft-popover-surface); background-color: var(--deepdrft-popover-surface); } .deepdrft-share-popover-body { padding: 0.75rem 1rem; min-width: 280px; max-width: 360px; } /* Monospace snippet so the iframe markup stays legible inside the readonly field. */ .deepdrft-share-embed-field { flex: 1 1 auto; } .deepdrft-share-embed-field .mud-input-slot { font-family: var(--deepdrft-font-mono) !important; font-size: 0.75rem; word-break: break-all; } /* ============================================================================= WAVEFORM VISUALIZER CONTROL PANEL (Phase 12 §3d-revised / §3g → Phase 15 re-layout) The control deck hosted inside WaveformVisualizerControlPopover, now a screen-centered tinted MudOverlay (Phase 15 §4). MudOverlay — like the former MudPopover — PORTALS its content out of the component's DOM subtree, so Blazor CSS isolation never reaches the rendered panel: its chrome, the three-row/section LAYOUT, the section labels, the slider, and the toggles all live here in the global sheet, not in the scoped WaveformVisualizerControls.razor.css. (The scoped file keeps only the legacy inline-bar fallback Mix's old TopRowCenter mount used, which is not portaled.) The waveform-visualizer-control-panel class is applied ONLY when the component's PanelChrome="true" parameter is set — which the popover host does and Mix's inline mount does NOT — so the chrome never leaks onto an inline bar. CHROME (Phase 15 §5 — NowPlayingCard treatment): SQUARE corners, lighter-navy ground (navy-mid), a thin LIGHT border (--deepdrft-border-light, the NowPlayingCard 0.12-alpha light-on-dark idiom as a token). All token-sourced; no hardcoded hex. COLOUR PRINCIPLE (§5 — green = interactive, light = non-interactive): the RadialKnob reads --mud-palette-* for its arc/pointer/center/label; we pin --mud-palette-primary to the green accent (interactive arcs/pointers) and --mud-palette-text-primary to light. Caption icons and section labels are LIGHT (static). The slider track/thumb and the lamp toggles are green. ============================================================================= */ .waveform-visualizer-control-panel.mix-visualizer-controls-bar { /* Theme-aware glass ground — dark charcoal in dark theme, light translucent glass in light (so the deck reads against the light page). Tunable in deepdrft-tokens.css. */ background: var(--deepdrft-panel-surface); /* Square corners + thin theme-aware border — NowPlayingCard chrome (§5). */ border: 1px solid var(--deepdrft-panel-border); border-radius: 0; /* Optional backdrop blur — cheap on a small modal panel, nice over the visualizer (§5). */ backdrop-filter: blur(8px); padding: 1rem 1.25rem; /* Three-row sectioned deck: stack the rows top-to-bottom; conditional rows reserve no permanent height (§3 reflow discipline). This OVERRIDES the inline-bar min-height + flex-wrap (which only matter for Mix's non-portaled legacy mount). */ display: flex; flex-direction: column; gap: 0.75rem; min-height: 0; max-width: 420px; /* Pin the MudBlazor palette vars the portaled RadialKnob + slider consume. */ --mud-palette-primary: var(--deepdrft-green-accent); /* knob arc/pointer + slider track/thumb (interactive) */ --mud-palette-surface: var(--deepdrft-navy); /* knob center fill — darkest navy reads against the panel */ --mud-palette-surface-variant: var(--deepdrft-muted); /* knob background track — muted-navy filler */ --mud-palette-text-primary: var(--deepdrft-panel-text); /* knob value label — flips dark on light glass */ } /* ── Row layout (§3). Each row is a horizontal band. Row 1 (MODE) and row 3 (WAVE) use space-between so the right-pinned control (color / width) hugs the far edge. Row 2 (LAVA) uses flex-start so its label + four knobs group left rather than spreading edge-to-edge. align-items: center so the section label and knobs vertically center with each other. ── */ .waveform-visualizer-control-panel .wvc-row { display: flex; flex-direction: row; align-items: center; gap: 0.85rem 1rem; } /* Row 1 (MODE): two direct flex children — the left toggle group and the color knob tooltip wrapper. space-between pins the color knob to the far right and keeps it there when collisions hides. */ .waveform-visualizer-control-panel .wvc-row-mode { justify-content: space-between; } /* Row 2 (LAVA): label + four knobs group left — no right-pinned control. */ .waveform-visualizer-control-panel .wvc-row-section { justify-content: flex-start; } /* Row 3 (WAVE): label + scroll-slider + width-knob tooltip wrappers are direct flex children. space-between pins the width knob to the far right while the label + slider sit left. */ .waveform-visualizer-control-panel .wvc-row-wave { justify-content: space-between; } /* The left group of row 1 (toggles + conditional collisions) flows left; the color knob is the space-between right sibling, so it stays put when collisions hides (§3). */ .waveform-visualizer-control-panel .wvc-row-left { display: flex; flex-direction: row; align-items: center; gap: 0.85rem 1rem; } /* ── Section label "LAVA:" / "WAVE:" (§3, §5). NowPlayingCard .np-label TYPOGRAPHY (mono, uppercase, tracked), coloured via --deepdrft-panel-text — theme-aware (navy in light, off-white in dark). ── */ .waveform-visualizer-control-panel .wvc-section-label { font-family: var(--deepdrft-font-mono); font-size: 0.6rem; letter-spacing: 0.25em; text-transform: uppercase; color: var(--deepdrft-panel-text); align-self: center; flex: 0 0 auto; opacity: 0.85; } /* ── The toggles (§3 row 1). Two state classes control the active-state chip treatment: ON (.wvc-toggle-on): green-accent filled chip — unmistakably active at a glance. OFF (.wvc-toggle-off): fully transparent background, glyph at low opacity — clearly inactive. The MudIconButton glyph is already driven green (Color.Primary → pinned green accent, interactive §5). The chip background reinforces state without recolouring the glyph further. ── */ .waveform-visualizer-control-panel .wvc-toggle { display: flex; align-items: center; justify-content: center; border-radius: 6px; transition: background 0.15s ease; } .waveform-visualizer-control-panel .wvc-toggle-on { background: color-mix(in srgb, var(--deepdrft-green-accent) 28%, transparent); box-shadow: 0 0 0 1px color-mix(in srgb, var(--deepdrft-green-accent) 55%, transparent); } .waveform-visualizer-control-panel .wvc-toggle-off .mud-icon-button { opacity: 0.38; } /* Caption icons inherit the portaled panel's body text — theme-aware (dark text on light glass, off-white on dark glass). !important beats the scoped .mix-visualizer-control ::deep .mix-visualizer-control-icon rule (which sets green for the legacy inline mount) when the icon also carries mix-visualizer-control-icon. Lamp toggles are MudIconButton not MudIcon so they are unaffected — they stay green (interactive, Color.Primary). (defect #3) */ .waveform-visualizer-control-panel .waveform-visualizer-control-icon { opacity: 0.85; translate: 0 -1rem; } /* ── The modal overlay (Phase 15 §4). MudOverlay is already a full-viewport flex scrim that centers its content (.mud-overlay { display:flex; align-items:center; justify-content:center }), which gives the screen-centered panel on every host for free — we do NOT fight that positioning. We: (a) Raise the overlay z-index above the header (100) and the player-dock footer (1200/1300) so the scrim tints the ENTIRE viewport uniformly — header and footer included (defect #7). The panel content needs z-index: auto (inherits from stacking context) so it sits above the scrim naturally; the RadialKnob capture div at 9999 remains above everything. (b) Set the mild tint from the SINGLE --deepdrft-modal-scrim-alpha token (§10.5, defect #6). (c) Remove overflow-y:auto on the content wrapper — it was the source of the drag scrollbar (defect #2). The panel's max-width/flex-column already contain its size; the outer overlay clips at 100vh. (d) Suppress body scroll while the overlay is present so no page-scroll occurs during a drag (defect #2). The overlay portals to the body, so these are plain global rules (no scope attribute). The doubled .mud-overlay-scrim.mud-overlay-dark selector (0,2,0) outranks MudBlazor's own .mud-overlay-dark (0,1,0), so the tint wins regardless of stylesheet load order. ── */ /* Raise the overlay itself above the sticky header (z-index:100) and the fixed player dock (z-index:1200). Use 1400 so it sits above the minimized-dock FAB (1300) too. The panel content inherits this context and stacks above the scrim; the RadialKnob capture div (z-index:9999) stays highest. */ .waveform-visualizer-control-overlay { z-index: 1400 !important; } .waveform-visualizer-control-overlay .mud-overlay-scrim.mud-overlay-dark { background-color: rgba(var(--deepdrft-scrim-rgb), var(--deepdrft-modal-scrim-alpha)); } /* No overflow-y:auto — removing it eliminates the spurious scrollbar that appeared while dragging a knob (defect #2). The panel's flex-column layout is self-contained and never overflows the overlay. */ .waveform-visualizer-control-overlay .mud-overlay-content { max-height: 90vh; overflow: visible; } /* Lock body scroll while the controls overlay is open so the page cannot be scrolled during a knob drag (defect #2). :has() degrades gracefully in older browsers (no lock, no crash). */ body:has(.waveform-visualizer-control-overlay) { overflow: hidden; } @media (max-width: 419.98px) { .deepdrft-track-detail-meta { flex-direction: column; } } /* ============================================================================= BUTTON UTILITIES (btn-primary, btn-ghost) ============================================================================= */ .btn-primary { font-family: var(--deepdrft-font-mono); font-size: 0.68rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--deepdrft-white); background: var(--deepdrft-navy); border: none; padding: 1rem 2.2rem; cursor: pointer; text-decoration: none; transition: background 0.25s, transform 0.2s; display: inline-block; } .btn-primary:hover { background: var(--deepdrft-green); transform: translateY(-1px); } .btn-ghost { font-family: var(--deepdrft-font-mono); font-size: 0.68rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--deepdrft-navy); background: transparent; border: 1px solid var(--deepdrft-border); padding: 1rem 2.2rem; cursor: pointer; text-decoration: none; transition: border-color 0.25s, color 0.25s; display: inline-block; } .btn-ghost:hover { border-color: var(--deepdrft-navy); } @media (max-width: 599px) { .btn-primary, .btn-ghost { text-align: center; } } /* Dark-mode button overrides (Phase 18, Wave 3). In dark, --deepdrft-navy fill/text blends into the #0D1B2A page ground. Primary: green-accent fill + navy text reads as a clear CTA (matches play-chip language). Ghost: white text + light border stands off the dark ground. */ .deepdrft-theme-dark .btn-primary { background: var(--deepdrft-green-accent); color: var(--deepdrft-navy); } .deepdrft-theme-dark .btn-primary:hover { background: var(--deepdrft-green-interactive); } .deepdrft-theme-dark .btn-ghost { color: var(--deepdrft-page-text); border-color: var(--deepdrft-border-light); } .deepdrft-theme-dark .btn-ghost:hover { border-color: var(--deepdrft-page-text); } /* ============================================================================= CUT ALBUM DETAIL (/cuts/{id}) Header splits left-meta / right-cover; the cover carries an explicit theme border (the new visual element vs. the borderless Session/Mix covers). ============================================================================= */ .cut-detail-header { display: flex; flex-direction: row; align-items: flex-start; justify-content: space-between; gap: 2rem; margin: 2rem 0 1.5rem; } .cut-detail-meta { display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; flex: 1 1 auto; } .cut-detail-subline { display: flex; align-items: center; gap: 0.5rem; opacity: 0.75; font-family: var(--deepdrft-font-mono); font-size: 0.85rem; margin-top: 0.25rem; } .cut-detail-sep { opacity: 0.5; } .cut-detail-actions { display: flex; flex-direction: row; align-items: center; gap: 0.75rem; margin-top: 1rem; } /* Square cover with a framed theme border — the new visual element this page introduces. */ .cut-detail-cover { aspect-ratio: 1 / 1; width: 260px; flex: 0 0 auto; overflow: hidden; box-shadow: 0 8px 28px color-mix(in srgb, var(--mud-palette-text-secondary) 18%, transparent); } .cut-detail-divider { margin: 1.5rem 0 0.5rem; } .cut-detail-empty { opacity: 0.7; padding: 1rem 0; } .cut-detail-tracklist { display: flex; flex-direction: column; } .cut-detail-track-row { display: flex; flex-direction: row; align-items: center; gap: 0.75rem; padding: 0.25rem 0; border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-text-secondary) 12%, transparent); } .cut-detail-track-row:last-child { border-bottom: none; } .cut-detail-track-number { width: 1.75rem; text-align: right; flex: 0 0 auto; opacity: 0.55; font-family: var(--deepdrft-font-mono); font-size: 0.9rem; } .cut-detail-track-play { flex: 0 0 auto; } .cut-detail-track-name { flex: 1 1 auto; min-width: 0; } /* Stack the header on narrow screens: cover above the meta column. */ @media (max-width: 599px) { .cut-detail-header { flex-direction: column-reverse; align-items: stretch; gap: 1.25rem; } .cut-detail-cover { width: 100%; max-width: 320px; margin: 0 auto; } } /* ============================================================================= 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. 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 , 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. The glyph clause .dd-accent-icon .mud-icon-button .mud-icon-root is specificity (0,3,0) + !important, which beats MudBlazor's standalone .mud-secondary-text (0,1,0) + !important on specificity alone — source order is not load-bearing for the glyph clause. 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; } /* 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); } .deepdrft-theme-dark .dd-accent-fill .mud-button-filled .mud-icon-root { color: var(--deepdrft-navy) !important; } /* Gas-lamp dark-mode toggle: the frame now carries an explicit #2A5C4F fill in its SVG (DDIcons.GasLampLit), so no CSS colour override is needed here in dark. The nav rule that previously set green-accent on the MudIconButton has been removed — it was the only .mud-icon-button in .dd-nav-actions and is now dead. */ /* ============================================================================= RELEASE DESCRIPTION BLURB Shared block rendered just below the hero/header on every release detail page (Session, Mix, Cut). Theme-driven colours keep it legible in both palettes. Borrows the eyebrow-label + divider-rule motif from the home page. ============================================================================= */ .deepdrft-release-description { margin: 2rem 0 2.5rem; } /* Header row: eyebrow label left + thin rule filling the rest */ .deepdrft-release-description-header { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.25rem; } /* Eyebrow label — mirrors .section-label / .split-eyebrow from Home */ .deepdrft-release-description-label { font-family: var(--deepdrft-font-mono); font-size: 0.62rem; letter-spacing: 0.28em; color: var(--deepdrft-green-accent); text-transform: uppercase; white-space: nowrap; flex-shrink: 0; } /* Thin rule to the right of the label — mirrors .divider-line from Home */ .deepdrft-release-description-rule { flex: 1; height: 1px; background: color-mix(in srgb, var(--deepdrft-muted) 35%, transparent); } /* Body paragraph — body font, display-serif feel via generous line-height */ .deepdrft-release-description-text { margin: 0; font-family: var(--deepdrft-font-display); font-size: 1.1rem; font-weight: 300; line-height: 1.75; color: var(--mud-palette-text-primary); opacity: 0.85; } /* ============================================================================= QUEUE OVERLAY + LIST (Phase 17 wave 17.2 — docked queue panel) The overlay is a direct lift of the visualizer-control modal (Phase 15 §4): a centered MudOverlay whose scrim tint + z-index + body-scroll lock match that idiom exactly. The panel chrome (square corners, lighter-navy ground, thin light border) is the NowPlayingCard treatment (§5). MudOverlay portals out of the component subtree to the body, so these are plain GLOBAL rules — CSS isolation cannot reach portaled content. ============================================================================= */ /* Raise the overlay above the sticky header (100), the fixed player dock (1200), and the minimized FAB (1300) — same stacking decision as the visualizer overlay so the scrim tints the whole viewport. */ .deepdrft-queue-overlay { z-index: 1400 !important; } /* Mild modal tint from the shared scrim token. The doubled selector (0,2,0) outranks MudBlazor's own .mud-overlay-dark (0,1,0) regardless of stylesheet load order. */ .deepdrft-queue-overlay .mud-overlay-scrim.mud-overlay-dark { background-color: rgba(var(--deepdrft-scrim-rgb), var(--deepdrft-modal-scrim-alpha)); } .deepdrft-queue-overlay .mud-overlay-content { max-height: 90vh; overflow: visible; } /* Lock body scroll while the queue overlay is open (matches the visualizer overlay). */ body:has(.deepdrft-queue-overlay) { overflow: hidden; } /* The mostly-square panel (§3.2: min(90vw, 520px)). NowPlayingCard chrome: square corners, lighter-navy ground, thin light border. Internal column: fixed header over a scrollable list body. */ .deepdrft-queue-modal { display: flex; flex-direction: column; width: min(90vw, 520px); height: min(90vw, 520px); max-height: 90vh; background: var(--deepdrft-panel-surface); border: 1px solid var(--deepdrft-panel-border); border-radius: 0; backdrop-filter: blur(8px); overflow: hidden; } .deepdrft-queue-modal-header { display: flex; align-items: center; justify-content: space-between; padding: 0.85rem 1rem; border-bottom: 1px solid var(--deepdrft-panel-border); } /* Mono uppercase eyebrow — the NowPlayingCard .np-label typography, theme-aware (static). */ .deepdrft-queue-modal-title { font-family: var(--deepdrft-font-mono); font-size: 0.72rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--deepdrft-panel-text); opacity: 0.85; } .deepdrft-queue-modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0.5rem 0.5rem 0.75rem; } /* ── The list itself (consumed by QueueList in both modes; styled here once). ── */ .deepdrft-queue-list { display: flex; flex-direction: column; } .deepdrft-queue-zone { display: flex; flex-direction: column; } .deepdrft-queue-row { display: flex; align-items: center; gap: 0.6rem; padding: 0.45rem 0.5rem; border-radius: 4px; color: var(--deepdrft-panel-text); transition: background 0.15s ease; } .deepdrft-queue-row:hover { background: var(--deepdrft-panel-row-hover); } /* Current track: a subtle green wash + left accent, matching the green = active principle. */ .deepdrft-queue-row-current { background: color-mix(in srgb, var(--deepdrft-green-accent) 14%, transparent); box-shadow: inset 2px 0 0 0 var(--deepdrft-green-accent); } .deepdrft-queue-drag-handle { cursor: grab; opacity: 0.45; flex: 0 0 auto; } .deepdrft-queue-position { font-family: var(--deepdrft-font-mono); font-size: 0.72rem; color: var(--deepdrft-panel-text-muted); min-width: 1.4rem; text-align: right; flex: 0 0 auto; } /* Row body grows + truncates; clicking it jumps playback (OQ2). */ .deepdrft-queue-body { display: flex; flex-direction: column; gap: 0.1rem; flex: 1 1 auto; min-width: 0; cursor: pointer; } .deepdrft-queue-title { font-size: 0.92rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .deepdrft-queue-artist { font-size: 0.74rem; color: var(--deepdrft-panel-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .deepdrft-queue-nowplaying, .deepdrft-queue-remove { flex: 0 0 auto; } /* Active (open) state for the bar's Queue toggle — a soft green chip behind the glyph, matching the visualizer toggle's on-state idiom. */ .deepdrft-queue-toggle-active { background: color-mix(in srgb, var(--deepdrft-green-accent) 22%, transparent); border-radius: 6px; } /* ── Fixed (embed) inline queue panel (Phase 17 §4, OQ6). ── Rendered below the player controls inside the embed surface. A fixed sensible height with internal scroll past N rows (NOT grow-to-cap): ~4.5 rows are visible, the rest scroll. A top hairline separates it from the controls. The list rows reuse the shared .deepdrft-queue-* styles above. */ .deepdrft-queue-embed-panel { margin-top: 0.5rem; padding-top: 0.5rem; border-top: 1px solid var(--deepdrft-border-light); max-height: 184px; overflow-y: auto; } /* ============================================================================= PRIVACY OVERLAY Screen-centered modal following the same MudOverlay idiom as the visualizer controls and queue overlays. MudOverlay portals to body — CSS isolation cannot reach portaled content, so chrome lives here in the global sheet. ============================================================================= */ /* Raise above the sticky header (100), player dock (1200), and minimized FAB (1300). */ .deepdrft-privacy-overlay { z-index: 1400 !important; } /* Mild tint: doubled selector (0,2,0) outranks MudBlazor's .mud-overlay-dark (0,1,0). */ .deepdrft-privacy-overlay .mud-overlay-scrim.mud-overlay-dark { background-color: rgba(var(--deepdrft-scrim-rgb), var(--deepdrft-modal-scrim-alpha)); } .deepdrft-privacy-overlay .mud-overlay-content { max-height: 90vh; overflow: visible; } /* Lock body scroll while the overlay is open. */ body:has(.deepdrft-privacy-overlay) { overflow: hidden; } /* Panel: compact width, navy-panel ground, thin light border — matches queue/visualizer chrome. */ .deepdrft-privacy-modal { display: flex; flex-direction: column; width: min(90vw, 480px); background: var(--deepdrft-panel-surface); border: 1px solid var(--deepdrft-panel-border); border-radius: 0; backdrop-filter: blur(8px); overflow: hidden; } .deepdrft-privacy-modal-header { display: flex; align-items: center; justify-content: space-between; padding: 0.85rem 0.85rem 0.85rem 1rem; border-bottom: 1px solid var(--deepdrft-panel-border); } /* Mono uppercase eyebrow — matches queue modal title. */ .deepdrft-privacy-modal-title { font-family: var(--deepdrft-font-mono); font-size: 0.72rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--deepdrft-panel-text); opacity: 0.85; } /* Tuck the close icon flush with the panel edge; keep it subtle. */ .deepdrft-privacy-modal-close { opacity: 0.6; color: var(--deepdrft-panel-text) !important; } .deepdrft-privacy-modal-close:hover { opacity: 1; } /* Privacy copy: same mono treatment as the former inline paragraph; theme-aware text colour so it stays legible on both the dark-glass (dark) and light-glass (light) panel surfaces. */ .deepdrft-privacy-modal-body { font-family: var(--deepdrft-font-mono); font-size: 0.72rem; letter-spacing: 0.06em; line-height: 1.7; color: var(--deepdrft-panel-text); opacity: 0.8; margin: 0; padding: 1rem 1rem 1.25rem; }