/* =================================================================
   queue.css — Now Playing / queue views.
   Queue hero (full-width current-track header), subheaders, song list,
   album-grouped view, work-grouped view, empty state, and the
   queue-related drag-and-drop visual states.
   ================================================================= */

.queue-song-item[draggable="true"],
.queue-album-group[draggable="true"] {
    cursor: grab;
}

.queue-song-item.dragging,
.queue-album-group.dragging {
    opacity: 0.45;
    cursor: grabbing;
}

.queue-song-item.drop-above,
.queue-album-group.drop-above {
    box-shadow: 0 -2px 0 0 var(--accent-primary);
}

.queue-song-item.drop-below,
.queue-album-group.drop-below {
    box-shadow: 0 2px 0 0 var(--accent-primary);
}

.queue-album-track--after-work {
    margin-top: 14px;
    border-top: 2px solid var(--border-subtle);
}

.queue-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 25px;
}

.queue-header h2 {
    font-size: 24px;
}

.queue-scroll {
    display: flex;
    flex-direction: column;
    gap: 24px;
}

/* Now Playing two-column layout. Hero (cover, labels, waveform,
   transport) on the LEFT; queue tabs + list on the RIGHT. The right
   column reuses the same .right-panel-queue scope used by the music-
   panel sidebar mirror, so styling and behavior of the Albums / Songs
   / Works tabs match identically. Falls back to a single column on
   very narrow main-area widths so the layout still reads. */
.queue-now-playing {
    display: grid;
    grid-template-columns: minmax(420px, 1.1fr) minmax(360px, 1fr);
    gap: 28px;
    align-items: start;
    min-height: 0;
}
.queue-now-playing-col {
    min-width: 0;
    min-height: 0;
}
/* Hero column matches the queue column's height. Top-aligned with
   padding equal to:
     np-queue-header height (~36 px) + rpq-tabs padding-top (6 px)
   so the hero CARD's top edge sits at the top of the Albums tab
   button, not at the bottom of the IN QUEUE label. The hero card
   itself STRETCHES to fill the remaining height — its bottom then
   matches the queue list's bottom. justify-content:center inside
   the stretched card keeps cover / title / waveform / controls
   visually centred in the taller frame. */
.queue-now-playing-hero-col {
    display: flex;
    flex-direction: column;
    justify-content: stretch;
    height: calc(100vh - var(--player-height) - 140px);
    min-height: 0;
    padding-top: 42px;
}
.queue-now-playing-hero-col .queue-hero {
    flex: 1 1 auto;
    justify-content: center;
    min-height: 0;
}

/* Now Playing fills the visible area exactly; nothing scrolls at the
   page level. Internal scroll on the queue list (handled by the rpq-
   list overflow-y:auto) is the only scrollable region. The :has() rule
   suspends .main's overflow:auto specifically when the consolidated
   queue view is active, leaving every other view's scroll behaviour
   unchanged. */
body:has(.view-section[data-view="queue-albums"].active) .main {
    overflow: hidden;
}
/* Constrain the queue column to the visible area so its internal flex
   chain has an upper bound to flex within — restoring the music-panel
   sidebar behaviour where the rpq-list scrolls itself instead of the
   whole .main scrolling. The 140px reserve covers the page header
   (sticky, ~70 px) + view-section top padding + the np-queue-header
   row above the tabs. Approximate but stable for typical viewports.
   Uses a fixed `height` (not max-height) — flex children with
   `flex: 1 1 0` need a definite parent height to actually grow into;
   max-height alone leaves the flex basis at 0 and the rpq-list
   collapses to nothing. */
.queue-now-playing-queue-col {
    display: flex;
    flex-direction: column;
    align-self: start;
    height: calc(100vh - var(--player-height) - 140px);
    min-height: 0;
}
.queue-now-playing-queue-col .right-panel-queue {
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-height: 0;
    height: auto;
    border-top: none;
    padding: 8px 14px 0;
}
.queue-now-playing-queue-col .right-panel-queue .rpq-list {
    flex: 1 1 0;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    max-height: none;
}
/* Visible breathing room between the Albums / Songs / Works tabs.
   The base sidebar uses gap: 4 px which read as touching in the wider
   main-pane column — bump it here so the tab pills clearly separate. */
.queue-now-playing-queue-col .rpq-tabs {
    gap: 10px;
}
.np-queue-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 4px 6px;
}
.np-queue-header .np-queue-title {
    font-size: 13px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
    font-weight: 700;
    margin: 0;
}

@media (max-width: 1100px) {
    .queue-now-playing {
        grid-template-columns: 1fr;
    }
    .queue-now-playing-hero-col .queue-hero {
        position: static;
    }
}

.queue-subheader {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 4px;
    margin-top: 8px;
}

.queue-subheader h3 {
    font-size: 14px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
    font-weight: 700;
}

.queue-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 28px 20px 24px;
    background: linear-gradient(180deg, rgba(var(--accent-primary-rgb), 0.08), rgba(var(--accent-purple-rgb), 0.04) 50%, transparent);
    border-radius: 20px;
    border: 1px solid var(--border-subtle);
    gap: 18px;
}

/* Right-sidebar variant of the queue-hero. Compacts the layout for a
   narrow column while reusing the same inner DOM structure so
   renderNowPlayingHero() can populate it unchanged. */
.right-panel-np {
    display: flex;
    flex-direction: column;
    min-height: 0;
    position: relative;
}

.right-panel-np[hidden] { display: none; }

/* × button in the top-right — kept in sync with .detail-close in
   album-detail.css. Same dimensions, same accent treatment, just
   anchored on the LEFT panel here. Update both rules together. */
