/* ==========================================================================
   DW-INDEX  dw-fixes-20260815.css
   Override sheet for the DREAMWAVE app. Loaded LAST, after
   minimal-only.v464.css (972KB / ~13,700 !important declarations).

   HOW TO WIN A SPECIFICITY DUEL IN THIS CODEBASE
   ---------------------------------------------
   Four overrides in this file lost to EARLIER rules in this same file.
   Before adding a rule, grep THIS file for the property first -- the
   opponent is usually a previous entry here, not the vendor sheet.

     * an ID beats any number of classes.  (1,3,1) beats (0,4,1).
       Rules scoped to #dreamAppContent therefore beat every class-only
       selector, however long.
     * the workhorse prefixes, in ascending strength:
         body.dream-app-open[data-dream-route]                    (0,3,1)
         body.mode-minimal.dream-app-open[data-dream-route]       (0,4,1)
         ...[data-dream-route] #dreamAppContent                   (1,3,1)
         body.mode-minimal...[data-dream-route] #dreamAppContent  (1,4,2)  <- strongest here
     * .mode-minimal is always present (set once at boot, never removed).
     * elements OUTSIDE #dreamAppContent (mini player, bottom nav, app
       header) need the class-only form -- the id form cannot match them.
     * when even that loses, set it from JS:
         el.style.setProperty(prop, val, "important")
       which outranks every stylesheet rule. Used for the desktop player
       width and the player wheel-scroll fix.

   VERIFY, DO NOT ASSUME: check the computed value after any change.
   Several "applied" fixes here silently did nothing until measured.

   Stats at time of writing: 243 rule blocks, 553 !important.

   SECTIONS (first line of each)
     L648    DW-FIX 2026-08-15: scope to the desktop row layout
     L1299   DW-FEAT 2026-08-15: track versions panel
     L1468   DW-UX 2026-08-15: mini-player opacity, cinematic entry, scene pill
     L1543   DW-UX 2026-08-15: desktop player uses its width
     L1574   DW-UX 2026-08-15: audit defects (scroller, badge, settings header, tap targets)
     L1649   DW-UX 2026-08-15: header scrim so scrolled text does not collide with the wordmark
     L1671   DW-UX 2026-08-15: touch floor at matching specificity
     L1691   DW-UX 2026-08-15: touch floor part 2
     L1719   DW-A11Y 2026-08-15: invisible controls + text over video
     L1765   DW-A11Y 2026-08-15: queue badge contrast + mobile nav label size
     L1785   DW-UX 2026-08-15: touch targets + font floor (final)
     L1865   DW-UX 2026-08-15: floors re-issued with #dreamAppContent specificity
     L1921   DW-A11Y 2026-08-15: reduced motion + last tap targets + nested span fonts
     L1967   DW-UX 2026-08-15: volume slider to a full 40px
   ========================================================================== */

/* ===========================================================================
   DREAMWAVE targeted fixes — 2026-08-15  (v3)
   Loaded LAST so it wins the cascade without editing minimal-only.v464.css
   (972KB / 13,736 !important declarations — not safe to edit in place).
   Every rule documents the bug it fixes. Remove this one <link> to revert.

   Design note: DREAMWAVE FM is a radio station, so the content reads as a
   station program log — open bands separated by hairlines, hierarchy carried
   by type and spacing — rather than a grid of nested cards. The previous pass
   fixed contrast by making every panel opaque, which traded "washed out" for
   "blocky". This pass replaces that with a single backdrop scrim so only leaf
   rows carry a surface.
   =========================================================================== */

:root {
  --dw-ink:        #0b0a14;
  --dw-text:       #f4efff;
  --dw-text-dim:   rgba(244, 239, 255, 0.66);
  --dw-text-faint: rgba(244, 239, 255, 0.44);
  --dw-hairline:   rgba(244, 239, 255, 0.12);
  --dw-surface:    rgba(18, 16, 32, 0.52);
  --dw-surface-hi: rgba(28, 24, 48, 0.68);
  --dw-accent:     #ff4fa3;
  --dw-accent-2:   #5ce1e6;
  --dw-radius:     14px;
}

/* ---------------------------------------------------------------------------
   1. FUNCTIONAL BUG — search scope tabs rendered one character per line
   ("C/r/e/a/t/o/r/s"). .dream-search-scope carries `min-width:0 !important`
   globally while the protective `flex: 0 0 auto` only exists inside media
   queries that never match desktop, so the flex item shrinks below its content
   width and wraps at every character. Fixing this also un-hid the result rows,
   which were being crushed to zero width rather than failing to render.
   --------------------------------------------------------------------------- */
/* SPECIFICITY NOTE (found in review): production has, inside @media(max-width:520px),
     minimal-only.v464.css:26882
     body.mode-minimal.dream-app-open .dream-search-idle-scope-bar .dream-search-scope
       { width: 100% !important; min-width: 0 !important; }          (0,4,1)
   `mode-minimal` is on <body> for every visitor, so on phones that rule beat the
   (0,3,1) selectors below and restored min-width:0 — re-creating the exact
   one-character-per-line "C/r/e/a/t/o/r/s" collapse this section fixes (and
   forcing each chip to 100% width). The html+#minimal-ui form below is (1,4,2). */
html body.dream-app-open[data-dream-route] #minimal-ui .dream-search-idle-scope-bar .dream-search-scope,
html body.mode-minimal.dream-app-open[data-dream-route] #minimal-ui .dream-search-scope,
body.dream-app-open .dream-search-scopes .dream-search-scope,
body.dream-app-open .dream-search-idle-scope-bar .dream-search-scope,
body.dream-app-open[data-dream-route="search"] .dream-search-scope {
  flex: 0 0 auto !important;
  width: auto !important;
  min-width: -moz-max-content !important;
  min-width: max-content !important;
  white-space: nowrap !important;
}

body.dream-app-open .dream-search-scope .dream-search-scope-label,
body.dream-app-open .dream-search-scope .dream-search-scope-count {
  white-space: nowrap !important;
  min-width: -moz-max-content !important;
  min-width: max-content !important;
  overflow: visible !important;
  text-overflow: clip !important;
}

body.dream-app-open .dream-search-scopes,
body.dream-app-open .dream-search-idle-scope-bar {
  flex-wrap: nowrap !important;
  align-items: center !important;
  overflow-x: auto !important;
  overflow-y: hidden !important;
  scrollbar-width: none !important;
}
body.dream-app-open .dream-search-scopes::-webkit-scrollbar,
body.dream-app-open .dream-search-idle-scope-bar::-webkit-scrollbar {
  display: none !important;
}

body.dream-app-open .dream-search-result-type-pill,
body.dream-app-open .dream-search-chip {
  flex: 0 0 auto !important;
  white-space: nowrap !important;
  min-width: -moz-max-content !important;
  min-width: max-content !important;
}

/* ---------------------------------------------------------------------------
   2. LEGIBILITY — one scrim instead of many opaque slabs.
   A bright full-bleed sunset sits behind transparent glass, so text washed out.
   Darkening every panel individually (previous pass) made the page muddy and
   blocky. Instead: dim the backdrop once and lay a vertical gradient over it,
   so a single surface carries contrast and panels can stay light.
   --------------------------------------------------------------------------- */
/* Dim the backdrop on the VIDEO ITSELF, never with an overlay element.
   A previous version used `body::after { position:fixed; z-index:0 }` as a
   scrim. That was wrong and put a dark film over the whole app:
     #bgVideo    z-index: 0
     #app        z-index: auto  — position:fixed CREATES a stacking context,
                                  so #minimal-ui's z-index:2 is trapped inside it
     body::after z-index: 0     — last in DOM order, so at root level it painted
                                  ON TOP of #app and everything in it
   Filtering the video needs no extra layer and cannot cover the UI. */
body.dream-app-open #bgVideo {
  filter: brightness(0.52) saturate(1.08) contrast(1.04) !important;
}

/* ---------------------------------------------------------------------------
   3. DE-BLOCKING — stop drawing a box around every box.
   Sections were filled, bordered cards that themselves contained filled,
   bordered rows and tiles: three nested surfaces deep. Sections become open
   bands; only leaf rows keep a surface.
   --------------------------------------------------------------------------- */
/* SPECIFICITY NOTE (found in review — this rule was silently losing on the two
   most-used routes). The de-blocking below was written as
   `body.dream-app-open .dream-section` = (0,2,1), but production re-paints the
   same element per-route at higher specificity:
     minimal-only.v464.css:22353  [data-dream-route="library"] .dream-section
                                  { background: rgba(7,8,12,.86); backdrop-filter: blur(16px) }   (0,3,1)
     minimal-only.v464.css:22435  html body…[library] #minimal-ui .dream-section                  (1,4,2)
     minimal-only.v464.css:23126  [data-dream-route="discover"] .dream-section
                                  { background: rgba(7,8,12,.62); backdrop-filter: blur(14px) }   (0,3,1)
   So Discover and Library kept their filled, blurred card look — exactly the
   "blocky" appearance this section exists to remove. The selector below now
   carries two ids + the route attribute → (2,3,2), which beats all of them. */
html body.dream-app-open[data-dream-route] #minimal-ui #dreamAppContent .dream-section,
html body.dream-app-open[data-dream-route] #minimal-ui #dreamAppContent .dream-search-module,
html body.dream-app-open[data-dream-route] #minimal-ui #dreamAppContent .dream-search-results-grid,
html body.dream-app-open[data-dream-route] #minimal-ui #dreamAppContent .dream-search-results,
html body.dream-app-open[data-dream-route] #minimal-ui #dreamAppContent .dream-collection-stack,
body.dream-app-open .dream-section,
body.dream-app-open .dream-search-module,
body.dream-app-open .dream-search-results-grid,
body.dream-app-open .dream-search-results,
body.dream-app-open .dream-collection-stack,
body.dream-app-open .dream-app-main-header {
  background: transparent !important;
  background-color: transparent !important;
  background-image: none !important;
  border: 0 !important;
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  border-radius: 0 !important;
}

/* Bands are separated by a rule, not by a container outline. */
body.dream-app-open .dream-section + .dream-section {
  border-top: 1px solid var(--dw-hairline) !important;
  padding-top: 22px !important;
  margin-top: 22px !important;
}

/* Leaf surfaces — the only things that still read as a "card". */
body.dream-app-open .dream-search-row,
body.dream-app-open .dream-search-result-row,
body.dream-app-open .dream-collection-row,
body.dream-app-open .dream-browse-tile,
body.dream-app-open .dream-track-meta-card {
  background: var(--dw-surface) !important;
  background-image: none !important;
  border: 1px solid var(--dw-hairline) !important;
  border-radius: var(--dw-radius) !important;
  box-shadow: none !important;
  transition: background-color 140ms ease, border-color 140ms ease !important;
}

body.dream-app-open .dream-search-row:hover,
body.dream-app-open .dream-search-result-row:hover,
body.dream-app-open .dream-collection-row:hover,
body.dream-app-open .dream-browse-tile:hover {
  background: var(--dw-surface-hi) !important;
  border-color: rgba(255, 79, 163, 0.42) !important;
}

/* ---------------------------------------------------------------------------
   4. TYPE — section heads read as station-log labels, titles get real weight.
   --------------------------------------------------------------------------- */
/* NOTE on specificity: the 972KB sheet scopes many rules as
   body.dream-app-open[data-dream-route="…"] .thing { … !important }, which
   outranks a plain body.dream-app-open .thing. Adding the bare [data-dream-route]
   attribute matches every route and restores parity without duplicating a rule
   per route. Section heads are h3 in most views (h4 in a few), so both are named. */
body.dream-app-open[data-dream-route] .dream-section-head h3,
body.dream-app-open[data-dream-route] .dream-section-head h4,
body.dream-app-open[data-dream-route] .dream-section-head h5,
body.dream-app-open[data-dream-route] .dream-section-title {
  font-size: 11px !important;
  font-weight: 700 !important;
  letter-spacing: 0.16em !important;
  text-transform: uppercase !important;
  color: var(--dw-text-dim) !important;
  margin: 0 0 12px !important;
}

/* The hero action row let "Details" and "Open player" overlap — the buttons had
   no shared flex context, so they painted on top of each other. */