.right-panel-np-close {
    position: absolute;
    top: 12px;
    right: 14px;
    z-index: 2;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: rgba(var(--surface-app-rgb), 0.55);
    border: 1px solid var(--border-subtle);
    color: var(--accent-primary);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.right-panel-np-close:hover {
    background: rgba(var(--accent-primary-rgb), 0.18);
    border-color: var(--accent-primary);
    color: var(--accent-primary);
}

.right-panel-hero {
    /* Horizontal padding matches the right-side .detail-panel-content
       (30px) so the cover renders at the same width as the album-detail
       cover when both sidebars share a width. Vertical padding is tight
       so the queue list below has more room. */
    padding: 14px 30px 8px;
    border-radius: 0;
    border: none;
    background: transparent;
    /* Tightened gap between cover, info block, progress, and controls
       so the hero is compact in the sidebar. */
    gap: 6px;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 0 0 auto;
}

/* ---- Sidebar hero compaction --------------------------------------------
   The standalone Now Playing view keeps the original generous spacing,
   but the .music-panel sidebar variant trims every text row and shrinks
   the transport buttons so the hero takes ~⅓ of the vertical real
   estate it used to. The cover keeps its full width via the existing
   .qh-cover rule above. */
.right-panel-hero .qh-info {
    gap: 1px;
    padding: 0 6px;
}

.right-panel-hero .qh-work {
    font-size: 9.5px;
    letter-spacing: 0.10em;
    margin-bottom: 0;
    line-height: 1.25;
}

.right-panel-hero .qh-credits {
    font-size: 11px;
    margin-top: 0;
    margin-bottom: 0;
    line-height: 1.25;
}

.right-panel-hero .qh-title {
    font-size: 17px;
    line-height: 1.2;
    margin-top: 2px;
}

.right-panel-hero .qh-artist {
    font-size: 12px;
    line-height: 1.2;
}

.right-panel-hero .qh-album {
    font-size: 10.5px;
    line-height: 1.2;
    margin-top: 0;
}

.right-panel-hero .qh-badge-row {
    margin-top: 2px;
}

.right-panel-hero .qh-progress {
    gap: 8px;
    width: 100%;
    margin-top: 4px;
}

.right-panel-hero .qh-time-current,
.right-panel-hero .qh-time-total {
    font-size: 10.5px;
}

.right-panel-hero .qh-progress-track {
    height: 28px;
}

.right-panel-hero .qh-controls {
    gap: 10px;
    margin-top: 2px;
}

/* Smaller transport buttons so the row doesn't dominate the panel. */
.right-panel-hero .qh-ctrl {
    width: 32px;
    height: 32px;
    font-size: 13px;
}

.right-panel-hero .qh-ctrl.qh-play-pause {
    width: 42px;
    height: 42px;
    font-size: 16px;
    box-shadow: 0 4px 12px rgba(var(--accent-primary-rgb), 0.30);
}

/* Hide the duplicate "credits" line when it would print the same name
   as the artist line right below it — common with classical recordings
   where the performer == the credited artist. Pure CSS dedupe via the
   :has() selector + the rendered DOM order from renderNowPlayingHero. */
.right-panel-hero .qh-credits:empty {
    display: none;
}

.right-panel-hero[hidden] { display: none; }

/* Sidebar queue pane — tabs + list below the hero. flex: 1 takes the
   remaining vertical space inside .right-panel-np so the inner .rpq-list
   has a real max-height to scroll within. min-height: 0 is the standard
   nested-flex escape so an inner overflow:auto can actually overflow. */
.right-panel-queue {
    padding: 8px 14px 18px;
    border-top: 1px solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-height: 0;
    flex: 1 1 0;
}

.right-panel-queue .rpq-tabs {
    display: flex;
    gap: 4px;
    padding-top: 6px;
}

.right-panel-queue .rpq-tab {
    flex: 1;
    background: transparent;
    border: 1px solid var(--border-subtle);
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 600;
    padding: 6px 10px;
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.right-panel-queue .rpq-tab:hover {
    color: var(--text-primary);
    background: var(--overlay-hover);
}

.right-panel-queue .rpq-tab.active {
    background: var(--accent-primary);
    color: var(--text-on-accent);
    border-color: var(--accent-primary);
}

.right-panel-queue .rpq-list {
    /* Block layout (NOT flex) so children stack at their natural content
       size and the parent's overflow:auto handles scrolling. The earlier
       `display: flex; flex-direction: column` made every album group a
       shrinking flex item — when total content exceeded the visible
       height, each group got squashed instead of the parent scrolling.
       Result: each album looked clipped internally and the user couldn't
       scroll to see the rest. Block layout fixes both at once. */
    display: block;
    overflow-y: auto;
    overflow-x: hidden;
    min-height: 0;
    /* Take all remaining vertical space inside .right-panel-queue so
       the scroll viewport has a constrained height to overflow within. */
    flex: 1 1 0;
}

/* Spacing between rows, replacing the old flex `gap` we removed when
   switching the list to display:block. */
.right-panel-queue .rpq-list > * {
    margin-bottom: 4px;
}
.right-panel-queue .rpq-list > .queue-album-group {
    margin-bottom: 8px;
}
.right-panel-queue .rpq-list > *:last-child {
    margin-bottom: 0;
}

/* Belt-and-braces: if the nested-flex chain (music-panel → right-panel-np
   → right-panel-queue → rpq-list) ever breaks, this max-height keeps the
   list at most viewport-height minus rough hero+tabs+player-bar overhead.
   The flex:1 above is the primary mechanism; this is a safety net so
   "can't scroll the queue" doesn't return when some other layout change
   knocks the flex chain loose. */
.music-panel .rpq-list {
    max-height: calc(100vh - 360px);
}

.right-panel-queue .rpq-list[hidden] { display: none; }

/* Compact the list items inside the sidebar so they fit a narrow column. */
.right-panel-queue .queue-song-item {
    padding: 10px 12px;
    border-radius: 8px;
    font-size: 12.5px;
}

/* Cover thumbnail scales down with the row in the sidebar mirror. The
   main-pane Songs view keeps the larger 50px cover for visual rhythm
   with the Albums tab. */
.right-panel-queue .queue-song-item .qs-cover {
    width: 36px;
    height: 36px;
    margin-right: 10px;
    border-radius: 6px;
}
.right-panel-queue .queue-song-item .qs-cover-placeholder {
    font-size: 13px;
}

.right-panel-queue .queue-album-group {
    margin-bottom: 8px;
}

.right-panel-queue .queue-album-header {
    padding: 8px 10px;
    gap: 10px;
}

.right-panel-queue .qah-cover {
    width: 40px;
    height: 40px;
}

.right-panel-queue .qah-title {
    font-size: 12.5px;
}

.right-panel-queue .qah-artist {
    font-size: 11px;
}

.right-panel-queue .queue-album-track {
    padding: 6px 10px 6px 58px;
    font-size: 12px;
}

.right-panel-hero .qh-cover {
    width: 100%;
    height: auto;
    aspect-ratio: 1;
    max-height: none;
}

.right-panel-hero .qh-info {
    max-width: 100%;
    padding: 0 6px;
}

.right-panel-hero .qh-title {
    font-size: 20px;
}

.right-panel-hero .qh-progress {
    max-width: 100%;
}

/* Suppress the in-view hero when the sidebar is hosting it — prevents
   the Now-Playing card from showing twice. */
.view-section[data-view^="queue-"] .queue-hero.queue-hero-hidden {
    display: none;
}

.qh-cover {
    width: 280px;
    height: 280px;
    max-width: 70vw;
    max-height: 50vh;
    aspect-ratio: 1;
    border-radius: 18px;
    background-size: cover;
    background-position: center;
    background-color: var(--bg-card);
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45), 0 8px 20px rgba(var(--accent-primary-rgb), 0.08);
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
}

.qh-cover-placeholder {
    font-size: 72px;
    color: var(--text-muted);
    opacity: 0.55;
}

/* Quality badge overlay (FLAC / 24-bit / Hi-Res / etc) — sits in the
   top-right corner of the cover so the format / sample-rate is visible
   at a glance without having to look at a separate row. .qh-cover is
   already position:relative so absolute positioning picks up its box. */
.qh-cover-badge {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 2;
    pointer-events: none;
    /* Subtle shadow so the badge reads cleanly on light covers too. */
    filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.45));
}

.qh-info {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    max-width: 640px;
    padding: 0 12px;
}

.qh-work {
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    /* Follow the user-configured accent (Settings → Appearance → Accent
       colour) instead of the cyan secondary. The eyebrow above the
       Now Playing title is a primary identifier line — it should
       match the rest of the active-state highlights in the app. */
    color: var(--accent-primary);
    font-weight: 700;
    margin-bottom: 4px;
}

.qh-title {
    font-size: 26px;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.15;
    word-break: break-word;
}

.qh-artist {
    font-size: 15px;
    color: var(--text-secondary);
    font-weight: 500;
}

.qh-album {
    font-size: 12px;
    color: var(--text-muted);
    margin-top: 2px;
}

.qh-credits {
    font-size: 13px;
    color: var(--text-secondary);
    font-style: italic;
    margin-top: -2px;
    margin-bottom: 6px;
    max-width: 620px;
    line-height: 1.35;
}

.qh-progress {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    max-width: 520px;
    font-variant-numeric: tabular-nums;
    font-size: 12px;
    color: var(--text-muted);
}

.qh-progress-track {
    flex: 1;
    height: 56px;
    background: transparent;
    border-radius: 6px;
    overflow: hidden;
    cursor: pointer;
    position: relative;
    /* Populated by updateNowPlayingHeroProgress() — drives the accent
       canvas clip below. Progress-bar movement is one CSS-variable write
       per tick; no DOM reflow. */
    --qh-progress: 0%;
}

/* Both waveforms are painted by drawHeroWaveforms() with the same peaks,
   just different fill colors. Stacking: grey is always visible; accent is
   overlaid and clipped so only the played portion shows. */
.qh-wave {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: block;
    pointer-events: none;
}

.qh-wave-grey {
    opacity: 0.45;
}

.qh-wave-accent {
    clip-path: inset(0 calc(100% - var(--qh-progress, 0%)) 0 0);
    transition: clip-path 0.1s linear;
}

/* Subtle seek-cursor line at the current play position — gives a clear
   visual cue even when the waveform is mostly at rest (silent passages). */
.qh-progress-track::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--qh-progress, 0%);
    width: 2px;
    background: var(--accent-primary);
    box-shadow: 0 0 4px rgba(var(--accent-primary-rgb), 0.6);
    transition: left 0.1s linear;
    pointer-events: none;
}

/* While the user is dragging, kill the smoothing transitions so the cursor
   and tint follow the mouse 1:1, and widen the cursor for feedback. */
.qh-progress-track.qh-scrubbing {
    cursor: grabbing;
}

.qh-progress-track.qh-scrubbing .qh-wave-accent,
.qh-progress-track.qh-scrubbing::after {
    transition: none;
}

.qh-progress-track.qh-scrubbing::after {
    width: 3px;
    box-shadow: 0 0 6px rgba(var(--accent-primary-rgb), 0.9);
}

.qh-controls {
    display: flex;
    align-items: center;
    gap: 18px;
}

/* Like / rating row — sits between the info block and the waveform.
   Hidden when the playing track has no DB id (preview mode, nothing
   playing) since both actions need a trackId to persist. */