body.dream-app-open[data-dream-route] .dream-hero-actions,
body.dream-app-open[data-dream-route] .dream-detail-pills {
  display: flex !important;
  flex-wrap: wrap !important;
  align-items: center !important;
  gap: 10px !important;
  width: auto !important;
}
body.dream-app-open[data-dream-route] .dream-hero-actions > * {
  flex: 0 0 auto !important;
  position: static !important;
  white-space: nowrap !important;
}

/* "Details" and "Open player" painted on top of each other on Discover. They are
   plain .dream-secondary buttons whose parent varies by view, so rather than
   guess the container, put the buttons themselves back in normal flow — the
   overlap comes from them being taken out of it. */
body.dream-app-open[data-dream-route] .dream-secondary {
  position: static !important;
  float: none !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  vertical-align: middle !important;
  margin: 4px 10px 4px 0 !important;
  white-space: nowrap !important;
}

body.dream-app-open .dream-search-row-copy strong,
body.dream-app-open .dream-collection-row strong {
  color: var(--dw-text) !important;
  font-weight: 700 !important;
  letter-spacing: -0.005em !important;
}
body.dream-app-open .dream-search-row-copy em,
body.dream-app-open .dream-search-row-meta {
  color: var(--dw-text-dim) !important;
  font-style: normal !important;
}

/* The app header was a hard black slab with "Sign in" and the close control
   colliding at the right edge. Let it sit on the scrim as plain type. */
body.dream-app-open .dream-app-main-header {
  padding: 18px 4px 10px !important;
  align-items: flex-start !important;
  gap: 16px !important;
}
body.dream-app-open .dream-app-main-header-kicker {
  font-size: 11px !important;
  letter-spacing: 0.18em !important;
  text-transform: uppercase !important;
  color: var(--dw-text-faint) !important;
  margin: 0 0 2px !important;
}
body.dream-app-open .dream-app-main-header-name {
  letter-spacing: 0.02em !important;
  line-height: 1 !important;
  margin: 0 !important;
}
body.dream-app-open .dream-app-main-header-actions {
  display: flex !important;
  align-items: center !important;
  gap: 10px !important;
  flex: 0 0 auto !important;
}

/* ---------------------------------------------------------------------------
   5. CLIPPING — tile titles were cut mid-word at the tile edge
   ("Eccojams Rotation 173…" hard-clipped with no ellipsis).
   --------------------------------------------------------------------------- */
/* Horizontal rails (Trending, Listen again, New drops) render fixed-width
   .dream-collection-row tiles. Their copy column had no min-width:0, so the text
   overflowed and was hard-cut mid-word by the tile's overflow:hidden — no ellipsis,
   e.g. "Eccojams Rotation 173" / "DREAMWAVE FM ROTATIO". Constrain the copy and
   let it truncate properly. */
body.dream-app-open[data-dream-route] .dream-trending-scroll .dream-collection-row,
body.dream-app-open[data-dream-route] .dream-listen-again-scroll .dream-collection-row,
body.dream-app-open[data-dream-route] .dream-new-drops-scroll .dream-collection-row {
  overflow: hidden !important;
}

body.dream-app-open[data-dream-route] .dream-trending-scroll .dream-collection-row > *,
body.dream-app-open[data-dream-route] .dream-listen-again-scroll .dream-collection-row > *,
body.dream-app-open[data-dream-route] .dream-new-drops-scroll .dream-collection-row > * {
  min-width: 0 !important;
}

body.dream-app-open[data-dream-route] .dream-trending-scroll .dream-collection-row strong,
body.dream-app-open[data-dream-route] .dream-trending-scroll .dream-collection-row em,
body.dream-app-open[data-dream-route] .dream-listen-again-scroll .dream-collection-row strong,
body.dream-app-open[data-dream-route] .dream-listen-again-scroll .dream-collection-row em,
body.dream-app-open[data-dream-route] .dream-new-drops-scroll .dream-collection-row strong,
body.dream-app-open[data-dream-route] .dream-new-drops-scroll .dream-collection-row em,
body.dream-app-open[data-dream-route] .dream-browse-tile span {
  display: block !important;
  min-width: 0 !important;
  max-width: 100% !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  white-space: nowrap !important;
}

/* ROOT CAUSE of the hard-cut rail titles (measured in-page):
     .dream-collection-row  → flex: 0 0 260px; overflow: hidden
     .dream-collection-track-main → display: grid, computed width 300.9px
   The inner grid was 41px WIDER than the tile that contains it, so the tile's
   overflow:hidden sliced it mid-word. The ellipsis on <strong>/<em> never fired
   because the text fits its oversized parent — the parent was the problem.
   A `1fr` column is `minmax(auto, 1fr)`, and that `auto` minimum is min-content,
   so a long title forces the column wider than the tile. `minmax(0, 1fr)` lets
   the column shrink, which lets the existing ellipsis do its job. */
body.dream-app-open[data-dream-route] .dream-collection-row .dream-collection-track-main {
  display: grid !important;
  grid-template-columns: auto minmax(0, 1fr) !important;
  flex: 1 1 auto !important;
  width: auto !important;
  min-width: 0 !important;
  max-width: 100% !important;
  overflow: hidden !important;
}

body.dream-app-open[data-dream-route] .dream-collection-row .dream-collection-track-copy {
  min-width: 0 !important;
  max-width: 100% !important;
  overflow: hidden !important;
}

/* Give the rails breathing room above the fixed mini-player. */
body.dream-app-open[data-dream-route] .dream-trending-scroll {
  padding-bottom: 8px !important;
}

/* At a 2486px viewport adjacent rail tiles collided (two .dream-collection-row
   articles overlapping by 20x52, their track-mains only 106px apart when the
   tile is 260px wide) — the tiles were being allowed to shrink past their own
   content inside the flex rail. Pin them and give the rail a real gap. */
body.dream-app-open[data-dream-route] .dream-trending-scroll,
body.dream-app-open[data-dream-route] .dream-listen-again-scroll,
body.dream-app-open[data-dream-route] .dream-new-drops-scroll,
body.dream-app-open[data-dream-route] .dream-creator-scroll {
  display: flex !important;
  gap: 10px !important;
  align-items: stretch !important;
}

body.dream-app-open[data-dream-route] .dream-trending-scroll > *,
body.dream-app-open[data-dream-route] .dream-listen-again-scroll > *,
body.dream-app-open[data-dream-route] .dream-new-drops-scroll > *,
body.dream-app-open[data-dream-route] .dream-creator-scroll > * {
  flex: 0 0 auto !important;
  margin: 0 !important;
}

/* Containment backstop. At 2486px, track tiles in one rail were painting over
   their neighbours (track-main 98px wide spilling 44px into the NEXT tile's play
   button). Rather than chase every rail variant's sizing, guarantee a tile can
   never paint outside its own box — the children then truncate instead of
   colliding, which is the correct behaviour for a fixed-width tile anyway. */
body.dream-app-open[data-dream-route] #dreamAppContent .dream-collection-row--track {
  overflow: hidden !important;
  min-width: 0 !important;
  contain: paint !important;
}
body.dream-app-open[data-dream-route] #dreamAppContent .dream-collection-row--track > * {
  min-width: 0 !important;
  max-width: 100% !important;
}

/* ---------------------------------------------------------------------------
   6. CLEARANCE — the fixed mini-player and bottom tabs sat on top of the last
   rows of content, cutting them off mid-card.
   --------------------------------------------------------------------------- */
/* NOTE: do NOT add padding-bottom to .dream-app-main — it is the scroll container,
   and padding there collapsed the scrollable area so everything below the mood
   filters became unreachable. Pad the inner content only. */
body.dream-app-open[data-dream-route] .dream-app-content,
body.dream-app-open[data-dream-route] .dream-search-results {
  padding-bottom: 184px !important;
}

/* ---------------------------------------------------------------------------
   7. TRACK NAMES WERE INVISIBLE IN LISTS  (measured in-page)
        BUTTON.dream-search-track-main   48x48   min-width:48px   ← wraps the copy
          SPAN.dream-search-row-copy      0x45   width:0px
            STRONG (the track name)       0x29   width:0px        ← invisible
   The element that wraps the artwork AND the copy was being sized like a 48px
   icon button, so the copy column inside it collapsed to zero and the title
   simply never painted. Let it fill the row and let the copy take the slack.
   --------------------------------------------------------------------------- */
/* Measured: the track row computed FOUR grid columns — 97.56px 98px 0px 265.56px —
   while its template named only two ("main controls" / ". controls"). The meta line
   carries no grid-area, so it auto-placed into an IMPLICIT column and took 265px,
   squeezing the `main` column (artwork + title) down to 97px. Give meta a named
   home in the second row so the grid stays two columns and `main` gets the slack.
   Scoped to --track only; plain .dream-search-row is flex and must stay that way. */
body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row--track {
  display: grid !important;
  grid-template-columns: minmax(0, 1fr) auto !important;
  grid-template-areas: "main controls" "meta controls" !important;
  align-items: center !important;
  column-gap: 12px !important;
  row-gap: 2px !important;
}

body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row--track .dream-search-row-meta {
  grid-area: meta !important;
  min-width: 0 !important;
  overflow: hidden !important;
}

body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row--track .dream-search-row-controls {
  grid-area: controls !important;
}

/* THE CULPRIT (minimal-only.v464.css:26548):
     body.dream-app-open[data-dream-route="search"] #dreamAppContent .dream-track-action {
       width:48px !important; min-width:48px !important;
       height:48px !important; min-height:48px !important; }
   That is a 48px touch-target rule intended for icon buttons. But
   .dream-search-track-main ALSO carries .dream-track-action, and it is the
   container wrapping the artwork AND the track name — so the accessibility rule
   squashed the whole title into a 48x48 box and the copy collapsed to 0 width.
   The selector contains an #id (specificity 1,3,1), which is why lower-specificity
   overrides silently lost. Restore the intended grid and beat that specificity.
   Do NOT set display:flex here — the element is a grid with `grid-area: main`. */
body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row .dream-search-track-main.dream-track-action,
body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row .dream-search-track-main {
  display: grid !important;
  grid-template-columns: 44px minmax(0, 1fr) !important;
  align-items: center !important;
  gap: 10px !important;
  width: 100% !important;
  min-width: 0 !important;
  max-width: 100% !important;
  height: auto !important;
  min-height: 0 !important;
  padding: 0 !important;
  text-align: left !important;
}

body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row .dream-search-row-copy {
  display: block !important;
  min-width: 0 !important;
  width: auto !important;
  max-width: 100% !important;
  overflow: hidden !important;
}

body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row-copy > strong,
body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row-copy > em {
  display: block !important;
  min-width: 0 !important;
  max-width: 100% !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  white-space: nowrap !important;
  -webkit-line-clamp: none !important;
}

/* The artwork inside the row must not grow or shrink the copy away. */
body.dream-app-open[data-dream-route] .dream-search-track-main > img,
body.dream-app-open[data-dream-route] .dream-search-row .dream-row-art {
  flex: 0 0 auto !important;
  width: 44px !important;
  height: 44px !important;
  border-radius: 8px !important;
  object-fit: cover !important;
}

/* ---------------------------------------------------------------------------
   8. RESULTS COLUMN WAS 231px WIDE INSIDE A 1222px VIEWPORT.
   The results grid kept collapsing to a narrow track, which is what made the
   whole page feel cramped and the rows feel oversized relative to their column.
   --------------------------------------------------------------------------- */
body.dream-app-open[data-dream-route="search"] .dream-search-results-grid,
body.dream-app-open[data-dream-route="search"] .dream-search-results-grid--single {
  display: block !important;
  width: 100% !important;
  max-width: none !important;
}

body.dream-app-open[data-dream-route] .dream-search-results-main,
body.dream-app-open[data-dream-route] .dream-search-section,
body.dream-app-open[data-dream-route] .dream-search-results {
  width: 100% !important;
  max-width: none !important;
  min-width: 0 !important;
}

/* ---------------------------------------------------------------------------
   9. FLUID TYPE + DENSITY — "text should scale better at all window sizes".
   The app mixed hard px sizes set at several breakpoints, so type was oversized
   in narrow windows and undersized in wide ones. clamp() ties each step to the
   viewport with a floor and a ceiling, so there is one continuous scale instead
   of jumps at breakpoints.
   --------------------------------------------------------------------------- */