.qh-rating-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    margin-top: -2px;
}
.qh-like {
    background: transparent;
    border: 0;
    cursor: pointer;
    color: var(--text-muted);
    font-size: 22px;
    line-height: 1;
    padding: 4px 6px;
    transition: color 0.15s, transform 0.1s;
}
.qh-like:hover {
    color: var(--accent-primary);
}
.qh-like.liked {
    color: var(--accent-primary);
    text-shadow: 0 0 8px rgba(var(--accent-primary-rgb), 0.45);
}
.qh-like:active {
    transform: scale(0.92);
}
.qh-rating {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.qh-rating-star {
    color: var(--text-muted);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    transition: color 0.12s, transform 0.1s;
    user-select: none;
}
.qh-rating-star:hover {
    color: var(--accent-primary);
    transform: scale(1.12);
}
.qh-rating-star.filled {
    color: var(--accent-primary);
}

/* Auxiliary row at the bottom of the hero card — equalizer button +
   inline volume slider mirror of the player-bar's right-edge
   controls. Adds a useful destination for the otherwise-empty space
   in the stretched hero card. */
.qh-aux-controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
    max-width: 520px;
    margin-top: 6px;
}
.qh-eq {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    color: var(--text-secondary);
    width: 36px;
    height: 36px;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
    flex: 0 0 auto;
}
.qh-eq:hover {
    color: var(--accent-primary);
    border-color: var(--accent-primary);
    background: rgba(var(--accent-primary-rgb), 0.08);
}
.qh-vol-icon {
    color: var(--text-muted);
    display: inline-flex;
    flex: 0 0 auto;
}
.qh-volume-slider {
    flex: 1 1 auto;
    height: 6px;
    background: var(--bg-card);
    border-radius: 3px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    min-width: 80px;
    border: 1px solid var(--border-subtle);
}
.qh-volume-fill {
    height: 100%;
    background: var(--accent-primary);
    border-radius: 3px;
    transition: width 0.08s linear;
}
.qh-volume-percent {
    color: var(--text-muted);
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    flex: 0 0 auto;
    min-width: 36px;
    text-align: right;
    cursor: default;
}

.qh-ctrl {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    color: var(--text-primary);
    width: 44px;
    height: 44px;
    border-radius: 50%;
    font-size: 16px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.15s;
}

.qh-ctrl:hover {
    border-color: var(--accent-primary);
    color: var(--accent-primary);
}

.qh-ctrl.qh-play-pause {
    width: 60px;
    height: 60px;
    font-size: 22px;
    /* Pure-accent gradient (lighter shade ↔ primary) — see base.css. The
       previous primary→secondary version produced a yellow-ish bottom
       half regardless of the user's accent. */
    background: var(--accent-gradient);
    border: none;
    color: white;
    box-shadow: 0 6px 18px rgba(var(--accent-primary-rgb), 0.35);
}

.qh-ctrl.qh-play-pause:hover {
    transform: scale(1.05);
    color: white;
}

.qh-ctrl.active {
    color: var(--accent-primary);
    border-color: var(--accent-primary);
}

.queue-clear-btn {
    background: var(--bg-card);
    border: none;
    padding: 10px 20px;
    border-radius: 20px;
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 13px;
}

.queue-clear-btn:hover {
    background: var(--bg-card-hover);
    color: var(--text-primary);
}

.queue-mode-toggle {
    display: flex;
    gap: 10px;
}

.queue-mode-btn {
    background: var(--bg-card);
    padding: 8px 16px;
    border-radius: 20px;
    font-size: 13px;
    color: var(--text-secondary);
    cursor: pointer;
}

.queue-mode-btn.active {
    background: var(--accent-primary);
    color: white;
}

.queue-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.queue-song-item {
    display: flex;
    align-items: center;
    padding: 15px;
    background: var(--bg-card);
    border-radius: 12px;
    cursor: pointer;
    transition: all 0.2s;
}

/* ---------------------------------------------------------------------------
   The accent bar — a STRAIGHT line, one width, everywhere.

   Every "currently playing / selected" row marks itself with this bar, and
   they all used to draw it differently: some with `border-left`, some with
   `box-shadow: inset`. That difference is the whole bug. An inset shadow is
   clipped to the element's own border-radius, and these rows are rounded
   (8px, 10px, 12px), so the inset versions rendered as rounded stubs —
   visibly fatter on the curve than on the straight run, which is what read
   as a lumpy frame rather than a line.

   So the bar is drawn here, once, as a pseudo-element. A plain rectangle has
   no corner rounding to inherit, so it is square no matter what radius the
   row carries, and it costs no layout width (absolutely positioned, so the
   text does not shift as it would with a real border).

   `.playing::after` is safe to claim: the speaker badge owns `::before`, and
   the drop-highlight and selection rings are all on other selectors.
--------------------------------------------------------------------------- */
.accent-bar-host { position: relative; }

/* Geometry only. The bar is INVISIBLE here — it is painted by the state
   rules below, because only the active/playing row is supposed to carry it.
   A row that merely happens to be a host must not grow a stripe. */
.accent-bar-host::after {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: var(--accent-bar-width, 3px);
    background: transparent;
    /* Square, unconditionally. If this ever picks up a radius the line stops
       being a line. */
    border-radius: 0;
    pointer-events: none;
    z-index: 3;
}

/* Every surface spells its selected state differently, so the bar follows
   all of them. Missing one is how a row ended up showing no indicator at
   all, which is a quieter bug than a lumpy one. */