body.dream-app-open[data-dream-route] .dream-app-main-header-name {
  font-size: clamp(20px, 1.1vw + 16px, 30px) !important;
}
body.dream-app-open[data-dream-route] .dream-app-main-header-kicker,
body.dream-app-open[data-dream-route] .dream-section-head h3,
body.dream-app-open[data-dream-route] .dream-section-head h4 {
  font-size: clamp(10px, 0.15vw + 9.5px, 12px) !important;
}
body.dream-app-open[data-dream-route] .dream-search-row-copy > strong,
body.dream-app-open[data-dream-route] .dream-collection-row strong {
  font-size: clamp(13px, 0.25vw + 12px, 15px) !important;
  line-height: 1.3 !important;
}
body.dream-app-open[data-dream-route] .dream-search-row-copy > em,
body.dream-app-open[data-dream-route] .dream-collection-row em,
body.dream-app-open[data-dream-route] .dream-search-meta-line,
body.dream-app-open[data-dream-route] .dream-row-stat {
  font-size: clamp(11px, 0.15vw + 10.5px, 12.5px) !important;
  line-height: 1.35 !important;
}
body.dream-app-open[data-dream-route] .dream-search-chip,
body.dream-app-open[data-dream-route] .dream-search-scope,
body.dream-app-open[data-dream-route] .dream-secondary {
  font-size: clamp(11px, 0.16vw + 10.4px, 13px) !important;
}

/* Row density: tighter, even rhythm instead of chunky uneven padding. */
body.dream-app-open[data-dream-route] .dream-search-row,
body.dream-app-open[data-dream-route] .dream-search-result-row {
  padding: 9px 12px !important;
  margin: 0 0 6px !important;
  min-height: 0 !important;
}
body.dream-app-open[data-dream-route] .dream-search-row-meta {
  gap: 6px !important;
  margin-top: 2px !important;
}

/* ---------------------------------------------------------------------------
   10. Catalog browser injected into Library by js/dw-enhancements.js.
   --------------------------------------------------------------------------- */
body.dream-app-open[data-dream-route] .dw-catalog-controls {
  display: flex !important;
  flex-wrap: wrap !important;
  align-items: center !important;
  gap: 8px !important;
  margin-bottom: 12px !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-input {
  flex: 1 1 220px !important;
  min-width: 0 !important;
  padding: 9px 12px !important;
  font-size: clamp(12px, 0.2vw + 11.5px, 14px) !important;
  color: var(--dw-text) !important;
  background: var(--dw-surface) !important;
  border: 1px solid var(--dw-hairline) !important;
  border-radius: 10px !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-input::placeholder {
  color: var(--dw-text-faint) !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-sorts {
  display: flex !important;
  gap: 6px !important;
  flex: 0 0 auto !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-sorts .dream-search-chip.active {
  border-color: var(--dw-accent) !important;
  color: var(--dw-text) !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-list {
  display: flex !important;
  flex-direction: column !important;
  gap: 6px !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-row {
  display: flex !important;
  align-items: center !important;
  gap: 12px !important;
  padding: 8px 12px !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-row .dw-catalog-main {
  display: flex !important;
  align-items: center !important;
  gap: 12px !important;
  flex: 1 1 auto !important;
  min-width: 0 !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-row .dream-row-art {
  flex: 0 0 auto !important;
  width: 40px !important;
  height: 40px !important;
  border-radius: 8px !important;
  object-fit: cover !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-play {
  flex: 0 0 auto !important;
  width: 34px !important;
  height: 34px !important;
  border-radius: 50% !important;
  border: 1px solid var(--dw-hairline) !important;
  background: rgba(255, 255, 255, 0.06) !important;
  color: var(--dw-text) !important;
  cursor: pointer !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-play:hover {
  background: var(--dw-accent) !important;
  border-color: var(--dw-accent) !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-empty {
  color: var(--dw-text-dim) !important;
  font-size: 13px !important;
  padding: 12px 0 !important;
}
body.dream-app-open[data-dream-route] .dw-catalog-more {
  margin-top: 10px !important;
}

/* ---------------------------------------------------------------------------
   11. NARROW WINDOWS — measured at a 407px viewport the three row actions took
   124px of a 329px row (38%), leaving 117px for the title. Rather than shrink
   the buttons below the 44px touch target, collapse like/queue into the overflow
   ("More") button, which already contains both. Standard mobile pattern, and the
   title reclaims ~90px.
   --------------------------------------------------------------------------- */
@media (max-width: 560px) {
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row--track .dream-toggle-track-like-action,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row--track .dream-queue-track-action {
    display: none !important;
  }
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row--track {
    padding: 8px 10px !important;
    column-gap: 8px !important;
  }
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-row--track .dream-row-art,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-track-main {
    grid-template-columns: 38px minmax(0, 1fr) !important;
  }
  body.dream-app-open[data-dream-route] .dw-catalog-controls {
    gap: 6px !important;
  }
}

/* ---------------------------------------------------------------------------
   12. DESKTOP: the header was sitting BESIDE the content, not above it.
   Measured at a 1222px viewport:
     .dream-app-main          at 264,22  958x1266  display:flex   (a ROW)
       .dream-app-main-header at 264,22  300x60    ← a 300px column
       .dream-app-content     at 564,22  640x1146  ← pushed 300px right
   createDreamAppMainHeader() inserts the header as the first child of the main
   shell, but that shell is a flex ROW, so the wordmark became a column floating
   to the middle-left and the content was squeezed to 640px of the 930px it is
   allowed. Let the row wrap and make the header claim a full line, so it reads
   as a banner and the content reclaims the width.
   --------------------------------------------------------------------------- */
/* DW-FIX 2026-08-15: scope to the desktop row layout
   These two rules are ONLY correct while .dream-app-main is a flex ROW, which
   the app does at >=1100px (its own breakpoint -- where the sidebar rail appears).
   Below that the shell switches to flex-direction: column, and in a column
   container flex-basis is the HEIGHT: `flex: 0 0 100%` made the header eat the
   whole column (726px tall) and `flex-wrap: wrap` let #dreamAppContent wrap into
   a SECOND column off-screen, which the parent's overflow:hidden then clipped.
   Result: an empty app at every width below 1100px. Measured content left-offset
   was 406px in a 390px viewport, 982px at 1000px wide.
   mobile.css already sets the correct `flex: 0 0 auto` for small screens; this
   block was simply out-specifying it. */
@media (min-width: 1100px) {
  body.dream-app-open[data-dream-route] .dream-app-main {
    flex-wrap: wrap !important;
    align-content: flex-start !important;
  }

  body.dream-app-open[data-dream-route] .dream-app-main-header {
    flex: 0 0 100% !important;
    width: 100% !important;
    max-width: 100% !important;
    order: -1 !important;
  }
}

/* With the header on its own line the content can use the full column.
   The width was frozen by (minimal-only.v464.css):
     body.mode-minimal.dream-app-open #minimal-ui #dreamAppContent.dream-app-content {
       width: clamp(640px, 48vw, 920px) !important; min-width: min(640px, …) !important; }
   At a 1222px viewport 48vw = 586px, which falls BELOW the 640px floor, so the
   column froze at 640px and left ~150px dead on each side of a 958px area.
   That selector carries TWO ids — specificity (2,3,1) — so beating it needs
   `html` + the route attribute as well: (2,4,2).
   Cap at 1100px so ultra-wide monitors still get a sane line length. */
html body.mode-minimal.dream-app-open[data-dream-route] #minimal-ui #dreamAppContent.dream-app-content,
html body.dream-app-open[data-dream-route] #minimal-ui #dreamAppContent.dream-app-content {
  width: 100% !important;
  min-width: 0 !important;
  max-width: min(1100px, 100%) !important;
  flex: 1 1 auto !important;
  margin-inline: auto !important;
}

/* ---------------------------------------------------------------------------
   13. AUDIT SWEEP (js/dw-audit.js, all five routes at a 1222px viewport).
   Every rule below fixes a specific measured finding; the measurement is quoted.
   --------------------------------------------------------------------------- */

/* FONT — sub-10px text. Status chips rendered at 9.5px on discover/search/library
   ("Playing", "hot", "1009"), and the player transport labels at 9px
   ("Prev" / "Play" / "Next", plus the EQ preset names). 9px is below the point
   where this typeface stays legible on a photographic backdrop. */
body.dream-app-open[data-dream-route] .dream-status-chip {
  font-size: clamp(10.5px, 0.1vw + 10.2px, 11.5px) !important;
  letter-spacing: 0.06em !important;
  padding: 3px 7px !important;
}
body.dream-app-open[data-dream-route="player"] .dream-player-transport button em,
body.dream-app-open[data-dream-route="player"] .dream-player-preset em,
body.dream-app-open[data-dream-route="player"] #dreamAppContent em {
  font-size: clamp(10.5px, 0.1vw + 10.2px, 11.5px) !important;
  font-style: normal !important;
}

/* CONTRAST — text rendered at alpha 0.32–0.38, which disappears against the
   sunset backdrop. Measured: .dream-row-like "♡" 0.35, .dream-player-tier-sep
   0.35, .dream-trackinfo-duration "Live now" 0.38,
   .dream-provenance-disclosure-hint "Session details" 0.32. */
body.dream-app-open[data-dream-route] .dream-row-like,
body.dream-app-open[data-dream-route] .dream-toggle-track-like-action {
  color: rgba(244, 239, 255, 0.72) !important;
}
body.dream-app-open[data-dream-route] .dream-row-like.liked,
body.dream-app-open[data-dream-route] .dream-toggle-track-like-action.liked {
  color: var(--dw-accent) !important;
}
body.dream-app-open[data-dream-route] .dream-player-tier-sep,
body.dream-app-open[data-dream-route] .dream-trackinfo-duration,
body.dream-app-open[data-dream-route] .dream-provenance-disclosure-hint {
  color: rgba(244, 239, 255, 0.62) !important;
}

/* TINY — interactive targets below a comfortable size.
   Measured: .dream-row-like 23x44 (23px WIDE), #dreamPlayerVolumeBtn 28x28,
   .dream-player-action pills 30px tall, and two inline links at 14px / 21px. */
body.dream-app-open[data-dream-route] .dream-row-like,
body.dream-app-open[data-dream-route] .dream-toggle-track-like-action {
  min-width: 36px !important;
  min-height: 36px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}

body.dream-app-open[data-dream-route="player"] #dreamPlayerVolumeBtn {
  width: 36px !important;
  height: 36px !important;
  min-width: 36px !important;
  min-height: 36px !important;
}

body.dream-app-open[data-dream-route="player"] .dream-player-action {
  min-height: 36px !important;
  padding-block: 7px !important;
}

/* Inline text links were only 14–21px tall. A full 44px target would wreck the
   inline flow, so give them a 24px hit area via padding — enough to hit reliably
   with a mouse while staying inline. */
body.dream-app-open[data-dream-route] .dream-artist-link,
body.dream-app-open[data-dream-route] .dream-inline-link {
  display: inline-flex !important;
  align-items: center !important;
  min-height: 24px !important;
  padding-block: 3px !important;
}

/* Second audit pass on the player, once the first tier was cleared. The
   "Up next" panel rendered at 8–9px ("upcoming" was 8px), and three controls
   were between 16px and 28px tall — .dream-player-tier-action--upgrade measured
   95x16, i.e. a 16px-tall button. */
body.dream-app-open[data-dream-route="player"] .dream-player-up-next-label,
body.dream-app-open[data-dream-route="player"] .dream-player-up-next-tag,
body.dream-app-open[data-dream-route="player"] .dream-player-up-next-btn {
  font-size: clamp(10.5px, 0.1vw + 10.2px, 11.5px) !important;
  letter-spacing: 0.04em !important;
}

body.dream-app-open[data-dream-route="player"] .dream-player-tier-action,
body.dream-app-open[data-dream-route="player"] .dream-player-mini-action,
body.dream-app-open[data-dream-route="player"] .dream-player-up-next-btn,
body.dream-app-open[data-dream-route="player"] #dreamPlayerBottomRecovery {
  min-height: 32px !important;
  padding-block: 6px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}

/* OVERLAP (measured at a 2486px viewport — does not reproduce at 1222px):
     .dream-player-actions      y=1181  flex/static
     #dreamPlayerQuickActions   y=1198  flex/relative   → overlap 19px
   The two rows are only 17px apart while their buttons are 30–36px tall, so the
   Save/Playlist/Details/Report row painted straight over Like/Shuffle/Repeat/Queue.
   The action row's container was not growing to fit its own buttons. Let it size
   to content and wrap, which pushes the following row clear instead of under it. */
body.dream-app-open[data-dream-route="player"] .dream-player-actions {
  height: auto !important;
  min-height: 0 !important;
  align-items: center !important;
  flex-wrap: wrap !important;
  row-gap: 8px !important;
  column-gap: 8px !important;
  margin-bottom: 10px !important;
}

body.dream-app-open[data-dream-route="player"] .dream-player-quick-actions {
  height: auto !important;
  min-height: 0 !important;
  flex-wrap: wrap !important;
  row-gap: 8px !important;
  clear: both !important;
}

/* ROOT CAUSE of that overlap (ancestry traced at 2486px):
     .dream-player-actions  <  .dream-player-transport-card
                            <  .dream-player-primary        {sticky, h=1263}
                            <  .dream-player-layout--desktop {grid,   h=1031}  ← 232px SHORTER
     #dreamPlayerQuickActions  <  .dream-player-surface--desktop  (sibling of the layout)
   The sticky primary column is 232px taller than the grid row containing it, so
   it spills out of the layout and lands on top of the quick-actions row that
   follows. The two rows are not siblings, which is why spacing them did nothing.
   Fix the container: let the grid size to its content instead of clipping the
   sticky child's height.

   The height itself comes from a pile of contradictory declarations on the SAME
   selector, all !important, resolved only by source order:
     .dream-player-surface  min-height:0; max-height:none; height:auto   (x2)
     .dream-player-surface  min-height:auto
     .dream-player-surface  min-height:calc(100dvh - 76px)
     .dream-player-surface  height:calc(100dvh - 76px)   ← last one wins
   i.e. the player is pinned to the window height even when its content is taller,
   so the overflow lands on whatever follows. Stop fitting the player to the
   viewport and let .dream-app-content (already overflow:auto) do the scrolling.
   #dreamAppContent gives specificity (1,4,1), which beats all of the above
   regardless of their order in the file. */
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-surface,
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-surface--desktop,
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-layout,
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-layout--desktop,
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-primary,
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-secondary {
  height: auto !important;
  min-height: 0 !important;
  max-height: none !important;
}

body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-layout,
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-layout--desktop {
  align-items: start !important;
  align-content: start !important;
  grid-auto-rows: auto !important;
}

body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-primary {
  align-self: start !important;
}

/* The two-column desktop variant let the primary column's content spill into the
   secondary column (scene chips painting over the preview card). Same root cause
   as the rail titles: a `1fr` track is `minmax(auto, 1fr)`, whose auto minimum is
   min-content, so a wide child forces the column past its share. minmax(0, 1fr)
   lets the columns hold their bounds. The stacked variant was already clean. */
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-layout--desktop {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) !important;
  column-gap: 20px !important;
}

body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-primary,
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-secondary {
  min-width: 0 !important;
  max-width: 100% !important;
  overflow: hidden !important;
}

/* Same container-shorter-than-content bug in the preview / scene rows:
   .dream-player-preview-copy started at y=992 and ran ~123px tall, while the
   .dream-player-scene-row below it began at y=1066 — a 49px collision. */
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-preview-row,
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-scene-row,
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-preview-copy {
  height: auto !important;
  min-height: 0 !important;
  max-height: none !important;
  align-items: start !important;
}

body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-preview-row {
  row-gap: 10px !important;
  margin-bottom: 10px !important;
}

/* ---------------------------------------------------------------------------
   15. MINI PLAYER + row play buttons.
   --------------------------------------------------------------------------- */

/* Measured 28x44 — the round play affordance was squeezed to 28px wide in some
   rows, so the glyph sat off-centre in a non-circular button. */
body.dream-app-open[data-dream-route] #dreamAppContent .dream-row-play,
body.dream-app-open[data-dream-route] #dreamAppContent .dream-row-play.dream-track-action {
  width: 44px !important;
  min-width: 44px !important;
  height: 44px !important;
  min-height: 44px !important;
  flex: 0 0 44px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  border-radius: 50% !important;
}

/* The mini-player seek bar is a 6px-tall absolutely-positioned strip at the very
   bottom of a 56px bar — accurate to hit only within 6px. Extend the HIT AREA
   with a transparent pseudo-element (pseudo-elements hit-test as their parent),
   so seeking gets a ~20px band without changing how the bar looks. */
body.dream-app-open #miniNpProgress {
  cursor: pointer !important;
}
body.dream-app-open #miniNpProgress::after {
  content: "" !important;
  position: absolute !important;
  left: 0 !important;
  right: 0 !important;
  top: -10px !important;
  bottom: -4px !important;
  background: transparent !important;
}

/* Make the fill readable against the artwork behind it. */
body.dream-app-open #miniNpProgressFill {
  background: linear-gradient(90deg, var(--dw-accent), var(--dw-accent-2)) !important;
}

/* ---------------------------------------------------------------------------
   17. DISCOVER BROWSE GRID — fixed 200px tiles colliding inside a 478px column.
   Auto-traced ancestry of an actually-overlapping tile at a 2478px viewport:
     article.dream-collection-row--track { x=1280 w=200  flex: 0 0 200px }
       < div.dream-collection-stack      { flex  w=478 }
         < section.dream-section         { w=510 }
           < div.dream-discover-browse-grid { grid cols=510px 510px }
   Two-plus non-shrinkable 200px tiles cannot fit a 478px column, so they piled
   onto each other. The container is named a *stack*, and everywhere else in the
   app this content reads as a full-width row list (see "In rotation", which is
   the same component and looks right) — so lay it out as one. This removes the
   collision by construction and gives titles the full column width.
   --------------------------------------------------------------------------- */
body.dream-app-open[data-dream-route] #dreamAppContent .dream-collection-stack {
  display: flex !important;
  flex-direction: column !important;
  gap: 8px !important;
  width: 100% !important;
  min-width: 0 !important;
}

body.dream-app-open[data-dream-route] #dreamAppContent .dream-collection-stack > .dream-collection-row,
body.dream-app-open[data-dream-route] #dreamAppContent .dream-collection-stack > * {
  flex: 0 0 auto !important;
  width: 100% !important;
  max-width: 100% !important;
  min-width: 0 !important;
}