.accent-bar-host.active::after,
.accent-bar-host.playing::after,
.accent-bar-host.selected::after,
.accent-bar-host.has-playing::after,
.queue-album-group.has-playing > .queue-album-header::after,
.accent-bar-host[data-playing="1"]::after {
    background: var(--accent-primary, #ff6b35);
}

.queue-song-item:hover {
    background: var(--bg-card-hover);
}

.queue-song-item.playing {
    background: rgba(var(--accent-primary-rgb), 0.15);
}


.queue-song-item .qs-cover {
    width: 50px;
    height: 50px;
    border-radius: 8px;
    margin-right: 15px;
    background-size: cover;
    background-position: center;
    background-color: var(--bg-dark);
    flex: 0 0 auto;
}

/* Placeholder fallback when an album cover isn't available — gradient
   background + initials, matches the avatar treatment used elsewhere
   (entity tiles, queue Albums tab placeholder). */
.queue-song-item .qs-cover-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, 0.92);
    font-weight: 700;
    font-size: 18px;
    letter-spacing: 0.02em;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}

.queue-song-item .qs-info {
    flex: 1;
}

.queue-song-item .qs-title {
    font-size: 14px;
    margin-bottom: 1px;
    line-height: 1.25;
}

.queue-song-item .qs-artist {
    font-size: 12px;
    color: var(--text-secondary);
    line-height: 1.2;
}

/* Currently-playing items reserve room on the left for the universal
   .playing::before loudspeaker badge (base.css). Without this padding
   bump, the icon sits on top of the title text. */
.queue-song-item.playing { padding-left: 28px; }
.right-panel-queue .queue-song-item.playing { padding-left: 26px; }

.queue-song-item .qs-duration {
    color: var(--text-muted);
    font-size: 13px;
    margin-right: 15px;
}

.queue-song-item .qs-remove {
    opacity: 0;
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 18px;
    transition: opacity 0.2s;
}

.queue-song-item:hover .qs-remove {
    opacity: 1;
}