/* The scene picker's chip row is a non-wrapping flex row: measured 396px wide
   while holding chips that ran to x=1485, i.e. 133px past the primary column's
   right edge (1352) and into the secondary column, where they painted over the
   preview card. Let the chips wrap so the picker stays inside its column. */
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-scene-row {
  flex-wrap: wrap !important;
  row-gap: 8px !important;
  column-gap: 8px !important;
  min-width: 0 !important;
  max-width: 100% !important;
  overflow: hidden !important;
}
body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-scene-picker {
  min-width: 0 !important;
  max-width: 100% !important;
  overflow: hidden !important;
}

/* Library sidecar close button measured 30x44 — one dimension under target. */
body.dream-app-open[data-dream-route] #dreamAppContent .dream-sidecar-inline-close {
  min-width: 36px !important;
  min-height: 36px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}

/* ---------------------------------------------------------------------------
   19. GLOBAL CHROME — defects that recurred on EVERY route audited
   (discover, search, library, player, account, upload, agent, settings,
   upgrade, studio, stats). All live in the mini player or the app header, so
   one fix each clears them everywhere.
   --------------------------------------------------------------------------- */

/* #minimalQueueBtn is a legacy control deliberately deactivated while the app
   shell is open (minimal-only.v464.css:2250 sets opacity:.28 + pointer-events:
   none) — but it still measured 0x0 with text, so it stayed keyboard-focusable
   and screen-reader visible while doing nothing. Remove it from the tree. */
body.dream-app-open #minimalQueueBtn {
  display: none !important;
}

/* Mini player type was below the legibility floor: the transport clock at 9.6px
   and the queue badge at 9px. */
body.dream-app-open #miniNpTime,
body.dream-app-open .mini-np-time {
  font-size: clamp(11px, 0.12vw + 10.6px, 12.5px) !important;
  font-variant-numeric: tabular-nums !important;
  color: rgba(244, 239, 255, 0.78) !important;
}
body.dream-app-open #miniNpQueueBadge,
body.dream-app-open .mini-np-queue-badge {
  font-size: clamp(10.5px, 0.1vw + 10.2px, 11.5px) !important;
  min-width: 18px !important;
  height: 18px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}

/* Mini player volume: the button measured 28x14 and the slider 48x3 — a 3px
   tall drag target. Keep the track visually thin but give it a real hit area. */
body.dream-app-open #miniNpVolume,
body.dream-app-open .mini-np-volume {
  width: 32px !important;
  height: 32px !important;
  min-width: 32px !important;
  min-height: 32px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}

body.dream-app-open #miniNpVolumeSlider {
  height: 20px !important;
  min-height: 20px !important;
  background: transparent !important;
  -webkit-appearance: none !important;
  appearance: none !important;
  cursor: pointer !important;
}
body.dream-app-open #miniNpVolumeSlider::-webkit-slider-runnable-track {
  height: 4px !important;
  border-radius: 2px !important;
  background: rgba(244, 239, 255, 0.28) !important;
}
body.dream-app-open #miniNpVolumeSlider::-webkit-slider-thumb {
  -webkit-appearance: none !important;
  width: 12px !important;
  height: 12px !important;
  margin-top: -4px !important;
  border-radius: 50% !important;
  border: 0 !important;
  background: var(--dw-text) !important;
}
body.dream-app-open #miniNpVolumeSlider::-moz-range-track {
  height: 4px !important;
  border-radius: 2px !important;
  background: rgba(244, 239, 255, 0.28) !important;
}
body.dream-app-open #miniNpVolumeSlider::-moz-range-thumb {
  width: 12px !important;
  height: 12px !important;
  border: 0 !important;
  border-radius: 50% !important;
  background: var(--dw-text) !important;
}

/* App header controls measured 50x23 ("Sign in") and 15x25 ("✕") — the close
   control was 15px wide, which is very hard to hit. */
body.dream-app-open[data-dream-route] .dream-app-main-header-close {
  width: 36px !important;
  height: 36px !important;
  min-width: 36px !important;
  min-height: 36px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  border-radius: 50% !important;
}
body.dream-app-open[data-dream-route] .dream-app-main-header-account {
  min-height: 32px !important;
  padding: 6px 12px !important;
  display: inline-flex !important;
  align-items: center !important;
}

/* Route-specific: settings back buttons were 23px tall, and the agent context
   checkbox 17x17. */
body.dream-app-open[data-dream-route] .dream-settings-back-btn,
body.dream-app-open[data-dream-route] .dream-settings-bottom-back-btn {
  min-height: 36px !important;
  padding-block: 8px !important;
  display: inline-flex !important;
  align-items: center !important;
}
body.dream-app-open[data-dream-route="agent"] #dreamAgentContextToggle {
  width: 20px !important;
  height: 20px !important;
  min-width: 20px !important;
  min-height: 20px !important;
  accent-color: var(--dw-accent) !important;
}

/* ---------------------------------------------------------------------------
   21. MOBILE (measured on a real 390x844 viewport via CDP device emulation).
   --------------------------------------------------------------------------- */

/* THE mobile bug: rail tiles collapsed and their titles rendered at 0px wide
   (strong 0x16, em 0x13, .dream-row-stat 0x26; .dream-collection-track-main
   just 24x63). This is an interaction between two things:
       .dream-trending-scroll > *        flex: 0 0 auto      (content-sized)
       .dream-collection-track-main      grid-template-columns: auto minmax(0,1fr)
   A `1fr` track inside a SHRINK-TO-FIT container resolves to its minimum, i.e.
   ZERO — on desktop the tile carried an explicit `flex: 0 0 260px` so 1fr had
   room, but on mobile the basis is auto and the copy column vanishes.
   Fix: give mobile rail tiles a DEFINITE basis. min(78vw, 300px) also gives the
   standard carousel "peek" of the next card. */