.queue-albums-list {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.queue-album-group {
    background: var(--bg-card);
    border-radius: 15px;
    overflow: hidden;
}

.queue-album-header {
    display: flex;
    align-items: center;
    padding: 15px;
    cursor: pointer;
    background: linear-gradient(135deg, var(--overlay-hover), transparent);
    position: relative;
}

.queue-album-header:hover {
    background: linear-gradient(135deg, var(--overlay-selected), transparent);
}

.queue-album-header .qah-cover {
    width: 60px;
    height: 60px;
    border-radius: 8px;
    margin-right: 15px;
}

.queue-album-header .qah-info {
    flex: 1;
}

.queue-album-header .qah-title {
    font-size: 15px;
    margin-bottom: 4px;
}

.queue-album-header .qah-artist {
    font-size: 13px;
    color: var(--text-secondary);
}

.queue-album-header .qah-toggle {
    font-size: 14px;
    color: var(--text-muted);
    transition: transform 0.2s;
}

/* ---- Drag-onto-Now-Playing drop highlight ---------------------------
   Applied while an internal drag (album / song / work) hovers over the
   left sidebar nav, the right-panel mini-player, or an active queue-*
   view. Just an accent-colored outline so the user sees "yes, drop
   here" without obscuring content. */
#queue-nav.drop-target-active,
#right-panel-np.drop-target-active,
.view-section[data-view^="queue-"].drop-target-active {
    outline: 2px dashed var(--accent-primary, #ff6b35);
    outline-offset: -3px;
    background: rgba(var(--accent-primary-rgb), 0.06);
    border-radius: 8px;
}

.queue-album-header .qah-remove {
    position: absolute;
    right: 30px;
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 18px;
    padding: 4px 8px;
    border-radius: 4px;
    transition: all 0.2s;
}

.queue-album-header .qah-remove:hover {
    color: var(--color-accent);
    background: rgba(var(--accent-primary-rgb), 0.1);
}

.queue-album-header.open .qah-toggle {
    transform: rotate(180deg);
}

.queue-album-tracks {
    display: none;
    border-top: 1px solid var(--border-subtle);
}

/* Direct-child selector: a group's tracks are visible iff THAT group is
   .open. Without the `>`, an .open work would force-show every nested
   movement's tracks regardless of the movement's own collapsed state —
   which is exactly the bug "the movement collapse arrow doesn't do
   anything" described. */
.queue-album-group.open > .queue-album-tracks {
    display: block;
}

.queue-album-work {
    padding: 10px 15px 6px 85px;
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    font-weight: 600;
    /* Work-section header inside an album group — same reasoning as
       .qh-work above. The work label is the primary navigational chip
       on this row, so it tracks the user's accent rather than the
       cyan secondary. */
    color: var(--accent-primary);
    border-top: 1px solid var(--border-subtle);
    background: rgba(var(--accent-primary-rgb), 0.04);
}

.queue-album-work + .queue-album-track {
    border-top: none;
}

.queue-album-track {
    display: flex;
    align-items: center;
    padding: 12px 15px 12px 85px;
    cursor: pointer;
    font-size: 13px;
    border-top: 1px solid var(--border-subtle);
}

.queue-album-track:hover {
    background: var(--bg-card-hover);
}

/* Currently-playing track inside a By Albums / By Works group.
   Targeting both `.playing` AND `[data-playing="1"]` (set by
   queue.js's _renderQueueAlbumsInto) so even if some narrower-scope
   CSS in the sidebar / tiny-player ever beats the class selector on
   specificity, the attribute selector gives us a second independent
   path. `!important` on the high-impact properties is intentional —
   the playing indicator is the single most important visual cue in
   the queue and must never be silently overridden by a contextual
   compactness rule (smaller font, smaller padding, etc.). */
.queue-album-track.playing,
.queue-album-track[data-playing="1"] {
    background:
        linear-gradient(
            to right,
            rgba(var(--accent-primary-rgb), 0.42) 0%,
            rgba(var(--accent-primary-rgb), 0.20) 40%,
            rgba(var(--accent-primary-rgb), 0.08) 100%) !important;
    box-shadow: /* bar: .accent-bar-host::after — this was `inset 5px 0 0 0`, the fattest
       accent bar in the app, 5px against everyone else's 3px. */
    box-shadow: none !important;
}

.queue-album-track.playing .qat-title,
.queue-album-track.playing .qat-duration,
.queue-album-track[data-playing="1"] .qat-title,
.queue-album-track[data-playing="1"] .qat-duration {
    color: var(--accent-primary) !important;
    font-weight: 600 !important;
}

/* Replace the track-number digit with a ▶ play arrow on the playing
   row. Number text is forced transparent (covers the existing tiny-
   player ID-specificity override that was leaving the digit visible)
   and the arrow is absolutely positioned over the same cell so
   widths / alignment of neighbouring columns don't shift between
   rows. */
.queue-album-track.playing .qat-num,
.queue-album-track[data-playing="1"] .qat-num {
    color: transparent !important;
    position: relative;
}
.queue-album-track.playing .qat-num::before,
.queue-album-track[data-playing="1"] .qat-num::before {
    content: "▶";
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--accent-primary);
    font-size: 13px;
    line-height: 1;
    /* Tiny pulse so it's clearly "live", not a static glyph. */
    animation: queue-album-playing-pulse 1.4s ease-in-out infinite;
}
@keyframes queue-album-playing-pulse {
    0%, 100% { opacity: 0.85; transform: scale(1);    }
    50%      { opacity: 1;    transform: scale(1.18); }
}
@media (prefers-reduced-motion: reduce) {
    .queue-album-track.playing .qat-num::before,
    .queue-album-track[data-playing="1"] .qat-num::before { animation: none; }
}

/* Suppress the universal .playing::before speaker badge on these rows —
   the ▶ in the qat-num column is the new indicator and keeping the
   speaker on top of it would just be noise. */
.queue-album-track.playing::before,
.queue-album-track[data-playing="1"]::before { display: none; }

/* When a group contains the currently-playing track, tint the album header so
   the user can see which album/work is "active" even if the group is
   collapsed and the track row itself is hidden. */
.queue-album-group.has-playing .queue-album-header {
    background: rgba(var(--accent-primary-rgb), 0.08);
    padding-left: 9px;   /* compensate for the 3px border so text doesn't shift */
}

.queue-album-group.has-playing .qah-title {
    color: var(--accent-primary);
}

.queue-album-track .qat-num {
    width: 25px;
    color: var(--text-muted);
    margin-right: 10px;
}

.queue-album-track .qat-title {
    flex: 1;
}

.queue-album-track .qat-duration {
    color: var(--text-muted);
}

.queue-album-track .qat-remove {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 16px;
    padding: 4px 8px;
    margin-left: 8px;
    border-radius: 4px;
    opacity: 0;
    transition: all 0.2s;
}

.queue-album-track:hover .qat-remove {
    opacity: 1;
}

.queue-album-track .qat-remove:hover {
    color: var(--color-accent);
    background: rgba(var(--accent-primary-rgb), 0.1);
}

.empty-queue {
    text-align: center;
    padding: 60px 20px;
    color: var(--text-muted);
}

.empty-queue .eq-icon {
    font-size: 48px;
    margin-bottom: 15px;
}

.empty-queue p {
    font-size: 14px;
}

.qh-badge-row {
    margin-top: 10px;
    display: flex;
    justify-content: center;
}

.qah-cover {
    width: 60px;
    height: 60px;
    border-radius: 8px;
    margin-right: 15px;
    background: var(--bg-card);
    background-size: cover;
    background-position: center;
}

.qah-toggle,
.dropdown-arrow {
    color: var(--text-muted);
}

/* Hierarchical track grouping in the "By Works" queue view. Tier 0 is
   the outermost header; deeper tiers indent and use lighter chrome so
   the tree shape is obvious. The .qah-field span shows which tag this
   group is keyed on (e.g. "Composer"). */
.queue-tg-tier-1 {
    margin-left: 18px;
}
.queue-tg-tier-2 {
    margin-left: 36px;
}

.queue-tg-tier-1 > .queue-tg-header {
    background: rgba(255, 255, 255, 0.02);
}
.queue-tg-tier-2 > .queue-tg-header {
    background: transparent;
}

/* Movement-name headers are identified by their leaf field rather than
   tier-depth: chain-fusion frequently compresses Composer+Work into
   tier-0, leaving the movement at tier-1, so a tier-N selector wouldn't
   match reliably. The data-tg-leaf-field attribute is set in queue.js's
   _renderQueueChain to the deepest field walked into the header.

   Movement headers are ALWAYS leaf rows (their children are the final
   track rows), and since _renderQueueChain now renders the deepest group
   as a flat track row (.queue-tg-leaf-row), this strip styling only
   applies to a hypothetical non-leaf movement header — the :not() guard
   keeps the two variants distinct without a specificity arms race. */
.queue-tg-group[data-tg-leaf-field="extra:MOVEMENTNAME"] {
    /* Reset the tier-N margin-left and indent the strip via the header's
       own padding-left instead — without this, a movement at tier-1
       would inherit the work's 18px indent which is too tight for a
       strip-style header. Leaf-row movement headers get their own reset
       below. */
    margin-left: 0;
}

.queue-tg-group[data-tg-leaf-field="extra:MOVEMENTNAME"]:not(.queue-tg-leaf-row) > .queue-tg-header {
    padding: 4px 10px 4px 18px;
    gap: 8px;
    align-items: center;
    background: transparent;
    border-radius: 4px;
}

.queue-tg-group[data-tg-leaf-field="extra:MOVEMENTNAME"]:not(.queue-tg-leaf-row) > .queue-tg-header .qah-cover {
    display: none;
}

/* Collapse the two-row info column into a single line — title on the
   left (uppercase accent strip), meta on the right. DOM order is
   subhead-then-title-text; we flip the visual order via flex `order`. */
.queue-tg-group[data-tg-leaf-field="extra:MOVEMENTNAME"]:not(.queue-tg-leaf-row) > .queue-tg-header .qah-info {
    flex-direction: row;
    align-items: baseline;
    gap: 10px;
    flex: 1 1 auto;
    min-width: 0;
}
.queue-tg-group[data-tg-leaf-field="extra:MOVEMENTNAME"]:not(.queue-tg-leaf-row) > .queue-tg-header .qah-info > .qah-title-text {
    order: 1;
    font-size: 10px;
    font-weight: 700;
    color: var(--accent-primary);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    line-height: 1.4;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1 1 auto;
    min-width: 0;
    word-break: normal;
    overflow-wrap: normal;
}
.queue-tg-group[data-tg-leaf-field="extra:MOVEMENTNAME"]:not(.queue-tg-leaf-row) > .queue-tg-header .qah-info > .qah-subhead {
    order: 2;
    margin-left: auto;
    flex: 0 0 auto;
}

/* Suppress the "MOVEMENT NAME" pill chip — the uppercase title carries
   the type signal at this depth. */
.queue-tg-group[data-tg-leaf-field="extra:MOVEMENTNAME"]:not(.queue-tg-leaf-row) > .queue-tg-header .qah-field {
    display: none;
}

/* Meta ("(2) · 3min") matches the strip — tiny + uppercase. */
.queue-tg-group[data-tg-leaf-field="extra:MOVEMENTNAME"]:not(.queue-tg-leaf-row) > .queue-tg-header .qah-subhead .qah-title-meta {
    font-size: 9.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-left: 0;
    color: var(--text-muted);
}

/* De-emphasise the remove + toggle controls so the strip's accent text
   reads as the dominant element. */
.queue-tg-group[data-tg-leaf-field="extra:MOVEMENTNAME"]:not(.queue-tg-leaf-row) > .queue-tg-header .qah-remove {
    font-size: 14px;
    opacity: 0.55;
}
.queue-tg-group[data-tg-leaf-field="extra:MOVEMENTNAME"]:not(.queue-tg-leaf-row) > .queue-tg-header .qah-toggle {
    font-size: 9px;
}

.qah-field {
    display: inline-flex;
    align-items: center;
    padding: 3px 9px;
    border-radius: 999px;
    background: rgba(var(--accent-primary-rgb), 0.18);
    color: var(--accent-primary);
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    vertical-align: middle;
    /* Don't let the chip shrink — the subhead's `gap` handles spacing
       to the meta, and the chip should always print at content size. */
    flex: 0 0 auto;
    white-space: nowrap;
    /* Subtle inner ring + outer halo so the chip reads as a refined
       label, not flat-coloured background paint. */
    box-shadow: inset 0 0 0 1px rgba(var(--accent-primary-rgb), 0.30);
}

/* ============================================================
   Works-view group header — slick two-row card layout.
   Row 1 (.qah-subhead): the COMPOSER / WORK chip on the left and
   the (n) · duration meta on the right. Both small + uppercase
   so they read as labels, not content.
   Row 2 (.qah-title-text): the actual composer/work label — big,
   primary text. Wraps cleanly when long.
   To the right of both rows: the × remove button (hover-only) and
   the ▼ toggle chevron, vertically centered.
   ============================================================ */
.queue-tg-header {
    align-items: stretch;
    padding: 12px 14px;
    gap: 10px;
    /* Reset the album-header's default linear-gradient so the works
       view gets its own monochrome accent-tinted card. */
    background: transparent;
}

.queue-tg-header .qah-info {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* Subhead row — chip + meta on the same line, meta right-aligned. */
.queue-tg-header .qah-subhead {
    display: flex;
    align-items: center;
    gap: 8px;
    line-height: 1;
}

.queue-tg-header .qah-subhead .qah-title-meta {
    margin-left: auto;
    font-size: 10.5px;
    color: var(--text-muted);
    font-weight: 500;
    letter-spacing: 0.04em;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* The big primary label. Word-wraps gracefully on long composer
   lists; tightish line-height keeps two-line wraps from looking
   sparse. */
.queue-tg-header .qah-title-text {
    font-size: 13.5px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--text-primary);
    word-break: break-word;
    overflow-wrap: anywhere;
}

/* Right-side actions — vertically center across the whole two-row
   header instead of aligning to one row's baseline. */
.queue-tg-header .qah-toggle {
    align-self: center;
    flex: 0 0 auto;
    color: var(--text-muted);
    transition: color 0.15s, transform 0.2s;
}

.queue-tg-group.open > .queue-tg-header .qah-toggle {
    color: var(--accent-primary);
}

.queue-tg-header .qah-remove {
    position: static;
    align-self: center;
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    padding: 0;
    font-size: 16px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    color: var(--text-muted);
    background: transparent;
    border: none;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s, background 0.15s, color 0.15s;
}

.queue-tg-header:hover .qah-remove {
    opacity: 0.85;
}

.queue-tg-header .qah-remove:hover {
    opacity: 1;
    background: rgba(var(--accent-primary-rgb), 0.18);
    color: var(--accent-primary);
}

/* Works-view track rows now carry their own album cover thumbnail
   (.qat-cover, rendered by _renderQueueWorksNode + the inline leaf in
   _renderQueueChain). Tight 12 px left padding so the cover sits flush
   with the group header's avatar above. */
.queue-tg-group .queue-album-track {
    padding-left: 12px;
    gap: 10px;
}

/* Per-track cover thumbnail in the works view. Falls back to the
   .bg-card colour when an album has no cover on file (background-image
   is empty in that case). */
.qat-cover {
    width: 36px;
    height: 36px;
    border-radius: 6px;
    background: var(--bg-card);
    background-size: cover;
    background-position: center;
    flex: 0 0 auto;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}

/* Same for the qat-title — let the title use the freed-up space rather
   than truncating early. */
.queue-tg-group .queue-album-track .qat-title {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Group-header cover / placeholder. When all tracks share an album we
   set background-image to that cover; otherwise the JS sets a gradient
   + initials (avatar-style) so multi-album groups (e.g. a composer
   spanning several recordings) still get an identifiable visual. */
.queue-tg-header .qah-cover {
    width: 44px;
    height: 44px;
    border-radius: 8px;
    background: var(--bg-card);
    background-size: cover;
    background-position: center;
    flex: 0 0 auto;
    align-self: center;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.30);
}

/* Avatar-style fallback — centred initials over the gradient set inline. */
.queue-tg-header .qah-cover.qah-cover-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-on-accent);
    font-weight: 700;
    font-size: 14px;
    letter-spacing: 0.04em;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

/* Tier-0 (top-level) gets a faint accent-tinted card surface and a
   1px accent-tinted border — distinguishes it from the body of nested
   children, gives the row a slight "card" feel. */
.queue-tg-tier-0 {
    background: linear-gradient(180deg,
        rgba(var(--accent-primary-rgb), 0.06),
        rgba(var(--accent-primary-rgb), 0.02));
    border: 1px solid rgba(var(--accent-primary-rgb), 0.14);
    border-radius: 12px;
    overflow: hidden;
    transition: border-color 0.2s, background 0.2s;
}

.queue-tg-tier-0:hover {
    border-color: rgba(var(--accent-primary-rgb), 0.28);
    background: linear-gradient(180deg,
        rgba(var(--accent-primary-rgb), 0.10),
        rgba(var(--accent-primary-rgb), 0.04));
}

/* Tier-0 with a currently-playing track inside — pull the accent
   forward so the user can see at a glance which group their
   playhead is in. Subtle; the per-row .playing highlight is the
   primary cue. */
.queue-tg-tier-0.has-playing {
    border-color: rgba(var(--accent-primary-rgb), 0.45);
    background: linear-gradient(180deg,
        rgba(var(--accent-primary-rgb), 0.14),
        rgba(var(--accent-primary-rgb), 0.05));
}

/* Deeper tiers — strip the top border so the nested feel is preserved
   visually. */
.queue-tg-tier-1, .queue-tg-tier-2 {
    background: transparent;
    border: none;
    border-radius: 0;
}

.qat-subline {
    display: block;
    font-size: 11.5px;
    color: var(--text-muted);
    margin-top: 2px;
}

/* ============================================================
   Single-click selection highlight (all queue views).
   A row / header with .selected is the user's last single-click
   target. Tinted background + inset accent ring, distinct from the
   .playing gradient (which keeps its stronger look for the actual
   playhead). Applied across every queue-list mirror by stamping the
   same stable key after each render.
   ============================================================ */
.queue-song-item.selected,
.queue-album-track.selected,
.queue-album-header.selected,
.queue-tg-header.selected {
    background:
        linear-gradient(
            to right,
            rgba(var(--accent-primary-rgb), 0.16) 0%,
            rgba(var(--accent-primary-rgb), 0.05) 100%
        );
    box-shadow: inset 0 0 0 1px rgba(var(--accent-primary-rgb), 0.35);
}

.queue-song-item.selected .qs-title,
.queue-album-track.selected .qat-title,
.queue-tg-header.selected .qah-title-text,
.queue-album-header.selected .qah-title,
.queue-album-header.selected .qah-artist,
.queue-tg-header.selected .qah-artist {
    color: var(--text-primary);
}

/* ============================================================
   Deepest group header as a flat track row (.queue-tg-leaf-row).
   _renderQueueChain assigns this class to the group whose header
   DIRECTLY wraps playable track rows (walker.tracks). The header
   keeps its identity (cover, fold chevron, remove, playing tint)
   but its body collapses the two-row card into a single title line
   with an artist subline + right-aligned duration — the same
   skeleton as a .queue-album-track, so the end of the tree reads
   as a track list.
   ============================================================ */
.queue-tg-leaf-row {
    /* Flush with the parent body; clobber the tier-N indent. */
    margin-left: 0;
}

.queue-tg-group.queue-tg-leaf-row > .queue-tg-header {
    align-items: center;
    padding: 10px 14px;
    gap: 10px;
    background: transparent;
}

.queue-tg-group.queue-tg-leaf-row > .queue-tg-header:hover {
    background: var(--bg-card-hover);
}

/* Cover drops from group-avatar size to near-qat thumb size so the
   row reads as a track. */
.queue-tg-group.queue-tg-leaf-row > .queue-tg-header .qah-cover {
    width: 36px;
    height: 36px;
    border-radius: 6px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}

.queue-tg-group.queue-tg-leaf-row > .queue-tg-header .qah-info {
    flex: 1 1 auto;
    min-width: 0;
    align-items: flex-start;
}

.queue-tg-group.queue-tg-leaf-row > .queue-tg-header .qah-title-text {
    font-size: 14px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: normal;
    overflow-wrap: normal;
}

.queue-tg-group.queue-tg-leaf-row > .queue-tg-header .qah-artist {
    font-size: 12px;
    color: var(--text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Duration aligned to the track-row column. */
.queue-tg-group.queue-tg-leaf-row > .queue-tg-header .qah-duration {
    flex: 0 0 auto;
    font-size: 12px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.queue-tg-group.queue-tg-leaf-row.has-playing > .queue-tg-header .qah-title-text {
    color: var(--accent-primary);
}