@media (max-width: 620px) {
  body.dream-app-open[data-dream-route] .dream-trending-scroll > .dream-collection-row,
  body.dream-app-open[data-dream-route] .dream-listen-again-scroll > .dream-collection-row,
  body.dream-app-open[data-dream-route] .dream-new-drops-scroll > .dream-collection-row,
  body.dream-app-open[data-dream-route] .dream-trending-scroll > article,
  body.dream-app-open[data-dream-route] .dream-listen-again-scroll > article,
  body.dream-app-open[data-dream-route] .dream-new-drops-scroll > article {
    flex: 0 0 min(78vw, 300px) !important;
    width: min(78vw, 300px) !important;
    max-width: min(78vw, 300px) !important;
    min-width: 0 !important;
  }

  /* With a definite tile width the inner grid can allocate the copy column. */
  body.dream-app-open[data-dream-route] .dream-trending-scroll .dream-collection-track-main,
  body.dream-app-open[data-dream-route] .dream-listen-again-scroll .dream-collection-track-main,
  body.dream-app-open[data-dream-route] .dream-new-drops-scroll .dream-collection-track-main {
    display: grid !important;
    grid-template-columns: 40px minmax(0, 1fr) !important;
    gap: 10px !important;
    width: 100% !important;
    min-width: 0 !important;
    align-items: center !important;
  }

  body.dream-app-open[data-dream-route] .dream-collection-track-copy {
    min-width: 0 !important;
    max-width: 100% !important;
    overflow: hidden !important;
  }

  /* Sub-10px text measured on mobile: the play glyph at 9px, play-count at
     9.5px, the "More" pill at 9.4px, the creator handle at 9px, and the creator
     CTA at SEVEN px. #dreamAppContent is needed — without the id these lose to
     the existing (1,x,1) rules and silently do nothing. */
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-row-play,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-row-play.dream-track-action {
    font-size: 13px !important;
  }
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-row-stat,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-row-pill,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-row-more-action,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-collection-track-copy em,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-discover-creator-card em {
    font-size: 10.5px !important;
  }

  /* Creator CTA measured 7px text in an 18px-tall button — unreadable and
     barely tappable. */
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-discover-creator-cta,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-view-creator-action {
    font-size: 11.5px !important;
    min-height: 32px !important;
    padding: 7px 12px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    border-radius: 999px !important;
    max-width: 100% !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
  }

  /* Rails should scroll smoothly and snap on touch. */
  body.dream-app-open[data-dream-route] .dream-trending-scroll,
  body.dream-app-open[data-dream-route] .dream-listen-again-scroll,
  body.dream-app-open[data-dream-route] .dream-new-drops-scroll {
    scroll-snap-type: x proximity !important;
    -webkit-overflow-scrolling: touch !important;
    overscroll-behavior-x: contain !important;
    padding-inline: 2px !important;
  }
  body.dream-app-open[data-dream-route] .dream-trending-scroll > *,
  body.dream-app-open[data-dream-route] .dream-listen-again-scroll > *,
  body.dream-app-open[data-dream-route] .dream-new-drops-scroll > * {
    scroll-snap-align: start !important;
  }

  /* Inline links need a real tap target on touch. */
  body.dream-app-open[data-dream-route] .dream-artist-link,
  body.dream-app-open[data-dream-route] .dream-inline-link {
    min-height: 32px !important;
    padding-block: 6px !important;
  }

  /* More sub-10px text found on mobile search + library:
       .dream-kicker              7.6px  ("Library")
       .dream-search-scope-count  9px    (the 1021 / 37 / 1 counts)
       .dream-library-filter      9.5px  (All / Playlists / …)
       .dream-library-sync-action 9.2px
       .dream-create-playlist-action 9.4px, and only 30px tall */
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-kicker,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-search-scope-count,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-library-filter,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-library-sub-tab,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-library-sync-action,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-create-playlist-action,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-primary,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-secondary {
    font-size: 11px !important;
    letter-spacing: 0.04em !important;
  }

  body.dream-app-open[data-dream-route] #dreamAppContent .dream-primary,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-secondary,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-library-filter,
  body.dream-app-open[data-dream-route] #dreamAppContent .dream-library-sub-tab {
    min-height: 36px !important;
    padding: 8px 12px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }
}

/* ---------------------------------------------------------------------------
   22. PROVENANCE / PLAYER LABELS — measured on the player route:
       .minimal-provenance-label   9px at alpha 0.22–0.38  ("Model", "Provider",
                                   "Prompt engineering")
       .dream-player-kicker        8.5px ("1 / 1021")
       .dream-player-preview-tag   9px
   Provenance is the point of an AI music app — "which model made this" should be
   readable, not a 9px ghost. Applied at all widths, not just mobile.
   --------------------------------------------------------------------------- */
body.dream-app-open[data-dream-route] .minimal-provenance-label,
body.dream-app-open[data-dream-route] .dream-provenance-badge-label,
body.dream-app-open[data-dream-route] .dream-player-kicker,
body.dream-app-open[data-dream-route] .dream-player-preview-tag,
body.dream-app-open[data-dream-route] #dreamAppContent .minimal-provenance-label,
body.dream-app-open[data-dream-route] #dreamAppContent .dream-player-kicker,
body.dream-app-open[data-dream-route] #dreamAppContent .dream-player-preview-tag {
  font-size: clamp(10.5px, 0.1vw + 10.2px, 11.5px) !important;
  color: rgba(244, 239, 255, 0.68) !important;
  letter-spacing: 0.05em !important;
}

body.dream-app-open[data-dream-route] #dreamAppContent .minimal-provenance-value,
body.dream-app-open[data-dream-route] #dreamAppContent .minimal-provenance-label + strong,
body.dream-app-open[data-dream-route] #dreamAppContent .minimal-provenance-label + em {
  color: rgba(244, 239, 255, 0.86) !important;
  font-style: normal !important;
}

/* The provenance rows render CLASSLESS spans inside .dream-provenance-row
   ("Model", "Provider", "Prompt engineering", "Negative prompt", "Seed"),
   measured at 9px and alpha 0.22 — effectively invisible. Target the row. */
body.dream-app-open[data-dream-route] .dream-provenance-group-separator span,
body.dream-app-open[data-dream-route] #dreamAppContent .dream-provenance-group-separator span,
body.dream-app-open[data-dream-route] .dream-provenance-row > span,
body.dream-app-open[data-dream-route] #dreamAppContent .dream-provenance-row > span,
body.dream-app-open[data-dream-route] #dreamAppContent .dream-provenance-row > em,
body.dream-app-open[data-dream-route] #dreamAppContent .dream-provenance-header span {
  font-size: clamp(10.5px, 0.1vw + 10.2px, 11.5px) !important;
  color: rgba(244, 239, 255, 0.70) !important;
}

body.dream-app-open[data-dream-route] #dreamAppContent .dream-provenance-row > span:last-child,
body.dream-app-open[data-dream-route] #dreamAppContent .dream-provenance-row > strong {
  color: rgba(244, 239, 255, 0.88) !important;
}

/* ---------------------------------------------------------------------------
   23. Accessibility floor.
   --------------------------------------------------------------------------- */
body.dream-app-open :focus-visible {
  outline: 2px solid var(--dw-accent-2) !important;
  outline-offset: 2px !important;
  border-radius: 6px !important;
}

@media (prefers-reduced-motion: reduce) {
  body.dream-app-open * {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}


/* ---------------------------------------------------------------------------
   DW-FEAT 2026-08-15: track versions panel
   Creator-only version history on the Studio route. Every selector is scoped by
   the #dwVersionsSection id, so none of this can leak into the rest of the app
   and none of it needs !important to win.
   --------------------------------------------------------------------------- */
#dwVersionsSection {
  margin: 28px 0 12px;
  padding: 18px 18px 22px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 18px;
  background: rgba(14, 10, 24, 0.55);
  backdrop-filter: blur(8px);
}
#dwVersionsSection .dw-ver-title {
  margin: 0 0 4px;
  font-size: clamp(1.05rem, 1.6vw, 1.35rem);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
#dwVersionsSection .dw-ver-sub {
  margin: 0 0 16px;
  font-size: 0.86rem;
  line-height: 1.5;
  opacity: 0.72;
  max-width: 62ch;
}
#dwVersionsSection .dw-ver-error {
  margin: 0 0 12px;
  padding: 8px 12px;
  border-radius: 10px;
  font-size: 0.82rem;
  background: rgba(255, 92, 92, 0.14);
  border: 1px solid rgba(255, 92, 92, 0.35);
}
#dwVersionsSection .dw-ver-track {
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  margin-bottom: 10px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.03);
}
#dwVersionsSection .dw-ver-head {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 13px 14px;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  min-height: 48px;
}
#dwVersionsSection .dw-ver-head:hover { background: rgba(255, 255, 255, 0.04); }
#dwVersionsSection .dw-ver-name {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#dwVersionsSection .dw-ver-count {
  flex: 0 0 auto;
  font-size: 0.76rem;
  letter-spacing: 0.06em;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  opacity: 0.85;
}
#dwVersionsSection .dw-ver-caret { flex: 0 0 auto; opacity: 0.6; }
#dwVersionsSection .dw-ver-body {
  padding: 4px 14px 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
#dwVersionsSection .dw-ver-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  font-size: 0.85rem;
}
#dwVersionsSection .dw-ver-row:last-of-type { border-bottom: 0; }
#dwVersionsSection .dw-ver-no {
  flex: 0 0 auto;
  min-width: 2.4em;
  font-weight: 700;
  letter-spacing: 0.04em;
}
#dwVersionsSection .dw-ver-label {
  flex: 1 1 auto;
  min-width: 0;
  opacity: 0.85;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#dwVersionsSection .dw-ver-date { flex: 0 0 auto; opacity: 0.5; font-size: 0.78rem; }
#dwVersionsSection .dw-ver-current {
  flex: 0 0 auto;
  font-size: 0.7rem;
  letter-spacing: 0.09em;
  padding: 4px 10px;
  border-radius: 999px;
  color: #0b1a12;
  background: #46e08a;
  font-weight: 700;
}
#dwVersionsSection .dw-ver-promote {
  flex: 0 0 auto;
  font-size: 0.76rem;
  padding: 7px 12px;
  min-height: 34px;
  border-radius: 999px;
  cursor: pointer;
  color: inherit;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.16);
}
#dwVersionsSection .dw-ver-promote:hover { background: rgba(255, 255, 255, 0.14); }
#dwVersionsSection .dw-ver-upload {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-top: 14px;
  flex-wrap: wrap;
}
#dwVersionsSection .dw-ver-newlabel {
  flex: 1 1 220px;
  min-width: 0;
  padding: 9px 12px;
  min-height: 40px;
  border-radius: 10px;
  color: inherit;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid rgba(255, 255, 255, 0.14);
  font: inherit;
  font-size: 0.83rem;
}
#dwVersionsSection .dw-ver-uploadbtn {
  flex: 0 0 auto;
  padding: 9px 16px;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  cursor: pointer;
  font-size: 0.83rem;
  font-weight: 600;
  color: #0b1a12;
  background: #46e08a;
}
#dwVersionsSection .dw-ver-uploadbtn:hover { filter: brightness(1.08); }
#dwVersionsSection .dw-ver-note { padding: 10px 0; opacity: 0.6; font-size: 0.83rem; }

@media (max-width: 620px) {
  #dwVersionsSection { padding: 14px 12px 18px; border-radius: 14px; }
  #dwVersionsSection .dw-ver-row { flex-wrap: wrap; gap: 6px 10px; }
  #dwVersionsSection .dw-ver-label { flex-basis: 100%; order: 3; }
  #dwVersionsSection .dw-ver-upload { flex-direction: column; align-items: stretch; }
  #dwVersionsSection .dw-ver-uploadbtn { justify-content: center; }
}


/* ---------------------------------------------------------------------------
   DW-UX 2026-08-15: mini-player opacity, cinematic entry, scene pill
   --------------------------------------------------------------------------- */

/* 1. The fixed mini-player was translucent, so the track list read straight
      through it (measured 84% box overlap between a row title and the bar's
      artist line). Content scrolling under a fixed bar is fine -- as long as you
      cannot see it. Solid backdrop + blur, and a lift so it reads as a layer. */
body.dream-has-mini-player .mini-now-playing,
#miniNowPlaying {
  background: linear-gradient(180deg, rgba(12, 9, 22, 0.92), rgba(9, 7, 17, 0.985)) !important;
  backdrop-filter: blur(18px) saturate(1.15) !important;
  -webkit-backdrop-filter: blur(18px) saturate(1.15) !important;
  border-top: 1px solid rgba(255, 255, 255, 0.10) !important;
  box-shadow: 0 -14px 34px rgba(0, 0, 0, 0.55) !important;
}

/* 2. Entry point to the cinematic / minimal player on the #player route. */
#dwCinematicEntry {
  margin: 0 0 14px;
  display: flex;
  justify-content: flex-end;
}
#dwCinematicEntry .dw-cine-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  min-height: 44px;
  border-radius: 999px;
  cursor: pointer;
  color: inherit;
  font: inherit;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.16);
  transition: background 140ms ease, border-color 140ms ease;
}
#dwCinematicEntry .dw-cine-btn:hover {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.28);
}
#dwCinematicEntry .dw-cine-icon { font-size: 1.05rem; opacity: 0.9; }
#dwCinematicEntry .dw-cine-label { font-weight: 600; font-size: 0.9rem; }
#dwCinematicEntry .dw-cine-sub {
  font-size: 0.74rem;
  opacity: 0.55;
  letter-spacing: 0.03em;
}
@media (max-width: 620px) {
  #dwCinematicEntry { justify-content: stretch; }
  #dwCinematicEntry .dw-cine-btn { width: 100%; justify-content: center; }
  #dwCinematicEntry .dw-cine-sub { display: none; }
}

/* 3. Scene pill rendered "SceneCrashing WavesOcean" -- three adjacent inline
      elements with nothing between them. */
.dream-minimal-scene-pill {
  display: inline-flex !important;
  align-items: baseline !important;
  gap: 8px !important;
  flex-wrap: wrap;
  justify-content: center;
}
.dream-minimal-scene-pill > span { opacity: 0.6; letter-spacing: 0.08em; font-size: 0.72rem; }
.dream-minimal-scene-pill > em { opacity: 0.6; font-style: normal; font-size: 0.75rem; }

/* The cinematic view stacks its own close button under the app's global one.
   Nudge the app chrome out of the way while that view is up. */
body[data-dream-route="player-minimal"] .dream-minimal-cinematic-close {
  top: 18px !important;
  right: 18px !important;
  z-index: 40 !important;
}


/* ---------------------------------------------------------------------------
   DW-UX 2026-08-15: desktop player uses its width
   At >=1100px the player was pinned to a single 720px column (measured: layout
   720 of 1042 available, children 456 wide, 3947 tall). Lay the two panels side
   by side so the screen is read rather than scrolled.
   --------------------------------------------------------------------------- */
@media (min-width: 1100px) {
  html body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-layout--desktop {
    max-width: 100% !important;
    width: 100% !important;
    grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr) !important;
    align-items: start !important;
    align-content: start !important;
    gap: 22px !important;
    place-items: start stretch !important;
  }
  html body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-primary,
  html body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-secondary {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
  /* the queue/scene lists inside the secondary column no longer need to be narrow */
  html body.dream-app-open[data-dream-route="player"] #dreamAppContent .dream-player-secondary > * {
    max-width: 100% !important;
  }
}


/* ---------------------------------------------------------------------------
   DW-UX 2026-08-15: audit defects (scroller, badge, settings header, tap targets)
   From a systematic route x viewport scan (overlap / clipped / tap-target /
   spill). Only the findings that survived triage are addressed here.
   --------------------------------------------------------------------------- */

/* 1. The creator row is a flex strip whose children extend far past it while the
      container is overflow:visible -- so an ancestor clips them and there is no
      way to reach them. Make it scroll. */
#dreamCreatorScroll {
  overflow-x: auto !important;
  overflow-y: hidden !important;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
  padding-bottom: 4px;
}
#dreamCreatorScroll > * {
  scroll-snap-align: start;
  flex: 0 0 auto;
}
/* a helper paragraph does not belong in a horizontal strip of cards; let it wrap
   to a sane width instead of stretching the row by 600px */
#dreamCreatorScroll .dream-account-helper {
  max-width: min(320px, 80vw) !important;
  white-space: normal !important;
}

/* 2. The nav badge is absolutely positioned but its button was static at some
      widths, so it anchored to a distant ancestor. */
.dream-tab-btn,
.dream-tab-btn.active,
.dream-tab-btn.is-playing {
  position: relative !important;
}

/* 3. Settings: video-select labels collided with the app header by ~14px. */
body.dream-app-open[data-dream-route="settings"] .dream-video-select-label {
  position: relative;
  z-index: 1;
}
body.dream-app-open[data-dream-route="settings"] .dream-app-main-header {
  margin-bottom: 10px;
}

/* 4. Touch-target floor. 66 controls measured under 40px, worst repeats being the
      header account (74x35) and close (36x36) buttons. Only applied at touch
      widths so desktop density is untouched. */
@media (max-width: 820px) {
  .dream-app-main-header-account,
  .dream-app-main-header-close,
  .dream-row-pill,
  .dream-row-play,
  .dream-row-like,
  .dream-player-up-next-btn,
  .dream-search-chip,
  .dream-minimal-ctrl,
  .dw-catalog-input,
  #dreamPlayerVolumeBtn,
  #dwCatalogQuery {
    min-height: 40px !important;
    min-width: 40px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }
  /* text inputs should stay left-aligned, not centred */
  .dw-catalog-input,
  #dwCatalogQuery {
    justify-content: flex-start !important;
    text-align: left !important;
  }
}


/* ---------------------------------------------------------------------------
   DW-UX 2026-08-15: header scrim so scrolled text does not collide with the wordmark
   --------------------------------------------------------------------------- */
body.dream-app-open:not([data-dream-route="player-minimal"]) .dream-app-main-header {
  position: relative;
  z-index: 6;
}
body.dream-app-open:not([data-dream-route="player-minimal"]) .dream-app-main-header::before {
  content: "";
  position: absolute;
  inset: -14px -18px -10px -18px;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(180deg,
      rgba(10, 8, 18, 0.82) 0%,
      rgba(10, 8, 18, 0.55) 55%,
      rgba(10, 8, 18, 0) 100%);
}
/* the cinematic view stays completely unadorned */
body[data-dream-route="player-minimal"] .dream-app-main-header { display: none !important; }


/* ---------------------------------------------------------------------------
   DW-UX 2026-08-15: touch floor at matching specificity
   The earlier compact-chrome rules in this same file are (0,3,1) with no media
   query, so a (0,1,0) floor could never win. Match their specificity and scope to
   touch widths: desktop stays compact, fingers get a 40px target.
   --------------------------------------------------------------------------- */
@media (max-width: 820px) {
  body.dream-app-open[data-dream-route] .dream-app-main-header-close {
    height: 40px !important;
    min-height: 40px !important;
    min-width: 40px !important;
  }
  body.dream-app-open[data-dream-route] .dream-app-main-header-account {
    min-height: 40px !important;
    padding-top: 8px !important;
    padding-bottom: 8px !important;
  }
}


/* ---------------------------------------------------------------------------
   DW-UX 2026-08-15: touch floor part 2
   23 controls remained under 40px at 390px, nearly all wide-but-short buttons
   (291x38, 304x36, 362x37). A height floor is enough; widths are already fine.
   Same (0,3,1) specificity as the compact-chrome rules earlier in this file,
   which a plain class selector cannot beat. Touch widths only.
   --------------------------------------------------------------------------- */
@media (max-width: 820px) {
  body.dream-app-open[data-dream-route] .dream-primary,
  body.dream-app-open[data-dream-route] .dream-secondary,
  body.dream-app-open[data-dream-route] .dream-inline-link,
  body.dream-app-open[data-dream-route] .dream-discover-creator-main,
  body.dream-app-open[data-dream-route] .dream-discover-creator-cta,
  body.dream-app-open[data-dream-route] .dream-discover-np-artist,
  body.dream-app-open[data-dream-route] .dream-player-mini-action,
  body.dream-app-open[data-dream-route] .dream-player-up-next-btn,
  body.dream-app-open[data-dream-route] .dream-settings-bottom-back-btn,
  body.dream-app-open[data-dream-route] .dream-track-detail-action,
  body.dream-app-open[data-dream-route] #dreamPlayerVolumeBtn,
  body.dream-app-open[data-dream-route] #dreamOpenAudioSettingsBtn,
  body.dream-app-open[data-dream-route] .dream-account-github-auth,
  body.dream-app-open[data-dream-route] .dream-account-email-toggle,
  body.dream-app-open[data-dream-route] .dream-connect-action {
    min-height: 40px !important;
  }
}


/* ---------------------------------------------------------------------------
   DW-A11Y 2026-08-15: invisible controls + text over video
   Measured with a WCAG contrast audit in Edge, triaged against each element's
   actual backdrop. Dark text on the green primary buttons is correct and is NOT
   touched here.
   --------------------------------------------------------------------------- */

/* 1. Controls that inherit the UA default black on a near-black app.
      Ratio was 1.0 -- foreground identical to background. */
body.dream-app-open #miniNpVolume,
body.dream-app-open .mini-np-volume {
  color: rgba(255, 255, 255, 0.88) !important;
  opacity: 1 !important;
}
body.dream-app-open[data-dream-route] .dream-settings-back-btn,
body.dream-app-open[data-dream-route] .dream-settings-bottom-back-btn {
  color: rgba(255, 255, 255, 0.92) !important;
}

/* 2. The cinematic scene pill rendered black over the video. */
body[data-dream-route="player-minimal"] .dream-minimal-scene-pill,
body[data-dream-route="player-minimal"] .dream-minimal-scene-pill > span,
body[data-dream-route="player-minimal"] #dreamMinimalSceneLabel,
body[data-dream-route="player-minimal"] #dreamMinimalSceneMood {
  color: rgba(255, 255, 255, 0.94) !important;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.75) !important;
}

/* 3. Bottom-nav labels sit directly on the video: 6.7:1 on a dark frame, 1.4:1 on
      a light one. A shadow keeps them legible on both without putting an opaque
      bar across the design. */
body.dream-app-open .dream-tab-label,
body.dream-app-open .dream-tab-btn .dream-tab-label {
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85), 0 0 10px rgba(0, 0, 0, 0.45) !important;
}

/* 4. Same treatment for the other controls the audit found floating on video. */
body.dream-app-open .dream-collection-icon,
body.dream-app-open .dream-row-play,
body.dream-app-open .dream-minimal-ctrl,
body.dream-app-open .dw-cine-label,
body.dream-app-open .dw-cine-icon {
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7) !important;
}


/* ---------------------------------------------------------------------------
   DW-A11Y 2026-08-15: queue badge contrast + mobile nav label size
   --------------------------------------------------------------------------- */
/* queue badge measured 2.5:1 against its pill -- below the 4.5 needed at 12px */
body.dream-app-open #miniNpQueueBadge,
body.dream-app-open .mini-np-queue-badge {
  color: rgba(255, 255, 255, 0.96) !important;
  background: rgba(255, 113, 206, 0.55) !important;
  font-weight: 700 !important;
}

/* primary nav labels were 10px on mobile -- the smallest interactive text here */
@media (max-width: 820px) {
  body.dream-app-open .dream-tab-label {
    font-size: 11.5px !important;
    letter-spacing: 0.02em !important;
  }
}


/* ---------------------------------------------------------------------------
   DW-UX 2026-08-15: touch targets + font floor (final)
   Measured: 50 controls under 40px across 29 selectors, and text down to 10px
   (including H3/H4 headings). Prefix is (0,3,2) so it beats the (0,3,1)
   compact-chrome rules earlier in this file.
   --------------------------------------------------------------------------- */

/* ---- 1. touch targets: 40px floor, touch widths only ---------------------- */
@media (max-width: 820px) {
  body.mode-minimal.dream-app-open[data-dream-route] button,
  body.mode-minimal.dream-app-open[data-dream-route] [role="button"],
  body.mode-minimal.dream-app-open[data-dream-route] summary,
  body.mode-minimal.dream-app-open[data-dream-route] a.dream-primary,
  body.mode-minimal.dream-app-open[data-dream-route] a.dream-secondary {
    min-height: 40px !important;
  }
  /* square icon buttons need width too */
  body.mode-minimal.dream-app-open[data-dream-route] #miniNpVolume,
  body.mode-minimal.dream-app-open[data-dream-route] .mini-np-volume,
  body.mode-minimal.dream-app-open[data-dream-route] .mini-np-play,
  body.mode-minimal.dream-app-open[data-dream-route] #dreamPlayerVolumeBtn,
  body.mode-minimal.dream-app-open[data-dream-route] .dream-minimal-cinematic-close,
  body.mode-minimal.dream-app-open[data-dream-route] .dream-player-action,
  body.mode-minimal.dream-app-open[data-dream-route] .dream-row-pill,
  body.mode-minimal.dream-app-open[data-dream-route] .dream-row-play {
    min-width: 40px !important;
  }
  /* the volume slider was 20px tall -- hard to grab */
  body.mode-minimal.dream-app-open[data-dream-route] input[type="range"] {
    min-height: 34px !important;
  }
  /* keep the enlarged controls centred rather than top-aligned */
  body.mode-minimal.dream-app-open[data-dream-route] button,
  body.mode-minimal.dream-app-open[data-dream-route] [role="button"] {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }
  /* text inputs stay left-aligned */
  body.mode-minimal.dream-app-open[data-dream-route] input[type="text"],
  body.mode-minimal.dream-app-open[data-dream-route] input[type="search"],
  body.mode-minimal.dream-app-open[data-dream-route] input[type="email"],
  body.mode-minimal.dream-app-open[data-dream-route] input[type="password"] {
    display: block !important;
    text-align: left !important;
    min-height: 40px !important;
  }
}

/* ---- 2. font floor: all widths (10px is unreadable anywhere) -------------- */
body.mode-minimal.dream-app-open[data-dream-route] em,
body.mode-minimal.dream-app-open[data-dream-route] .dream-row-stat,
body.mode-minimal.dream-app-open[data-dream-route] .dream-video-select-label,
body.mode-minimal.dream-app-open[data-dream-route] .dream-search-chip,
body.mode-minimal.dream-app-open[data-dream-route] .mini-np-artist,
body.mode-minimal.dream-app-open[data-dream-route] #miniNpArtist,
body.mode-minimal.dream-app-open[data-dream-route] .dream-mood-chip,
body.mode-minimal.dream-app-open[data-dream-route] .dream-secondary,
body.mode-minimal.dream-app-open[data-dream-route] .dream-discover-creator-cta {
  font-size: 12px !important;
}
body.mode-minimal.dream-app-open[data-dream-route] h3,
body.mode-minimal.dream-app-open[data-dream-route] h4 {
  font-size: 12.5px !important;
}
body.mode-minimal.dream-app-open[data-dream-route] .dream-status-chip,
body.mode-minimal.dream-app-open[data-dream-route] .dream-row-pill,
body.mode-minimal.dream-app-open[data-dream-route] .dream-row-more-action,
body.mode-minimal.dream-app-open[data-dream-route] .dream-video-select-mood,
body.mode-minimal.dream-app-open[data-dream-route] .dream-app-main-header-kicker,
body.mode-minimal.dream-app-open[data-dream-route] .dream-kicker,
body.mode-minimal.dream-app-open[data-dream-route] .dream-search-scope-label,
body.mode-minimal.dream-app-open[data-dream-route] .dream-search-scope-count,
body.mode-minimal.dream-app-open[data-dream-route] .dream-player-up-next-tag,
body.mode-minimal.dream-app-open[data-dream-route] .mini-np-queue-badge,
body.mode-minimal.dream-app-open[data-dream-route] #miniNpQueueBadge {
  font-size: 11.5px !important;
}


/* ---------------------------------------------------------------------------
   DW-UX 2026-08-15: floors re-issued with #dreamAppContent specificity
   The class-only floors lost to earlier rules in this file that carry
   #dreamAppContent (an id beats any number of classes). Same values, id included.
   --------------------------------------------------------------------------- */

/* touch targets, touch widths only */
@media (max-width: 820px) {
  body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent button,
  body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent [role="button"],
  body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent summary {
    min-height: 40px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }
  body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent input[type="text"],
  body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent input[type="search"],
  body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent input[type="email"],
  body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent input[type="password"] {
    min-height: 40px !important;
    display: block !important;
    text-align: left !important;
  }
  body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent input[type="range"] {
    min-height: 34px !important;
  }
}

/* font floors, all widths */
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent em,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-row-stat,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-video-select-label,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-search-chip,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-mood-chip,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-secondary,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-primary,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-discover-creator-cta {
  font-size: 12px !important;
}
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent h3,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent h4 {
  font-size: 12.5px !important;
}
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-status-chip,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-row-pill,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-row-more-action,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-video-select-mood,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-kicker,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-search-scope-label,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-search-scope-count,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-player-up-next-tag {
  font-size: 11.5px !important;
}


/* ---------------------------------------------------------------------------
   DW-A11Y 2026-08-15: reduced motion + last tap targets + nested span fonts
   --------------------------------------------------------------------------- */

/* 1. Honour prefers-reduced-motion. The app previously had exactly one rule for
      this query, and the background video ignored it entirely. */
@media (prefers-reduced-motion: reduce) {
  html body *,
  html body *::before,
  html body *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  /* keep the frame, lose the movement */
  html body #bgVideo,
  html body video.dream-bg-video {
    animation: none !important;
  }
}

/* 2. Last sub-40px controls. These sit OUTSIDE #dreamAppContent (mini player),
      so the id-scoped floor could not match them. */
@media (max-width: 820px) {
  body.mode-minimal.dream-app-open #miniNpVolume,
  body.mode-minimal.dream-app-open .mini-np-volume,
  body.mode-minimal.dream-app-open .mini-np-play,
  body.mode-minimal.dream-app-open .dream-search-clear {
    min-height: 40px !important;
    min-width: 40px !important;
  }
  body.mode-minimal.dream-app-open #miniNpVolumeSlider,
  body.mode-minimal.dream-app-open .mini-np-volume-slider {
    min-height: 34px !important;
  }
}

/* 3. The remaining 10.5px text: unclassed spans inside these two wrappers. */
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-collection-track-copy span,
body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-row-copy span,
body.mode-minimal.dream-app-open[data-dream-route] .dream-collection-track-copy span,
body.mode-minimal.dream-app-open[data-dream-route] .dream-row-copy span {
  font-size: 11.5px !important;
}


/* DW-UX 2026-08-15: volume slider to a full 40px */
@media (max-width: 820px) {
  body.mode-minimal.dream-app-open #miniNpVolumeSlider,
  body.mode-minimal.dream-app-open .mini-np-volume-slider,
  body.mode-minimal.dream-app-open[data-dream-route] input[type="range"] {
    min-height: 40px !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   SECTION 20 — contrast and font floors (2026-08-16)

   Found by sweeping every route at 1440 and 390 and reading COMPUTED styles, not
   by looking at screenshots.

   CONTRAST. Body text is rgb(244,239,255) on rgb(5,5,6). Several labels fade that
   to alpha 0.30-0.44, which composites to roughly rgb(77,75,80) at the low end --
   about 2.3:1 against the background, well under the 4.5:1 WCAG AA needs. Raising
   alpha to ~0.70 gives ~8.7:1 and keeps the hue, so nothing is restyled, only made
   legible. The worst case was the minimal player's elapsed/total clock at alpha
   0.30: the one number a listener actually reads.

   FONT. Floor is 10.5px, matching the floor set on 2026-08-15 rather than inventing
   a new one. Only selectors identifiable by class or id are touched. Bare
   `#dreamAppContent strong` / `span` / `p` at 9.5-10px are deliberately left alone:
   CSS cannot express "raise only if below the floor", so a blanket rule on a bare
   tag would SHRINK every larger instance of it. Those are the documented micro-label
   long tail.

   SPECIFICITY. Every rule is anchored on an id, because an id beats any number of
   classes in this codebase's 13,736-!important stylesheet. Each rule below was
   verified by reading getComputedStyle afterwards -- see the note at the end of
   DW-INDEX about proving a selector won rather than assuming it.
   ═══════════════════════════════════════════════════════════════════════════ */

/* --- contrast floor ------------------------------------------------------ */

/* The playback clock. Worst offender: alpha 0.30 AND 10px. */
html body #dreamMinimalElapsed,
html body #dreamMinimalTotal {
  color: rgba(244, 239, 255, 0.78) !important;
  font-size: 10.5px !important;
}

html body #dreamMinimalCinematic .dream-minimal-track-album {
  color: rgba(244, 239, 255, 0.70) !important;
}

html body #dreamAppContent .dream-row-stat,
html body #dwCatalogSection .dream-row-stat {
  color: rgba(244, 239, 255, 0.70) !important;
}

html body #dreamAppContent .dream-player-up-next-label,
html body #dreamPlayerUpNextCard1 .dream-player-up-next-label,
html body #dreamPlayerUpNextCard2 .dream-player-up-next-label,
html body #dreamPlayerUpNextCard3 .dream-player-up-next-label {
  color: rgba(244, 239, 255, 0.70) !important;
}

html body #dreamAppContent .dream-player-section-note,
html body #dreamCommentsSection .dream-player-section-note {
  color: rgba(244, 239, 255, 0.70) !important;
}

html body #dreamAppContent .dream-player-preview-hint,
html body #dreamAppContent .dream-player-preview-tagline {
  color: rgba(244, 239, 255, 0.70) !important;
}

html body #dreamAppContent .dream-audio-hint {
  color: rgba(244, 239, 255, 0.70) !important;
}

html body #dreamAppMain .dream-app-main-header-kicker {
  color: rgba(244, 239, 255, 0.70) !important;
}

/* --- font floor (10.5px) ------------------------------------------------- */

html body #dreamAppContent .dream-player-context-queue,
html body #dreamAppContent .dream-player-up-next-artist,
html body #dreamPlayerUpNextCard1 .dream-player-up-next-artist,
html body #dreamPlayerUpNextCard2 .dream-player-up-next-artist,
html body #dreamPlayerUpNextCard3 .dream-player-up-next-artist,
html body #dreamAppContent .dream-report-status-chip,
html body #dreamAppContent .dream-inline-link,
html body #dreamAppContent .dream-trackinfo-pill--mood,
html body #dreamAppContent .dream-player-tier-action--upgrade,
html body #dreamAppContent .dream-player-context-detail,
html body #dreamAppContent .dream-player-preview-more-action {
  font-size: 10.5px !important;
}

html body #dreamMinimalCinematic .dream-minimal-track-album {
  font-size: 10.5px !important;
}

/* --- touch target: the like toggle was 36px wide against a 44px floor ---- */
html body #dreamAppContent .dream-row-like {
  min-width: 44px !important;
}

/* .dream-player-section-note was 10.2px -- class-identified, so it can join the
   10.5px floor without the collateral risk that stops the bare-tag cases. */
html body #dreamAppContent .dream-player-section-note,
html body #dreamCommentsSection .dream-player-section-note {
  font-size: 10.5px !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   SECTION 21 — mini-player surface and offset (2026-08-16)

   MEASURED, both widths, computed styles:

     mobile  #miniNowPlaying  bg rgba(7,8,12,.94)  bottom 104px   <- correct
             nav.dream-bottom-tabs                 bottom  12px  h 73

     desktop #miniNowPlaying  bg rgba(0,0,0,0)     bottom  58px   <- both wrong
             (no bottom tab bar exists at this width)

   Two separate defects, same element:

   1. On desktop the bar has NO background at all. It leans entirely on
      `backdrop-filter: blur(18px)`, and a backdrop filter blurs what is behind
      without darkening it — so scrolling track rows read straight through the
      bar and its own title/artist text sits on moving, variably-bright content.
      Mobile already sets a near-opaque surface; desktop simply never got one.

   2. `bottom: 58px` is the mobile tab-bar allowance applied at every width.
      Desktop has no tab bar (navigation is the left rail), so it floats above
      a 58px dead gap with content visible underneath it.

   Both are expressed against tokens below rather than fresh magic numbers, so
   the next person changing the tab bar changes one value.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* Fixed chrome. --dw-tabbar-inset is the gap the floating tab bar leaves at
     the viewport edge; the player clears tab bar + inset on mobile and only the
     inset on desktop, where no tab bar is rendered. */
  --dw-tabbar-h:      73px;
  --dw-tabbar-inset:  12px;
  --dw-player-h:      56px;

  /* An opaque player surface. --dw-surface is deliberately translucent for
     panels that sit over the background video; the player is the one element
     that must never let content read through it, so it gets its own token. */
  --dw-surface-solid: rgba(7, 8, 12, 0.94);
}

/* Desktop and up: no tab bar exists, so the player only clears the edge inset.
   Scoped by width because the mobile values are already correct — this must not
   touch them. The id gives (1,0,2), which beats the class-only vendor rules. */
@media (min-width: 1100px) {
  html body #miniNowPlaying {
    bottom: var(--dw-tabbar-inset) !important;
    background: var(--dw-surface-solid) !important;
  }
}

/* Below the desktop breakpoint the tab bar is present. Restate the clearance
   from the tokens so the two numbers cannot drift apart, and keep the surface
   opaque here too rather than relying on it being set elsewhere. */
@media (max-width: 1099px) {
  html body #miniNowPlaying {
    bottom: calc(var(--dw-tabbar-h) + var(--dw-tabbar-inset) * 2) !important;
    background: var(--dw-surface-solid) !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   SECTION 22 — the ghost wordmark above the mobile header (2026-08-16)

   At 390px the top of the app shows a faint second "DREAMWAVE" sitting ~40px
   above the real header wordmark, which reads as a rendering fault rather than
   branding.

   It is NOT a duplicate element: enumerating every node whose own text is the
   wordmark found exactly one on-screen (h2.dream-app-main-header-name at y=53);
   all others measured 0x0. It is a pseudo-element —

       #minimal-ui::before { content: "DREAMWAVE"; position: fixed; top: 12px;
                             font-size: 10px; opacity: .78 }

   — which is why hit-testing the spot returned the header: pseudo-elements
   hit-test as their parent. Worth remembering; this is the third time a
   screenshot in this app pointed at the wrong element.

   Hidden below the desktop breakpoint only. On desktop the two visible
   wordmarks (sidebar brand + page title) are deliberate and the watermark does
   not collide, so that width is left alone.
   ═══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 1099px) {
  html body #minimal-ui::before {
    content: none !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   SECTION 23 — empty / error screens (2026-08-16)

   Styles the shared dreamEmptyState() component that replaced three divergent
   hand-rolled dead-ends (track / playlist / share). One component, one set of
   rules — previously each screen inherited whatever .dream-empty happened to do
   and none of them had a heading.

   Deliberately quiet: these screens are a wrong turn, not a destination. The job
   is to say what happened and make the way out obvious, so the action button is
   the only thing with any weight.

   Tokens come from the :root block in section 21 rather than fresh values.
   ═══════════════════════════════════════════════════════════════════════════ */

html body #dreamAppContent .dream-empty-state {
  display: flex !important;
  flex-direction: column !important;
  align-items: flex-start !important;
  gap: 18px !important;
  max-width: 46ch !important;
  padding: 40px 0 !important;
}

html body #dreamAppContent .dream-empty-state .dream-empty {
  background: none !important;
  border: 0 !important;
  padding: 0 !important;
  margin: 0 !important;
  text-align: left !important;
}

html body #dreamAppContent .dream-empty-title {
  margin: 0 0 8px !important;
  font-size: clamp(20px, 2.2vw, 27px) !important;
  line-height: 1.2 !important;
  font-weight: 700 !important;
  letter-spacing: -0.01em !important;
  color: var(--dw-text) !important;
}

html body #dreamAppContent .dream-empty-body {
  margin: 0 !important;
  font-size: 14.5px !important;
  line-height: 1.55 !important;
  /* Readable, not decorative: this is the sentence that tells someone what to do.
     0.70 clears WCAG AA against the app's near-black ground; the sheet's default
     faint value (~0.44) does not. */
  color: rgba(244, 239, 255, 0.70) !important;
}

html body #dreamAppContent .dream-empty-action {
  min-height: 44px !important;   /* the one control on screen: give it a real target */
  padding: 0 20px !important;
  border-radius: var(--dw-radius) !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   SECTION 24 — the stranded rows in the Discover hero (2026-08-16)

   MEASURED: .dream-discover-marquee-track is a <button>, 1010px wide, 44px tall,
   cursor:pointer — a real clickable row. But it is display:flex with
   `justify-content: center`, so its 195px label cluster floats in the middle of
   a full-width row with ~400px of empty space either side. It reads as unstyled
   placeholder text rather than a control, and it is the only list in the app
   that is centre-aligned; every other track row is left-aligned with its meta
   pushed right.

   This is a grammar mismatch, not a broken layout: the row already works, it
   just does not look like the thing it is. Aligning it with the app's existing
   row pattern (title left, meta right, hover affordance) makes the affordance
   obvious without inventing a new component.
   ═══════════════════════════════════════════════════════════════════════════ */

html body #dreamAppContent .dream-discover-marquee-track {
  justify-content: flex-start !important;
  gap: 10px !important;
  padding: 10px 14px !important;
  border-radius: var(--dw-radius) !important;
  /* colour/background transition only — transform on a list row is the kind of
     motion that reads as noise rather than feedback */
  transition: background-color 140ms ease !important;
}

/* Push the trailing meta ("public · Romantic") to the right edge so the row's
   width does something. :last-child rather than a class because these spans are
   unclassed in the markup. */
html body #dreamAppContent .dream-discover-marquee-track > :last-child {
  margin-left: auto !important;
}

html body #dreamAppContent .dream-discover-marquee-track:hover,
html body #dreamAppContent .dream-discover-marquee-track:focus-visible {
  background: rgba(255, 255, 255, 0.07) !important;
}

/* Keyboard users get the same signal as pointer users. */
html body #dreamAppContent .dream-discover-marquee-track:focus-visible {
  outline: 2px solid var(--dw-accent-2) !important;
  outline-offset: -2px !important;
}

/* The justify-content rule above LOST its duel: the computed value stayed
   `center` (the layout only looked right because margin-left:auto on the last
   child forced the children apart). That is fragile -- a row without trailing
   meta would re-centre. Restated with the strongest documented prefix in this
   file, body.mode-minimal...[data-dream-route] #dreamAppContent = (1,4,2).
   Verified by re-reading the computed value, not by looking at it. */
html body.mode-minimal.dream-app-open[data-dream-route] #dreamAppContent .dream-discover-marquee-track {
  justify-content: flex-start !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   SECTION 25 — touch targets (2026-08-16)

   Profiled every interactive element on every route at 1440 and 390, grouped by
   controlling class. 197 distinct findings collapse to ~20 classes, in two kinds
   that need different treatment:

     SHORT   height 32-43, width already fine.  min-height is low risk: these are
             pills and toolbar buttons whose height is content-driven.
     NARROW  width under 44 — the icon buttons. Needs min-width, and needs
             checking for row overflow afterwards, which is why it is a short
             explicit list rather than a wildcard.

   The ones that matter most were the smallest: mini-np-play and mini-np-queue
   measured 32x32 — the persistent player's transport, the controls used more
   than anything else in the app.

   44px is the WCAG 2.5.5 AAA target. The previous pass here settled at 36px as
   a compromise; with the layout now verified free of horizontal overflow at both
   widths, the full target is affordable.

   DELIBERATELY EXCLUDED
     .mini-np-progress      1176x6 seek bar — already carries a transparent
                            ::after hit band (~20px). Changing its height would
                            change how the player looks, not how it works.
     .mini-np-volume-slider 48x20 range input — native control; forcing height
                            distorts the thumb rendering across engines.
     bare <input>           matched at 20-976px wide; too broad to touch safely.
   ═══════════════════════════════════════════════════════════════════════════ */

/* --- SHORT: height only ------------------------------------------------- */
html body #dreamAppContent .dream-secondary,
html body #dreamAppContent .dream-primary,
html body #dreamAppContent .dream-search-chip,
html body #dreamAppContent .dream-mood-chip,
html body #dreamAppContent .dream-library-filter,
html body #dreamAppContent .dream-library-view-mode,
html body #dreamAppContent .dream-library-workspace-mode,
html body #dreamAppContent .dream-library-sub-tab,
html body #dreamAppContent .dream-player-action,
html body #dreamAppContent .dream-player-quick-action,
html body #dreamAppContent .dream-player-mini-action,
html body #dreamAppContent .dream-discover-creator-cta,
html body #dreamAppContent .dream-eq-preset-btn,
html body #dreamAppContent .dream-settings-back-btn,
html body #dreamAppContent .dream-policy-nav-btn,
html body #dreamAppContent .dream-policy-doc-link,
html body #dreamAppContent .playlist-drawer-toggle {
  min-height: 44px !important;
}

/* --- NARROW: icon buttons need both axes -------------------------------- */
/* These live OUTSIDE #dreamAppContent (mini player / app header), so the id
   form cannot match them — class-only, per this file's index. */
html body .mini-np-play,
html body .mini-np-queue,
html body .mini-np-gear,
html body .dream-app-main-header-close {
  min-width: 44px !important;
  min-height: 44px !important;
}

/* Keep the icon glyphs centred now that their boxes grew. */
html body .mini-np-play,
html body .mini-np-queue,
html body .mini-np-gear,
html body .dream-app-main-header-close {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}

/* .dream-app-main-header-close stayed 36x36: the class-only form (0,1,2) lost.
   It sits outside #dreamAppContent so the id prefix cannot reach it; using the
   body-state prefix instead gives (0,4,2). Verified by re-reading the box, not
   by assuming the rule applied. */
html body.mode-minimal.dream-app-open[data-dream-route] .dream-app-main-header-close {
  min-width: 44px !important;
  min-height: 44px !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   SECTION 26 — buffering state on the transport (2026-08-16)

   The transport used to show the pause glyph a median 164ms (worst 2.7s) before
   any sound, because `audio.paused` flips when play() is CALLED. It now renders
   a distinct loading state; this makes that state read as activity rather than
   as a third mystery glyph.
   ═══════════════════════════════════════════════════════════════════════════ */

html body .dw-buffering {
  opacity: 0.72 !important;
  animation: dw-buffer-pulse 1s ease-in-out infinite !important;
}

@keyframes dw-buffer-pulse {
  0%, 100% { opacity: 0.42; }
  50%      { opacity: 0.95; }
}

/* Someone who has asked for less motion still needs to know it is working --
   keep the dimmed state, drop the pulse. */
@media (prefers-reduced-motion: reduce) {
  html body .dw-buffering {
    animation: none !important;
    opacity: 0.6 !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   SECTION 27 — touch targets, second pass (2026-08-16)

   Section 25 scoped its rules to `#dreamAppContent`, and inside that container they
   work: .dream-secondary / .dream-search-chip / .dream-library-filter /
   .dream-library-view-mode all measure exactly 44px on the library route.

   But the profiler still reported 38-40px for the same classes, because several of
   them ALSO render OUTSIDE that container -- in the app header, the mini player and
   the settings surfaces -- where an id-scoped selector cannot match. This restates
   them without the id, using the body-state prefix documented at the top of this
   file, so the floor holds wherever the class appears.

   Also picks up classes the first pass missed entirely (toggles, agent prompts,
   creator CTAs, scope tabs, up-next buttons, text inputs).

   Still deliberately excluded, for the same reasons as before:
     .mini-np-progress       a 6px seek bar with a transparent ::after hit band
     .mini-np-volume-slider  native range input; forcing height distorts the thumb

   NARROW is now zero classes -- every icon button measures at least 44px wide, so
   this pass only needs to raise heights.
   ═══════════════════════════════════════════════════════════════════════════ */

html body.mode-minimal.dream-app-open[data-dream-route] .dream-secondary,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-primary,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-search-chip,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-search-scope,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-mood-chip,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-library-filter,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-library-view-mode,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-library-workspace-mode,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-library-sub-tab,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-player-quick-action,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-player-up-next-btn,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-minimal-action,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-discover-creator-cta,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-discover-creator-main,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-eq-preset-btn,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-settings-back-btn,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-policy-nav-btn,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-policy-doc-link,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-agent-prompt,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-toggle-switch,
html body.mode-minimal.dream-app-open[data-dream-route] .playlist-drawer-toggle,
html body.mode-minimal.dream-app-open[data-dream-route] .dream-app-main-header-account {
  min-height: 44px !important;
}

/* Text entry: a 25px-tall input is hard to hit and harder to read. Height only --
   widths here are already generous. */
html body.mode-minimal.dream-app-open[data-dream-route] .dream-text-input,
html body.mode-minimal.dream-app-open[data-dream-route] .dw-catalog-input {
  min-height: 44px !important;
}
