/* SPDX-License-Identifier: AGPL-3.0-only */
/* FXRoute — Redesigned Styles */
/* Dark, warm, product-like. Touch-friendly. */

/* Geist variable (SIL OFL 1.1, bundled in static/fonts/): one file covers
   all weights, so no extra cuts are needed. font-display: swap keeps first
   paint on the system fallback. */
@font-face {
    font-family: 'Geist';
    src: url('fonts/Geist.woff2?v=0.9.149') format('woff2');
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Geist Mono';
    src: url('fonts/GeistMono.woff2?v=0.9.149') format('woff2');
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

:root {
    --bg-primary:    #0d0d0f;
    --bg-surface:    #161619;
    --bg-elevated:   #1e1e22;
    --bg-hover:      #26262b;
    --bg-input:      #1c1c20;
    --text-primary:   #ececf0;
    --text-secondary: #a0a0ac;
    --text-muted:     #848490;
    --accent:        #6ee7b7;   /* fresh teal */
    --accent-dim:    rgba(110, 231, 183, 0.12);
    --accent-hover:  #4dd8a0;
    --danger:        #f87171;
    --danger-dim:    rgba(248, 113, 113, 0.12);
    --success:       #34d399;
    --border:        rgba(255, 255, 255, 0.06);
    --border-strong: rgba(255, 255, 255, 0.10);
    --scrollbar:     var(--bg-hover);
    --shadow:        rgba(0, 0, 0, 0.4);
    --radius-sm:  8px;
    --radius-md:  12px;
    --radius-lg:  16px;
    --radius-xl:  20px;
    --action-gap: 12px;
    --action-gap-mobile: 8px;
    /* Shared tile grid basis: Library albums, TIDAL tiles and radio station
       cards derive their column sizing from these two values so all three
       surfaces keep one tile rhythm across breakpoints. Radio reads a
       narrower derivative; vertical scroll comfort beats horizontal fill. */
    --tile-min: 208px;
    --tile-min-radio: 164px;
    --tile-gap: clamp(0.85rem, 1.2vw, 1.1rem);
    --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
    --playback-footer-space: 142px;
    /* Stacking-order tokens: semantic names for the layering the stylesheet
       already implements. Values are the historical literal z-index numbers,
       preserved exactly so the visible order is unchanged; the tokens only
       make the hierarchy legible and give one place to adjust a layer.
       Ascending from the page background to the topmost transient layer. */
    --z-underlay:        0;      /* blurred detail-hero backdrop */
    --z-base:            1;      /* badges, hero gradient overlays, seat in the room view */
    --z-raised:          2;      /* interactive controls on tiles/covers, room mic, cover */
    --z-tabs:            4;      /* tab bar (header) */
    --z-playback-bar:    100;    /* fixed playback footer */
    --z-banner:          1002;   /* offline/disconnect banner */
    --z-toast:           1005;   /* transient toasts */
    --z-header-menu:     1007;   /* open power menu: the header creates no
                                    stacking context, so this value competes
                                    in the root context and must sit above
                                    the tab bar and toasts */
    --z-cover-detail-backdrop: 1040;
    --z-cover-detail:    1041;   /* cover detail card */
    --z-overlay:         1100;   /* generic modal overlay (manage/settings) */
    --z-measurement:     1200;   /* measurement dialog overlay */
    --z-measurement-hybrid: 1230;/* hybrid measurement overlay */
    --z-skip-link:       2000;   /* visually-hidden skip link */
    --z-tooltip:         3000;   /* custom header tooltips */
    --font-sans: 'Geist', -apple-system, BlinkMacSystemFont, "Segoe UI", "Inter", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
    --font-mono: 'Geist Mono', ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
    /* Native form controls (select option popups, autofill, scrollbars)
       follow the dark theme instead of the system light scheme. */
    color-scheme: dark;
    /* Native control accents (checkboxes, radios) use the brand mint. */
    accent-color: var(--accent);
}
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    /* Global dark scrollbars for the page and unscoped scroll areas. */
    scrollbar-width: thin;
    scrollbar-color: var(--bg-hover) transparent;
}
html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}
*::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}
*::-webkit-scrollbar-track {
    background: transparent;
}
*::-webkit-scrollbar-thumb {
    background: var(--bg-hover);
    border-radius: 4px;
}
*::-webkit-scrollbar-thumb:hover {
    background: var(--border-strong);
}
::selection {
    background: rgba(110, 231, 183, 0.18);
    color: var(--text-primary);
}
/* Visually hidden skip link, revealed on keyboard focus. */
.skip-link {
    position: absolute;
    top: -40px;
    left: 0.75rem;    z-index: var(--z-skip-link);
    padding: 0.6rem 0.9rem;
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    color: var(--accent);
    font-weight: 600;
    font-size: 0.88rem;
    text-decoration: none;
    box-shadow: 0 8px 24px var(--shadow);
    transition: top 0.15s var(--ease);
}
.skip-link:focus-visible {
    top: 0.75rem;
}
body {
    font-family: var(--font-sans);
    background:
        radial-gradient(circle at 50% -20%, rgba(110,231,183,.035), transparent 34%),
        linear-gradient(180deg, #0b0b0e 0%, #0d0d10 55%, #0b0b0e 100%);
    color: var(--text-primary);
    min-height: 100vh;
    min-height: 100dvh;
    padding-bottom: var(--playback-footer-space);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}
/* ============================================================
   Offline / Connection banner
   ============================================================ */
.offline-indicator {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    /* Error stays red, but reads as part of the dark theme: translucent
       dark-red tint instead of a full-saturation danger band. The red dot
       and the danger border keep the disconnect meaning unambiguous. */
    background: rgba(120, 27, 27, 0.6);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid rgba(248, 113, 113, 0.32);
    color: #ffe9e9;
    text-align: center;
    padding: 0.5rem 1rem;
    font-weight: 600;
    font-size: 0.88rem;
    z-index: var(--z-banner);
    letter-spacing: 0.02em;
    animation: bannerSlide 0.3s var(--ease);
}
.offline-indicator::before {
    content: '';
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-right: 0.5rem;
    vertical-align: -1px;
    border-radius: 50%;
    background: var(--danger);
    box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.22);
}
.offline-indicator.hidden { display: none; }
/* Live mode notice: compact pill above the playback footer, mirroring the
   web-demo banner (demo/demo.css). Only shown when /api/status reports
   live:true (volatile Try session). Dismissible, auto-hides after a few
   minutes, never covers header controls or the footer. */
.live-banner {
    position: fixed;
    left: 50%;
    bottom: calc(var(--footer-height, 92px) + 12px);
    transform: translateX(-50%);
    z-index: 60;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: 999px;
    background: rgba(13, 13, 15, 0.88);
    border: 1px solid rgba(251, 191, 36, 0.45);
    color: var(--text-secondary, #cbd5e1);
    font-size: 0.8rem;
    line-height: 1.2;
    backdrop-filter: blur(8px);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
    pointer-events: auto;
    max-width: calc(100vw - 24px);
}
.live-banner strong { color: #fbbf24; }
.live-banner-close {
    display: inline-grid;
    place-items: center;
    width: 22px;
    height: 22px;
    margin-left: 2px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text-muted, #848490);
    font: inherit;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}
.live-banner-close:hover,
.live-banner-close:focus-visible { color: var(--text-primary, #ececf0); background: rgba(255,255,255,.08); }
.live-banner-close:focus-visible { outline: 2px solid var(--accent, #6ee7b7); outline-offset: 2px; }
.live-banner.is-hidden { display: none; }
@media (max-width: 720px) {
    .live-banner {
        left: 12px;
        right: 12px;
        transform: none;
        justify-content: center;
        text-align: center;
        flex-wrap: wrap;
        bottom: calc(var(--footer-height, 150px) + 10px);
        gap: 4px 10px;
        padding: 7px 12px;
        border-radius: 14px;
        font-size: 0.76rem;
        background: rgba(13, 13, 15, 0.92);
        backdrop-filter: blur(10px) saturate(1.1);
        -webkit-backdrop-filter: blur(10px) saturate(1.1);
        box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
    }
}
.hidden { display: none !important; }
@keyframes bannerSlide {
    from { transform: translateY(-100%); }
    to   { transform: translateY(0); }
}
/* ============================================================
   Unified primitives — single source for duplicated rows/favs
   ============================================================ */
.track-row-favorite,
.track-fav,
.streaming-fav{flex:0 0 auto;width:34px;height:34px;min-height:34px;border-radius:50%;border:1px solid var(--border);background:transparent;color:var(--text-muted);font:inherit;font-size:0.95rem;line-height:1;display:inline-flex;align-items:center;justify-content:center;padding:0;cursor:pointer;transition:color .12s var(--ease),border-color .12s var(--ease),background .12s var(--ease),transform .12s var(--ease);-webkit-tap-highlight-color:transparent}
.track-row-favorite:hover,
.track-fav:hover,
.streaming-fav:hover,
.track-row-favorite.active,
.track-fav.active,
.streaming-fav.active,
.track-fav.is-active,
.streaming-fav.is-active{color:var(--accent);border-color:var(--accent)}
.track-row-favorite:active,
.track-fav:active,
.streaming-fav:active{transform:scale(.92)}
.track-row-favorite:focus-visible,
.track-fav:focus-visible,
.streaming-fav:focus-visible{color:var(--accent);outline:2px solid var(--accent);outline-offset:-2px}
.track-row-favorite:disabled,
.track-fav:disabled,
.streaming-fav:disabled{opacity:.45;cursor:wait}
.track-row-favorite.active{ text-shadow:0 0 10px rgba(110,231,183,.18)}
/* Favorite heart: one inline SVG painted from currentColor, so the muted /
   accent colours above stay authoritative and no platform colour-emoji font
   can repaint an active heart. Outline when idle, filled when the button
   carries its active state. */
.fav-heart{display:block;width:1em;height:1em;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linejoin:round;pointer-events:none}
.active>.fav-heart,
.is-active>.fav-heart{fill:currentColor}
.track-add,
.streaming-add{flex:0 0 auto;width:34px;height:34px;min-height:34px;border-radius:50%;border:1px solid var(--border);background:transparent;color:var(--text-muted);font:inherit;font-size:1.05rem;line-height:1;display:inline-flex;align-items:center;justify-content:center;padding:0;cursor:pointer;transition:color .12s var(--ease),border-color .12s var(--ease),background .12s var(--ease),transform .12s var(--ease);-webkit-tap-highlight-color:transparent}
.track-add:hover,
.streaming-add:hover{color:var(--accent);border-color:var(--accent)}
.track-add:active,
.streaming-add:active{transform:scale(.92)}
.track-add:focus-visible,
.streaming-add:focus-visible{color:var(--accent);outline:2px solid var(--accent);outline-offset:-2px}
.track-add.is-active,
.streaming-add.is-active{color:var(--accent);border-color:var(--accent);background:var(--accent-dim)}
.track-row,
.streaming-result,
.album-detail-tracks .track-item{display:flex;align-items:center;gap:.7rem;padding:.45rem .6rem;border-radius:var(--radius-md);background:var(--bg-surface);border:1px solid var(--border);cursor:pointer;min-width:0;transition:background 0.12s,border-color 0.12s}
.track-row:hover,
.streaming-result:hover,
.album-detail-tracks .track-item:hover{background:var(--bg-hover);border-color:var(--border-strong)}
/* Selected TIDAL rows mirror the library .track-item.selected highlight. */
.streaming-result.is-selected{border-color:var(--accent);background:rgba(110,231,255,.08)}
/* Playing TIDAL row mirrors the library .track-item.active highlight. */
.streaming-result.active{background:var(--accent-dim);border-color:rgba(110,231,183,.45)}
.streaming-result.active .track-title{color:#f0fff8}
.track-play{flex:0 0 auto;width:34px;height:34px;border-radius:50%;border:1px solid var(--border);background:transparent;color:var(--text-secondary);cursor:pointer;font-size:0.85rem;display:inline-flex;align-items:center;justify-content:center;transition:color 0.12s,border-color 0.12s,background 0.12s}
.track-play:hover{color:var(--accent);border-color:var(--accent)}
.track-play:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* Inline SVG icons in generated markup (playlist/folder delete, compact
   labels, streaming transport) inherit currentColor. */
.playlist-delete-btn svg,
.folder-action-btn svg,
.label-compact svg,
.streaming-btn-sm-icon svg {
    width: 15px;
    height: 15px;
    display: block;
}

/* ============================================================
   Header
   ============================================================ */

/* Shared compact view tabs (Library Tracks/Folders/Albums + TIDAL
   Tracks/Albums/Artists): one segmented-navigation standard instead of the
   oversized library action buttons and the undersized TIDAL filter chips.
   Inactive tabs are quiet (muted text, transparent); the active tab keeps the
   mint accent. Touch height stays adequate at 38px. */
.view-tabs {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex-wrap: wrap;
}
.view-tab {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 38px;
    padding: 0.3rem 0.9rem;
    font-size: 0.86rem;
    font-weight: 650;
    letter-spacing: 0.01em;
    white-space: nowrap;
    color: var(--text-muted);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-family: inherit;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
}
.view-tab:hover {
    color: var(--text-secondary);
    background: var(--bg-hover);
    border-color: var(--border-strong);
}
.view-tab.active,
.view-tab.is-active {
    color: var(--accent);
    background: var(--accent-dim);
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px rgba(110, 231, 183, 0.2);
}

/* Shared compact grid/list toggle (Library albums + TIDAL Albums/Artists/
   Playlists). One segmented icon pair; the active mode keeps the same mint
   accent language as .view-tab. Grid stays the default. */
.view-mode-toggle {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
}
.view-mode-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    padding: 0;
    font-size: 0.95rem;
    line-height: 1;
    color: var(--text-muted);
    background: transparent;
    border: 1px solid var(--border);
    cursor: pointer;
    font-family: inherit;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
}
.view-mode-btn:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.view-mode-btn:last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.view-mode-btn + .view-mode-btn { border-left: none; }
.view-mode-btn:hover {
    color: var(--text-secondary);
    background: var(--bg-hover);
}
.view-mode-btn.active {
    color: var(--accent);
    background: var(--accent-dim);
    border-color: var(--accent);
}

/* Visually hidden but available to screen readers (page h1, live labels). */
.visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}
.header {
    background: rgba(14, 14, 17, 0.94);
    min-height: 72px;
    padding: .85rem clamp(1rem, 2.1vw, 2rem);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.9rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.055);
    /* No backdrop-filter here: it would create a stacking context that
       traps the header tooltips and power menu behind the tab bar. The
       header is a static bar (nothing ever scrolls underneath it) and its
       background is nearly opaque, so the blur had no visible effect. With
       no context on the header, the popups escape to the root stacking
       context via their own z-index values (--z-tooltip, --z-header-menu). */
}
.brand-lockup {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}
.brand-lockup-button {
    position: relative;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.brand-lockup-button:hover .brand-mark,
.brand-lockup-button:focus-visible .brand-mark {
    box-shadow: none;
}
.brand-lockup-button:focus-visible {
    /* Same visible keyboard ring as the power button next in the header. */
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
/* Custom CSS tooltips (header buttons): the brand/settings trigger and the
   power button use the same look. The attribute selector keeps the shared
   visuals in one place; per-button rules only set the horizontal anchor. */
.brand-lockup-button[data-tooltip]::after,
.power-btn[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    top: calc(100% + 0.45rem);
    z-index: var(--z-tooltip);
    padding: 0.32rem 0.52rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    color: var(--text-primary);
    box-shadow: 0 8px 24px var(--shadow);
    font-size: 0.72rem;
    font-weight: 650;
    line-height: 1.2;
    white-space: nowrap;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(-2px);
    transition: opacity 0.15s var(--ease), visibility 0.15s var(--ease), transform 0.15s var(--ease);
}
.brand-lockup-button[data-tooltip]::after {
    left: 0;
}
.power-btn[data-tooltip]::after {
    right: 0;
}
.brand-lockup-button[data-tooltip]:hover::after,
.brand-lockup-button:focus-visible::after,
.power-btn[data-tooltip]:hover::after,
.power-btn:focus-visible::after {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}
/* The open power menu covers the area under the button, so its tooltip must
   stay hidden while the button is expanded. */
.power-btn[data-tooltip][aria-expanded="true"]::after {
    opacity: 0;
    visibility: hidden;
    transform: translateY(-2px);
}

.brand-lockup .brand-mark {
    display: inline-block;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: 0;
    background: url('./route-mark.svg') center / contain no-repeat;
    box-shadow: none;
    flex-shrink: 0;
}
.brand-lockup .brand-text-block {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
    line-height: 1;
    padding-top: 0;
}
.brand-lockup .brand-title {
    color: var(--text-primary);
    font-size: 1.16rem;
    font-weight: 520;
    letter-spacing: -0.045em;
}
.brand-lockup .brand-title-fx {
    color: var(--text-primary);
    font-weight: 740;
}

/* Header-right cluster: power button */
.header-status {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    flex-shrink: 0;
}

/* Power menu (header) */
.power-menu-root {
    position: relative;
    display: flex;
    align-items: center;
}
.power-btn {
    position: relative;
    width: 38px;
    height: 38px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    cursor: pointer;
    padding: 0;
    transition: color 0.18s var(--ease),
                background 0.18s var(--ease),
                border-color 0.18s var(--ease);
    -webkit-tap-highlight-color: transparent;
}
.power-btn:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
    border-color: var(--border-strong);
}
.power-btn:focus-visible {
    color: var(--text-primary);
    background: var(--bg-hover);
    border-color: var(--border-strong);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.power-btn[aria-expanded="true"] {
    color: var(--text-primary);
    background: var(--bg-hover);
    border-color: var(--border-strong);
}
.power-btn-icon {
    width: 18px;
    height: 18px;
    display: block;
}
.power-btn.is-online .power-btn-icon {
    color: var(--success);
}
.power-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 168px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    box-shadow: 0 18px 36px -18px var(--shadow);
    padding: 0.35rem;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    z-index: var(--z-header-menu);
}
/* The open menu's --z-header-menu value keeps it above the tab bar and
   transient toasts in the root stacking context; the header itself must
   never be raised (it would cover the tab bar). */
.power-menu-item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    background: transparent;
    border: 0;
    color: var(--text-primary);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 500;
    text-align: left;
    padding: 0.55rem 0.7rem;
    border-radius: 9px;
    cursor: pointer;
    width: 100%;
    transition: background 0.15s var(--ease), color 0.15s var(--ease);
    -webkit-tap-highlight-color: transparent;
}
.power-menu-item:hover {
    background: var(--bg-hover);
}
.power-menu-item:focus-visible {
    background: var(--bg-hover);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.power-menu-item-icon {
    width: 17px;
    height: 17px;
    flex-shrink: 0;
    color: var(--text-secondary);
}
.power-menu-item-icon-danger {
    color: var(--danger);
}
.power-menu-item:hover .power-menu-item-icon-danger {
    color: var(--danger);
}
.power-menu-item.active,
.power-menu-item[data-pending="true"] {
    color: var(--text-muted);
    pointer-events: none;
}
.power-menu-item[data-pending="true"] .power-menu-item-icon {
    color: var(--accent);
}

/* ============================================================
   Tabs
   ============================================================ */
.tabs {
    display: flex;
    position: relative;
    z-index: var(--z-tabs);
    background: rgba(14, 14, 17, 0.94);
    padding: .42rem clamp(.7rem, 1.4vw, 1.2rem);
    gap: .25rem;
    border-top: 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.055);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.tabs.can-scroll::after {
    content: '';
    position: sticky;
    right: 0;
    margin-left: auto;
    flex-shrink: 0;
    align-self: stretch;
    width: 44px;
    pointer-events: none;
    background: linear-gradient(90deg, transparent, var(--bg-surface));
}
.tabs::-webkit-scrollbar { display: none; }
/* ARIA tablist wrapper inside the nav landmark; inherits the responsive
   gap/justify tweaks applied to .tabs so button spacing stays consistent. */
.tabs-list {
    display: flex;
    gap: inherit;
    justify-content: inherit;
    align-items: center;
    flex: 1 1 auto;
    min-width: max-content;
}
.tab-btn {
    flex: 0 0 auto;
    min-width: 112px;
    min-height: 42px;
    padding: .52rem .9rem;
    background: transparent;
    border: none;
    color: var(--text-secondary);
    cursor: pointer;
    font-family: var(--font-sans);
    font-size: .9rem;
    font-weight: 560;
    border-radius: var(--radius-md);
    transition: color 0.2s var(--ease), background 0.2s var(--ease), box-shadow 0.2s var(--ease);
    white-space: nowrap;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
}
.tab-btn:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}
.tab-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}
/* The active accent stays inside the tab: a short centered underline on a
   quiet mint surface. No glow or edge bleeds toward the brand lockup. */
.tab-btn.active {
    color: #f3f3f5;
    background: rgba(110, 231, 183, 0.07);
    font-weight: 600;
    position: relative;
}
.tab-btn.active::after {
    content: '';
    position: absolute;
    left: 30%;
    right: 30%;
    bottom: 3px;
    height: 2px;
    border-radius: 2px;
    background: var(--accent);
    opacity: 0.9;
}
/* Tab content */
.tab-content {
    max-width: 1500px;
    padding: 1.35rem clamp(1rem, 2.2vw, 2rem) calc(2rem + var(--playback-footer-space));
    margin: 0 auto;
    min-height: 350px;
}
.tab-panel { display: none; }
.tab-panel.active { display: block; animation: fadeIn 0.25s var(--ease); }
@keyframes fadeIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}
/* Shared compact content state — one vocabulary for Loading / Empty / Error
   text slots used by Library, Radio and TIDAL browse. Base padding and type
   stay identical when a slot switches between states, so there is no layout
   jump; the modifier only changes the tone and the loading pulse dot. */
.content-state {
    text-align: center;
    color: var(--text-secondary);
    padding: 2rem 1rem;
    font-size: 0.88rem;
    line-height: 1.5;
}
.content-state--empty {
    color: var(--text-muted);
}
.content-state--error {
    color: var(--danger);
}
.content-state--loading {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.55rem;
}
.content-state--loading::before {
    content: '';
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent);
    opacity: 0.6;
    animation: content-state-pulse 1.6s ease-in-out infinite;
}
@keyframes content-state-pulse {
    0%, 100% { opacity: 0.2; }
    50%      { opacity: 0.7; }
}
/* ============================================================
   Station Cards — Radio tab
   ============================================================ */
.section-title {
    font-size: 1.05rem;
    font-weight: 650;
    letter-spacing: -0.02em;
}
.section-subtitle {
    margin-top: 0.2rem;
    color: var(--text-secondary);
    font-size: 0.92rem;
}

/* ============================================================
   2026 visual refresh — shell, navigation and content rhythm
   (Duplicate base/override rules were folded into their base definitions;
   the rest are refresh-only chrome and responsive refinements.)
   ============================================================ */

.tab-glyph {
    width: 1.05rem;
    display: inline-grid;
    place-items: center;
    color: rgba(110,231,183,0.75);
    font-size: .9rem;
}
.tab-btn[data-tab="spotify"] .tab-glyph { color: #4ed68b; }
.tab-btn[data-tab="radio"] .tab-glyph { color: #7fe2b7; }
.tab-btn.active .tab-glyph { color: var(--accent); }
.manage-overlay {
    position: fixed;
    inset: 0;
    z-index: var(--z-overlay);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.25rem;
}
.manage-overlay-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}
.manage-dialog {
    position: relative;
    width: min(520px, 100%);
    max-height: 85vh;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--bg-hover) transparent;
    background: var(--bg-surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-xl);
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
    padding: 1.1rem;
    touch-action: manipulation;
}
.manage-dialog::-webkit-scrollbar {
    width: 5px;
}
.manage-dialog::-webkit-scrollbar-track {
    background: transparent;
}
.manage-dialog::-webkit-scrollbar-thumb {
    background: var(--bg-hover);
    border-radius: 3px;
}
.manage-dialog-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.8rem;
    margin-bottom: 0.9rem;
}
.manage-dialog-header .section-title {
    font-size: 1.15rem;
}
.manage-dialog-header .section-subtitle {
    margin-top: 0.15rem;
    font-size: 0.9rem;
}

.radio-manage-section {
    display: flex;
    flex-direction: column;
    gap: 0.78rem;
    padding: 0.95rem;
    border-radius: var(--radius-lg);
    border: 1px solid var(--border);
    background: rgba(255,255,255,0.015);
}
.radio-manage-section-header {
    display: flex;
    flex-direction: column;
    gap: 0.16rem;
}
.radio-manage-section-header h3 {
    font-size: 0.97rem;
    font-weight: 700;
    letter-spacing: -0.02em;
}
.radio-manage-section-header p {
    color: var(--text-secondary);
    font-size: 0.84rem;
    line-height: 1.4;
}
.radio-manage-submit-row {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    row-gap: 0.5rem;
    margin-top: 0.1rem;
}
.radio-manage-submit-row .btn-primary {
    min-width: 0;
    width: auto;
}
#station-existing-fields:not(.hidden) {
    display: flex;
    flex-direction: column;
    gap: 0.72rem;
}
.radio-manage-submit-row-station-manage {
    justify-content: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-top: 0.85rem;
}
/* Qobuz/qbzd and TIDAL logins stack above the settings dialog they are launched from. */
.qobuz-login-overlay,
.tidal-login-overlay {
    z-index: calc(var(--z-overlay) + 10);
}
.qobuz-login-overlay .url-input,
.tidal-login-overlay .url-input {
    width: 100%;
}
.qobuz-login-overlay a.btn-primary,
.tidal-login-overlay a.btn-primary {
    text-decoration: none;
    display: inline-flex;
    align-items: center;
}

.settings-dialog {
    width: min(560px, 100%);
}
.settings-stack {
    gap: 0.85rem;
}
.settings-section {
    gap: 0.7rem;
}
.settings-field-group {
    margin-top: 0.1rem;
}
.settings-field-group label {
    display: block;
    margin-bottom: 0.38rem;
    color: var(--text-secondary);
    font-size: 0.82rem;
    font-weight: 600;
}
.settings-inline-note {
    margin-top: 0.45rem;
    color: var(--text-secondary);
    font-size: 0.78rem;
    line-height: 1.4;
}
.settings-inline-note.switching {
    color: var(--accent);
    animation: switching-pulse 1.2s ease-in-out infinite;
}
.settings-routing-label {
    display: block;
    margin-bottom: 0.38rem;
    color: var(--text-secondary);
    font-size: 0.82rem;
    font-weight: 600;
}
.settings-routing-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
    gap: 0.5rem;
}
.settings-routing-cell {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
}
.settings-routing-cell label {
    margin-bottom: 0;
    font-size: 0.75rem;
}
.settings-routing-cell select {
    width: 100%;
}
@keyframes switching-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}
.settings-certificate-note {
    margin: 0.1rem 0 0;
    text-align: right;
}
/* Settings -> Providers: one calm row per provider. */
.settings-providers-list {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}
.settings-provider-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.4rem 0.8rem;
    flex-wrap: wrap;
}
.settings-provider-info {
    display: flex;
    flex-direction: column;
    gap: 0.12rem;
    min-width: 0;
    flex: 1 1 12rem;
}
.settings-provider-toggle {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
}
.settings-provider-toggle input {
    accent-color: var(--accent);
}
.settings-provider-status {
    color: var(--text-secondary);
    font-size: 0.78rem;
}
.settings-provider-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.4rem;
    flex-shrink: 0;
    flex-wrap: wrap;
}
.settings-provider-operation {
    margin-top: 0.45rem;
}
.settings-provider-operation pre {
    margin: 0;
    max-height: 9rem;
    overflow: auto;
    padding: 0.5rem 0.65rem;
    border-radius: 8px;
    background: color-mix(in srgb, var(--text-secondary) 8%, transparent);
    font-size: 0.72rem;
    line-height: 1.45;
    white-space: pre-wrap;
    word-break: break-word;
}
.field-group.settings-device-name-row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}
.settings-device-name-row .url-input {
    flex: 1 1 18rem;
    min-width: 0;
}
.settings-device-name-row .btn-secondary {
    flex: 0 0 auto;
}
.settings-certificate-note a {
    color: var(--text-secondary);
    text-decoration: underline;
    text-underline-offset: 0.18em;
}
.settings-certificate-note a:hover {
    color: var(--accent);
}
.settings-maintenance-status {
    display: grid;
    gap: 0.45rem;
    margin: 0 0 0.75rem;
}
.settings-maintenance-status div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.42rem 0;
    border-bottom: 1px solid rgba(148, 163, 184, 0.16);
}
.settings-maintenance-status dt {
    color: var(--text-secondary);
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.settings-maintenance-status dd {
    min-width: 0;
    margin: 0;
    color: var(--text-primary);
    font-size: 0.86rem;
    font-weight: 700;
    text-align: right;
    overflow-wrap: anywhere;
}
.settings-maintenance-actions {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
    width: min(100%, 420px);
    margin: 0 auto;
}
.settings-maintenance-actions .btn-primary,
.settings-maintenance-actions .btn-secondary {
    width: 100%;
    min-width: 0;
}
.settings-restore-note {
    margin-top: 0.6rem;
    margin-bottom: 0.5rem;
}
#settings-restore-section .btn-danger {
    width: min(100%, 420px);
    display: block;
    margin: 0 auto;
}
.settings-details-toggle {
    appearance: none;
    align-self: center;
    margin-top: 0.68rem;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    font: inherit;
    font-size: 0.78rem;
    font-weight: 700;
    text-decoration: underline;
    text-underline-offset: 0.2em;
    cursor: pointer;
}
.settings-details-toggle:hover {
    color: var(--accent);
}
.settings-update-details {
    margin-top: 0.65rem;
}
.settings-update-log {
    max-height: 220px;
    overflow: auto;
    margin: 0;
    padding: 10px 12px;
    border: 1px solid rgba(148, 163, 184, 0.24);
    border-radius: 6px;
    background: rgba(15, 23, 42, 0.56);
    color: #d1d5db;
    font-size: 0.78rem;
    line-height: 1.45;
    white-space: pre-wrap;
}

.dialog-header-corner-close {
    margin-bottom: 1rem;
    padding-right: 3rem;
}
.dialog-header-corner-close .btn-close-manage {
    position: absolute;
    top: 1rem;
    right: 1rem;
    width: 34px;
    height: 34px;
    min-height: 34px;
    padding: 0;
    align-items: center;
    justify-content: center;
    gap: 0;
    line-height: 1;
}
.dialog-header-corner-close .dialog-close-label {
    display: none;
}
.dialog-header-corner-close .btn-close-manage .btn-ghost-icon {
    font-size: 0.95rem;
    opacity: 0.9;
    line-height: 1;
}

/* ============================================================
   Toasts
   ============================================================ */
.toast-container {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    /* The column owns the width; every toast (incl. the now-playing cue)
       fills it. Phones re-inset the column in _responsive.css. */
    width: min(330px, calc(100% - 2rem));
}
.toast {
    padding: 0.85rem 1.1rem;
    border-radius: var(--radius-sm);
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-left: 3px solid var(--accent);
    box-shadow: 0 8px 24px var(--shadow);
    animation: toastIn 0.3s var(--ease);
    font-size: 0.88rem;
    line-height: 1.4;
}
.toast.success { border-left-color: var(--success); }
.toast.error   { border-left-color: var(--danger); }
.toast.info    { border-left-color: var(--accent); }
.toast.now-playing-cue {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    /* One component, no separate tablet variant: it takes the container's
       width instead of carrying a second fixed value. */
    width: 100%;
    min-width: 0;
    padding: 0.65rem 0.85rem;
}
.now-playing-cover {
    width: 0;
    height: 56px;
    border-radius: 0.7rem;
    object-fit: contain;
    background: var(--bg-elevated);
    flex: 0 0 auto;
    opacity: 0;
    border: 0;
    box-shadow: none;
    transition: width 0.18s var(--ease), opacity 0.18s var(--ease);
}
.now-playing-cue.has-cover .now-playing-cover.is-ready {
    width: 56px;
    opacity: 1;
    border: 1px solid var(--border);
    box-shadow: 0 6px 18px var(--shadow);
}
.now-playing-text {
    min-width: 0;
}
.now-playing-label {
    color: var(--text-muted);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: 0.12rem;
}
.now-playing-title,
.now-playing-meta {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.now-playing-title {
    color: var(--text-primary);
    font-weight: 700;
}
.now-playing-meta {
    color: var(--text-secondary);
    font-size: 0.8rem;
    margin-top: 0.1rem;
}
.toast.remove {
    animation: toastOut 0.25s ease-in forwards;
}
@keyframes toastIn {
    from { opacity: 0; transform: translateX(30px); }
    to   { opacity: 1; transform: translateX(0); }
}
@keyframes toastOut {
    to { opacity: 0; transform: translateX(30px); }
}
/* ── Albums grid ─────────────────────────────────────────────── */
/* Shared tile basis with TIDAL tiles and radio station cards
   (see --tile-* tokens); auto-fit keeps columns equal-width and
   centered instead of stretching the last row edge-to-edge. */
.albums-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(var(--tile-min), var(--tile-min)));
    justify-content: center;
    gap: var(--tile-gap);
    margin-top: 1.25rem;
}
.album-card {
    background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01));
    border: 1px solid rgba(255,255,255,0.07);
    border-radius: var(--radius-lg);
    padding: 0.82rem;
    cursor: pointer;
    transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease), border-color 0.18s var(--ease), background 0.18s var(--ease);
    position: relative;
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    gap: 0.8rem;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    box-shadow: none;
}
.album-art-wrap {
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: var(--radius-md);
    overflow: hidden;
    background: rgba(255,255,255,0.03);
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
}
.album-art {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: contain;
    object-position: center;
    padding: 0.35rem;
    background: rgba(0,0,0,0.08);
}
.album-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.18);
    border-color: rgba(255,255,255,0.14);
    background: linear-gradient(180deg, rgba(255,255,255,0.04), rgba(255,255,255,0.015));
}
.album-card:active {
    transform: scale(0.98) translateY(-1px);
}
.album-card:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.album-card-smart {
    border-color: rgba(74, 222, 128, 0.24);
}
.album-smart-badge {
    position: absolute;
    top: 0.55rem;
    left: 0.55rem;
    z-index: var(--z-base);
    padding: 0.22rem 0.46rem;
    border-radius: 999px;
    border: 1px solid rgba(74, 222, 128, 0.35);
    background: rgba(8, 20, 14, 0.78);
    color: rgba(187, 247, 208, 0.96);
    font-size: 0.68rem;
    font-weight: 800;
    line-height: 1;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
/* Favorite heart on normal album cards — same language as the TIDAL
   .streaming-fav on album tiles: absolute top-right on the cover, semi-
   transparent background, round button. */
.album-card-fav {
    position: absolute;
    top: 1.05rem;
    right: 1.05rem;
    z-index: var(--z-raised);
    width: 32px;
    height: 32px;
    min-height: 32px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.18);
    background: rgba(8, 18, 26, 0.72);
    backdrop-filter: blur(4px);
    color: var(--text-muted);
    font-size: 0.95rem;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    cursor: pointer;
    transition: color .12s var(--ease), border-color .12s var(--ease), transform .12s var(--ease);
    -webkit-tap-highlight-color: transparent;
}
.album-card-fav:hover,
.album-card-fav.is-active { color: var(--accent); border-color: var(--accent); }
.album-card-fav:active { transform: scale(.92); }
.album-card-fav:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* List view: the heart leaves the cover corner and joins the row end. */
.albums-grid.is-list .album-card-fav {
    position: static;
    order: 5;
    z-index: auto;
    width: 34px;
    height: 34px;
    min-height: 34px;
    margin-left: auto;
    background: transparent;
    backdrop-filter: none;
}
.album-name {
    font-weight: 600;
    font-size: 0.98rem;
    color: var(--text-primary);
    line-height: 1.3;
    letter-spacing: -0.015em;
    min-height: 2.55em;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.album-artist {
    font-size: 0.82rem;
    color: var(--text-secondary);
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: -0.4rem;
}

/* ── Albums list view (shared with TIDAL tiles) ──────────────── */
/* Same objects, compact-row presentation: square mini cover left,
   name + subtitle beside it. Only the container layout changes. */
.albums-grid.is-list,
.tidal-tiles.is-list {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 860px;
    margin-left: auto;
    margin-right: auto;
    gap: 0.55rem;
    margin-top: 1rem;
}
.albums-grid.is-list .album-card,
.tidal-tiles.is-list .album-card {
    flex-direction: row;
    align-items: center;
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius-md);
    gap: 0.85rem;
}
.albums-grid.is-list .album-art-wrap,
.tidal-tiles.is-list .album-art-wrap {
    width: 52px;
    height: 52px;
    flex: 0 0 52px;
    border-radius: 10px;
}
.albums-grid.is-list .album-art,
.tidal-tiles.is-list .album-art { padding: 2px; }
.albums-grid.is-list .album-name,
.tidal-tiles.is-list .album-name {
    min-height: 0;
    -webkit-line-clamp: 1;
    font-size: 0.95rem;
}
.albums-grid.is-list .playlist-collage-cell.is-fallback { padding: 8%; }
.albums-grid.is-list .album-smart-badge {
    top: 0.3rem;
    left: 0.3rem;
    font-size: 0.58rem;
}

/* ── Playlist cards + cover collage ─────────────────────────────── */
.playlist-card {
    border-color: rgba(74, 222, 128, 0.18);
}
.playlist-collage {
    position: absolute;
    inset: 0;
    display: grid;
    gap: 2px;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.35);
}
.playlist-collage-cell {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.playlist-collage-cell.is-fallback {
    object-fit: contain;
    padding: 12%;
    opacity: 0.9;
    background: rgba(9, 17, 27, 0.85);
}
.playlist-collage--1 {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr;
}
.playlist-collage--2 {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr;
}
.playlist-collage--3 {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
}
.playlist-collage--3 .playlist-collage-cell:first-child {
    grid-column: 1 / -1;
}
.playlist-collage--4 {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
}
.playlist-collage-fallback {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #080808;
}
.playlist-collage-fallback-mark {
    width: 54%;
    height: 54%;
    opacity: 0.9;
    object-fit: contain;
}
.playlist-detail-cover {
    position: relative;
    overflow: hidden;
    flex-shrink: 0;
}

/* ── Album detail ────────────────────────────────────────────── */
.album-detail {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
/* Baseline detail header grid for the library album/playlist and TIDAL details.
   The artwork-led roots below opt into the larger framed hero composition. */
.album-detail-header,
.streaming-detail-header {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "cover meta back";
    align-items: start;
    gap: 1.2rem;
}
.album-detail-cover,
.streaming-detail-cover {
    grid-area: cover;
}
.album-detail-meta,
.streaming-detail-main {
    grid-area: meta;
    min-width: 0;
}
.album-detail-back {
    grid-area: back;
    align-self: start;
    justify-self: end;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    min-height: 34px;
    padding: 0.26rem 0.56rem;
    border-radius: 7px;
    border: 1px solid rgba(255,255,255,0.08);
    background: transparent;
    color: var(--text-secondary);
    font-size: 0.84rem;
    font-weight: 650;
    font-family: inherit;
    cursor: pointer;
    transition: color 0.15s var(--ease), border-color 0.15s var(--ease), background 0.15s var(--ease), transform 0.1s var(--ease);
    -webkit-tap-highlight-color: transparent;
}
.album-detail-back:hover {
    color: var(--text-primary);
    border-color: rgba(255,255,255,0.16);
    background: rgba(255,255,255,0.04);
}
.album-detail-back:active {
    transform: translateY(1px);
}
.album-detail-back:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.album-detail-cover {
    width: 160px;
    height: 160px;
    border-radius: 14px;
    object-fit: contain;
    background: rgba(255,255,255,0.03);
    border: 1px solid var(--border);
    flex-shrink: 0;
}
.album-detail-meta {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.album-detail-title-row {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
}
.album-detail-name {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0;
    min-width: 0;
}
.album-detail-artist {
    font-size: 1rem;
    color: var(--text-secondary);
    margin: 0;
}
.album-detail-count {
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin: 0;
}
.album-favorite-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    flex: 0 0 auto;
    border: 0;
    background: transparent;
    color: var(--text-secondary);
    font-size: 1.32rem;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
}
.album-favorite-toggle.active {
    color: var(--accent);
}
.album-favorite-toggle:hover {
    color: var(--text-primary);
}
.album-favorite-toggle.active:hover {
    color: var(--accent-hover);
}
.album-favorite-toggle:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 6px;
}

.album-detail-facts {
    display: flex;
    flex-direction: column;
    gap: 0.22rem;
    margin-top: 0.22rem;
    color: var(--text-secondary);
    font-size: 0.86rem;
    line-height: 1.35;
}
.album-detail-about {
    margin-top: 0.42rem;
    color: var(--text-secondary);
    font-size: 0.86rem;
    line-height: 1.38;
}
.album-detail-about p {
    margin: 0.35rem 0 0;
    max-width: 64ch;
}
.detail-fact-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.15rem 0.75rem;
    min-width: 0;
}
.detail-fact-row > span {
    min-width: 0;
    overflow-wrap: anywhere;
}
.detail-fact-row > span + span {
    border-inline-start: 1px solid var(--border-strong);
    padding-inline-start: 0.75rem;
}
.album-detail-about.detail-description {
    width: 100%;
    max-width: 76ch;
    margin-top: 0.35rem;
    padding-top: 0.8rem;
    border-top: 1px solid var(--border-strong);
}
.detail-description p {
    max-width: none;
    margin: 0;
    overflow-wrap: anywhere;
}

/* Artwork-led detail heroes: the local album and playlist details and the
   TIDAL detail roots share the same framed composition. */
.album-detail--hero,
.streaming-detail--hero {
    gap: clamp(1rem, 1.8vw, 1.5rem);
}
.album-detail--hero .detail-hero-header,
.streaming-detail--hero .detail-hero-header {
    position: relative;
    display: grid;
    grid-template-columns: clamp(200px, 22vw, 280px) minmax(0, 1fr) auto;
    grid-template-areas: "cover meta back";
    align-items: center;
    gap: clamp(1.1rem, 2.4vw, 2.4rem);
    min-height: clamp(280px, 24vw, 360px);
    padding: clamp(1rem, 2.2vw, 2rem);
    overflow: hidden;
    isolation: isolate;
    border: 1px solid rgba(255, 255, 255, 0.09);
    border-radius: 24px;
    background: linear-gradient(135deg, rgba(23, 31, 35, 0.96), rgba(13, 14, 18, 0.98) 72%);
    box-shadow: 0 22px 50px rgba(0, 0, 0, 0.26), inset 0 1px 0 rgba(255, 255, 255, 0.035);
}
.detail-hero-header::before,
.detail-hero-header::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
}
.detail-hero-header::before {
    z-index: var(--z-base);
    background:
        linear-gradient(90deg, rgba(10, 13, 17, 0.5), rgba(10, 13, 17, 0.84) 54%, rgba(10, 13, 17, 0.94)),
        linear-gradient(180deg, rgba(6, 8, 11, 0.08), rgba(6, 8, 11, 0.34));
}
.detail-hero-header::after {
    z-index: var(--z-base);
    background: radial-gradient(circle at 14% 20%, rgba(110, 231, 183, 0.12), transparent 34%);
    mix-blend-mode: screen;
    opacity: 0.55;
}
.detail-header-backdrop {
    position: absolute;
    z-index: var(--z-underlay);
    inset: -12%;
    overflow: hidden;
    pointer-events: none;
    opacity: 0.34;
    filter: blur(36px) saturate(1.25);
    transform: scale(1.08);
}
.detail-header-backdrop[hidden] {
    display: none;
}
.detail-header-backdrop:empty {
    display: none;
}
.detail-header-backdrop img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.album-detail--hero .detail-hero-header > :not(.detail-header-backdrop),
.streaming-detail--hero .detail-hero-header > :not(.detail-header-backdrop) {
    position: relative;
    z-index: var(--z-raised);
}
.album-detail--hero .detail-hero-header .detail-hero-cover,
.streaming-detail--hero .detail-hero-header .detail-hero-cover {
    grid-area: cover;
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    min-width: 0;
    align-self: center;
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 20px;
    background: rgba(7, 10, 13, 0.7);
    box-shadow: 0 18px 36px rgba(0, 0, 0, 0.42), 0 0 0 6px rgba(255, 255, 255, 0.018);
}
.album-detail--hero .detail-hero-cover {
    object-fit: cover;
    padding: 0;
}
.streaming-detail--hero .detail-hero-cover img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.streaming-detail--hero .detail-hero-cover:empty {
    display: grid;
    place-items: center;
    background-color: #080808;
    background-image: url('/fxroute/static/artwork-placeholder.svg?v=2');
    background-position: center;
    background-repeat: no-repeat;
    background-size: 100% 100%;
}
.album-detail--hero .detail-hero-meta,
.streaming-detail--hero .detail-hero-meta {
    grid-area: meta;
    align-self: center;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.62rem;
    min-width: 0;
    max-width: 780px;
    padding-bottom: 0.15rem;
}
.album-detail--hero .detail-hero-title-row,
.streaming-detail--hero .detail-hero-title-row {
    display: flex;
    align-items: flex-start;
    gap: 0.7rem;
    width: fit-content;
    max-width: 100%;
    min-width: 0;
}
.album-detail--hero .detail-hero-title,
.streaming-detail--hero .detail-hero-title {
    flex: 0 1 auto;
    min-width: 0;
    color: var(--text-primary);
    font-size: clamp(1.4rem, 2.4vw, 2.6rem);
    font-weight: 720;
    line-height: 1.08;
    letter-spacing: -0.045em;
    overflow-wrap: anywhere;
}
.album-detail--hero .album-detail-artist,
.streaming-detail--hero .tidal-detail-artist {
    color: rgba(236, 236, 240, 0.82);
    font-size: clamp(1rem, 1.55vw, 1.3rem);
    line-height: 1.25;
}
.album-detail--hero .album-detail-count,
.streaming-detail--hero .streaming-detail-facts,
.album-detail--hero .album-detail-facts {
    margin-top: 0;
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.45;
}
.album-detail--hero .album-detail-facts,
.streaming-detail--hero .streaming-detail-facts {
    gap: 0.28rem;
}
.album-detail--hero .album-detail-about,
.streaming-detail--hero .album-detail-about,
.streaming-detail--hero .tidal-artist-about {
    margin-top: 0.15rem;
    color: rgba(208, 211, 219, 0.82);
    font-size: 0.9rem;
    line-height: 1.55;
}
.album-detail--hero .album-favorite-toggle,
.streaming-detail--hero .album-favorite-toggle {
    width: 42px;
    height: 42px;
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 50%;
    background: rgba(7, 10, 13, 0.38);
    color: var(--text-secondary);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}
.album-detail--hero .detail-hero-title-row > .album-favorite-toggle,
.streaming-detail--hero .detail-hero-title-row > .album-favorite-toggle {
    align-self: flex-start;
    margin: 0;
}
.album-detail--hero .album-favorite-toggle:hover,
.streaming-detail--hero .album-favorite-toggle:hover,
.album-detail--hero .album-favorite-toggle.active,
.streaming-detail--hero .album-favorite-toggle.active {
    border-color: rgba(110, 231, 183, 0.62);
    color: var(--accent);
    background: rgba(110, 231, 183, 0.1);
}
.album-detail--hero .detail-hero-header .album-detail-back,
.streaming-detail--hero .detail-hero-header .album-detail-back {
    grid-area: back;
    align-self: start;
    justify-self: end;
    min-height: 38px;
    padding: 0.35rem 0.7rem;
    border-color: rgba(255, 255, 255, 0.13);
    background: rgba(7, 10, 13, 0.34);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}
.streaming-detail--hero #tidal-detail-play {
    min-height: 42px;
    margin-top: 0.25rem;
    padding-inline: 1.05rem;
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.22);
}
.album-detail--hero > .album-detail-tracks,
.streaming-detail--hero > .streaming-results {
    margin-top: 0.2rem;
}
.album-detail-tracks {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.album-detail-tracks .track-item {
    align-items: center;
}
.album-discover {
    margin-top: 0.55rem;
}
.album-discover-panel {
    color: var(--text-secondary);
    font-size: 0.86rem;
}
.album-discover-panel summary {
    position: relative;
    display: inline-flex;
    align-items: baseline;
    gap: 0.45rem;
    padding-left: 1.8rem;
    width: fit-content;
    color: var(--text-primary);
    cursor: pointer;
    font-weight: 650;
    list-style: none;
}
.album-discover-panel summary::-webkit-details-marker {
    display: none;
}
.album-discover-panel summary::before {
    content: "▸";
    position: absolute;
    left: 0.9rem;
    margin-left: 0;
    top: 0.34rem;
    font-size: 0.78rem;
    line-height: 1;
    color: var(--text-secondary);
}
.album-discover-panel[open] summary::before {
    content: "▾";
}
.album-discover-panel summary small {
    color: var(--text-muted);
    font-size: 0.78rem;
    font-weight: 500;
}
.album-discover-list {
    display: grid;
    gap: 0.28rem;
    margin: 0.5rem 0 0;
    padding: 0;
    list-style: none;
}
.album-discover-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.7rem;
    min-height: 2.1rem;
    padding: 0.42rem 0.56rem;
    border: 1px solid var(--border);
    border-radius: 7px;
    background: rgba(15, 23, 42, 0.22);
}
.album-discover-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text-primary);
    font-weight: 600;
}
.track-item-empty {
    justify-content: center;
    color: var(--text-muted);
    font-size: 0.88rem;
    cursor: default;
}
.track-duration {
    align-self: stretch;
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    flex: 0 0 4.4rem;
    padding: 0.8rem 0 0.8rem 0.4rem;
    color: var(--text-secondary);
    font-size: 0.86rem;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    white-space: nowrap;
}

/* ============================================================
   Library tab
   ============================================================ */
#tab-library {
    --control-gap: 12px;
    padding-top: 0.55rem;
}
/* TIDAL shares the library panel top rhythm (0.55rem) so both views start
   at the same height; the provider shell keeps only its bottom spacing. */
#tab-tidal {
    padding-top: 0.55rem;
}
#tab-tidal .streaming-shell {
    padding-top: 0;
}
.library-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.75rem;
    gap: var(--control-gap);
    flex-wrap: wrap;
}
.library-toolbar {
    display: flex;
    align-items: center;
    gap: var(--action-gap);
    flex-wrap: wrap;
}
.library-actions-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--control-gap);
    flex-wrap: nowrap;
    margin: 0.15rem 0 1.15rem;
    /* Same horizontal separator as the TIDAL subbar so both browse headers
       share one underline language. */
    border-bottom: 1px solid var(--border-strong);
    padding-bottom: 0.5rem;
}
.library-view-toggle {
    display: flex;
    align-items: center;
    /* Shrinkable like the TIDAL tabs row so the four tabs wrap instead of
       pushing past the panel edge on narrow screens. */
    flex: 0 1 auto;
    min-width: 0;
}
.library-search-wrap {
    display: flex;
    align-items: center;
    gap: var(--action-gap);
    flex: 0 1 auto;
    margin-left: auto;
    min-width: 0;
}
.library-search-field {
    /* Same width language as the TIDAL search (430px, right-flush via the
       wrap). Definite flex-basis: the wrap shrink-fits its content, so a
       percentage width would have no definite base to resolve against. */
    flex: 0 1 430px;
    width: 430px;
    max-width: 100%;
    min-width: 0;
    position: relative;
}
.library-search-field .library-search-input {
    width: 100%;
    padding-right: 2.1rem;
    font-size: 0.86rem;
}
/* One shared search-field tone for Radio, TIDAL and Library: the same
   opaque background and border on all three inputs, so they render the
   identical gray on every backdrop. The ID selectors (and the doubled
   library class) beat the translucent radio .url-input override by
   specificity, regardless of file load order. The background stays pinned
   in every state (no :focus rule touches it), while the border is only
   pinned while unfocused: during :focus the accent border must win, or the
   ID specificity would suppress it. */
#station-search,
#tidal-search-input,
.library-search-field .library-search-input {
    background: var(--bg-input);
}
#station-search:not(:focus),
#tidal-search-input:not(:focus),
.library-search-field .library-search-input:not(:focus) {
    border-color: var(--border);
}
.library-search-input::-webkit-search-cancel-button,
.library-search-input::-webkit-search-decoration {
    appearance: none;
    -webkit-appearance: none;
}
.library-search-clear {
    position: absolute;
    right: 0.32rem;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.55rem;
    height: 1.55rem;
    border: 0;
    border-radius: 999px;
    background: var(--border);
    color: var(--text-secondary);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.42;
    -webkit-tap-highlight-color: transparent;
}
.library-search-clear:not(:disabled) {
    opacity: 1;
}
.library-search-clear:not(:disabled):hover {
    background: var(--border-strong);
    color: var(--text-primary);
}
.library-search-clear:disabled {
    cursor: default;
}
.library-search-clear:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.library-selection-toolbar {
    display: flex;
    align-items: center;
    gap: var(--action-gap);
    flex-wrap: nowrap;
    flex: 0 0 auto;
}
/* An emptied toolbar (every action hidden, e.g. Select-all in albums
   mode) collapses so the wrap gap cannot indent the search field. */
.library-selection-toolbar:not(:has(> :not(.hidden))) {
    display: none;
}
.library-selection-toolbar .btn-secondary {
    min-width: 118px;
}
.playlist-save-row {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    margin-bottom: 0.75rem;
    flex-wrap: nowrap;
    overflow: hidden;
    width: 100%;
}
.playlist-save-controls {
    display: flex;
    align-items: center;
    gap: var(--control-gap);
    min-width: 0;
    flex: 1 1 auto;
    width: 100%;
}
.playlist-save-controls #save-playlist {
    min-width: 74px;
}
.playlist-save-row .url-input {
    flex: 1 1 0;
    min-width: 140px;
    font-size: 0.88rem;
    padding: 0.3rem 0.6rem;
}
.playlist-save-row .btn-secondary {
    flex: 0 0 auto;
    white-space: nowrap;
}
/* TIDAL save row: the library save concept extended with the "add to
   existing playlist" target, so the row wraps instead of clipping. */
.tidal-playlist-save-row {
    flex-wrap: wrap;
    overflow: visible;
    gap: var(--action-gap);
}
/* Compact and left-aligned like the library save row: the controls sit at
   the row start with a uniform 12px gap (--action-gap). Single line on
   roomy viewports; the responsive rules switch to wrapping when the tab
   runs out of width. --control-gap is scoped to the library tab, so the
   TIDAL row pins its own spacing instead of silently collapsing. */
.tidal-playlist-save-row .playlist-save-controls {
    flex: 0 1 auto;
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: var(--action-gap);
}
.tidal-playlist-save-row .url-input[type="text"] {
    flex: 0 1 160px;
}
.tidal-playlist-save-row select.url-input {
    flex: 0 1 200px;
}
/* Album detail: the playlist action row uses the full content width. The two
   text/select fields absorb the extra space (existing target slightly wider);
   Save as new, Add and Cancel keep their compact natural button widths. */
.playlist-save-row.tidal-playlist-save-row--album {
    width: 100%;
    max-width: none;
    flex: 1 1 auto;
}
.tidal-playlist-save-row--album .playlist-save-controls {
    flex: 1 1 auto;
    width: 100%;
    max-width: none;
    flex-wrap: nowrap;
    align-items: center;
}
.tidal-playlist-save-row--album #tidal-playlist-name {
    flex: 1 1 0;
    min-width: 140px;
}
.tidal-playlist-save-row--album #tidal-playlist-target {
    flex: 1.25 1 0;
    min-width: 170px;
}
.tidal-playlist-save-row--album .btn-secondary {
    flex: 0 0 auto;
    white-space: nowrap;
}
.tidal-playlist-save-error {
    flex: 0 0 100%;
    color: var(--danger);
    font-size: 0.84rem;
    margin-top: 0.15rem;
}
.playlist-item {
    position: relative;
}
.playlist-download-btn,
.playlist-delete-btn,
.folder-action-btn--delete {
    flex: 0 0 auto;
    align-self: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: transparent;
    color: var(--text-muted);
    font-size: 0.82rem;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    transition: color .12s var(--ease), border-color .12s var(--ease), background .12s var(--ease);
}
.playlist-download-btn:hover {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-dim);
}
.playlist-delete-btn:hover,
.folder-action-btn--delete:hover {
    color: var(--danger);
    border-color: var(--danger);
    background: var(--danger-dim);
}
.playlist-download-btn:focus-visible,
.playlist-delete-btn:focus-visible,
.folder-action-btn--delete:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.library-import-panel {
    margin-bottom: 0.85rem;
}
.import-card {
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 1rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.import-form-row {
    margin-bottom: 0;
}
#library-info {
    font-size: 0.85rem;
    color: var(--text-muted);
    margin-top: 0.75rem;
}
.library-folder-path {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin: 0 0 0.6rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}
.library-folder-path button {
    border: 1px solid var(--border);
    background: var(--bg-surface);
    color: var(--text-primary);
    border-radius: 999px;
    padding: 0.25rem 0.55rem;
    cursor: pointer;
}
.library-folder-path button:hover {
    background: var(--bg-hover);
}
.library-folder-back {
    margin-left: auto;
    flex: 0 0 auto;
    min-height: 34px;
    padding: 0.26rem 0.56rem;
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 7px;
    background: transparent;
    color: var(--text-secondary);
    font: inherit;
    font-size: 0.84rem;
    font-weight: 650;
    cursor: pointer;
    white-space: nowrap;
}
.library-folder-back:hover {
    color: var(--text-primary);
    border-color: rgba(255,255,255,0.16);
    background: rgba(255,255,255,0.04);
}
.library-folder-back:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.folder-actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    flex-shrink: 0;
    opacity: 0.72;
    transition: opacity 0.15s var(--ease);
}
.folder-item:hover .folder-actions,
.folder-actions:focus-within {
    opacity: 1;
}
.folder-action-btn {
    width: 30px;
    height: 30px;
    border-radius: 999px;
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 0.82rem;
    line-height: 1;
}
.folder-action-btn:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
    border-color: var(--border);
}
.folder-action-btn:focus-visible {
    color: var(--text-primary);
    background: var(--bg-hover);
    border-color: var(--border);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.track-item {
    display: flex;
    align-items: stretch;
    gap: 0.75rem;
    min-height: 52px;
    border-bottom: 1px solid var(--border);
    position: relative;
    padding: 0 0.8rem;
    background: var(--bg-surface);
    cursor: pointer;
    transition: background 0.15s var(--ease);
    user-select: none;
    -webkit-tap-highlight-color: transparent;
}
.track-item:last-child { border-bottom:none; }
.track-item:hover { background: var(--bg-hover); }
.track-item.selected { background: rgba(110, 231, 255, 0.08); }
.track-item.active {
    background: var(--accent-dim);
    box-shadow: inset 0 0 0 1px rgba(110, 231, 183, 0.32);
}
.track-item.active .track-title {
    color: #f0fff8;
}
.track-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.92rem;
    font-weight: 500;
}
.track-artist {
    font-size: 0.82rem;
    color: var(--text-secondary);
    min-width: 90px;
    text-align: right;
    flex-shrink: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.album-detail-tracks .track-row-favorite {
    margin-left: .1rem;
}

/* ============================================================
   Library list rows — shared card language with the album detail
   (rounded bordered rows, stacked title/sub, round play + heart).
   Applies to the Tracks / Folders / Playlist lists only; the Albums
   grid and the album-detail rows keep their existing rules.
   ============================================================ */
#tracks-list {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
#tracks-list .track-item {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.45rem 0.6rem;
    border-radius: var(--radius-md);
    background: var(--bg-surface);
    border: 1px solid var(--border);
    cursor: pointer;
    min-height: 0;
    min-width: 0;
    transition: background 0.12s var(--ease), border-color 0.12s var(--ease);
}
#tracks-list .track-item:hover {
    background: var(--bg-hover);
    border-color: var(--border-strong);
}
#tracks-list .track-item.selected {
    background: var(--accent-dim);
    border-color: rgba(110, 231, 183, 0.35);
}
#tracks-list .track-item.active {
    background: var(--accent-dim);
    border-color: rgba(110, 231, 183, 0.45);
}
#tracks-list .track-item.active .track-play {
    color: var(--accent);
    border-color: var(--accent);
}
#tracks-list .track-item.active .track-title {
    color: #f0fff8;
}
#tracks-list .track-item .track-info {
    flex: 1;
    min-width: 0;
    gap: 0.12rem;
}
#tracks-list .track-artist {
    text-align: left;
    min-width: 0;
    flex-shrink: 1;
    font-size: 0.78rem;
    color: var(--text-muted);
}
#tracks-list .folder-item,
#tracks-list .playlist-item {
    align-items: center;
}
#tracks-list .folder-actions {
    opacity: 0;
}
#tracks-list .folder-item:hover .folder-actions,
#tracks-list .folder-actions:focus-within {
    opacity: 1;
}

/* Small square album-cover thumbnail on the left of a track row, shared
   with the streaming track rows. */
.track-thumb {
    width: 42px;
    height: 42px;
    flex: 0 0 auto;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--bg-elevated);
    display: flex;
    align-items: center;
    justify-content: center;
}
.track-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.track-thumb:empty {
    background-color: #080808;
    background-image: url('/fxroute/static/artwork-placeholder.svg?v=2');
    background-position: center;
    background-repeat: no-repeat;
    background-size: 100% 100%;
}

/* ============================================================
   Download / import shared
   ============================================================ */
.download-form {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 1rem;
    flex-wrap: wrap;
}
.library-import-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 0.95rem;
    align-items: stretch;
}
.library-import-option {
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.library-import-option .upload-area {
    min-height: 124px;
    height: 100%;
    flex: 1;
    box-sizing: border-box;
}
/* Shared three-row interior for both import tiles: icon row, main-text
   row, sub-text row — one rule set, so both zones share height,
   typography, line-height and vertical rhythm exactly. */
.upload-area-import {
    display: grid;
    grid-template-rows: auto auto auto;
    align-content: center;
    justify-items: center;
    gap: 0.35rem;
    min-height: 124px;
    height: 100%;
    box-sizing: border-box;
    margin-bottom: 0;
    padding: 1rem 1rem 0.95rem;
    border-width: 2px;
    border-style: dashed;
    background: linear-gradient(180deg, rgba(110,231,183,0.08), rgba(110,231,183,0.05));
}
.upload-area-import .upload-area-icon {
    display: inline-flex;
    align-items: center;
    height: 1.4rem;
    font-size: 1.4rem;
    line-height: 1;
}
.upload-area-import .upload-area-icon svg {
    width: 1.4rem;
    height: 1.4rem;
}
.upload-area-import .upload-area-text {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 2.6em;
    margin: 0;
    padding: 0;
    color: var(--text-primary);
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.3;
    text-align: center;
}
.upload-area-import .upload-area-filename {
    display: block;
    min-height: 1.2em;
    margin: 0;
    padding: 0;
    color: var(--text-secondary);
    font-size: 0.85rem;
    font-weight: 500;
    line-height: 1.35;
    text-align: center;
}
.upload-area-url-station .upload-area-text {
    min-height: 2.6em;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.3;
}
.upload-area-url-station .upload-area-filename {
    min-height: 1.2em;
    color: var(--text-secondary);
    font-size: 0.85rem;
    font-weight: 500;
    line-height: 1.35;
}
.upload-area-url {
    margin-bottom: 0.75rem;
    padding: 1rem 1rem 0.95rem;
    border-style: solid;
    background: linear-gradient(180deg, rgba(110,231,183,0.05), rgba(110,231,183,0.04));
}
.upload-area-url-primary {
    min-height: 124px;
    border-width: 2px;
    border-style: dashed;
    background: linear-gradient(180deg, rgba(110,231,183,0.08), rgba(110,231,183,0.05));
}
.upload-area-file-primary {
    min-height: 124px;
}
.upload-area-url-station {
    min-height: 112px;
    border-width: 2px;
    border-style: dashed;
    background: linear-gradient(180deg, rgba(110,231,183,0.08), rgba(110,231,183,0.05));
}
.upload-area-url .upload-area-icon {
    font-size: 1.1rem;
}
.upload-area-url-primary .upload-area-icon {
    font-size: 1.4rem;
}
.upload-area-url-station .upload-area-icon {
    font-size: 1.45rem;
}
.upload-area-url .upload-area-text,
.upload-area-url-station .upload-area-text {
    color: var(--text-primary);
}
.upload-area-text-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0.015;
    border: 0;
    background: transparent;
    color: transparent;
    cursor: text;
    z-index: var(--z-raised);
}
.upload-area-text-input:focus {
    outline: none;
}
.library-import-cancel-row {
    justify-content: flex-end;
    margin-top: -0.1rem;
}

.download-form .btn-primary,
.download-form .btn-secondary,
.download-form .btn-danger {
    min-width: fit-content;
}
.url-input {
    flex: 1;
    max-width: 100%;
    min-width: 200px;
    padding: 0.7rem 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: 0.95rem;
    font-family: inherit;
    transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
    box-sizing: border-box;
    min-height: 44px;
}
.url-input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-dim);
}
.url-input::placeholder { color: var(--text-muted); }
.download-status {
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 1.1rem 1.25rem;
    min-height: 80px;
    font-size: 0.9rem;
}
.library-import-panel .download-status {
    min-height: 0;
}
.download-progress { margin-bottom: 0.5rem; }
.progress-bar {
    width: 100%;
    height: 6px;
    background: var(--bg-elevated);
    border-radius: 3px;
    overflow: hidden;
    margin: 0.6rem 0;
}
.progress-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--accent), var(--accent-hover));
    border-radius: 3px;
    transition: width 0.3s var(--ease);
    width: 0%;
}

/* =========================================================================
   Spotify tab: the tab renders through the shared streaming shell today
   (static/streaming.js .streaming-shell), so the legacy in-tab player rules
   are gone. No provider-specific panel offset may exist — Spotify and Qobuz
   must start at the same height.
   ========================================================================= */

/* ============ Cover detail card (shared radio/library) ============ */
.cover-detail-backdrop {
    position: fixed;
    inset: 0;
    z-index: var(--z-cover-detail-backdrop);
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}
.cover-detail-card {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: var(--playback-footer-space, calc(102px + 8px + 14px));
    z-index: var(--z-cover-detail);
    width: min(720px, calc(100% - 2rem));
    max-height: calc(100vh - var(--playback-footer-space, calc(102px + 8px + 14px)) - 1rem);
    max-height: calc(100dvh - var(--playback-footer-space, calc(102px + 8px + 14px)) - 1rem);
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--bg-hover) transparent;
    background: var(--bg-surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-xl);
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
    padding: 0.95rem;
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    grid-template-areas:
        "cover info"
        "cover history"
        "cover queue";
    gap: 0.85rem 1.1rem;
    align-items: start;
    touch-action: manipulation;
}
/* Wide layout, local playback with an active queue: move the whole meta
   block (incl. tech line and tag-info block) under the cover into the left
   column; the right column then holds only the queue heading + list.
   Radio, library without a queue and the narrow layout keep the original
   arrangement (queue section carries .hidden when no queue is active). */

.cover-detail-cover-col {
    grid-area: cover;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    min-width: 0;
}
.cover-detail-cover {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: var(--radius-lg);
    background: var(--bg-hover);
    display: block;
}
.cover-detail-extra {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    font-size: 0.78rem;
    color: var(--text-muted);
    line-height: 1.35;
    min-width: 0;
}
.cover-detail-extra-line {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cover-detail-info {
    grid-area: info;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.cover-detail-source {
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--accent);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cover-detail-title {
    font-size: 1.15rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--text-primary);
    overflow-wrap: anywhere;
}
.cover-detail-artist {
    font-size: 0.95rem;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cover-detail-album {
    font-size: 0.85rem;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cover-detail-tech {
    font-size: 0.8rem;
    color: var(--text-muted);
    font-family: var(--font-mono, monospace);
    margin-top: 0.15rem;
}
.cover-detail-section {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    min-width: 0;
}
.cover-detail-heading {
    margin: 0;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-secondary);
}
.cover-detail-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.cover-detail-row {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.38rem 0.55rem;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.06);
    min-width: 0;
}
.cover-detail-row.current {
    background: var(--accent-dim);
    border-color: var(--accent);
}
/* Library queue rows are interactive (jump to index via canonical play path).
   Radio "Recently played" rows stay non-interactive. */
.cover-detail-row[data-queue-index] {
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.cover-detail-row[data-queue-index]:hover {
    background: rgba(255, 255, 255, 0.07);
    border-color: rgba(255, 255, 255, 0.16);
}
.cover-detail-row[data-queue-index]:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
    background: rgba(255, 255, 255, 0.06);
}
.cover-detail-row[data-queue-index].current:hover {
    background: var(--accent-dim);
    border-color: var(--accent);
    cursor: default;
}
.cover-detail-row-index {
    flex: 0 0 auto;
    font-size: 0.78rem;
    color: var(--text-muted);
    min-width: 1.4rem;
    text-align: right;
}
.cover-detail-row-current-mark {
    flex: 0 0 auto;
    color: var(--accent);
    font-size: 0.8rem;
}
.cover-detail-row-body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
}
.cover-detail-row-title {
    font-size: 0.92rem;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cover-detail-row-artist {
    font-size: 0.8rem;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
#cover-detail-history {
    grid-area: history;
}
#cover-detail-queue {
    grid-area: queue;
}
.cover-detail-card::-webkit-scrollbar {
    width: 5px;
}
.cover-detail-card::-webkit-scrollbar-track {
    background: transparent;
}
.cover-detail-card::-webkit-scrollbar-thumb {
    background: var(--bg-hover);
    border-radius: 3px;
}
.radio-panel {
    background: rgba(22, 22, 26, 0.72);
    border: 1px solid rgba(255, 255, 255, 0.065);
    border-radius: 22px;
    padding: clamp(1rem, 1.7vw, 1.45rem);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.018);
}
.radio-panel-header {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(420px, 820px) minmax(0, 1fr);
    align-items: center;
    gap: 0.8rem;
    margin-bottom: 1.45rem;
}
.radio-panel-header .section-title {
    margin: 0;
}
/* Narrow panels: put the search on its own row so the action buttons on the
   right never push the header past the viewport (base grid keeps a 420px
   search minimum, which overflows at 601-660px). Mirrors the <=600px rules. */

.radio-search-field {
    width: 100%;
    max-width: 820px;
    justify-self: center;
    display: flex;
    flex-direction: column;
    gap: 0.42rem;
}
.radio-search-input-wrap {
    position: relative;
    min-width: 0;
}
.station-search-input {
    width: 100%;
    padding: 0.55rem 2.1rem 0.55rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: 0.86rem;
    font-family: inherit;
    outline: none;
    transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
    box-sizing: border-box;
    height: 44px;
}
.station-search-input::-webkit-search-cancel-button,
.station-search-input::-webkit-search-decoration {
    appearance: none;
    -webkit-appearance: none;
}
.station-search-input::placeholder {
    color: var(--text-muted);
}
.station-search-input:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-dim);
}
.station-search-clear {
    position: absolute;
    right: 0.32rem;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.55rem;
    height: 1.55rem;
    border: 0;
    border-radius: 999px;
    background: var(--border);
    color: var(--text-secondary);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.42;
    -webkit-tap-highlight-color: transparent;
}
.station-search-clear:not(:disabled) {
    opacity: 1;
}
.station-search-clear:not(:disabled):hover {
    background: var(--border-strong);
    color: var(--text-primary);
}
.station-search-clear:disabled {
    cursor: default;
}
.station-search-clear:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.radio-header-right {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-shrink: 0;
    justify-self: end;
}
.btn-icon-only {
    padding: 0.5rem;
    min-width: 44px;
}
.radio-station-sections {
    display: flex;
    flex-direction: column;
    gap: 1.6rem;
}
.station-catalog-section {
    margin: 0;
    position: relative;
}
.station-catalog-summary {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.7rem 3rem 0.7rem 0;
    color: var(--text-primary);
    cursor: pointer;
    user-select: none;
}
.station-catalog-summary:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 6px;
}
.station-catalog-summary::marker {
    content: '';
}
.station-catalog-summary::-webkit-details-marker {
    display: none;
}
.station-catalog-summary > span:first-child {
    font-size: 0.95rem;
    font-weight: 700;
}
.station-catalog-summary-hint {
    color: var(--text-secondary);
    font-size: 0.8rem;
    font-weight: 400;
}
.station-catalog-toggle {
    position: absolute;
    top: 50%;
    right: 0;
    transform: translateY(-50%);
    width: 2.25rem;
    height: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    color: var(--text-primary);
    pointer-events: none;
    transition: color 0.16s ease;
}
.station-catalog-section[open] .station-catalog-toggle {
    color: var(--accent);
}
.station-catalog-toggle svg {
    width: 1.25rem;
    height: 1.25rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.25;
    stroke-linecap: round;
    stroke-linejoin: round;
    transition: transform 0.18s ease;
}
.station-catalog-section[open] .station-catalog-toggle svg {
    transform: rotate(180deg);
}
.station-catalog-content {
    padding-top: 0.45rem;
}
.station-catalog-groups {
    display: flex;
    flex-direction: column;
    gap: 1.45rem;
}
.station-catalog-group {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
.station-catalog-group-title {
    margin: 0;
    color: var(--text-primary);
    font-size: 0.9rem;
    font-weight: 700;
}
.radio-search-results {
    gap: 0.55rem;
}
.radio-search-groups {
    display: flex;
    flex-direction: column;
    gap: 1.1rem;
}
.station-result-group {
    display: flex;
    flex-direction: column;
    gap: 0.72rem;
}
.station-result-group + .station-result-group {
    padding-top: 1.1rem;
    border-top: 1px solid var(--border);
}
.station-result-group-header {
    display: flex;
    align-items: baseline;
    gap: 0.65rem;
}
.station-result-group-header h4 {
    margin: 0;
    color: var(--text-primary);
    font-size: 0.92rem;
    font-weight: 700;
}
.station-result-group-header span {
    color: var(--text-secondary);
    font-size: 0.78rem;
}
.radio-search-results .station-name {
    min-height: calc(1.3em * 2);
}
.radio-search-results .online-station-meta {
    min-height: calc(1.3em * 2);
}
.catalog-station-card .station-name {
    min-height: calc(1.3em * 2);
}
.catalog-station-card .catalog-station-action {
    margin-top: auto;
}
.radio-station-section {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}
.radio-station-section + .radio-station-section {
    padding-top: 1.35rem;
    border-top: 1px solid var(--border);
}
.radio-station-section-header h3 {
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: -0.02em;
}
.radio-station-section-header p {
    margin-top: 0.16rem;
    color: var(--text-secondary);
    font-size: 0.84rem;
}
.btn-manage-trigger {
    flex-shrink: 0;
}
.btn-ghost {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-primary);
    cursor: pointer;
    font-size: 0.82rem;
    font-weight: 500;
    font-family: inherit;
    min-height: 44px;
    padding: 0.5rem 1rem;
    border-radius: var(--radius-sm);
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    transition: color 0.15s var(--ease), background 0.15s var(--ease), border-color 0.15s var(--ease);
    user-select: none;
    -webkit-tap-highlight-color: transparent;
}
.btn-ghost:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
}
.btn-ghost:active {
    transform: scale(0.96);
}
.btn-primary:focus-visible,
.btn-secondary:focus-visible,
.btn-ghost:focus-visible,
.btn-danger:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.btn-ghost-icon {
    font-size: 0.88rem;
    opacity: 0.7;
    transition: opacity 0.15s var(--ease);
}
.btn-ghost:hover .btn-ghost-icon {
    opacity: 1;
}
.btn-close-manage {
    padding: 0.3rem 0.55rem;
    font-size: 0.8rem;
}
.stations-grid {
    display: grid;
    /* Shared tile basis (narrower radio derivative token) so stations,
       albums and TIDAL tiles keep one size rhythm across breakpoints. */
    grid-template-columns: repeat(auto-fill, minmax(var(--tile-min-radio), 1fr));
    justify-content: stretch;
    gap: var(--tile-gap);
}
.station-card {
    background: linear-gradient(180deg, rgba(255,255,255,0.028), rgba(255,255,255,0.012));
    border: 1px solid rgba(255,255,255,0.07);
    border-radius: var(--radius-lg);
    padding: .7rem;
    cursor: pointer;
    transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease), border-color 0.18s var(--ease), background 0.18s var(--ease);
    position: relative;
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    gap: .68rem;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    box-shadow: none;
}
.station-art-wrap {
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: var(--radius-md);
    overflow: hidden;
    background: rgba(255,255,255,0.03);
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
}
.station-art-wrap--real {
    background:
        radial-gradient(circle at top right, rgba(255,255,255,0.08), transparent 34%),
        linear-gradient(180deg, rgba(255,255,255,0.05), rgba(0,0,0,0.16));
    border-color: rgba(255,255,255,0.08);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);
}
.station-art-wrap--real::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(255,255,255,0.035), transparent 36%, rgba(0,0,0,0.1));
}
.station-art-wrap--fallback {
    background: rgba(255,255,255,0.03);
}
.station-art {
    width: 100%;
    height: 100%;
    display: block;
    object-position: center;
    background: rgba(0,0,0,0.08);
}
.station-art--real {
    object-fit: contain;
    padding: 0.35rem;
}
.station-art--fallback {
    object-fit: contain;
    padding: 0.45rem;
}
.station-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.18);
    border-color: rgba(255,255,255,0.14);
    background: linear-gradient(180deg, rgba(255,255,255,0.04), rgba(255,255,255,0.015));
}
.station-card:active {
    transform: scale(0.98) translateY(-1px);
}
/* Keyboard focus */
.station-card:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
/* Touch feedback: subtle ripple-like press */
@supports (-webkit-tap-highlight-color: transparent) {
    .station-card {
        touch-action: manipulation;
    }
}
.station-card.active::after {
    content: '♫';
    position: absolute;
    top: 0.7rem;
    right: 0.8rem;
    font-size: 0.96rem;
    color: var(--accent);
    animation: pulse 1.5s ease-in-out infinite;
    display: none;
}
@keyframes pulse {
    0%, 100% { opacity: 0.6; }
    50% { opacity: 1; }
}
.station-name {
    font-weight: 600;
    font-size: .95rem;
    color: var(--text-primary);
    line-height: 1.3;
    letter-spacing: -0.015em;
    min-height: auto;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.catalog-station-card {
    cursor: default;
}
.catalog-station-card:hover {
    transform: none;
}
.catalog-station-action {
    width: 100%;
    min-height: 36px;
    padding: 0.48rem 0.65rem;
    border: 1px solid var(--accent);
    border-radius: var(--radius-sm);
    background: var(--accent-dim);
    color: var(--text-primary);
    font: inherit;
    font-size: 0.8rem;
    font-weight: 700;
    cursor: pointer;
}
.catalog-station-action:hover:not(:disabled) {
    background: var(--accent);
    color: var(--bg-primary);
}
.catalog-station-action:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.catalog-station-action--saved {
    border-color: var(--border);
    background: rgba(255,255,255,0.035);
    color: var(--text-secondary);
    cursor: default;
}
/* Station favorite heart — same language as the Library .album-card-fav and
   the TIDAL .streaming-fav on tiles: absolute top-right on the cover,
   semi-transparent round button, muted when unsaved, green when in
   My Stations. */
.station-card-fav {
    position: absolute;
    top: 0.95rem;
    right: 0.95rem;
    z-index: var(--z-raised);
    width: 32px;
    height: 32px;
    min-height: 32px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.18);
    background: rgba(8, 18, 26, 0.72);
    backdrop-filter: blur(4px);
    color: var(--text-muted);
    font-size: 0.95rem;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    cursor: pointer;
    transition: color .12s var(--ease), border-color .12s var(--ease), transform .12s var(--ease);
    -webkit-tap-highlight-color: transparent;
}
.station-card-fav:hover,
.station-card-fav.is-active { color: var(--accent); border-color: var(--accent); }
.station-card-fav:active { transform: scale(.92); }
.station-card-fav:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.station-card-fav:disabled { opacity: .45; cursor: wait; }
.station-browser-status {
    min-height: 1.25rem;
    color: var(--text-secondary);
    font-size: 0.84rem;
}
.online-station-meta {
    min-height: calc(1.3em * 2);
    color: var(--text-secondary);
    font-size: 0.76rem;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.radio-manage-stack {
    gap: 0.8rem;
}

.station-search-input,
.url-input {
    border-color: rgba(255,255,255,.075);
    background: rgba(255,255,255,.035);
}

.station-card.active {
    border-color: rgba(110,231,183,.55);
    background: linear-gradient(180deg, rgba(110,231,183,.07), rgba(255,255,255,.014));
    box-shadow: inset 0 0 0 1px rgba(110,231,183,.08);
}
/* =========================================================================
   Responsive — consolidated (Task 4)
   Playback: 3 canonical ranges (desktop/tablet/phone) + shared grouped by range
   ========================================================================= */
/* =========================================================================
   Streaming provider tabs (Spotify / Qobuz / TIDAL)
   ========================================================================= */
.streaming-shell {
    padding: 0.7rem 0;
}
.streaming-provider {
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
}

/* Player pages (Spotify/Qobuz) share one top-anchored stage: the now-playing
   card starts at the top of the stage, so both pages have the same vertical
   geometry no matter how their metadata heights differ. The provider status
   lives inside the card (top-right chip); catalog providers (TIDAL) keep a
   full-width browser surface with the standalone status line. */
.streaming-provider-player {
    min-height: calc(100dvh - 18rem);
    justify-content: flex-start;
}

/* The shared hidden contract for every streaming component: the per-element
   display rules below (flex/grid) must never override the JS-toggled hidden
   attribute, otherwise empty state and now-playing card show at the same
   time. Scoped to the streaming shell, provider-neutral. */
.streaming-provider [hidden] {
    display: none !important;
}

/* Empty / not-connected state — one shared disconnected card for
   Spotify/Qobuz (.streaming-empty) and TIDAL (.streaming-auth--disconnected):
   same width, padding, centering, heading/text sizes and primary button. */
.streaming-empty,
.streaming-auth--disconnected {
    width: min(100%, 560px);
    margin: 0 auto;
    padding: 1.5rem 1.5rem 1.7rem;
    text-align: center;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    /* Standby/disconnected is not an active state: neutral edge like the DSP cards. */
    border-top: 3px solid var(--border-strong);
    border-radius: var(--radius-lg);
}
.streaming-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
.streaming-auth--disconnected {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0;
}
.streaming-empty-icon {
    font-size: 2.25rem;
    margin-bottom: 0.5rem;
    opacity: 0.4;
}
.streaming-empty-title,
.streaming-auth--disconnected .streaming-auth-title {
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0;
}
.streaming-empty-msg,
.streaming-auth--disconnected .streaming-auth-hint {
    color: var(--text-muted);
    font-size: 0.88rem;
    margin: 0.3rem 0 0;
    line-height: 1.45;
    max-width: 34rem;
}
.streaming-empty-actions,
.streaming-auth--disconnected .streaming-auth-actions--primary {
    margin-top: 1rem;
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
}
/* Subordinate second login option: plain text action with a muted quality
   note underneath — deliberately not a second equal-rank button. */
.streaming-auth-alternative {
    margin-top: 0.9rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
}
.streaming-auth-secondary {
    background: transparent;
    border: 0;
    padding: 0.25rem 0.5rem;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 0.2em;
    cursor: pointer;
}
.streaming-auth-secondary:hover { color: var(--text-secondary); }
.streaming-auth-secondary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.streaming-auth-note {
    color: var(--text-muted);
    font-size: 0.78rem;
    line-height: 1.45;
    margin: 0;
    max-width: 34rem;
}

/* Now-playing card — the shared player composition for Spotify/Qobuz. A
   compact, centered single-column player: cover on top, metadata, transport
   and a progress bar that stops well short of the card edges. Quality facts
   live in the global footer meta-tag, not in the card. */
.streaming-now-playing {
    width: 100%;
    max-width: 560px;
    margin: 0 auto;
    position: relative;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    /* Active playback keeps the mint edge (same logic as the DSP A/B card). */
    border-top: 3px solid var(--accent);
    border-radius: var(--radius-lg);
    padding: 1.5rem 1.5rem 1.7rem;
    display: grid;
    grid-template-columns: 1fr;
    grid-template-areas:
        "header"
        "cover"
        "meta"
        "controls"
        "secondary"
        "progress";
    justify-items: center;
    text-align: center;
    gap: 0.7rem;
}
/* Card header row: provider name left, status chip right — one calm,
   symmetric line inside the card. Replaces the standalone page titles that
   used to sit above the card. */
.streaming-card-header {
    grid-area: header;
    width: 100%;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}
.streaming-provider-name {
    min-width: 0;
    font-size: 0.8rem;
    font-weight: 650;
    letter-spacing: 0.03em;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Shared connected-status pill for every streaming provider: one compact,
   restrained status language in the Spotify/Qobuz card header and the TIDAL
   browse toolbar. The mint dot is the only accent; the label stays muted gray
   and the pill is clearly smaller and calmer than an action button (same
   typography, height, radius and spacing everywhere). The provider/backend
   detail lives in the tooltip. */
.streaming-status {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.32rem;
    max-width: 62%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    color: var(--text-muted);
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 0.1rem 0.55rem;
}
.streaming-status::before {
    content: '';
    flex: 0 0 auto;
    width: 0.42rem;
    height: 0.42rem;
    border-radius: 50%;
    background: var(--accent);
}
.streaming-cover-wrap {
    grid-area: cover;
    display: flex;
    justify-content: center;
}
.streaming-cover {
    width: 200px;
    height: 200px;
    border-radius: var(--radius-md);
    object-fit: cover;
    background: var(--bg-elevated);
    box-shadow: 0 4px 20px rgba(0,0,0,0.35);
}
.streaming-meta {
    grid-area: meta;
    min-width: 0;
    width: 100%;
    align-self: center;
}
.streaming-title {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.streaming-artist {
    font-size: 0.95rem;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-top: 0.2rem;
}
.streaming-album {
    font-size: 0.85rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-top: 0.2rem;
}
/* Transport */
.streaming-controls {
    grid-area: controls;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.15rem;
}
.streaming-btn {
    background: var(--bg-elevated);
    border: 1.5px solid var(--border-strong);
    color: var(--text-primary);
    border-radius: 50%;
    width: 46px;
    height: 46px;
    font-size: 1.05rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, transform 0.1s, border-color 0.15s;
}
.streaming-btn:hover { background: var(--bg-hover); border-color: var(--accent); }
.streaming-btn:active { transform: scale(0.93); }
.streaming-btn-main {
    width: 56px;
    height: 56px;
    font-size: 1.35rem;
    background: var(--accent);
    color: var(--bg-primary);
    border-color: var(--accent);
    border-width: 2px;
}
.streaming-btn-main:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

.streaming-secondary {
    grid-area: secondary;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.7rem;
    flex-wrap: wrap;
}
.streaming-btn-sm {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-muted);
    border-radius: var(--radius-sm);
    min-width: 104px;
    height: 34px;
    padding: 0 0.75rem;
    font-size: 0.85rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
    user-select: none;
}
.streaming-btn-sm:hover {
    color: var(--text-secondary);
    border-color: var(--border-strong);
    background: var(--bg-hover);
}
.streaming-btn-sm.active {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-dim);
}
.streaming-btn-sm-icon { font-size: 0.95rem; line-height: 1; }
.streaming-btn-sm-label { font-size: 0.78rem; font-weight: 600; letter-spacing: 0.01em; white-space: nowrap; }

.streaming-progress-row {
    grid-area: progress;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    max-width: 360px;
    padding-top: 0.15rem;
}
.streaming-time {
    font-size: 0.72rem;
    color: var(--text-muted);
    min-width: 2.5rem;
    text-align: center;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
}
.streaming-progress {
    flex: 1;
    -webkit-appearance: none;
    appearance: none;
    height: 4px;
    background: var(--bg-elevated);
    border-radius: 2px;
    outline: none;
    cursor: pointer;
    min-width: 0;
}
.streaming-progress::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: #ececf0;
    border: 1px solid rgba(13,13,15,0.8);
    box-shadow: 0 0 0 1px rgba(255,255,255,0.12);
    cursor: pointer;
}
.streaming-progress:focus-visible::-webkit-slider-thumb {
    box-shadow: 0 0 0 4px rgba(110,231,183,.14);
}
.streaming-progress::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: #ececf0;
    border: 1px solid rgba(13,13,15,0.8);
    box-shadow: 0 0 0 1px rgba(255,255,255,0.12);
    cursor: pointer;
}
.streaming-progress:disabled { opacity: 0.4; cursor: default; }

/* Provider content (TIDAL) */
.streaming-content {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    width: 100%;
}

/* Auth */
.streaming-auth {
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    max-width: 42rem;
}
.streaming-auth-title { font-size: 1.05rem; font-weight: 700; color: var(--text-primary); margin: 0; }
.streaming-auth-hint { color: var(--text-muted); font-size: 0.85rem; line-height: 1.45; margin: 0; }
.streaming-auth-steps { margin: 0; padding-left: 1.25rem; color: var(--text-secondary); font-size: 0.85rem; line-height: 1.5; }
.streaming-auth-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; margin-top: 0.25rem; }
.streaming-auth-url-row { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.streaming-auth-url {
    flex: 1;
    min-width: 0;
    font-size: 0.76rem;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 0.5rem 0.6rem;
    color: var(--text-secondary);
    word-break: break-all;
    user-select: all;
}
.streaming-auth-input { width: 100%; }
.streaming-auth-device-code {
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: 0.2em;
    color: var(--text-primary);
    text-align: center;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 0.6rem;
}
.streaming-auth-error { color: var(--danger); font-size: 0.82rem; margin: 0; }

/* Browse (categories / search). Spans the full content column — the same
   width the album/playlist detail header uses — so the toolbar actions and
   the search group (right-aligned in rows 1/2) share one right edge with
   the detail Back button and browse <-> detail never shifts horizontally. */
.streaming-browse {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.tidal-toolbar {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 0.4rem 0.8rem;
}
.tidal-toolbar-title {
    margin: 0;
    justify-self: start;
}
.tidal-toolbar-actions {
    justify-self: end;
    display: flex;
    align-items: center;
    /* Same control rhythm as the local library toolbar. */
    gap: var(--action-gap);
    min-width: 0;
}
/* Second row: the single Tracks/Albums/Artists/Playlists navigation left,
   search group right — the library pattern. All four categories share the
   compact .view-tab component (no separate Favorites level, no inner
   category chips), and the subbar carries the underline. */
.tidal-subbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 0.8rem;
    flex-wrap: wrap;
    border-bottom: 1px solid var(--border-strong);
    padding-bottom: 0.5rem;
}
.tidal-subbar .view-tabs {
    flex: 0 1 auto;
    min-width: 0;
}
.tidal-subbar .streaming-search {
    min-width: 0;
    width: min(100%, 430px);
    margin-left: auto;
}
.streaming-search { display: flex; flex-direction: column; gap: 0.7rem; }
.streaming-search-row { display: flex; gap: 0.5rem; align-items: center; width: 100%; }
.streaming-search-input {
    flex: 1 1 auto;
    min-width: 0;
    width: 100%;
    height: 44px;
    padding: 0.55rem 2.1rem 0.55rem 0.8rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: 0.86rem;
    font-family: inherit;
    outline: none;
    transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.streaming-search-input::placeholder { color: var(--text-muted); }
.streaming-search-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-dim); }
.streaming-search-field {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
}
.streaming-search-input::-webkit-search-cancel-button,
.streaming-search-input::-webkit-search-decoration {
    appearance: none;
    -webkit-appearance: none;
}
.streaming-search-clear {
    position: absolute;
    right: 0.32rem;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.55rem;
    height: 1.55rem;
    border: 0;
    border-radius: 999px;
    background: var(--border);
    color: var(--text-secondary);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.42;
    -webkit-tap-highlight-color: transparent;
}
.streaming-search-clear:not(:disabled) {
    opacity: 1;
}
.streaming-search-clear:not(:disabled):hover {
    background: var(--border-strong);
    color: var(--text-primary);
}
.streaming-search-clear:disabled {
    cursor: default;
}
.streaming-search-clear:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.streaming-results { min-height: 2rem; }
#tidal-fav-results,
#tidal-playlists-results,
#tidal-search-items { margin-top: 0.35rem; }
.tidal-search-results-header { display: flex; flex-direction: column; gap: 0.5rem; }
.streaming-results-title { margin: 0; color: var(--text-primary); font-size: 1rem; font-weight: 700; }
.streaming-results-heading {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    margin: 0.9rem 0 0.4rem;
}
.streaming-results-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.streaming-result-cover {
    width: 42px;
    height: 42px;
    flex: 0 0 auto;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--bg-elevated);
}
.streaming-result-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Neutral placeholder for rows without art (e.g. TIDAL artists without a
   picture). */
.streaming-result-cover:empty {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #080808;
    background-image: url('/fxroute/static/artwork-placeholder.svg?v=2');
    background-position: center;
    background-repeat: no-repeat;
    background-size: 100% 100%;
}
.streaming-result-info,
.streaming-result .track-info { flex: 1; min-width: 0; }


.streaming-detail { display: flex; flex-direction: column; gap: 0.7rem; }
/* The detail header grid (cover/meta/back) is the shared rule defined with
   .album-detail-header above; this block keeps the streaming-specific chrome. */
.streaming-detail-cover {
    width: 132px;
    height: 132px;
    flex: 0 0 auto;
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--bg-elevated);
    box-shadow: 0 4px 16px rgba(0,0,0,0.3);
}
.streaming-detail-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.streaming-detail-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
}
.streaming-detail-title {
    min-width: 0;
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0;
    /* Long titles wrap inside the meta column like the library album title;
       they are never clipped or pushed out of the container. */
}
.streaming-detail-artist {
    min-width: 0;
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin: 0;
}
.streaming-detail-facts {
    min-width: 0;
    font-size: 0.78rem;
    color: var(--text-muted);
    margin: 0;
}

/* TIDAL detail-specific type and spacing sit on top of the shared artwork-led
   hero. Album, artist and playlist retain their existing actions and facts. */
.tidal-detail-header .streaming-detail-cover {
    width: 160px;
    height: 160px;
    border-radius: 14px;
}
.tidal-detail-meta { gap: 0.3rem; }
.tidal-detail-title-row {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
    min-width: 0;
    max-width: 100%;
}
.tidal-detail-title-row .streaming-detail-title {
    flex: 1 1 auto;
    min-width: 0;
}
.tidal-detail-title { font-size: 1.4rem; font-weight: 700; }
.tidal-detail-artist { font-size: 1rem; color: var(--text-secondary); margin: 0; }
.tidal-detail-facts { font-size: 0.86rem; color: var(--text-secondary); line-height: 1.35; margin: 0; }

/* TIDAL playlist header info: the description or the single-artist about
   share the album facts rhythm; long descriptions stay bounded. */
.tidal-playlist-info {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    min-width: 0;
    max-width: 64ch;
    margin-top: 0.2rem;
}
.tidal-playlist-description {
    margin: 0;
    color: var(--text-secondary);
    font-size: 0.86rem;
    line-height: 1.45;
}

/* TIDAL artist about: directly visible in the hero, reusing the library
   .album-detail-about text styling (colors, size, max-width) without its
   accordion. Long bios clamp to a few lines with a subtle More/Less toggle. */
.tidal-artist-about { margin-top: 0.5rem; }
.streaming-about-text {
    margin: 0;
    max-width: 64ch;
    color: var(--text-secondary);
    font-size: 0.86rem;
    line-height: 1.45;
}
.streaming-about-text.is-clamped {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.about-more-toggle {
    margin-top: 0.3rem;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 0.8rem;
    font-weight: 650;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.about-more-toggle:hover { color: var(--text-secondary); }
.about-more-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

/* TIDAL Albums / Artists / Playlists browse surfaces reuse the Library
   album-card grid + tile so they look the same as the local collection:
   large square cover, name, subtitle, heart in the corner. Track lists
   keep the compact streaming-result rows. */
.tidal-tiles {
    display: grid;
    /* Same shared tile basis as the Library albums grid so both surfaces
       keep one tile rhythm; radio reads its narrower derivative token. */
    grid-template-columns: repeat(auto-fit, minmax(var(--tile-min), var(--tile-min)));
    justify-content: center;
    gap: var(--tile-gap);
    margin-top: 1.25rem;
    list-style: none;
    padding: 0;
}
/* Browse results share one optical content start below the subbar divider:
   the Tracks list (no tile margin) is the reference; the card grids drop
   their library-inherited top margin so Albums/Artists/Playlists start at
   the same height. Scoped to the browse containers so detail views keep
   their own rhythm. */
#tidal-fav-results > .tidal-tiles,
#tidal-playlists-results > .tidal-tiles { margin-top: 0; }
/* Search results share one optical gap below the result-type tabs: the card
   grids stay the reference; the track list gains the same top margin so both
   start at the same height. Scoped to search so the browse Tracks reference
   stays untouched. */
#tidal-search-items > .streaming-results-list,
#tidal-search-items > .tidal-tiles { margin-top: 1.125rem; }
.tidal-tiles .album-card .streaming-fav {
    position: absolute;
    /* Same cover inset as Library favorites on the shared album card. */
    top: 1.05rem;
    right: 1.05rem;
    z-index: var(--z-raised);
    width: 32px;
    height: 32px;
    min-height: 32px;
    background: rgba(8, 18, 26, 0.72);
    backdrop-filter: blur(4px);
}
/* List view: the heart leaves the cover corner and joins the row end
   (same canonical favorite control, only repositioned). */
.tidal-tiles.is-list .album-card .streaming-fav {
    position: static;
    order: 5;
    z-index: auto;
    width: 34px;
    height: 34px;
    min-height: 34px;
    margin-left: auto;
    background: transparent;
    backdrop-filter: none;
}

/* Discover Similar artist tiles: cover placeholder (reuses the shared
   .streaming-result-cover tile) + name, responsive grid. */
.streaming-similar-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(var(--tile-min), var(--tile-min)));
    justify-content: center;
    gap: var(--tile-gap);
    width: 100%;
    max-width: calc(100% - 2rem);
    margin: 0.5rem auto 0;
    padding: 0;
    list-style: none;
}
.streaming-similar-item {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.35rem;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.streaming-similar-item .streaming-result-cover {
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    border-radius: 12px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    overflow: hidden;
}
.streaming-similar-item .streaming-result-cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.streaming-similar-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text-secondary);
    font-size: 0.82rem;
    font-weight: 600;
    text-align: center;
}
.streaming-similar-item:hover .streaming-similar-name { color: var(--text-primary); }
.measurement-overlay {
    z-index: var(--z-measurement);
    align-items: stretch;
    padding: 1rem;
}

.measurement-dialog {
    position: relative;
    width: min(1240px, 100%);
    min-height: min(820px, calc(100vh - 2rem));
    min-height: min(820px, calc(100dvh - 2rem));
    max-height: calc(100vh - 2rem);
    max-height: calc(100dvh - 2rem);
    overflow: auto;
}


.measurement-layout {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
}

.measurement-sidebar,
.measurement-main {
    min-width: 0;
}

.measurement-main {
    display: grid;
    gap: 1rem;
}

.measurement-main.is-setup > :not(.measurement-card-setup) {
    display: none;
}

#measurement-setup-back {
    align-self: flex-start;
    margin-bottom: 1rem;
}

.measurement-sidebar {
    display: none;
}

.measurement-card {
    min-height: 0;
    min-width: 0;
}

.measurement-stack {
    gap: 0.9rem;
}

.measurement-actions {
    display: flex;
    justify-content: flex-start;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.measurement-inline-note,
.measurement-inline-status,
.measurement-summary {
    color: var(--text-secondary);
    font-size: 0.88rem;
}

.measurement-input-channel-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

/* Multi-channel interfaces add a separate electrical reference per side. */
.measurement-input-channel-grid.is-split {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.measurement-list-title a,
.effects-compare-active a,
.effects-compare-chain a {
    color: inherit;
    text-decoration: none;
}

.measurement-list-title a {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: bottom;
    white-space: nowrap;
}

.measurement-list-title a:hover,
.effects-compare-active a:hover,
.effects-compare-chain a:hover {
    text-decoration: underline;
    text-underline-offset: 0.14em;
}

.measurement-card-header-split {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

.measurement-summary {
    display: none;
}

.measurement-graph-header-actions {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    margin-left: auto;
    flex-wrap: wrap;
    justify-content: flex-end;
}

.measurement-assist-select {
    min-width: 130px;
    min-height: 34px;
    padding: 0.38rem 0.65rem;
    font-size: 0.84rem;
}

.measurement-assist-select.hidden {
    display: none;
}

#measurement-setup-toggle,
#measurement-clear {
    flex: 0 0 auto;
    width: 5.25rem;
    height: 44px;
    min-height: 44px;
    padding: 0.5rem 0.85rem;
    white-space: nowrap;
    justify-self: end;
}

.measurement-actions-top {
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.65rem;
}

.measurement-workflow-list {
    display: flex;
    flex: 1 1 680px;
    flex-direction: column;
    gap: 0.5rem;
}

/* Workflow areas: quiet micro-labels group the action list into
   measurement / subwoofer / calibration without adding cards. */
.measurement-workflow-section {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.measurement-workflow-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}

.measurement-workflow-section + .measurement-workflow-section {
    margin-top: 0.35rem;
    padding-top: 0.7rem;
    border-top: 1px solid var(--border);
}

.measurement-workflow-label {
    color: var(--text-muted);
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.measurement-workflow-group {
    display: grid;
    grid-template-columns: 190px minmax(0, 1fr);
    align-items: center;
    gap: 0.55rem;
    min-height: 0;
}

#measurement-sweep-toggle,
#measurement-auto-sub-start,
#measurement-spl-calibration-open {
    width: 190px;
    min-width: 190px;
    min-height: 44px;
}

.measurement-workflow-menu {
    position: relative;
    width: 190px;
}

.measurement-workflow-menu-panel {
    position: absolute;
    top: calc(100% + 0.45rem);
    left: 0;
    z-index: var(--z-raised);
    display: flex;
    width: min(280px, calc(100vw - 2rem));
    flex-direction: column;
    gap: 0.45rem;
    padding: 0.45rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--bg-elevated);
    box-shadow: 0 18px 36px -18px var(--shadow);
    animation: measurement-menu-in 0.2s var(--ease);
}

@keyframes measurement-menu-in {
    from {
        opacity: 0;
        transform: translateY(-3px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* While the sweep menu is open the toggle reads as active, matching the
   .power-btn[aria-expanded="true"] pattern. */
#measurement-sweep-toggle[aria-expanded="true"] {
    background: var(--accent-hover);
}

.measurement-workflow-menu-panel:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.measurement-workflow-menu-choice {
    display: grid;
    gap: 0.4rem;
}

.hybrid-header-actions {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.hybrid-header-actions #measurement-sweep-toggle {
    width: 190px;
}

.measurement-workflow-menu-panel > button,
.measurement-workflow-menu-choice > button {
    width: 100%;
    min-width: 0;
    justify-content: flex-start;
}

/* The large secondary action buttons (Start LR Repeat, Advanced) center their
   label like Start Sweep; the help texts below stay left-aligned. */
.measurement-workflow-menu-choice > .btn-secondary {
    justify-content: center;
    background: var(--accent-dim);
    border-color: var(--accent-dim);
}

.measurement-workflow-menu-choice > .btn-secondary:hover {
    background: color-mix(in srgb, var(--accent) 22%, transparent);
    border-color: var(--accent-hover);
}

.measurement-workflow-menu-panel .measurement-channel-chip-row {
    padding: 0.1rem 0.1rem 0.15rem;
}

.measurement-workflow-row {
    display: grid;
    grid-template-columns: 190px minmax(0, 1fr);
    align-items: center;
    gap: 0.55rem;
    min-width: 0;
}

#measurement-repeat-start,
#measurement-hybrid-open {
    min-height: 42px;
}

.measurement-repeat-help {
    max-width: 620px;
    color: var(--text-secondary);
    font-size: 0.8rem;
    line-height: 1.25;
}

/* Bottom status line: kept visually apart from the action blocks so
   running/cancelled messages read as panel status, not as part of one row. */
#measurement-setup-status {
    margin-top: 0.6rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--border);
}

#measurement-setup-status:empty {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}

.spl-calibration-dialog {
    position: relative;
    width: min(560px, 100%);
    max-height: calc(100dvh - 2rem);
    overflow-y: auto;
}

#spl-calibration-panel {
    align-items: center;
}

.spl-calibration-dialog .effects-stack {
    gap: 0.85rem;
}

.spl-calibration-dialog #spl-calibration-status {
    margin-top: 0.35rem;
}

.hybrid-measurement-overlay {
    z-index: var(--z-measurement-hybrid);
    align-items: center;
}

.hybrid-measurement-dialog {
    position: relative;
    width: min(980px, 100%);
    max-height: calc(100dvh - 2rem);
    overflow-y: auto;
}

.hybrid-mode-label {
    margin: 0 0 0.25rem;
    color: var(--accent);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.hybrid-wizard-grid {
    display: grid;
    /* Min tracks stay under the narrowest two-column container (>=600px) so
       the wizard never overflows the dialog before it stacks on phones. */
    grid-template-columns: minmax(240px, 0.9fr) minmax(240px, 1.1fr);
    gap: 1.25rem;
}

.hybrid-room-view {
    position: relative;
    min-height: 470px;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--radius-xl);
    background:
        radial-gradient(circle at 50% 78%, color-mix(in srgb, var(--accent) 11%, transparent), transparent 34%),
        linear-gradient(160deg, var(--bg-elevated), var(--bg-surface));
}

.hybrid-speaker,
.hybrid-sub,
.hybrid-seat,
.hybrid-mic {
    position: absolute;
    display: grid;
    place-items: center;
    transform: translate(-50%, -50%);
}

.hybrid-speaker {
    top: 16%;
    width: 58px;
    height: 74px;
    border: 2px solid var(--border);
    border-radius: 12px 12px 18px 18px;
    background: var(--bg-surface);
    color: var(--text-secondary);
    font-size: 1.35rem;
    font-weight: 800;
    transition: 180ms ease;
}

.hybrid-speaker-left { left: 23%; }
.hybrid-speaker-right { left: 77%; }
.hybrid-speaker.is-active {
    border-color: var(--accent);
    box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 14%, transparent), 0 0 28px color-mix(in srgb, var(--accent) 24%, transparent);
    color: var(--text-primary);
}

.hybrid-sub {
    top: 34%;
    width: 48px;
    height: 48px;
    border: 1px solid var(--border);
    border-radius: 50%;
    background: var(--bg-surface);
    color: var(--text-secondary);
    font-size: 0.62rem;
}
.hybrid-sub-left { left: 11%; }
.hybrid-sub-right { left: 89%; }
.hybrid-sub-left.is-single { left: 50%; }
.hybrid-sub.is-active { border-color: var(--accent); color: var(--accent); }

.hybrid-seat {
    left: 50%;
    top: 79%;
    width: 210px;
    height: 92px;
    z-index: var(--z-base);
}
.hybrid-seat-back {
    position: absolute;
    inset: 0 16px 26px;
    border: 2px solid var(--border);
    border-radius: 28px 28px 12px 12px;
    background: color-mix(in srgb, var(--text-secondary) 12%, var(--bg-surface));
}
.hybrid-seat-cushion {
    position: absolute;
    bottom: 10px;
    width: 82px;
    height: 38px;
    border: 1px solid var(--border);
    border-radius: 10px 10px 16px 16px;
    background: color-mix(in srgb, var(--text-secondary) 18%, var(--bg-surface));
}
.hybrid-seat-cushion-left { left: 22px; }
.hybrid-seat-cushion-right { right: 22px; }
.hybrid-seat-arm {
    position: absolute;
    bottom: 4px;
    width: 24px;
    height: 54px;
    border: 2px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--bg-surface);
}
.hybrid-seat-arm-left { left: 0; }
.hybrid-seat-arm-right { right: 0; }

.hybrid-mic {
    width: 48px;
    height: 34px;
    z-index: var(--z-raised);
    border: 1px dashed var(--border);
    border-radius: 999px;
    color: var(--text-muted);
    font-size: 0.62rem;
    transition: 180ms ease;
}
.hybrid-mic-direct-left { left: 23%; top: 38%; }
.hybrid-mic-direct-right { left: 77%; top: 38%; }
.hybrid-mic-left { left: 37%; top: 69%; }
.hybrid-mic-mlp { left: 50%; top: 66%; }
.hybrid-mic-right { left: 63%; top: 69%; }
.hybrid-mic.is-target {
    border: 2px solid var(--success);
    background: color-mix(in srgb, var(--success) 18%, var(--bg-surface));
    box-shadow: 0 0 0 7px color-mix(in srgb, var(--success) 10%, transparent);
    color: var(--text-primary);
}

.hybrid-step-card {
    display: flex;
    min-height: 470px;
    flex-direction: column;
    padding: 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-xl);
    background: var(--bg-surface);
}
.hybrid-progress-row { display: flex; justify-content: space-between; color: var(--text-secondary); font-size: 0.8rem; }
.hybrid-step-card h3 { margin: 1.75rem 0 0.65rem; font-size: clamp(1.4rem, 3vw, 2rem); }
.hybrid-instruction { margin: 0; color: var(--text-primary); font-size: 1.05rem; line-height: 1.5; }
.hybrid-instruction.is-move::before { content: 'Move microphone'; display: block; margin-bottom: 0.3rem; color: var(--accent); font-size: 0.72rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.hybrid-instruction:not(.is-move):not(.is-complete)::before { content: 'Keep microphone here'; display: block; margin-bottom: 0.3rem; color: var(--success); font-size: 0.72rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.hybrid-active { color: var(--text-secondary); }
.hybrid-status { min-height: 3rem; margin-top: auto; padding: 0.8rem; border-radius: var(--radius-md); background: var(--bg-elevated); color: var(--text-secondary); }
.hybrid-status.is-busy::before {
    content: '';
    display: inline-block;
    width: 0.9rem;
    height: 0.9rem;
    margin-right: 0.55rem;
    vertical-align: -0.12rem;
    border: 2px solid color-mix(in srgb, var(--accent) 25%, transparent);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: hybrid-status-spin 0.8s linear infinite;
}
@keyframes hybrid-status-spin { to { transform: rotate(360deg); } }
.hybrid-status[data-level="ok"] { color: var(--success); }
.hybrid-status[data-level="error"] { color: var(--danger); }
.hybrid-action-row { display: grid; grid-template-columns: minmax(90px, 0.35fr) minmax(180px, 1fr); gap: 0.7rem; margin-top: 0.9rem; }
.hybrid-action-row button { min-height: 54px; }
.hybrid-summary { display: grid; gap: 0.45rem; margin: 0.7rem 0; }
.hybrid-summary-item { padding-left: 1.2rem; color: var(--text-secondary); font-size: 0.84rem; }
.hybrid-summary-item::before { content: '✓'; float: left; margin-left: -1.2rem; color: var(--success); }
.hybrid-advanced-details { margin-top: 0.35rem; color: var(--text-muted); font-size: 0.78rem; }
.hybrid-advanced-details summary { cursor: pointer; color: var(--text-secondary); }
.hybrid-advanced-details p { margin: 0.5rem 0 0; line-height: 1.45; }

.measurement-channel-chip-row,
.measurement-smoothing-chips,
.measurement-view-toggle {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    flex-wrap: wrap;
}

.measurement-view-toggle {
    margin-right: 0.5rem;
}

.measurement-view-toggle .measurement-chip {
    min-height: 34px;
}

.measurement-chip {
    min-height: 36px;
    padding: 0.38rem 0.8rem;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,0.12);
    background: rgba(255,255,255,0.04);
    color: var(--text-secondary);
    font-size: 0.82rem;
    font-weight: 700;
}

.measurement-chip:not(.is-active):not(:disabled):hover {
    background: var(--bg-hover);
    border-color: var(--border-strong);
    color: var(--text-primary);
}

.measurement-chip.is-active {
    color: #0d0d0f;
    background: var(--accent);
    border-color: transparent;
}

.measurement-chip:disabled,
.measurement-chip.is-active:disabled {
    color: var(--text-muted);
    background: rgba(255,255,255,0.025);
    border-color: rgba(255,255,255,0.08);
    box-shadow: none;
    cursor: not-allowed;
    opacity: 0.48;
}

.measurement-name-input {
    flex: 1 1 260px;
    min-width: 180px;
}

.measurement-graph-wrap {
    border-radius: var(--radius-md);
    border: 1px solid var(--border);
    background: linear-gradient(180deg, rgba(255,255,255,0.03), rgba(255,255,255,0.01));
    padding: 0.75rem;
}

.measurement-ir-diagnostics {
    display: none;
}

.measurement-graph {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 7;
    min-height: 320px;
    touch-action: pan-y;
}

.measurement-empty {
    margin-top: 0.9rem;
    color: var(--text-secondary);
    text-align: center;
}

.measurement-peq-panel {
    display: grid;
    gap: 0.85rem;
    margin-top: 1rem;
    padding-top: 0.95rem;
    border-top: 1px solid rgba(255,255,255,0.08);
}

.measurement-peq-panel.hidden {
    display: none;
}

.measurement-peq-panel-header {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
}

.measurement-peq-panel-header h4 {
    margin: 0;
    font-size: 0.98rem;
}

.measurement-peq-panel-header p {
    margin: 0.2rem 0 0;
    color: var(--text-secondary);
    font-size: 0.84rem;
    line-height: 1.5;
}

.measurement-peq-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
}

.measurement-slot-chip,
.measurement-peq-chip {
    min-width: 3.25rem;
    min-height: 32px;
    padding: 0.35rem 0.7rem;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,0.12);
    background: rgba(255,255,255,0.04);
    color: var(--text-secondary);
    font-size: 0.8rem;
    font-weight: 700;
    line-height: 1.2;
    text-align: center;
}

.measurement-slot-chip {
    flex: 0 0 3.25rem;
}

.measurement-peq-chip.is-active {
    color: #08110d;
    border-color: transparent;
    box-shadow: 0 0 0 1px rgba(255,255,255,0.06) inset;
}

.measurement-peq-chip.is-empty {
    border-style: dashed;
    opacity: 0.72;
}

.measurement-peq-editor {
    display: grid;
    gap: 0.8rem;
    padding: 0.9rem;
    border-radius: var(--radius-md);
    border: 1px solid var(--border);
    background: rgba(255,255,255,0.03);
}

.measurement-peq-editor-empty {
    color: var(--text-secondary);
    font-size: 0.88rem;
}

.measurement-peq-editor-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr) minmax(0, 0.95fr) minmax(0, 0.9fr) auto;
    gap: 0.65rem;
    align-items: end;
}

.measurement-peq-editor-grid .field-group {
    margin: 0;
    min-width: 0;
}

.measurement-peq-direct-input-field {
    min-width: 0;
}

.measurement-peq-editor-grid .field-group label {
    font-size: 0.75rem;
}

.measurement-peq-editor-grid .url-input {
    min-width: 0;
    min-height: 40px;
    padding: 0.55rem 0.75rem;
    font-size: 0.9rem;
}

.measurement-peq-stepper {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: 0.45rem;
    align-items: center;
}

/* Match the effects steppers: the value sits centered between the
   -/+ buttons instead of hugging the left field edge. */
.measurement-peq-stepper .measurement-peq-number-input {
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.measurement-peq-number-input {
    appearance: textfield;
    -moz-appearance: textfield;
}

.measurement-peq-number-input::-webkit-inner-spin-button,
.measurement-peq-number-input::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.measurement-peq-step-btn {
    min-width: 40px;
    min-height: 40px;
    padding: 0;
    font-size: 1rem;
}

.measurement-peq-editor-actions {
    display: flex;
    justify-content: flex-end;
}

.measurement-peq-take-row,
.measurement-save-row {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.measurement-peq-take-row {
    justify-content: flex-end;
}

/* Custom house-curve save row: keep the name and action together until the existing mobile breakpoint. */
#measurement-custom-house-curve-panel > .measurement-peq-panel-header,
#measurement-custom-house-curve-panel > .measurement-peq-chips,
#measurement-custom-house-curve-panel > .measurement-peq-editor {
    grid-column: 1 / -1;
}

#measurement-custom-house-curve-panel {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
}

#measurement-custom-house-curve-panel > .field-group {
    grid-column: 1;
    min-width: 0;
    margin: 0;
}

#measurement-custom-house-curve-panel > .measurement-peq-take-row {
    grid-column: 2;
    align-items: center;
    flex-wrap: nowrap;
    min-width: max-content;
    margin: 0;
}

#measurement-custom-house-curve-panel > .measurement-peq-take-row .btn-primary {
    flex: 0 0 auto;
    white-space: nowrap;
}

.measurement-peq-take-row .btn-secondary.is-active {
    background: var(--accent-dim);
    border-color: var(--accent);
    color: var(--accent);
    box-shadow: inset 0 0 0 1px rgba(110, 231, 183, 0.22);
}

.measurement-convolver-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
    padding: 0.9rem;
    border-radius: var(--radius-md);
    border: 1px solid rgba(96, 165, 250, 0.22);
    background: rgba(96, 165, 250, 0.06);
}

.measurement-convolver-grid .field-group {
    margin: 0;
    min-width: 0;
}

.measurement-convolver-grid .url-input {
    min-width: 0;
}

.measurement-convolver-summary {
    color: var(--text-secondary);
    font-size: 0.84rem;
    line-height: 1.5;
}

.measurement-convolver-warnings {
    display: grid;
    gap: 0.35rem;
    color: #fde68a;
    font-size: 0.84rem;
}

.measurement-convolver-warnings.hidden {
    display: none;
}

.measurement-peq-take-feedback {
    min-height: 1.2rem;
    margin-top: -0.2rem;
    text-align: right;
    color: var(--success);
    font-size: 0.8rem;
    font-weight: 600;
    opacity: 0;
    transform: translateY(-3px);
    transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
    pointer-events: none;
}

.measurement-peq-take-feedback.is-visible {
    opacity: 1;
    transform: translateY(0);
}

.measurement-save-row {
    align-items: center;
    justify-content: flex-start;
    margin-top: 0.5rem;
}

.measurement-save-row .btn-secondary {
    min-height: 40px;
}

.measurement-list {
    display: grid;
    gap: 0.75rem;
}

.measurement-list-item {
    display: grid;
    gap: 0.35rem;
    padding: 0.85rem 0.95rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: rgba(255,255,255,0.02);
}

.measurement-list-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}

.measurement-toggle {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    cursor: pointer;
}

.measurement-swatch {
    width: 12px;
    height: 12px;
    border-radius: 999px;
    box-shadow: 0 0 0 1px rgba(255,255,255,0.12);
    flex: 0 0 auto;
}

.measurement-swatch-inactive {
    background: rgba(148, 163, 184, 0.18);
    box-shadow: 0 0 0 1px rgba(148, 163, 184, 0.22);
}

.measurement-list-title {
    font-weight: 600;
}

.measurement-list-meta,
.measurement-list-points {
    color: var(--text-secondary);
    font-size: 0.84rem;
}

.measurement-saved-group {
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: rgba(255,255,255,0.02);
    padding: 0.2rem 0.2rem 0.4rem;
}

.measurement-saved-group > summary {
    cursor: pointer;
    list-style: none;
    padding: 0.65rem 0.75rem;
    font-weight: 600;
}

.measurement-saved-group > summary::-webkit-details-marker {
    display: none;
}

.measurement-saved-list {
    display: grid;
    gap: 0.75rem;
    padding: 0 0.3rem 0.3rem;
}

.measurement-saved-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-bottom: 0.1rem;
}

.measurement-saved-toolbar-selection {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0.75rem;
    flex-wrap: wrap;
    flex: 1 1 auto;
}
.measurement-saved-close-action {
    margin-left: auto;
}
.label-compact {
    display: none;
}

.measurement-select-all-toggle {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.measurement-saved-merge-action,
.measurement-saved-delete-action {
    min-width: 142px;
}

.measurement-saved-merge-action.is-inert,
.measurement-saved-delete-action.is-inert {
    visibility: hidden;
    pointer-events: none;
}
/* ============================================================
   Effects tab styling
   ============================================================ */
#tab-effects { padding-top: 0.75rem; }

.effects-shell {
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 1rem 1rem;
}
.effects-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 1rem;
}
.effects-header-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--action-gap);
    flex: 0 0 auto;
    margin-right: var(--control-gap, 12px);
}

.effects-header-action {
    min-width: 112px;
    min-height: 38px;
    padding-inline: 0.95rem;
}
.effects-import-panel {
    margin-bottom: 1rem;
}

.effects-import-card-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
}

.effects-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
    align-items: stretch;
}
.effects-card {
    display: flex;
    flex-direction: column;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    /* Neutral edge for regular cards; mint stays reserved for active or
       selected surfaces so they read at a glance. */
    border-top: 3px solid var(--border-strong);
    border-radius: var(--radius-lg);
    padding: 1rem;
}

/* The A/B compare card mirrors the active listening chain ("Listening: A ·
   Neutral") and keeps the mint edge regular cards no longer carry. */
.effects-card-manage {
    border-top-color: var(--accent);
}
.effects-card-header {
    margin-bottom: 1.25rem;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--border);
}
.effects-card h3 {
    margin-bottom: 0.4rem;
    font-size: 1.1rem;
    font-weight: 600;
    letter-spacing: -0.015em;
    line-height: 1.25;
}
.effects-card-header p,
.effects-info {
    color: var(--text-secondary);
    line-height: 1.7;
    font-size: 0.9rem;
}

/* Preset compare A/B row */
.effects-compare-row {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    padding: 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: rgba(255,255,255,0.015);
}

.effects-compare-fields {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.75rem;
}

.effects-compare-slot {
    padding: 0.8rem;
    border-radius: var(--radius-md);
    border: 1px solid var(--border);
    background: rgba(255,255,255,0.02);
    transition: border-color 0.15s var(--ease), background 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

.effects-compare-slot.is-active {
    border-color: rgba(110, 231, 183, 0.45);
    background: rgba(110, 231, 183, 0.08);
    box-shadow: none;
}

.effects-compare-slot.is-armed {
    border-color: rgba(110, 231, 183, 0.22);
}

.effects-compare-fields .field-group {
    margin-bottom: 0;
}

.compare-select {
    cursor: pointer;
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
}

/* All native select option lists follow the dark theme. color-scheme: dark
   on :root makes Chromium render the popup dark; these tokens keep the
   option text readable and the selected option distinct regardless. */
select option {
    background: var(--bg-input);
    color: var(--text-primary);
}

select option:checked {
    background: var(--bg-elevated);
    color: var(--accent);
}

.effects-compare-active-badge {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 0.22rem;
    width: 100%;
    padding: 0.9rem 1rem;
    background: rgba(110, 231, 183, 0.08);
    border: 1px solid rgba(110, 231, 183, 0.26);
    border-radius: var(--radius-md);
    font-weight: 600;
    font-size: 1rem;
    color: #bff9de;
    text-align: center;
    box-shadow: none;
}

.effects-compare-active-badge span {
    display: block;
    width: 100%;
    min-width: 0;
    max-width: 100%;
    color: inherit;
}

.effects-compare-chain {
    font-size: 0.8rem;
    font-weight: 600;
    opacity: 0.88;
    line-height: 1.35;
    white-space: normal;
    overflow-wrap: anywhere;
}

.effects-compare-active-badge.is-side-a {
    background: rgba(110, 231, 183, 0.1);
    border-color: rgba(110, 231, 183, 0.34);
}

.effects-compare-active-badge.is-side-b {
    background: rgba(110, 231, 183, 0.1);
    border-color: rgba(110, 231, 183, 0.34);
    color: #f0fff8;
}

.effects-compare-actions {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.75rem;
    padding-top: 0.35rem;
    flex-wrap: wrap;
}

.effects-compare-actions .btn-primary {
    min-width: 108px;
}

.effects-compare-active {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--accent);
    white-space: nowrap;
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    flex-shrink: 1;
}

/* Dark scrollbar for dropdowns and scrollable areas */
.compare-select,
.url-input,
select.url-input {
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.15) rgba(255, 255, 255, 0.05);
}

.compare-select::-webkit-scrollbar,
.url-input::-webkit-scrollbar,
select.url-input::-webkit-scrollbar {
    width: 6px;
}

.compare-select::-webkit-scrollbar-track,
.url-input::-webkit-scrollbar-track,
select.url-input::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.05);
    border-radius: 3px;
}

.compare-select::-webkit-scrollbar-thumb,
.url-input::-webkit-scrollbar-thumb,
select.url-input::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.15);
    border-radius: 3px;
}

.compare-select::-webkit-scrollbar-thumb:hover,
.url-input::-webkit-scrollbar-thumb:hover,
select.url-input::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.25);
}

.effects-stack {
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
}
.field-group {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

/* Keep checkbox label compact — don't expand click area */
.field-group > label.checkbox-row {
    width: fit-content;
}
.field-group label {
    color: var(--text-secondary);
    font-size: 0.85rem;
    font-weight: 600;
}
/* Scoped field styles for radio manage dialog */
.manage-dialog .field-group {
    gap: 0.45rem;
}
.manage-dialog .url-input {
    min-height: 42px;
    min-width: 0;
    max-width: 100%;
}
#station-delete-select {
    width: 100%;
    text-overflow: ellipsis;
}
.btn-inline {
    min-width: 0;
    min-height: 34px;
    padding: 0.35rem 0.7rem;
    font-size: 0.8rem;
    font-weight: 500;
    border-radius: 999px;
    color: var(--text-secondary);
}
.btn-inline:hover {
    color: var(--text-primary);
}
.checkbox-row {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    color: var(--text-secondary);
    min-height: 44px;
}
.effects-actions-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-top: 0.5rem;
}
.effects-actions-right {
    margin-top: 0.5rem;
}
.effects-actions-row .btn-primary,
.effects-actions-row .btn-danger,
.effects-actions-row .btn-secondary {
    min-width: 160px;
    min-height: 44px;
    padding: 0.7rem 1rem;
    border-radius: var(--radius-md);
}
.effects-info {
    min-height: 1.5rem;
    margin-top: auto;
    padding-top: 0.5rem;
}

.effects-filter-import-area {
    min-height: 112px;
}

.effects-combine-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
}

.effects-card-combine .effects-stack {
    gap: 1rem;
}

.effects-combine-name-input {
    flex: 1 1 220px;
    max-width: 320px;
    min-width: 0;
    min-height: 34px;
    padding: 0.4rem 0.65rem;
    font-size: 0.88rem;
}

.effects-actions-combine {
    margin-top: 0;
    align-items: center;
    justify-content: space-between;
    gap: 0.65rem;
    flex-wrap: wrap;
}

.effects-actions-combine .btn-primary {
    min-width: 200px;
}

.effects-label-optional {
    color: var(--text-secondary);
    font-size: 0.78rem;
    font-weight: 500;
}

.effects-card-combine .field-group {
    min-width: 0;
}

.effects-card-combine .compare-select {
    width: 100%;
}

.effects-card-combine .effects-card-header p {
    max-width: 42ch;
}

.effects-card-subwoofer {
    grid-column: 1 / -1;
    order: 20;
}

.effects-card-subwoofer-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
}

.effects-subwoofer-mode-badge {
    flex: 0 0 auto;
    padding: 0.34rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    color: var(--text-secondary);
    font-size: 0.78rem;
    font-weight: 800;
}

.effects-subwoofer-mode-badge.is-active {
    color: #bff9de;
    border-color: rgba(110, 231, 183, 0.42);
    background: rgba(110, 231, 183, 0.1);
}

.effects-subwoofer-stack {
    gap: 0.75rem;
}

.effects-subwoofer-preview-wrap {
    width: min(100%, 1100px);
    margin: 0 auto;
    border: 1px solid rgba(110, 231, 183, 0.18);
    border-radius: var(--radius-md);
    background: #08111f;
    overflow: hidden;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);
}

.effects-subwoofer-preview {
    display: block;
    width: 100%;
    height: 136px;
    background: #08111f;
    touch-action: pan-y;
    cursor: ew-resize;
}

.effects-subwoofer-controls {
    display: grid;
    grid-template-columns: minmax(148px, 1.08fr) minmax(112px, 0.78fr) repeat(6, minmax(92px, 1fr));
    align-items: stretch;
    gap: 0.75rem;
    width: min(100%, 1100px);
    margin: 0 auto;
}

.effects-subwoofer-control-group {
    min-width: 0;
    overflow: hidden;
    padding: 0.7rem;
    border: 1px solid rgba(148, 163, 184, 0.18);
    border-radius: var(--radius-sm);
    background: rgba(15, 23, 42, 0.38);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.025);
}

.effects-subwoofer-global-group {
    grid-column: 1 / span 2;
    display: grid;
    /* Same principle as the channel groups: tracks hug their content and
       the leftover width becomes even spacing, so controls can neither
       overlap nor clip at any card width. */
    grid-template-columns: repeat(2, auto);
    justify-content: space-evenly;
    align-items: end;
    gap: 0.7rem;
}

.effects-subwoofer-channel-group {
    grid-column: 3 / -1;
    display: grid;
    /* One principle for every field: tracks hug their content (steppers and
       selects keep their compact fixed sizes) and the leftover width becomes
       even spacing between the columns. Nothing can overlap or clip, no
       per-control track sizing, and Sub 1 / Sub 2 share the class and stay
       symmetric. Headings and controls share one center axis (field-group
       centering below). */
    grid-template-columns: repeat(3, auto);
    justify-content: space-evenly;
    align-items: end;
    gap: 0.8rem;
    background: rgba(8, 47, 73, 0.2);
    border-color: rgba(110, 231, 183, 0.26);
}

.effects-card-subwoofer.is-subwoofer-22 .effects-subwoofer-sub1-group {
    grid-column: 3 / span 3;
}

.effects-card-subwoofer.is-subwoofer-22 .effects-subwoofer-sub2-group {
    grid-column: 6 / span 3;
}

.effects-subwoofer-sub2-group {
    background: rgba(30, 41, 59, 0.44);
    border-color: rgba(147, 197, 253, 0.24);
}

.effects-subwoofer-group-label {
    grid-column: 1 / -1;
    color: var(--text-secondary);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0;
    text-transform: none;
}

.effects-subwoofer-control-group .field-group {
    min-width: 0;
    gap: 0.42rem;
    justify-content: end;
    /* Headings and controls share one center axis, so every box sits
       centered under its heading at any track width. */
    align-items: center;
}

.effects-subwoofer-control-group .field-group label {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    min-height: 2.05em;
    color: var(--text-secondary);
    font-size: 0.8rem;
    line-height: 1.14;
}

.effects-subwoofer-derived-delays {
    grid-column: 3 / -1;
    align-self: stretch;
    min-width: 0;
    padding: 0.48rem 0.65rem;
    border: 1px solid rgba(148, 163, 184, 0.14);
    border-radius: var(--radius-sm);
    background: rgba(15, 23, 42, 0.28);
    text-align: center;
    color: var(--text-secondary);
    font-size: 0.74rem;
    font-weight: 600;
    line-height: 1.25;
}

.effects-subwoofer-derived-delays span {
    color: var(--text-primary);
    font-weight: 700;
}

.effects-subwoofer-polarity-field,
.effects-subwoofer-highpass-field {
    min-width: 0;
    align-self: end;
}

/* Subwoofer selects share the common #tab-effects control metrics; the
   Main highpass cap (5.2rem) fits the widest option ("On"/"Off") with room
   beside the native arrow on Android, where the narrower cap clipped "On".
   The polarity selects keep the tighter 4.2rem cap beside the single-letter
   "N"/"I" values. Centered text keeps the boxes calm between heading and
   native arrow. The select type selectors are load-bearing: #tab-effects
   .url-input (equal specificity, later in the file) would otherwise keep
   width:100% alive and stretch the selects back across their grid tracks. */
#tab-effects select.effects-subwoofer-compact-select {
    width: min(100%, 5.2rem);
    min-width: 0;
    max-width: 100%;
    text-align: center;
}
#tab-effects select.effects-subwoofer-polarity-select {
    width: min(100%, 4.2rem);
    min-width: 0;
    max-width: 100%;
    text-align: center;
}

.effects-filter-import-area.is-busy {
    opacity: 0.75;
    pointer-events: none;
}

.effects-filter-import-area.is-busy .upload-area-text::after {
    content: ' · importing…';
}

.effects-filter-import-area.is-ready .upload-area-filename {
    color: var(--accent);
}

.effects-filter-import-area.is-ready .upload-area-filename::after {
    content: ' · imports automatically';
}

.effects-import-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}

.effects-import-section-title {
    font-size: 0.84rem;
    font-weight: 700;
    color: var(--text-primary);
}

.effects-import-section-meta {
    font-size: 0.76rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-secondary);
}

.effects-import-section-head-secondary {
    margin-top: 0.15rem;
    padding-top: 0.2rem;
    border-top: 1px solid rgba(255,255,255,0.05);
}

.effects-rew-dual-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.9rem;
}

.effects-rew-pane {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    min-width: 0;
}

.effects-rew-pane-header label,
.effects-pane-title {
    color: var(--text-secondary);
    font-size: 0.85rem;
    font-weight: 600;
}

.effects-rew-upload-area {
    min-height: 74px;
}

.effects-rew-upload-area .upload-area-icon {
    font-size: 1.15rem;
}

.effects-rew-textarea {
    min-height: 150px;
    resize: vertical;
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.84rem;
    line-height: 1.45;
    white-space: pre;
    overflow: auto;
}

.effects-actions-rew-dual {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.9rem;
    align-items: start;
}

.effects-rew-dual-preset-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.75rem;
    min-width: 0;
}

.effects-rew-dual-name-input {
    width: 100%;
    max-width: none;
    min-width: 0;
    min-height: 34px;
    padding: 0.4rem 0.65rem;
    font-size: 0.88rem;
}

.effects-peq-dual-grid {
    gap: 0.8rem;
}

.effects-peq-pane {
    gap: 0.5rem;
}

.effects-peq-add-row {
    display: grid;
    grid-template-columns: minmax(0, 220px) auto;
    justify-content: space-between;
    align-items: end;
    gap: 1rem;
    margin-bottom: 0.35rem;
}

.effects-peq-mode-field {
    width: 100%;
    max-width: 220px;
    margin: 0;
}

.effects-peq-mode-field label {
    font-size: 0.78rem;
    color: var(--text-secondary);
    margin-bottom: 0.3rem;
}

.effects-peq-mode-field .url-input {
    min-height: 40px;
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
}

.effects-peq-add-row .btn-inline {
    flex: 0 0 auto;
    justify-self: end;
    min-width: 92px;
    min-height: 44px;
    padding: 0.45rem 1rem;
}

.effects-peq-pane-header {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0.6rem;
    min-height: 34px;
}

.effects-actions-peq-dual {
    /* Single action row (preset name + Create): full card width, unlike the
       two-column REW dual import row this class is derived from. */
    grid-template-columns: minmax(0, 1fr);
    gap: 0.8rem;
    align-items: start;
}

.effects-actions-peq-dual .effects-rew-dual-name-input {
    width: 100%;
    max-width: none;
    min-width: 0;
}

.effects-actions-peq-dual .btn-primary {
    min-width: 110px;
}

.delay-field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    min-width: 0;
}

.delay-field-compact {
    flex-direction: row;
    align-items: center;
    gap: 0.35rem;
}

.delay-field-compact label {
    margin: 0;
}

.delay-field-compact .delay-input-wrap {
    gap: 0.3rem;
}

.delay-field-compact .delay-unit {
    font-size: 0.76rem;
}

.delay-field label {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text-primary);
}

.delay-input-wrap {
    display: flex;
    align-items: center;
    /* Stepper wraps hold a single child, so this gap only spaces the
       SPL-calibration number from its unit; keep it snug like the steppers. */
    gap: 0.2rem;
}

/* Bigger up/down arrows for number inputs */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
    opacity: 1;
    height: 26px;
    width: 12px;
    margin-right: 2px;
}

.delay-unit {
    flex-shrink: 0;
    /* Match .stepper-unit typography so every number+unit pair reads the
       same across the UI. */
    color: var(--text-muted);
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1;
    user-select: none;
}

.effects-extras-feedback {
    font-size: 0.82rem;
    color: var(--text-muted);
    min-height: 1.4em;
    transition: color 0.2s ease;
}

.effects-extras-feedback.saving {
    color: var(--accent, #6ee7b7);
}

.effects-extras-feedback.success {
    color: var(--success, #34d399);
}

.effects-extras-feedback.error {
    color: var(--danger, #f87171);
}

.effects-card-extras {
    border: 1px solid var(--border);
    /* Re-assert the shared neutral card edge after the border shorthand. */
    border-top: 3px solid var(--border-strong);
    border-radius: var(--radius-lg);
    background: var(--bg-surface);
    overflow: hidden;
}

.effects-card-extras .effects-card-header {
    padding: 0 0 0.75rem;
    border-bottom: 1px solid var(--border);
    margin-bottom: 1.25rem;
}

.effects-card-extras .effects-card-header h3 {
    font-size: 1.1rem;
    font-weight: 600;
    margin-bottom: 0.4rem;
}

.effects-card-extras .effects-card-header p {
    font-size: 0.9rem;
    color: var(--text-secondary);
    line-height: 1.7;
    margin: 0;
}

.effects-card-extras .effects-stack {
    padding: 0 0 1rem;
}

.effects-extras-stack {
    align-items: center;
}

.effects-extras-inner {
    width: min(100%, 540px);
    padding: 1rem 1.05rem;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    background: transparent;
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
}

.effects-extras-group {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    padding: 0.8rem 0.85rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: rgba(255,255,255,0.02);
}

.effects-extras-group-header {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.effects-extras-group-header h4 {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-primary);
}

.effects-extras-row {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0.8rem;
    flex-wrap: wrap;
}

.effects-extras-row-helpers {
    gap: 1rem;
}

/* Loudness row wraps when the narrow two-column card cannot fit checkbox
   + Strength + FFT on one line. The old nowrap overflowed the card in the
   768–~880px band where the two-column grid starts but cards are small. */
.effects-loudness-row {
    flex-wrap: wrap;
}

.effects-loudness-controls {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem 1rem;
    flex-wrap: wrap;
    max-width: 100%;
}

.effects-headroom-controls {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    flex-wrap: wrap;
}

.effects-inline-control {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    flex-wrap: wrap;
}

.effects-headroom-select,
.effects-compact-control {
    width: auto;
    min-width: 5.3rem;
    min-height: 46px;
    height: 46px;
    padding: 0.7rem 2rem 0.7rem 0.85rem;
    padding-right: 2rem;
}

.effects-inline-control-label {
    color: var(--text-secondary);
    font-size: 0.8rem;
    line-height: 1.2;
    white-space: nowrap;
}

.effects-bass-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.65rem 0.95rem;
    width: 100%;
}

.effects-bass-controls {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    flex-wrap: wrap;
    max-width: 100%;
}

.effects-bass-controls .effects-inline-control-label {
    white-space: nowrap;
}

.effects-bass-controls .delay-input-wrap {
    gap: 0.45rem;
}

.effects-card-peq-workshop {
    padding-top: 1.45rem;
}

/* Collapsed PEQ card: read-only draft preview plus hint. Both hide while
   the editor is expanded; the summary text is filled from the draft. */
.effects-peq-summary {
    margin-top: 0.5rem;
    font-size: 0.8rem;
    line-height: 1.55;
    color: var(--text-muted);
    font-family: var(--font-mono);
    white-space: pre-line;
    overflow-wrap: anywhere;
}

.effects-peq-summary-hint {
    display: block;
    margin-top: 0.35rem;
    font-size: 0.76rem;
    letter-spacing: 0.01em;
    color: var(--text-muted);
}

.effects-disclosure[open] .effects-peq-summary,
.effects-disclosure[open] .effects-peq-summary-hint {
    display: none;
}

.effects-disclosure {
    width: 100%;
}

.effects-disclosure-summary {
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.8rem;
    cursor: pointer;
}

.effects-disclosure-summary::-webkit-details-marker {
    display: none;
}

.effects-disclosure-summary h3 {
    margin: 0 0 0.4rem;
}

.effects-disclosure-summary p {
    margin: 0;
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.7;
}

.effects-disclosure-meta {
    flex: 0 0 auto;
    padding: 0.35rem 0.7rem;
    border-radius: 999px;
    border: 1px solid var(--border);
    color: var(--text-secondary);
    font-size: 0.78rem;
    font-weight: 700;
    white-space: nowrap;
}

.effects-disclosure[open] .effects-disclosure-meta {
    color: var(--text-primary);
    border-color: var(--border-strong);
}

.effects-disclosure-body {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
}

.effects-peq-bands {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.effects-peq-band {
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 0.7rem 0.75rem;
    background: rgba(255,255,255,0.02);
}
.effects-peq-band-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    margin-bottom: 0.55rem;
}
.effects-peq-band-title {
    font-size: 0.84rem;
    font-weight: 600;
    color: var(--text-secondary);
}
.effects-peq-band-subtitle {
    color: var(--text-secondary);
    font-size: 0.85rem;
}
.effects-peq-remove-spacer,
.effects-peq-band .btn-inline {
    min-width: 78px;
    min-height: 34px;
}
.effects-peq-band .btn-inline {
    padding: 0.35rem 0.75rem;
}
.effects-peq-band-fields {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem 0.65rem;
}
.effects-peq-band-fields-gain {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.effects-peq-band-fields > * {
    min-width: 0;
}
.effects-peq-band-fields .field-group {
    gap: 0.22rem;
}
.effects-peq-band-fields .field-group label {
    font-size: 0.78rem;
    color: var(--text-secondary);
}
.effects-peq-band-fields .url-input,
.effects-peq-band-fields select,
.effects-peq-band-fields input {
    width: 100%;
    max-width: 100%;
    min-width: 0;
    box-sizing: border-box;
    min-height: 36px;
    padding: 0.45rem 0.6rem;
    font-size: 0.84rem;
}
.effects-peq-empty {
    color: var(--text-secondary);
    font-size: 0.9rem;
}

#tab-effects .url-input,
#tab-effects select {
    width: 100%;
    min-height: 46px;
    padding: 0.7rem 0.85rem;
    border-radius: var(--radius-sm);
    font-size: 0.92rem;
}
/* Delay number inputs keep the shared #tab-effects control metrics
   (46px min-height, shared padding/font) so mixed number/select rows
   align; only the inline width stays compact. The #tab-effects prefix
   keeps equal-specificity priority over the shared sizing rule. */
#tab-effects .delay-number-input {
    max-width: 100%;
    min-width: 0;
    flex: 0 0 auto;
    /* Steppers override width/alignment below; outside them this class now
       only styles the SPL-calibration field: centered value, width sized to
       the widest entry ("130.0") so the unit sits close like in steppers. */
    width: 4.6rem;
    text-align: center;
}
#tab-effects .delay-field-compact .delay-number-input {
    width: 4.6rem;
}
#tab-effects .effects-bass-controls .delay-number-input {
    width: 4.6rem;
    min-width: 4.6rem;
}
/* Compact − / value / + stepper for small-range DSP numbers. Replaces the
   native spinners where stepping is the primary interaction; the value
   stays directly editable and keeps its step/min/max semantics. Placed
   after the delay-number overrides so its sizing wins the cascade. */
.stepper-control {
    display: inline-flex;
    align-items: stretch;
    height: 46px;
    /* Never shrink inside tight grid cells: overflow clipping would hide
       the + button. Slight overflow into the column gap is fine. */
    flex: 0 0 auto;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

.stepper-btn {
    flex: 0 0 auto;
    width: 26px;
    border: 0;
    padding: 0;
    background: transparent;
    color: var(--text-secondary);
    font-family: inherit;
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    transition: color 0.12s var(--ease), background 0.12s var(--ease);
}

.stepper-btn:first-child {
    border-radius: var(--radius-sm) 0 0 var(--radius-sm);
}
.stepper-btn:last-child {
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.stepper-btn:hover {
    color: var(--accent);
    background: var(--accent-dim);
}
.stepper-btn:active {
    color: var(--accent);
}
/* Keyboard focus is shown by tinting the pressed button (same colors as
   hover); the green ring itself moves to the control outline below so no
   indicator is drawn inside the field. */
.stepper-btn:focus-visible {
    outline: none;
    color: var(--accent);
    background: var(--accent-dim);
}

/* Focus ring on the control border, same look as .url-input:focus: the ring
   hugs the field contour instead of floating around the inner value box,
   where it collided with number and unit. */
.stepper-control:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-dim);
}
/* The embedded value field keeps .url-input focus colors off: the control
   above carries the shared focus look. */
.stepper-control .stepper-input:focus {
    outline: none;
    border-color: transparent;
    box-shadow: none;
}

/* Display-only unit suffix inside the control (− 75 Hz +). Not part of
   the input value; the number input keeps its own step/min/max. */
.stepper-unit {
    flex: 0 0 auto;
    align-self: center;
    padding-right: 0.15rem;
    color: var(--text-muted);
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1;
    user-select: none;
}

#tab-effects .stepper-control .stepper-input {
    width: 3.1rem;
    min-width: 0;
    min-height: 0;
    height: auto;
    border: 0;
    background: transparent;
    /* Centering and readability come only from internal presentation: the
       compact outer size is load-bearing for the 3-column sub rows (Level /
       Alignment / Polarity share tight tracks) and must stay near the
       original footprint. 3.1rem fits the widest alignment value ("-39.9")
       unclipped next to its unit; the unit stays snug against the value
       area. */
    text-align: center;
    padding: 0.35rem 0;
    font-size: 0.92rem;
}

.stepper-control input[type="number"]::-webkit-inner-spin-button,
.stepper-control input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.stepper-control input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

/* Stacked mobile fields have full cell width: restore comfortable touch
   targets for the stepper buttons. */
@media (max-width: 520px) {
    .stepper-btn {
        width: 34px;
    }
    #tab-effects .stepper-control .stepper-input {
        width: 3.4rem;
    }
}
/* ============================================================
   Buttons
   ============================================================ */
.btn-primary,
.btn-secondary,
.btn-danger {
    padding: 0.65rem 1.25rem;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 0.9rem;
    font-weight: 600;
    font-family: inherit;
    min-height: 44px;
    transition: transform 0.1s var(--ease), opacity 0.15s var(--ease), filter 0.15s var(--ease);
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
}
.btn-primary:active,
.btn-secondary:active,
.btn-danger:active { transform: scale(0.96); }
.btn-primary {
    background: var(--accent);
    color: #0d0d0f;
}
.btn-primary:hover { background: var(--accent-hover); filter: brightness(1.05); }
.btn-secondary {
    background: var(--bg-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border);
    min-height: 44px;
    padding: 0.5rem 1rem;
}
.btn-secondary:hover { background: var(--bg-hover); border-color: var(--border-strong); }
.btn-icon {
    min-width: 44px;
    width: 44px;
    padding: 0.65rem;
    font-size: 1.05rem;
}
.btn-icon svg {
    width: 18px;
    height: 18px;
    display: block;
}
#download-selected-tracks .btn-spinner { display: none; }
#download-selected-tracks.is-busy .btn-spinner {
    display: inline-block;
    width: 0.9em;
    height: 0.9em;
    margin-right: 0.35rem;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    vertical-align: -0.1em;
    animation: btn-spin 0.7s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

.btn-danger {
    /* Ghost-danger: destructive actions stay quiet until hovered; the red
       tint signals intent without competing with primary actions. */
    background: var(--danger-dim);
    color: var(--danger);
    border: 1px solid rgba(248, 113, 113, 0.32);
}
.btn-danger:hover {
    background: rgba(248, 113, 113, 0.2);
    border-color: rgba(248, 113, 113, 0.52);
    color: var(--danger);
    opacity: 1;
    filter: none;
}
.btn-primary:disabled,
.btn-secondary:disabled,
.btn-danger:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    transform: none;
}
.btn-danger.hidden { display: none; }

/* Unified upload area */
.upload-area {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    padding: 1.2rem 1rem;
    border: 2px dashed var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--bg-surface);
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
    text-align: center;
    min-height: 80px;
}
.upload-area:hover,
.upload-area.drag-over,
.upload-area:focus-visible {
    border-color: var(--accent);
    background: var(--bg-elevated);
}
.upload-area:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--accent-dim);
}
.upload-area-icon {
    display: inline-flex;
    color: var(--text-secondary);
}

.upload-area-icon svg {
    width: 20px;
    height: 20px;
}
.upload-area-text {
    color: var(--text-secondary);
    font-size: 0.88rem;
}
.upload-area-text u {
    color: var(--accent);
    cursor: pointer;
}
.upload-area-filename {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.upload-area-input {
    position: absolute;
    inset: 0;
    opacity: 0;
    cursor: pointer;
    width: 100%;
    height: 100%;
}

.library-header,
.album-detail-header,
.effects-header {
    gap: 1rem;
}

.btn-primary,
.btn-secondary,
.btn-ghost {
    border-radius: 11px;
}
.measurement-calibration-select-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    gap: 0.5rem;
    align-items: stretch;
}

.measurement-calibration-select-row .btn-secondary,
.measurement-calibration-select-row .btn-danger {
    min-width: 92px;
    padding-left: 0.9rem;
    padding-right: 0.9rem;
}

.measurement-calibration-upload-area {
    min-height: 64px;
    padding: 0.9rem 1rem;
}

.measurement-calibration-upload-area .upload-area-icon {
    font-size: 1.1rem;
}

/* ============================================================
   Playback Bar (fixed bottom)
   ============================================================ */
.playback-bar {
    position: fixed;
    left: 50%;
    bottom: max(6px, env(safe-area-inset-bottom));
    width: min(1560px, calc(100% - 20px));
    min-height: 112px;
    transform: translateX(-50%);
    z-index: var(--z-playback-bar);
    display: grid;
    grid-template-columns: minmax(180px, 0.72fr) minmax(390px, 1.75fr) minmax(130px, 0.52fr) minmax(200px, 0.78fr);
    grid-template-areas: "track transport meter volume";
    align-items: center;
    gap: clamp(0.75rem, 1.3vw, 1.35rem);
    padding: 0.82rem clamp(0.9rem, 1.55vw, 1.45rem);
    border: 1px solid rgba(255,255,255,0.085);
    border-radius: 22px;
    background:
        radial-gradient(circle at 18% 0%, rgba(110,231,183,0.045), transparent 30%),
        linear-gradient(180deg, rgba(24,24,29,0.96), rgba(14,14,18,0.965));
    box-shadow: 0 18px 50px rgba(0,0,0,0.46), inset 0 1px 0 rgba(255,255,255,0.035);
    backdrop-filter: blur(24px) saturate(1.12);
    -webkit-backdrop-filter: blur(24px) saturate(1.12);
    transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.playback-bar.is-playing {
    border-color: rgba(110,231,183,0.18);
    box-shadow: 0 18px 50px rgba(0,0,0,0.46), 0 -1px 22px rgba(110,231,183,0.045), inset 0 1px 0 rgba(255,255,255,0.035);
}
.playback-bar.is-paused {
    border-color: rgba(110, 231, 183, 0.16);
}

.playback-bar .track-info {
    grid-area: track;
    min-width: 0;
    max-width: 100%;
    display: grid;
    grid-template-columns: 72px minmax(0, 1fr);
    align-items: center;
    gap: 0.82rem;
}
.playback-visual {
    position: relative;
    width: 72px;
    height: 72px;
    border-radius: 14px;
    overflow: hidden;
    display: grid;
    place-items: center;
    background:
        radial-gradient(circle at 25% 15%, rgba(110,231,183,0.11), transparent 42%),
        rgba(255,255,255,0.035);
    border: 1px solid rgba(255,255,255,0.09);
    box-shadow: 0 8px 22px rgba(0,0,0,0.28);
}
.playback-cover {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
    cursor: pointer;
    position: relative;
    z-index: var(--z-raised);
}
.playback-cover.hidden { display: none; }
.playback-cover-placeholder {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
}
.playback-visual:has(.playback-cover:not(.hidden)) .playback-cover-placeholder { display: none; }

.track-copy {
    min-width: 0;
    display: grid;
    gap: 0.38rem;
}
.track-fallback,
.playback-bar .song-info {
    grid-column: 1;
    grid-row: 1;
    min-width: 0;
    max-width: 100%;
    display: grid;
    gap: 0.08rem;
}
.playback-bar .song-info:not(:has(> :not(:empty))) { display: none; }
.playback-bar .song-info > :empty { display: none; }
.playback-bar .track-title,
.playback-bar .song-info .sc-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: rgba(255,255,255,0.97);
    font-weight: 720;
    font-size: clamp(0.9rem, 1vw, 1.02rem);
    line-height: 1.25;
    text-align: left;
}
.playback-bar .track-title.placeholder { color: var(--text-muted); font-weight: 560; }
.playback-bar .track-artist,
.playback-bar .song-info .sc-artist,
.playback-bar .song-info .sc-album {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: left;
    color: var(--text-secondary);
    line-height: 1.2;
}
.playback-bar .track-artist,
.playback-bar .song-info .sc-artist { font-size: 0.76rem; font-weight: 590; }
.playback-bar .song-info .sc-album { font-size: 0.7rem; color: var(--text-muted); }
.track-favorite-btn:hover {
    color: var(--accent);
    background: rgba(110,231,183,0.08);
}
.track-favorite-btn:focus-visible {
    color: var(--accent);
    background: rgba(110,231,183,0.08);
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}
.track-favorite-btn:active { transform: scale(.92); }
.track-favorite-btn.active { color: var(--accent); text-shadow: 0 0 12px rgba(110,231,183,.22); }
.track-favorite-btn:disabled { opacity: .45; cursor: wait; }
.playback-meta-row {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex-wrap: nowrap;
    min-height: 1.25rem;
    /* The row must never paint past the track column into the gap before
       the seek time: pills already shrink with ellipsis, this clips any
       remainder at the row edge. */
    overflow: hidden;
}
.playback-meta-row:not(:has(> :not(.hidden):not(:empty))) { display: none; }
.samplerate-status,
.queue-status {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 1.25rem;
    padding: .08rem .48rem;
    border-radius: 999px;
    font-size: .64rem;
    font-weight: 680;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    line-height: 1;
    white-space: nowrap;
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.samplerate-status { background: rgba(148,163,184,.10); color: var(--text-secondary); padding: .08rem .36rem; }
/* The queue pill is text-only: no leading icon, so longer track numbers
   cost less width and the gap to the seek time stays untouched. */
.queue-status { background: rgba(110,231,183,.08); color: var(--accent); }

.playback-center {
    grid-area: transport;
    min-width: 0;
    width: 100%;
    display: grid;
    align-items: center;
    gap: 0.48rem;
}
.control-btn {
    width: 56px;
    height: 56px;
    flex: 0 0 auto;
    display: inline-grid;
    place-items: center;
    border-radius: 50%;
    border: 1px solid rgba(110,231,183,.38);
    background: #203b32;
    color: #f0fff8;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.06);
    cursor: pointer;
    font-size: 1.25rem;
    transition: transform .12s var(--ease), border-color .15s var(--ease), background .15s var(--ease), box-shadow .15s var(--ease);
}
.control-btn:hover:not(:disabled),
.control-btn:focus-visible:not(:disabled) {
    border-color: rgba(110,231,183,.64);
    box-shadow: 0 0 0 3px rgba(110,231,183,.12);
    outline: none;
}
.control-btn:active:not(:disabled) { transform: scale(.94); }
.control-btn:disabled { opacity: .32; cursor: default; }
.control-btn-secondary,
.control-btn-clear {
    width: 38px;
    height: 38px;
    border-color: transparent;
    background: transparent;
    color: var(--text-secondary);
    box-shadow: none;
    font-size: .98rem;
}
.control-btn-secondary:hover:not(:disabled),
.control-btn-secondary:focus-visible:not(:disabled),
.control-btn-clear:hover:not(:disabled),
.control-btn-clear:focus-visible:not(:disabled) {
    color: var(--text-primary);
    background: rgba(255,255,255,.045);
    border-color: rgba(255,255,255,.06);
    box-shadow: none;
}

.seek-row {
    display: grid;
    /* Time cells grow past 2.5rem for long durations instead of overflowing
       toward the slider or the queue pill; the slider yields the width. */
    grid-template-columns: minmax(2.5rem, max-content) minmax(100px, 1fr) minmax(2.5rem, max-content);
    align-items: center;
    gap: .35rem;
    width: 100%;
    min-width: 0;
}
.seek-time {
    color: var(--text-muted);
    font-size: .66rem;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    line-height: 1;
    text-align: center;
    white-space: nowrap;
}
.seek-slider,
.volume-slider {
    --range-progress: 0%;
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    /* Touch hit area: transparent padding expands the drag target to ~25px
       while the negative margin keeps the layout height at the 4px visual
       track. background-clip keeps the gradient on the content box only. */
    margin-block: -10px;
    padding-block: 10px;
    border: 0;
    border-radius: 999px;
    outline: none;
    cursor: pointer;
    box-sizing: content-box;
    /* One slider dialect for the whole footer: seek and volume share track
       height and thumb size in every range. Integer px only, so OS display
       scaling cannot round one slider up and the other down. The ranges
       below only switch the shared desktop size to the shared phone size;
       both sliders always move together. */
    height: 4px;
    background: linear-gradient(to right,
        var(--accent) 0%,
        var(--accent) var(--range-progress),
        rgba(255,255,255,.10) var(--range-progress),
        rgba(255,255,255,.10) 100%);
    background-clip: content-box;
    box-shadow: none;
}
/* Seek and volume share one thumb in every range (single rule, no
   per-slider sizes). */
.seek-slider::-webkit-slider-thumb,
.volume-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #ececf0;
    border: 1px solid rgba(13,13,15,0.8);
    box-shadow: 0 0 0 1px rgba(255,255,255,0.12);
    transition: transform .12s var(--ease), box-shadow .12s var(--ease);
}
.seek-slider::-moz-range-thumb,
.volume-slider::-moz-range-thumb {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #ececf0;
    border: 1px solid rgba(13,13,15,0.8);
    box-shadow: 0 0 0 1px rgba(255,255,255,0.12);
}
.seek-slider:hover::-webkit-slider-thumb,
.volume-slider:hover::-webkit-slider-thumb {
    transform: scale(1.18);
    box-shadow: 0 0 0 2px rgba(110,231,183,.22), 0 2px 6px rgba(0,0,0,0.6);
}
.seek-slider:hover::-moz-range-thumb,
.volume-slider:hover::-moz-range-thumb {
    transform: scale(1.18);
    box-shadow: 0 0 0 2px rgba(110,231,183,.22), 0 2px 6px rgba(0,0,0,0.6);
}
.seek-slider:focus-visible::-webkit-slider-thumb,
.volume-slider:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 3px rgba(110,231,183,.28); }
.seek-slider:focus-visible::-moz-range-thumb,
.volume-slider:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 3px rgba(110,231,183,.28); }

.meter-segments i.is-lit { background: #55d99f; }
.meter-segments i.is-lit.is-warn { background: #e9b949; }
.meter-segments i.is-lit.is-hot { background: #ef7b4f; }
.meter-segments i.is-peak {
    background: #ff5a5f;
    box-shadow: 0 0 8px rgba(255,90,95,.72);
}

.playback-bar .controls {
    grid-area: volume;
    min-width: 0;
}
.volume-control {
    display: grid;
    grid-template-columns: 24px minmax(130px,1fr) 2.5rem;
    align-items: center;
    gap: .5rem;
    min-width: 0;
}
.volume-icon {
    width: 24px;
    height: 24px;
    display: grid;
    place-items: center;
    color: var(--text-secondary);
}
.volume-icon svg { width: 20px; height: 20px; display: block; }
.volume-slider { min-width: 130px; }
.playback-bar .controls.is-adjusting-volume .volume-display { color: var(--text-primary); }

.playback-bar.progress-readonly .seek-slider:disabled {
    cursor: default;
    opacity: 0.9;
}

/* ============================================================
   Playback footer refinement — consolidated survivors
   (verbatim rules previously spread across the v1-v4 blocks)
   ============================================================ */

.control-btn-mode:hover:not(:disabled), .control-btn-mode:focus-visible:not(:disabled) { color: var(--text-primary);
    border-color: rgba(255,255,255,.065);
    background: rgba(255,255,255,.04);
    box-shadow: none; }
.control-btn-mode.active { color: var(--accent);
    border-color: rgba(110,231,183,.16);
    background: rgba(110,231,183,.055); }
.control-btn-mode:disabled { opacity: .28; }
.playback-meter.is-active { opacity: .94; }
.meter-row { display: contents; }
.meter-row[data-channel="left"] .meter-channel { grid-column: 1; grid-row: 1; }
.meter-row[data-channel="left"] .meter-segments { grid-column: 2; grid-row: 1; }
.meter-row[data-channel="right"] .meter-channel { grid-column: 1; grid-row: 2; }
.meter-row[data-channel="right"] .meter-segments { grid-column: 2; grid-row: 2; }
.meter-channel { font-size: .54rem;
    color: rgba(160,160,172,.68);
    text-align: center;
    font-weight: 760;
    line-height: 1; }

/* ============================================================
   Playback footer refinement — consolidated desktop rules
   (v5/v6/v7 passes merged into a single ≥1181px block)
   ============================================================ */
/* The volume cluster stays bounded by its own grid track: speaker left,
   slider middle, percentage right, with constant column gaps. The slider
   is the only flexible part and grows with the track; the percentage
   stays anchored at the track's right edge at every desktop width. The
   metadata caps at 430px and the footer compacts to 98px min-height at
   a 5px bottom inset. */

.transport-controls { display: flex;
    align-items: center;
    justify-content: center;
    min-height: 52px;
    gap: .32rem; }
/* Source switcher replaces transport in bluetooth-input / external-input
   footer modes: compact ‹ label › stepping plus a native select for direct
   choice. No per-input button row, so large interfaces stay compact. */
.playback-bar.source-mode .transport-controls { display: none; }
/* The track/metadata block is irrelevant for line sources: hide it and let
   the switcher absorb its column. Meter and master volume stay untouched. */
.playback-bar.source-mode {
    grid-template-columns: minmax(300px, 1.7fr) minmax(130px, 0.52fr) minmax(200px, 0.78fr);
    grid-template-areas: "transport meter volume";
}
.playback-bar.source-mode .track-info { display: none; }
.source-switcher { display: flex;
    align-items: center;
    justify-content: center;
    min-height: 52px;
    gap: .45rem; }
.source-switcher.hidden { display: none; }
.source-select {
    min-width: 0;
    flex: 1 1 auto;
    max-width: min(460px, 100%);
    padding: .45rem .6rem;
    border: 1px solid rgba(110,231,183,.28);
    border-radius: 999px;
    background: #203b32;
    color: #f0fff8;
    font: inherit;
    font-size: .92rem;
    font-weight: 600;
    text-align: center;
    text-overflow: ellipsis;
    cursor: pointer;
}
.source-select:disabled { opacity: .45; cursor: default; }
.source-select option { background: #16281f; color: #f0fff8; }
.control-btn, .control-btn-secondary, .control-btn-mode, .control-btn-clear { padding: 0;
    line-height: 1;
    align-self: center;
    vertical-align: middle; }
.control-btn-secondary { width: 36px;
    height: 36px;
    font-size: .94rem; }
.control-btn-mode { width: 30px;
    height: 30px;
    border-color: transparent;
    background: transparent;
    color: rgba(160,160,172,.72);
    box-shadow: none;
    font-size: .84rem;
    font-weight: 700; }
.control-btn-clear { width: 30px;
    height: 30px;
    font-size: .78rem;
    margin-left: .08rem;
    color: var(--text-muted); }
.track-copy-main { display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto;
    align-items: start;
    gap: 0.55rem;
    min-width: 0; }
.track-favorite-btn { grid-column: 2;
    grid-row: 1;
    width: 34px;
    height: 34px;
    display: inline-grid;
    place-items: center;
    flex-shrink: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text-secondary);
    font: inherit;
    font-size: 1.3rem;
    cursor: pointer;
    transition: color .15s var(--ease), background .15s var(--ease), transform .12s var(--ease);
    align-self: start;
    margin-top: -.16rem; }
.playback-meter { grid-area: meter;
    min-width: 0;
    display: grid;
    gap: .28rem;
    grid-template-columns: .65rem minmax(94px, 118px) 3.35rem;
    grid-template-rows: 5px 5px;
    width: max-content;
    max-width: none;
    min-height: 28px;
    column-gap: .52rem;
    row-gap: .5rem;
    align-content: center;
    align-items: center;
    justify-self: center;
    align-self: center;
    opacity: .48;
    transition: opacity .15s var(--ease); }
.meter-segments { display: grid;
    grid-template-columns: repeat(12, minmax(3px, 1fr));
    width: 112px;
    min-width: 94px;
    max-width: 118px;
    gap: 2px;
    align-self: center; }
.meter-segments i { display: block;
    height: 5px;
    border-radius: 999px;
    background: rgba(255,255,255,.075);
    transition: background .08s linear, box-shadow .08s linear, opacity .08s linear; }
.output-level-badge { display: inline-flex;
    align-items: center;
    grid-column: 3;
    grid-row: 1 / 3;
    align-self: center;
    justify-self: start;
    width: 2.48rem;
    min-width: 2.48rem;
    padding: 0;
    margin-left: 0;
    justify-content: flex-start;
    text-align: left;
    line-height: 1;
    white-space: nowrap;
    border: 0;
    background: transparent;
    color: rgba(160,160,172,.78);
    font-size: .62rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums; }
.output-level-badge.is-peak {
    color: #ff5a5f;
    text-shadow: 0 0 8px rgba(255,90,95,.48);
}
.volume-display { display: inline-flex;
    position: static;
    justify-content: flex-start;
    min-width: 2.25rem;
    text-align: left;
    padding: 0;
    border: 0;
    background: transparent;
    box-shadow: none;
    color: var(--text-secondary);
    font-size: .69rem;
    font-weight: 650;
    font-variant-numeric: tabular-nums; }

/* Hidden meter segments (JS-driven via .meter-segment-hidden): must win
   over the base .meter-segments i { display: block } row rule. */
.meter-segments .meter-segment-hidden { display: none; }

/* Tablet / compact desktop: give the transport real vertical breathing room,
   keep the album/queue chip inside the track-copy column, and preserve a
   compact right-side meter/volume stack. */

/* Phone: keep the six-segment stereo meter, but give transport/seek/volume
   more air. Seek and volume use identical outer gutters so both slider tracks
   share the same center line and width. */

/* ============================================================
   Playback footer refinement v7 — desktop/tablet vertical compacting
   ============================================================ */
/* Preserve the four-zone layout and control sizing; only reclaim vertical
   breathing room above and below the existing content. Desktop rules live
   in the consolidated ≥1181px block above; this block covers tablets. */

/* ============================================================
   Playback footer refinement v8 — quieter desktop/tablet sliders
   ============================================================ */
/* Keep the input box unchanged for pointer/touch behavior. Only the native
   track paint and thumb are made slightly lighter than the volume control. */

/* Phone: soften only the visible range paint; the input box remains the
   existing size so pointer and touch targeting do not change. */
/* Shared detail track-row body (library album detail + Tidal album/playlist
   detail): track number, round play button, stacked title/sub, favorite,
   duration. One visual language for both providers; the row container chrome
   above is shared too. */
.track-index {
    flex: 0 0 auto;
    width: 1.4rem;
    text-align: right;
    color: var(--text-muted);
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
/* Leading number/play wrapper: transparent so both keep their own flex
   slots on desktop; phones hide the play button and keep the number. */
.track-numplay {
    display: contents;
}
.track-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.12rem;
}
.track-info .track-title {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.track-sub {
    font-size: 0.78rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.track-album {
    flex: 0 1 30%;
    min-width: 0;
    font-size: 0.78rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Desktop-only brand scale-down (~12%): the whole logo lockup shrinks
   uniformly so the first nav tab keeps more clearance from the brand
   without touching the nav buttons or rebalancing the header. */

/* Mobile touch targets: keep the header power button tappable on narrow
   screens (base 38px, refreshed at all widths below). */

/* Small phones: slightly smaller brand lockup than the 760px tablet size.
   Placed after the 760px override so these win on narrow screens. */

/* Mobile: tighten the Spotify/Qobuz player; Tidal browse stays compact and the
   search row may wrap so the button never overflows the viewport. Detail
   headers (library + Tidal) keep the compact side-by-side hero at every
   width: back button on its own right-aligned line, cover anchored left, meta
   block right beside it and left-aligned. No stacking, no centered hero. */


/* Respect reduced-motion preference: collapse animations and transitions. */

/* =========================================================================
   Playback footer — canonical 3 ranges
   ========================================================================= */
@media (min-width: 1181px) {
    .playback-bar {
        grid-template-columns:
            minmax(280px, 430px)
            minmax(390px, 1fr)
            minmax(150px, 220px)
            minmax(220px, 300px);
        row-gap: clamp(.9rem, 1.35vw, 1.35rem);
        column-gap: clamp(.75rem, 1.2vw, 1.25rem);
        bottom: max(5px, env(safe-area-inset-bottom));
        min-height: 98px;
        padding-block: .55rem;
    }
    .playback-bar .track-info {
        width: min(100%, 430px);
        max-width: 430px;
    }
    .playback-bar.source-mode {
        grid-template-columns:
            minmax(390px, 1fr)
            minmax(150px, 220px)
            minmax(220px, 300px);
    }
    .playback-bar .controls {
        width: min(100%, 360px);
        max-width: 360px;
        min-width: 0;
        justify-self: start;
        margin-left: 0;
        margin-right: 0;
        padding-right: 0;
    }
    .volume-control {
        width: 100%;
        max-width: 360px;
        min-width: 0;
        grid-template-columns: 24px minmax(130px, 1fr) 2.5rem;
        column-gap: .42rem;
    }
    .volume-slider {
        width: 100%;
        max-width: none;
        min-width: 0;
    }
    .volume-display {
        width: 2.5rem;
        min-width: 2.5rem;
        justify-content: flex-end;
        text-align: right;
        padding: 0;
    }
    .playback-center { gap: .7rem; }
    .transport-controls {
        margin-top: 1px;
        min-height: 44px;
    }
    .control-btn {
        width: 44px;
        height: 44px;
        font-size: 1rem;
    }
    .control-btn-secondary {
        width: 32px;
        height: 32px;
    }
    .control-btn-mode,
    .control-btn-clear {
        width: 27px;
        height: 27px;
    }
    .track-copy { gap: .28rem; }
    /* Re-assert the intended footer title scale on desktop: the shared
       detail-row ".track-info .track-title" rule (same specificity, later
       source) otherwise pins the footer title to 0.88rem and the vw clamp
       never applies. Id selector keeps this out of the media-range count. */
    #playback-bar .track-title,
    #playback-bar .song-info .sc-title {
        font-size: clamp(0.9rem, 1vw, 1.02rem);
    }
    .playback-meta-row { min-height: 1.1rem; }
    .playback-meter {
        grid-template-columns: .62rem 112px 2.48rem;
        column-gap: .18rem;
        justify-self: center;
    }
    .output-level-badge {
        width: 2.48rem;
        min-width: 2.48rem;
        margin-left: -.04rem;
        justify-content: flex-start;
        text-align: left;
    }
    /* Desktop slider paint and thumb geometry (also applied at ≥901px).
       Both sliders share one reference geometry: 4px line, 12px thumb.
       Integer px only, so fractional OS scaling cannot rasterize seek and
       volume differently. Layout and hit area stay untouched (input
       layout height is absorbed by the time labels and the icon row;
       only paint shrinks). */
    .seek-slider,
    .volume-slider {
        padding-block: 6px;
        margin-block: -6px;
    }
    @media (pointer: coarse) {
        .seek-slider,
        .volume-slider {
            padding-block: 8px;
            margin-block: -8px;
        }
    }
    .seek-slider::-webkit-slider-runnable-track,
    .volume-slider::-webkit-slider-runnable-track {
        height: 4px;
        border-radius: 999px;
        background: linear-gradient(to right,
            var(--accent) 0%,
            var(--accent) var(--range-progress),
            rgba(255,255,255,.10) var(--range-progress),
            rgba(255,255,255,.10) 100%);
    }
    .seek-slider::-moz-range-track,
    .volume-slider::-moz-range-track {
        height: 4px;
        border-radius: 999px;
        background: linear-gradient(to right,
            var(--accent) 0%,
            var(--accent) var(--range-progress),
            rgba(255,255,255,.10) var(--range-progress),
            rgba(255,255,255,.10) 100%);
    }
    .seek-slider::-webkit-slider-thumb { width: 12px; height: 12px; }
    .seek-slider::-moz-range-thumb { width: 12px; height: 12px; }
    .volume-slider::-webkit-slider-thumb { width: 12px; height: 12px; }
    .volume-slider::-moz-range-thumb { width: 12px; height: 12px; }
    /* Chromium anchors the thumb to the track top when the track is shorter
       than the thumb; lift it by half the size difference so the thumb sits
       centered on the 4px line. Integer offset, no fractional rounding.
       Firefox centers natively (webkit only). */
    .seek-slider::-webkit-slider-thumb { margin-top: -4px; }
    .volume-slider::-webkit-slider-thumb { margin-top: -4px; }
    /* Both lines paint slimmer than the input box (both engines); the input
       paint height drops with them so the green fill reads 4px too. */
    .seek-slider,
    .volume-slider { height: 4px; }
    /* Meter segments match the 4px slider lines. */
    .meter-segments i { height: 4px; }

    /* Small-laptop Full-HD viewports (13-14", effective CSS width up to
       1600px, e.g. 1920px at 125% OS scale): type reads slightly larger
       while controls keep the discreet desktop sizing above. Nested inside
       the desktop range so the 3-range playback contract (1181 / 701-1180 /
       700) stays intact; footer selectors use the #playback-bar id so this
       band adds no new ".playback-bar" media range. */
    @media (max-width: 1600px) {
        #playback-bar .track-title,
        #playback-bar .song-info .sc-title {
            font-size: clamp(0.96rem, 0.82rem + 0.45vw, 1.04rem);
        }
        #playback-bar .track-artist,
        #playback-bar .song-info .sc-artist { font-size: 0.8rem; }
        #playback-bar .song-info .sc-album { font-size: 0.73rem; }
        #playback-bar .seek-time { font-size: 0.7rem; }
        #playback-bar .volume-display { font-size: 0.73rem; }
        #playback-bar .samplerate-status,
        #playback-bar .queue-status { font-size: 0.67rem; }
        #playback-bar .meter-channel { font-size: 0.57rem; }
        #playback-bar .output-level-badge { font-size: 0.65rem; }
        .tab-btn { font-size: 0.94rem; }
        .section-title { font-size: 1.12rem; }
        .section-subtitle { font-size: 0.96rem; }
        .station-name { font-size: 1rem; }
    }
}

@media (min-width: 701px) and (max-width: 1180px) {
    .playback-bar {
        bottom: max(5px, env(safe-area-inset-bottom));
        width: calc(100% - 16px);
        min-height: 116px;
        grid-template-columns:
            minmax(220px, .96fr)
            minmax(240px, 1.18fr)
            minmax(170px, .78fr);
        grid-template-rows: minmax(46px, auto) minmax(42px, auto);
        grid-template-areas:
            "track transport meter"
            "track transport volume";
        column-gap: clamp(.72rem, 1.2vw, 1rem);
        row-gap: .4rem;
        align-items: center;
        padding: .6rem .9rem .64rem;
        border-radius: var(--radius-xl);
    }
    .playback-bar .track-info {
        grid-template-columns: 60px minmax(0, 1fr);
        gap: .7rem;
        max-width: none;
        min-width: 0;
    }
    .playback-bar.source-mode {
        grid-template-columns:
            minmax(240px, 1.18fr)
            minmax(170px, .78fr);
        grid-template-rows: minmax(46px, auto) minmax(42px, auto);
        grid-template-areas:
            "transport meter"
            "transport volume";
    }
    .playback-visual {
        width: 60px;
        height: 60px;
        border-radius: var(--radius-md);
    }
    .track-copy,
    .track-copy-main,
    .playback-meta-row {
        min-width: 0;
        max-width: 100%;
    }
    .track-copy { gap: .24rem; }
    .playback-meta-row {
        min-height: 1.1rem;
        overflow: hidden;
    }
    .samplerate-status {
        max-width: calc(100% - 3rem);
        flex: 1 1 auto;
    }
    .queue-status {
        flex: 0 0 auto;
    }
    .playback-center {
        width: 100%;
        gap: .64rem;
        align-self: center;
    }
    .transport-controls {
        min-height: 40px;
        margin: 0;
        gap: .3rem;
    }
    .control-btn {
        width: 40px;
        height: 40px;
        font-size: .92rem;
    }
    .control-btn-secondary {
        width: 30px;
        height: 30px;
        font-size: .86rem;
    }
    .control-btn-mode,
    .control-btn-clear {
        width: 25px;
        height: 25px;
        font-size: .76rem;
    }
    .seek-row {
        grid-template-columns: minmax(2.65rem, max-content) minmax(100px, 1fr) minmax(2.65rem, max-content);
        gap: .42rem;
        min-width: 0;
        margin-top: .02rem;
    }
    .playback-meter {
        width: max-content;
        max-width: none;
        grid-template-columns: .58rem 82px;
        grid-template-rows: 4px 4px;
        column-gap: .26rem;
        row-gap: .42rem;
        justify-self: center;
        align-self: end;
        margin: 0 0 .2rem;
    }
    .meter-segments {
        grid-template-columns: repeat(8, minmax(3px, 1fr));
        width: 82px;
        min-width: 82px;
        max-width: 82px;
        gap: 1.7px;
    }
    .meter-segments i { height: 4px; }
    .playback-bar .controls {
        width: min(100%, 235px);
        max-width: 235px;
        justify-self: center;
        align-self: start;
        margin-top: .2rem;
        padding: 0;
    }
    .volume-control {
        width: 100%;
        justify-self: center;
        margin: 0 auto;
        grid-template-columns: 20px minmax(0, 1fr) 2.25rem;
        gap: .42rem;
    }
    .volume-slider { min-width: 0; }
    .volume-display {
        min-width: 2.25rem;
        justify-content: flex-start;
    }
    /* Tablet slider paint and thumb geometry (applied at ≥901px).
       Same shared 4px/12px reference geometry as desktop for both sliders.
       The 10px touch padding from the base rule is untouched so the tap
       target stays large. */
    .seek-slider::-webkit-slider-runnable-track,
    .volume-slider::-webkit-slider-runnable-track {
        height: 4px;
        border-radius: 999px;
        background: linear-gradient(to right,
            var(--accent) 0%,
            var(--accent) var(--range-progress),
            rgba(255,255,255,.10) var(--range-progress),
            rgba(255,255,255,.10) 100%);
    }
    .seek-slider::-moz-range-track,
    .volume-slider::-moz-range-track {
        height: 4px;
        border-radius: 999px;
        background: linear-gradient(to right,
            var(--accent) 0%,
            var(--accent) var(--range-progress),
            rgba(255,255,255,.10) var(--range-progress),
            rgba(255,255,255,.10) 100%);
    }
    .seek-slider::-webkit-slider-thumb { width: 12px; height: 12px; }
    .seek-slider::-moz-range-thumb { width: 12px; height: 12px; }
    .volume-slider::-webkit-slider-thumb { width: 12px; height: 12px; }
    .volume-slider::-moz-range-thumb { width: 12px; height: 12px; }
    /* Chromium anchors the thumb to the track top when the track is shorter
       than the thumb; lift it by half the size difference so the thumb sits
       centered on the 4px line. Integer offset, no fractional rounding.
       Firefox centers natively (webkit only). */
    .seek-slider::-webkit-slider-thumb { margin-top: -4px; }
    .volume-slider::-webkit-slider-thumb { margin-top: -4px; }
    /* Both lines paint slimmer than the input box (both engines); the input
       paint height drops with them so the green fill reads 4px too. */
    .seek-slider,
    .volume-slider { height: 4px; }
}

@media (max-width: 700px) {
    .playback-bar {
        bottom: max(3px, env(safe-area-inset-bottom));
        width: calc(100% - 12px);
        min-height: 0;
        grid-template-columns: minmax(0, 1fr) 84px;
        grid-template-rows: auto auto auto;
        grid-template-areas:
            "track meter"
            "transport transport"
            "volume volume";
        column-gap: .6rem;
        row-gap: .66rem;
        align-items: center;
        padding: .76rem .7rem .82rem;
        border-radius: 18px;
    }
    .playback-bar .track-info {
        grid-template-columns: 50px minmax(0, 1fr);
        gap: .6rem;
        max-width: none;
        align-self: center;
    }
    .playback-bar.source-mode {
        grid-template-columns: minmax(0, 1fr) 84px;
        grid-template-areas:
            "meter meter"
            "transport transport"
            "volume volume";
    }
    .playback-visual {
        width: 50px;
        height: 50px;
        border-radius: 11px;
    }
    .track-copy { gap: .18rem; }
    .track-copy-main { gap: .25rem; }
    .playback-bar .track-title,
    .playback-bar .song-info .sc-title {
        font-size: .86rem;
        line-height: 1.15;
    }
    .playback-bar .track-artist,
    .playback-bar .song-info .sc-artist {
        display: block;
        font-size: .68rem;
    }
    .track-favorite-btn,
    .track-row-favorite,
    .track-fav,
    .streaming-fav {
        width: 28px;
        height: 28px;
        min-height: 28px;
        margin-top: -.08rem;
        font-size: 1.08rem;
    }
    .playback-meta-row {
        gap: .25rem;
        min-height: 1rem;
        margin-top: 0;
    }
    .samplerate-status,
    .queue-status {
        min-height: 1rem;
        padding: .06rem .38rem;
        font-size: .56rem;
    }
    .samplerate-status { padding: .06rem .30rem; }
    .playback-center {
        width: 100%;
        gap: .72rem;
        align-self: center;
        margin: 0;
    }
    .transport-controls {
        min-height: 40px;
        margin: 0;
        gap: .32rem;
    }
    .control-btn {
        width: 40px;
        height: 40px;
        font-size: .92rem;
    }
    .control-btn-secondary {
        width: 29px;
        height: 29px;
        font-size: .8rem;
    }
    .control-btn-mode,
    .control-btn-clear {
        width: 24px;
        height: 24px;
        font-size: .72rem;
    }
    .seek-row {
        width: 100%;
        grid-template-columns: minmax(2.55rem, max-content) minmax(0, 1fr) minmax(2.55rem, max-content);
        row-gap: .38rem;
        column-gap: .4rem;
        margin: 0;
    }
    .seek-time {
        text-align: center;
        font-size: .59rem;
    }
    #seek-duration {
        text-align: right;
        padding-right: .08rem;
    }
    .seek-slider,
    .volume-slider {
        width: 100%;
        min-width: 0;
    }
    .playback-meter {
        width: 84px;
        max-width: 84px;
        grid-template-columns: .52rem 62px;
        grid-template-rows: 4px 4px;
        column-gap: .22rem;
        row-gap: .4rem;
        justify-self: end;
        align-self: center;
        min-height: 20px;
        margin: 0;
    }
    .meter-channel { font-size: .5rem; }
    .meter-segments {
        grid-template-columns: repeat(6, minmax(3px, 1fr));
        width: 62px;
        min-width: 62px;
        max-width: 62px;
        gap: 1.6px;
    }
    .meter-segments i {
        height: 4px;
        border-radius: 999px;
    }
    .output-level-badge { display: none; }
    /* Phone: volume percent shares the seek duration right value column. */
    .playback-bar .controls {
        width: 100%;
        max-width: none;
        justify-self: stretch;
        padding: 0;
        margin: 0;
    }
    .volume-control {
        width: 100%;
        grid-template-columns: minmax(2.55rem, max-content) minmax(0, 1fr) minmax(2.55rem, max-content);
        align-items: center;
        row-gap: .44rem;
        column-gap: .4rem;
    }
    .volume-icon {
        width: 20px;
        height: 20px;
        justify-self: center;
    }
    .volume-icon svg {
        width: 18px;
        height: 18px;
    }
    /* One slider dialect on phone too: seek and volume share the 4px line
       and the 12px thumb, same as desktop; both sliders always move
       together. */
    .seek-slider,
    .volume-slider { height: 4px; }
    .seek-slider::-webkit-slider-thumb { width: 12px; height: 12px; }
    .seek-slider::-moz-range-thumb { width: 12px; height: 12px; }
    .volume-slider::-webkit-slider-thumb { width: 12px; height: 12px; }
    .volume-slider::-moz-range-thumb { width: 12px; height: 12px; }
    .volume-display {
        width: 2.55rem;
        min-width: 2.55rem;
        justify-content: flex-end;
        align-items: center;
        text-align: right;
        padding-right: .08rem;
        font-size: .64rem;
        line-height: 1;
    }
    /* Phone: no-media fallback keeps track + volume only. */
    .playback-bar:not(.has-media) {
        grid-template-areas:
            "track track"
            "volume volume";
    }
    .playback-bar:not(.has-media) .playback-center,
    .playback-bar:not(.has-media) .playback-meter { display: none; }
    /* Phone slider paint and thumb geometry. */
    .seek-slider::-webkit-slider-runnable-track,
    .volume-slider::-webkit-slider-runnable-track {
        height: 4px;
        border-radius: 999px;
        background: linear-gradient(to right,
            var(--accent) 0%,
            var(--accent) var(--range-progress),
            rgba(255,255,255,.10) var(--range-progress),
            rgba(255,255,255,.10) 100%);
    }
    .seek-slider::-moz-range-track,
    .volume-slider::-moz-range-track {
        height: 4px;
        border-radius: 999px;
        background: linear-gradient(to right,
            var(--accent) 0%,
            var(--accent) var(--range-progress),
            rgba(255,255,255,.10) var(--range-progress),
            rgba(255,255,255,.10) 100%);
    }
    .seek-slider::-webkit-slider-thumb { width: 12px; height: 12px; }
    .seek-slider::-moz-range-thumb { width: 12px; height: 12px; }
    /* Chromium anchors the thumb to the track top when the track is shorter
       than the thumb; lift it by half the size difference so the thumb sits
       centered on the 4px track. Integer offset, no fractional rounding.
       Firefox centers natively (webkit only). */
    .seek-slider::-webkit-slider-thumb { margin-top: -4px; }
    .volume-slider::-webkit-slider-thumb { margin-top: -4px; }

    @media (max-width: 360px) {
        .playback-bar .track-info {
            grid-template-columns: 46px minmax(0, 1fr);
            gap: .5rem;
        }
        .playback-visual {
            width: 46px;
            height: 46px;
        }
        .playback-bar {
            grid-template-columns: minmax(0, 1fr) 78px;
            row-gap: .6rem;
            padding-inline: .6rem;
        }
        .playback-meter {
            width: 78px;
            max-width: 78px;
            grid-template-columns: .5rem 57px;
        }
        .meter-segments {
            width: 57px;
            min-width: 57px;
            max-width: 57px;
        }
        .seek-row,
        .volume-control {
            grid-template-columns: 2.35rem minmax(0, 1fr) 2.35rem;
            column-gap: .34rem;
        }
        .volume-display {
            width: 2.35rem;
            min-width: 2.35rem;
        }
    }

    @media (max-width: 390px) {
        .playback-bar {
            grid-template-areas: "track track" "transport transport" "volume volume";
        }
        .playback-meter { display: none; }
    }
}

/* =========================================================================
   Shared component queries — grouped by range
   ========================================================================= */
@media (hover: none), (pointer: coarse) {
    /* from _layout.css */
    .brand-lockup-button[data-tooltip]::after,
        .power-btn[data-tooltip]::after {
            display: none;
        }

    /* from _radio.css */
    #tracks-list .folder-actions {
            opacity: 1;
        }

    /* Touch hit-area expansion: visuals stay compact while the tap target
       reaches ~44px via an invisible overlay. No layout shift on desktop. */
    .control-btn-mode,
    .control-btn-clear,
    .track-favorite-btn,
    .streaming-fav,
    .track-row-favorite,
    .track-fav,
    .stepper-btn,
    .measurement-chip,
    .measurement-slot-chip,
    .measurement-peq-chip {
        position: relative;
    }
    /* Cover favorites are already absolutely positioned. Keep that anchor:
       making them relative pulls them into the card flow on touch screens. */
    .control-btn-mode::after,
    .control-btn-clear::after,
    .track-favorite-btn::after,
    .album-card-fav::after,
    .station-card-fav::after,
    .streaming-fav::after,
    .track-row-favorite::after,
    .track-fav::after,
    .stepper-btn::after,
    .measurement-chip::after,
    .measurement-slot-chip::after,
    .measurement-peq-chip::after {
        content: '';
        position: absolute;
        inset: -8px;
    }
    .control-btn-mode::after,
    .control-btn-clear::after {
        inset: -10px;
    }

}

@media (max-width: 540px) {
    /* from _layout.css */
    .power-btn-icon { width: 20px; height: 20px; }

    /* from _playback.css */
    .power-btn { width: 44px; height: 44px; }

}

@media (max-width: 980px) {
    /* from _streaming.css */
    .measurement-layout {
            grid-template-columns: 1fr;
        }

        .measurement-dialog {
            min-height: auto;
        }

}

@media (min-width: 641px) and (max-width: 980px) {
    .measurement-overlay {
        padding: 0.5rem;
    }
    .measurement-dialog {
        width: min(1040px, 100%);
        min-height: min(960px, calc(100vh - 1rem));
        min-height: min(960px, calc(100dvh - 1rem));
        max-height: calc(100vh - 1rem);
        max-height: calc(100dvh - 1rem);
        padding: 1rem;
    }
    .measurement-actions-top {
        align-items: flex-start;
    }
    .measurement-workflow-list {
        width: 100%;
    }
    .measurement-graph-wrap {
        padding: 0.9rem;
    }
    .measurement-graph {
        min-height: 460px;
    }
    .measurement-peq-editor-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0.75rem 0.8rem;
        align-items: start;
    }
    .measurement-peq-direct-input-field {
        grid-column: auto;
    }
    .measurement-peq-stepper {
        grid-template-columns: 42px minmax(96px, 1fr) 42px;
    }
    .measurement-peq-editor-actions {
        grid-column: 1 / -1;
        justify-content: flex-start;
    }
    .library-search-field {
        flex-basis: clamp(260px, 30vw, 400px);
        width: clamp(260px, 30vw, 400px);
    }
    .library-selection-toolbar .btn-secondary {
        min-width: 104px;
    }
}

@media (min-width: 600px) and (max-width: 640px) {
    .measurement-overlay {
        padding: 0.5rem;
        align-items: stretch;
    }
    .measurement-dialog {
        width: min(1040px, 100%);
        min-height: min(960px, calc(100vh - 1rem));
        min-height: min(960px, calc(100dvh - 1rem));
        max-height: calc(100vh - 1rem);
        max-height: calc(100dvh - 1rem);
        padding: 1rem;
        border-radius: var(--radius-xl);
    }
    .measurement-actions-top {
        align-items: flex-start;
    }
    .measurement-workflow-list {
        width: 100%;
    }
    .measurement-graph-wrap {
        padding: 0.9rem;
    }
    .measurement-graph {
        min-height: 460px;
    }
    .measurement-peq-editor-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0.75rem 0.8rem;
        align-items: start;
    }
    .measurement-peq-direct-input-field {
        grid-column: auto;
    }
    .measurement-peq-stepper {
        grid-template-columns: 42px minmax(96px, 1fr) 42px;
    }
    .measurement-peq-editor-actions {
        grid-column: 1 / -1;
        justify-content: flex-start;
    }
}

@media (min-width: 600px) and (max-width: 980px) and (orientation: portrait) {
    /* from _streaming.css */
    .measurement-graph {
            height: min(430px, 42vh);
            min-height: 0;
        }

}

@media (max-width: 599px) {
    /* from _streaming.css */
    .measurement-overlay {
            padding: 0.5rem;
            overflow-x: hidden;
            align-items: center;
        }

        .measurement-dialog {
            width: 100%;
            min-height: auto;
            max-height: calc(100dvh - 1rem);
            padding: 0.85rem;
            border-radius: var(--radius-lg);
            overflow-x: hidden;
        }

        .measurement-dialog input,
        .measurement-dialog select,
        .measurement-dialog textarea {
            font-size: 16px;
        }

        .measurement-card-header-split,
        .measurement-list-row,
        .measurement-actions-top {
            flex-direction: column;
            align-items: flex-start;
        }

        .measurement-graph-header-actions {
            width: 100%;
            display: grid;
            grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
            gap: 0.55rem;
            margin-left: 0;
            align-items: stretch;
        }

        .measurement-graph-header-actions .measurement-view-toggle {
            grid-column: 1;
            grid-row: 1;
            min-width: 0;
            justify-content: flex-start;
        }

        .measurement-graph-header-actions .measurement-clear-btn {
            grid-column: 2;
            grid-row: 1;
            width: 100%;
        }

        .measurement-graph-header-actions #measurement-assist-mode,
        .measurement-graph-header-actions #measurement-target-curve {
            grid-row: 2;
            width: 100%;
            min-width: 0;
        }

        .measurement-graph-header-actions #measurement-assist-mode {
            grid-column: 1;
        }

        .measurement-graph-header-actions #measurement-target-curve {
            grid-column: 2;
        }

        .measurement-summary {
            text-align: left;
            max-width: none;
        }

        .measurement-saved-merge-action.is-inert,
        .measurement-saved-delete-action.is-inert {
            display: none;
        }

        .measurement-saved-group > summary,
        .measurement-saved-toolbar button,
        .measurement-select-all-toggle {
            font-size: 16px;
            touch-action: manipulation;
        }

        .measurement-graph {
            min-height: 260px;
        }

        .measurement-convolver-grid { grid-template-columns: 1fr; }
        .measurement-peq-panel-header {
            flex-direction: column;
            align-items: stretch;
        }

        #measurement-custom-house-curve-panel {
            grid-template-columns: 1fr;
        }

        #measurement-custom-house-curve-panel > .field-group,
        #measurement-custom-house-curve-panel > .measurement-peq-take-row {
            grid-column: 1 / -1;
        }

        #measurement-custom-house-curve-panel > .measurement-peq-take-row {
            flex-direction: column;
            align-items: stretch;
            min-width: 0;
        }

        #measurement-custom-house-curve-panel > .measurement-peq-take-row .btn-primary {
            width: 100%;
        }

        .measurement-peq-editor-grid {
            grid-template-columns: 1fr 1fr;
        }

        .measurement-peq-editor-grid .measurement-peq-direct-input-field {
            grid-column: 1 / -1;
        }

        .measurement-peq-stepper {
            grid-template-columns: 44px minmax(0, 1fr) 44px;
        }

        .measurement-peq-editor-grid .url-input {
            font-size: 16px;
        }

        .measurement-peq-editor-actions,
        .measurement-peq-take-row,
        .measurement-save-row {
            justify-content: stretch;
        }

        .measurement-save-row,
        .measurement-workflow-list {
            align-items: stretch;
        }

        .measurement-workflow-list {
            flex: 0 0 auto;
            width: 100%;
            gap: 0.9rem;
        }

        .measurement-workflow-group {
            display: flex;
            align-items: stretch;
            flex-direction: column;
            gap: 0.55rem;
        }

        .measurement-workflow-menu {
            width: 100%;
        }

        .measurement-workflow-menu-panel {
            position: static;
            width: 100%;
            max-width: none;
            box-sizing: border-box;
        }

        .measurement-workflow-row {
            display: flex;
            align-items: stretch;
            flex-direction: column;
            gap: 0.55rem;
        }

        .measurement-repeat-help {
            flex: 0 0 auto;
        }

        #measurement-sweep-toggle,
        #measurement-repeat-start,
        #measurement-hybrid-open,
    #measurement-auto-sub-start,
        #measurement-spl-calibration-open {
            width: 100%;
            min-width: 0;
        }

        .spl-calibration-dialog {
            width: 100%;
            max-height: calc(100dvh - 1rem);
            padding: 0.85rem;
            border-radius: var(--radius-lg);
        }

        .hybrid-measurement-dialog {
            width: 100%;
            max-height: calc(100dvh - 1rem);
            padding: 0.85rem;
            border-radius: var(--radius-lg);
        }

        .hybrid-wizard-grid { grid-template-columns: 1fr; }
        .hybrid-room-view { min-height: 300px; }
        .hybrid-step-card { min-height: 390px; }
        .hybrid-action-row { position: sticky; bottom: -0.85rem; margin-inline: -0.85rem; padding: 0.75rem 0.85rem; background: var(--bg-surface); }

        .measurement-channel-chip-row,
        .measurement-smoothing-chips {
            width: 100%;
            justify-content: flex-start;
        }

        .measurement-channel-chip-row {
            justify-content: center;
        }

        .measurement-card-setup,
        .measurement-card-setup .measurement-stack,
        .measurement-card-setup .field-group {
            min-width: 0;
        }

        .measurement-input-channel-grid,
        .measurement-input-channel-grid.is-split {
            grid-template-columns: 1fr;
        }

        .measurement-card-setup .url-input,
        #measurement-input-refresh {
            width: 100%;
            min-width: 0;
        }

        .measurement-calibration-select-row {
            grid-template-columns: 1fr;
        }

        .measurement-calibration-select-row .btn-secondary,
        .measurement-calibration-select-row .btn-danger {
            width: 100%;
            min-width: 0;
        }

        .measurement-peq-editor-actions .btn-danger,
        .measurement-peq-take-row .btn-secondary,
        .measurement-save-row .btn-secondary,
        #measurement-repeat-start {
            width: 100%;
        }

        .measurement-peq-step-btn {
            width: 44px;
        }

}

@media (min-width: 1200px) and (max-width: 2559px) {
    /* from _playback.css */
    .radio-search-input-wrap {
            margin-inline: 6.5rem;
        }

}

@media (min-width: 900px) and (max-width: 1199px) {
    /* from _playback.css */
    .radio-search-input-wrap {
            margin-inline: 5.125rem;
        }

}

@media (min-width: 2560px) {
    /* from _playback.css */
    .radio-search-input-wrap {
            margin-inline: 4.125rem;
        }
        .manage-dialog {
            width: min(620px, 100%);
        }

}

@media (min-width: 701px) and (max-width: 1199px) {
    .radio-panel-header {
            grid-template-columns: minmax(0, 1fr) minmax(420px, calc(100% - 13.8rem)) minmax(0, 1fr);
        }

}

@media (max-width: 900px) {
    /* from _playback.css */
    .manage-dialog {
            width: min(620px, 100%);
        }
        .effects-grid {
            grid-template-columns: 1fr;
            gap: 1rem;
        }
        .effects-card { padding: 1.25rem; }
        .effects-actions-right { justify-content: flex-end; }

}

@media (max-width: 1180px) {
    /* from _playback.css */
    .library-actions-row {
            align-items: center;
            margin-bottom: 0.5rem;
        }
        .playlist-save-row {
            flex-direction: column;
            align-items: stretch;
            gap: 0.5rem;
            margin-bottom: 0.7rem;
        }
        .playlist-save-controls {
            width: 100%;
            flex: 0 1 auto;
        }
        /* TIDAL save row: with the full-width controls container the five
           controls wrap left-aligned instead of overflowing. */
        .tidal-playlist-save-row .playlist-save-controls {
            flex-wrap: wrap;
        }

}

@media (max-width: 1180px) and (min-width: 601px) {
    /* from _playback.css */
    .library-actions-row {
            margin-bottom: var(--action-gap);
        }
    /* Album detail keeps a single continuous action line on tablet: the row
       stays horizontal and the fields shrink before anything wraps. Only the
       phone layout below switches to a stacked grid. */
    .playlist-save-row.tidal-playlist-save-row--album {
        flex-direction: row;
        align-items: center;
        width: 100%;
    }
    .tidal-playlist-save-row--album .playlist-save-controls {
        flex-wrap: nowrap;
        width: 100%;
    }
    .tidal-playlist-save-row--album #tidal-playlist-name {
        min-width: 120px;
    }
    .tidal-playlist-save-row--album #tidal-playlist-target {
        min-width: 140px;
    }

}

@media (max-width: 600px) {
    /* from _playback.css */
    .library-toolbar,
        .effects-header-actions {
            gap: var(--action-gap-mobile);
        }
        .library-toolbar {
            flex-wrap: nowrap;
            overflow-x: auto;
            scrollbar-width: none;
            -webkit-overflow-scrolling: touch;
        }
        .library-toolbar::-webkit-scrollbar {
            display: none;
        }

        .track-artist {
            display: block;
            min-width: 0;
            max-width: 100%;
            font-size: 0.72rem;
            line-height: 1.2;
        }
        .library-toolbar #toggle-import {
            width: auto;
            min-width: 104px;
            max-width: none;
            height: auto;
            min-height: 44px;
            max-height: none;
            padding: 0.55rem 0.8rem;
            font-size: 0.84rem;
            line-height: 1;
            align-self: center;
            white-space: nowrap;
            overflow: visible;
            display: inline-flex;
            align-items: center;
            justify-content: center;
        }
        #tab-library {
            padding-top: 0;
        }
        #tab-effects {
            padding-top: 0;
        }
        .header {
            flex-direction: row;
            gap: 0.65rem;
        }
        .brand-lockup {
            gap: 0.5rem;
            flex: 1;
            min-width: 0;
        }
        .brand-text-block {
            gap: 0.06rem;
            padding-top: 0;
        }
        .manage-overlay {
            padding: 0.75rem;
            align-items: flex-end;
        }
        .manage-dialog {
            width: 100%;
            max-height: 85vh;
            overflow: auto;
            border-radius: 18px 18px 0 0;
        }
        .manage-dialog-header {
            flex-direction: column;
            align-items: stretch;
        }
        .radio-manage-submit-row {
            justify-content: stretch;
        }
        .radio-manage-submit-row .btn-primary,
        .manage-dialog-header .btn-secondary {
            width: 100%;
        }
        .settings-maintenance-actions {
            grid-template-columns: 1fr;
            width: 100%;
            margin-left: 0;
        }
        .btn-ghost {
            font-size: 0.78rem;
            padding: 0.3rem 0.55rem;
            min-height: 32px;
        }
        .btn-ghost-icon {
            font-size: 0.85rem;
        }
        /* Library tighter */
        .library-actions-row {
            align-items: stretch;
            justify-content: flex-start;
            flex-wrap: wrap;
            margin-bottom: 0.5rem;
        }
        .library-search-wrap {
            flex-basis: 100%;
            width: 100%;
            display: grid;
            grid-template-columns: minmax(0, 1fr);
            gap: var(--action-gap-mobile, 8px);
            align-items: stretch;
        }
        .library-search-field {
            flex: 1 1 auto;
            width: 100%;
            min-width: 0;
        }
        .library-selection-toolbar {
            width: 100%;
            min-width: 0;
            display: flex;
            gap: var(--action-gap-mobile, 8px);
            flex-wrap: wrap;
        }
        .library-selection-toolbar .btn-secondary {
            flex: 1 1 0;
            width: auto;
            min-width: 0;
            height: 44px;
            min-height: 44px;
        }
        .track-item { padding: 0.7rem 0.75rem; }
        /* Phones: no separate play button in track rows; the row stays the tap trigger. */
        .track-item .track-play,
        .streaming-result .track-play { display: none; }
        /* Download */
        .playlist-save-row {
            flex-wrap: nowrap;
            align-items: stretch;
            margin-bottom: 0.7rem;
        }
        .playlist-save-controls {
            width: 100%;
            display: grid;
            grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
            gap: var(--action-gap-mobile, 8px);
            align-items: stretch;
            flex: 1 1 auto;
            min-width: 0;
        }
        .playlist-save-row .url-input {
            grid-column: 1 / -1;
            flex: initial;
            width: 100%;
            min-width: 0;
            font-size: 16px;
            padding: 0.28rem 0.5rem;
        }
        #save-playlist,
        #cancel-playlist-selection {
            width: 100%;
            min-width: 0;
            height: 44px;
            min-height: 44px;
        }
        .download-form { flex-direction: column; }
        .download-form .btn-primary,
        .download-form .btn-danger { width: 100%; }
        /* Effects */
        #tab-effects,
        #tab-effects .effects-shell,
        #tab-effects .effects-grid,
        #tab-effects .effects-card {
            width: 100%;
            max-width: 100%;
            min-width: 0;
        }
        #tab-effects,
        #tab-effects .effects-shell {
            overflow-x: clip;
        }
        .effects-shell { padding: 0; }
        .effects-header {
            flex-direction: column;
            align-items: stretch;
            gap: 0.75rem;
            margin-bottom: 0.75rem;
        }
        .effects-header-actions { justify-content: flex-start; }
        .effects-peq-band-fields {
            grid-template-columns: 1fr;
        }
        .effects-peq-band-header,
        .effects-peq-pane-header {
            flex-direction: column;
            align-items: stretch;
        }
        .effects-actions-row .btn-primary,
        .effects-actions-row .btn-danger,
        .effects-actions-row .btn-secondary { width: 100%; min-width: unset; }
        .effects-actions-right { flex-direction: column; align-items: stretch; }
        .toast-container {
            /* Limit the width instead of letting the toasts span nearly the
               whole viewport: 20px each side, capped so the column does not
               grow on wider phones, and centered exactly. */
            left: 50%;
            right: auto;
            width: calc(100% - 40px);
            max-width: 360px;
            transform: translateX(-50%);
        }

    /* from _playback.css */
    .cover-detail-card {
            bottom: var(--playback-footer-space, calc(102px + 8px + 14px));
            width: min(400px, calc(100% - 1.2rem));
            max-height: calc(100vh - var(--playback-footer-space, calc(102px + 8px + 14px)) - 1rem);
            max-height: calc(100dvh - var(--playback-footer-space, calc(102px + 8px + 14px)) - 1rem);
            grid-template-columns: 1fr;
            grid-template-areas:
                "cover"
                "info"
                "history"
                "queue";
        }
        .cover-detail-cover-col {
            align-items: center;
        }
        .cover-detail-cover {
            width: auto;
            max-width: 100%;
            max-height: 34vh;
            margin-inline: auto;
        }
        .cover-detail-extra {
            align-items: center;
            text-align: center;
        }

    /* Touch targets that can grow without moving surrounding layout. */
    .catalog-station-action { min-height: 44px; }
    .dialog-header-corner-close .btn-close-manage { width: 44px; height: 44px; min-height: 44px; }
    .measurement-chip { min-height: 44px; }
    .measurement-view-toggle .measurement-chip { min-height: 44px; }
    .measurement-slot-chip,
    .measurement-peq-chip { min-height: 44px; }

    /* iOS auto-zoom guard: text inputs stay at 16px on phones. */
    .station-search-input,
    .library-search-field .library-search-input,
    .streaming-search-input,
    .playlist-save-row .url-input {
        font-size: 16px;
    }

}

@media (max-width: 760px) {
    /* from _playback.css */
    #tab-effects .url-input,
        #tab-effects select,
        #tab-effects textarea {
            font-size: 16px;
        }
    /* iOS auto-zoom guard for the remaining form controls (library, radio,
       streaming, settings, measurement). Desktop keeps the compact sizes. */
    .station-search-input,
        .library-search-field .library-search-input,
        .streaming-search-input,
        .url-input,
        select.url-input,
        .manage-dialog input,
        .manage-dialog select,
        .manage-dialog textarea,
        .measurement-dialog input,
        .measurement-dialog select,
        .measurement-dialog textarea {
            font-size: 16px;
        }

        #tab-effects .effects-actions-rew-dual {
            grid-template-columns: repeat(2, minmax(0, 1fr));
            align-items: start;
            gap: 0.9rem;
        }

        #tab-effects .effects-actions-peq-dual {
            grid-template-columns: minmax(0, 1fr);
            align-items: start;
            gap: 0.8rem;
        }

        #tab-effects .effects-actions-combine {
            display: grid;
            grid-template-columns: minmax(0, 1fr) auto;
            align-items: center;
            gap: 0.7rem;
        }

        #tab-effects .effects-actions-peq-dual .effects-rew-dual-name-input {
            max-width: none;
        }

        #tab-effects .effects-actions-rew-dual .effects-rew-dual-name-input,
        #tab-effects .effects-actions-peq-dual .effects-rew-dual-name-input,
        #tab-effects .effects-actions-combine .effects-combine-name-input {
            width: 100%;
            max-width: none;
            min-width: 0;
            min-height: 36px;
            height: 36px;
            padding: 0.4rem 0.7rem;
            font-size: 16px;
            line-height: 1.2;
        }

        #tab-effects .effects-actions-rew-dual .btn-primary,
        #tab-effects .effects-actions-rew-dual .btn-secondary,
        #tab-effects .effects-actions-peq-dual .btn-primary,
        #tab-effects .effects-actions-combine .btn-primary {
            width: auto;
            min-width: 88px;
            min-height: 36px;
            height: 36px;
            padding: 0.4rem 0.85rem;
        }

    /* from _playback.css */
    .header { min-height: 64px; padding: .72rem .8rem; }
        .tabs { justify-content: space-between; }
        .tab-btn { flex: 1 0 auto; min-width: 86px; min-height: 44px; padding: .48rem .62rem; }
        .tab-content { padding: 1rem .75rem calc(1.5rem + var(--playback-footer-space)); }
        .radio-panel { padding: .9rem; border-radius: 18px; }
        .radio-panel-header { gap: .65rem; }
        .stations-grid { grid-template-columns: repeat(2, minmax(0,1fr)); }
        .station-card { padding: .58rem; border-radius: 15px; }
        .station-name { font-size: .88rem; }

    /* from _responsive.css */
    .streaming-provider-player {
            min-height: 0;
            justify-content: flex-start;
        }
        .streaming-now-playing {
            padding: 1.15rem 1rem 1.3rem;
            gap: 0.75rem;
        }
        .streaming-cover { width: 180px; height: 180px; }
        .tidal-toolbar { gap: 0.35rem; }
        .tidal-subbar { gap: 0.35rem; }
        .tidal-subbar .streaming-search { width: 100%; }
        .streaming-search-row { flex-wrap: nowrap; }
        .streaming-search-row .streaming-search-field { flex: 1 1 0; width: 100%; }
        .streaming-search-row .streaming-search-field .streaming-search-input { width: 100%; }
        .album-detail-header,
        .streaming-detail-header {
            grid-template-columns: auto minmax(0, 1fr);
            grid-template-areas:
                "back back"
                "cover meta";
            align-items: start;
            gap: 0.9rem;
        }
        .album-detail-back { justify-self: end; }
        /* Mobile: the favorite star flows inline right after the title text so it
           stays visually coupled to multi-line titles instead of floating at the
           right edge of the hero. Plain inline flow: titles wrap normally, the
           star takes only its own width, no fixed positioning. */
        .album-detail-title-row,
        .tidal-detail-title-row {
            display: block;
        }
        .album-detail-name,
        .tidal-detail-title-row .streaming-detail-title {
            display: inline;
        }
        .album-detail-title-row .album-favorite-toggle,
        .tidal-detail-title-row .album-favorite-toggle {
            display: inline-flex;
            vertical-align: middle;
            margin-left: 0.45rem;
        }
        .track-album { display: none; }
        .streaming-btn,
        .track-play { min-width: 44px; min-height: 44px; }

    /* from _effects.css */
    .effects-card-subwoofer-header,
        .effects-subwoofer-controls {
            grid-template-columns: 1fr;
        }

        .effects-subwoofer-controls {
            display: grid;
        }

        .effects-subwoofer-global-group,
        .effects-subwoofer-channel-group {
            grid-column: 1;
            grid-template-columns: repeat(2, minmax(0, 1fr));
        }

        /* 2.2 mode pins Sub 1/Sub 2 to base-grid columns with (0,3,0)
           specificity; re-reset them (and the derived-delays row) so the
           single-column stack carries no implicit extra tracks. */
        .effects-card-subwoofer.is-subwoofer-22 .effects-subwoofer-sub1-group,
        .effects-card-subwoofer.is-subwoofer-22 .effects-subwoofer-sub2-group,
        .effects-subwoofer-derived-delays {
            grid-column: 1;
        }

    /* from _effects.css */
    .effects-rew-dual-grid,
        .effects-combine-grid {
            grid-template-columns: 1fr;
        }

        .effects-actions-rew-dual,
        .effects-actions-peq-dual {
            grid-template-columns: 1fr;
        }

        .effects-actions-combine {
            flex-direction: row;
            align-items: center;
            justify-content: flex-start;
            flex-wrap: wrap;
        }

        .effects-actions-rew-dual .effects-rew-dual-name-input,
        .effects-actions-peq-dual .effects-rew-dual-name-input {
            width: 100%;
            max-width: none;
        }

        .effects-actions-rew-dual .btn-primary,
        .effects-actions-rew-dual .btn-secondary,
        .effects-actions-peq-dual .btn-primary,
        .effects-actions-peq-dual .btn-secondary {
            width: auto;
            min-width: 96px;
            flex: 0 0 auto;
        }

        .effects-peq-add-row {
            grid-template-columns: 1fr auto;
        }

        .effects-peq-mode-field {
            max-width: none;
        }

    /* from _effects.css */
    .effects-loudness-row {
            display: grid;
            grid-template-columns: minmax(0, 1fr);
            align-items: center;
        }

        .effects-loudness-controls {
            display: inline-flex;
            width: max-content;
            max-width: 100%;
            gap: 0.65rem;
        }

        .effects-loudness-controls .effects-inline-control {
            flex-wrap: nowrap;
        }

        .effects-bass-row,
        .effects-bass-controls {
            display: flex;
            align-items: center;
            gap: 0.65rem;
            flex-wrap: wrap;
        }

        .effects-extras-inner {
            width: 100%;
            padding: 0.95rem 0.9rem;
        }

}

@media (min-width: 761px) and (max-width: 1100px) {
    /* Keep the TIDAL navigation and direct-search field on one tablet row.
       The relative basis gives the tabs the remaining space without making
       the search field carry its desktop width. */
    .tidal-subbar {
        flex-wrap: nowrap;
    }
    .tidal-subbar .view-tabs {
        flex: 1 1 auto;
    }
    .tidal-subbar .streaming-search {
        flex: 0 1 34vw;
        width: auto;
    }

    /* Tablet subwoofer layout: Global across the full width, Sub 1 and
       Sub 2 sharing the row below (merged with the TIDAL tablet block
       above; identical media condition). Scoped to ≥761px so the
       one-column mobile layout at ≤760px wins the cascade. Base-grid
       placements (grid-column on the groups and the 2.2 column pins) all
       collapse to plain auto flow so DOM order lays out the rows. */
    .effects-subwoofer-controls {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .effects-subwoofer-global-group,
    .effects-subwoofer-channel-group {
        grid-column: auto;
    }

    .effects-subwoofer-global-group {
        grid-column: 1 / -1;
    }

    .effects-card-subwoofer.is-subwoofer-22 .effects-subwoofer-sub1-group,
    .effects-card-subwoofer.is-subwoofer-22 .effects-subwoofer-sub2-group {
        grid-column: auto;
    }

    .effects-subwoofer-derived-delays {
        grid-column: 1 / -1;
    }
}

/* Narrow tablet: before the three channel columns could ever run into each
   other, Polarity wraps centered below Level and Alignment. */
@media (min-width: 761px) and (max-width: 860px) {
    .effects-subwoofer-channel-group {
        grid-template-columns: repeat(2, auto);
    }

    .effects-subwoofer-channel-group .effects-subwoofer-polarity-field {
        grid-column: 1 / -1;
        justify-self: center;
    }
}

@media (min-width: 601px) and (max-width: 760px) {
    .brand-title { font-size: 1.08rem; }
}

@media (max-width: 767px) {
    /* from _playback.css */
    .measurement-overlay {
            padding: 0.5rem;
            align-items: center;
            overflow-x: hidden;
        }

        .measurement-dialog {
            width: 100%;
            min-height: auto;
            max-height: calc(100dvh - 1rem);
            padding: 0.85rem;
            border-radius: var(--radius-lg);
            overflow-x: hidden;
        }

        .measurement-saved-group > summary,
        .measurement-saved-toolbar button,
        .measurement-select-all-toggle {
            font-size: 16px;
            touch-action: manipulation;
        }

        .measurement-saved-group {
            padding: 0.1rem 0.1rem 0.25rem;
        }

        .measurement-saved-group > summary {
            padding: 0.45rem 0.55rem;
        }

        .measurement-saved-list {
            gap: 0.5rem;
            padding: 0 0.15rem 0.15rem;
        }

        .measurement-saved-toolbar,
        .measurement-saved-toolbar-selection {
            gap: 0.5rem;
        }
        .measurement-saved-toolbar {
            justify-content: space-between;
        }
        .measurement-saved-toolbar-selection {
            flex: 1 1 auto;
        }
        .measurement-saved-delete-action,
        .measurement-saved-merge-action {
            width: 38px;
            min-width: 38px;
            padding-inline: 0;
            font-size: 1rem;
        }
        .measurement-saved-delete-action .label-full,
        .measurement-saved-merge-action .label-full,
        .measurement-saved-close-action .label-full {
            display: none;
        }
        .measurement-saved-delete-action .label-compact,
        .measurement-saved-merge-action .label-compact,
        .measurement-saved-close-action .label-compact {
            display: inline;
        }
        .measurement-saved-close-action {
            width: 38px;
            min-width: 38px;
            padding-inline: 0;
            font-size: 1rem;
        }

        .measurement-list-item {
            gap: 0.24rem;
            padding: 0.62rem 0.68rem;
        }

        .measurement-list-row {
            gap: 0.45rem;
        }

        .measurement-toggle {
            gap: 0.48rem;
        }

        .measurement-saved-toolbar button {
            min-height: 36px;
            padding: 0.42rem 0.72rem;
        }

}

@media (min-width: 601px) {
    /* from _playback.css */
    .cover-detail-card:has(#cover-detail-queue:not(.hidden)) {
            grid-template-areas:
                "cover queue"
                "info queue";
            /* Keep the left column compact: the queue spans both rows and can be
               taller than the left content; with auto 1fr only the info row
               absorbs the extra height, so no gap appears between the cover
               tag block and the meta block. */
            grid-template-rows: auto 1fr;
        }

}

@media (min-width: 761px) {
    .brand-lockup { gap: 0.5rem; }
        .brand-text-block { gap: 0.1rem; }
        .brand-title { font-size: 1.07rem; }

}

@media (min-width: 761px) and (max-width: 1179px) {
    /* Tablet/medium two-row header: center the whole tab group with its
       existing internal gaps. Auto margins on the group (not container
       centering) keep the row left-aligned and scrollable if it ever
       overflows; the buttons keep their size and spacing, only the group
       moves. Mobile and desktop ranges are untouched. */
    .tabs-list { flex: 0 1 auto; margin-inline: auto; }
}

@media (min-width: 1180px) {
    /* from _playback.css */
    .tabs {
            width: max-content;
            margin: -72px auto 0;
            height: 72px;
            align-items: center;
            background: transparent;
            border-bottom: 0;
            padding: 0;
            pointer-events: none;
        }
        .tab-btn { pointer-events: auto; min-width: 124px; }

}

/* At the single-row transition, leave breathing room for the full brand and
   all six providers even with small platform differences in font metrics. */
@media (min-width: 1180px) and (max-width: 1279px) {
    .tab-btn { min-width: 116px; }
}

@media (max-width: 420px) {
    /* from _playback.css */
    .header-status { gap: .32rem; }
        .tabs { gap: .12rem; padding-inline: .38rem; }
        .tab-btn { min-width: 74px; font-size: .78rem; gap: .22rem; }
        .tab-glyph { width: .8rem; font-size: .8rem; }
        .stations-grid { gap: .58rem; }

    /* Very narrow phones: drop the row cover so its width serves title/artist. */
    .track-thumb { display: none; }

}

@media (max-width: 640px) {
    /* from _responsive.css */
    .album-detail-cover,
        .tidal-detail-header .streaming-detail-cover {
            width: 120px;
            height: 120px;
        }

    /* from _library.css */
    .albums-grid,
        .tidal-tiles,
        .streaming-similar-grid {
            grid-template-columns: repeat(auto-fit, minmax(160px, 160px));
        }
        .track-duration {
            flex-basis: 3.8rem;
            font-size: 0.8rem;
        }

    /* from _radio.css */
    .track-row-favorite,
        .track-fav,
        .streaming-fav {
            width: 40px;
            height: 40px;
            min-height: 40px;
            flex-basis: 40px;
            font-size: 1rem;
        }

}

@media (max-width: 700px) {
    /* from _overlays.css */
    .radio-panel-header {
            grid-template-columns: 1fr auto;
        }
        .radio-search-field {
            display: block;
            grid-column: 1 / -1;
            grid-row: 2;
            max-width: none;
        }

    /* from _effects.css */
    .effects-compare-actions {
            justify-content: center;
            flex-wrap: wrap;
        }

}

@media (max-width: 720px) {
    /* from _radio.css */
    .library-import-grid {
            grid-template-columns: 1fr;
        }

}

@media (min-width: 768px) {
    /* from _effects.css */
    .effects-shell {
            padding: 0 1.5rem 1.5rem;
        }

        .effects-header {
            gap: 1rem;
            margin-bottom: 1.5rem;
        }

        .effects-grid {
            grid-template-columns: repeat(2, 1fr);
            gap: 1.5rem;
        }

        .effects-card {
            padding: 1.5rem;
        }

        .effects-card-extras {
            padding-left: 1rem;
            padding-right: 1rem;
        }

}

@media (min-width: 480px) {
    /* from _effects.css */
    .effects-compare-fields {
            grid-template-columns: 1fr 1fr;
        }

}

@media (max-width: 1100px) {
    /* from _effects.css */
    .effects-peq-dual-grid {
            grid-template-columns: 1fr;
        }

}

@media (max-width: 520px) {
    /* from _effects.css */
    .effects-subwoofer-global-group,
        .effects-subwoofer-channel-group {
            grid-template-columns: 1fr;
        }

}

/* Detail heroes keep the shared single-row composition on tablets; only the
   cover column narrows to preserve the available reading width. */
@media (min-width: 601px) and (max-width: 1099px) {
    .album-detail--hero .detail-hero-header,
    .streaming-detail--hero .detail-hero-header {
        grid-template-columns: minmax(170px, 24vw) minmax(0, 1fr) auto;
        grid-template-areas: "cover meta back";
        gap: 0.75rem 1.1rem;
        min-height: 0;
        padding: 1rem;
    }
}

/* Larger heroes keep the metadata visually suspended between the cover and
   the lower edge. The intrinsic title row lets the favorite read as part of
   the title zone instead of floating at the far edge of a wide column. */
@media (min-width: 601px) {
    .album-detail--hero .detail-hero-meta,
    .streaming-detail--hero .detail-hero-meta {
        align-self: start;
        margin-block-start: clamp(0.5rem, calc(12vw - 5.1rem), 3.2rem);
    }
}

/* Phones use the cover as the first visual beat instead of forcing a narrow
   side-by-side title column. This keeps long artist/album names readable and
   gives the image enough scale to carry the hero. */
@media (max-width: 600px) {
    .album-detail--hero .detail-hero-header,
    .streaming-detail--hero .detail-hero-header {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "back"
            "cover"
            "meta";
        align-items: start;
        gap: 0.9rem;
        min-height: 0;
        padding: 0.9rem;
        border-radius: 20px;
    }
    .album-detail--hero .detail-hero-header .detail-hero-cover,
    .streaming-detail--hero .detail-hero-header .detail-hero-cover {
        width: min(62vw, 220px);
        max-width: 100%;
        justify-self: center;
        align-self: start;
    }
    .album-detail--hero .detail-hero-meta,
    .streaming-detail--hero .detail-hero-meta {
        align-self: stretch;
        padding: 0.1rem 0 0.2rem;
    }
    .album-detail--hero .album-detail-name,
    .streaming-detail--hero .tidal-detail-title {
        display: block;
    }
    .album-detail--hero .detail-hero-title,
    .streaming-detail--hero .detail-hero-title {
        font-size: clamp(1.3rem, 6.2vw, 1.8rem);
    }
    .album-detail--hero .detail-hero-header .album-detail-back,
    .streaming-detail--hero .detail-hero-header .album-detail-back {
        justify-self: start;
    }
    .streaming-detail--hero #tidal-detail-play {
        width: 100%;
    }
}

/* Album headers use a compact two-column composition. The Back action only
   reserves space in the title row, leaving the full text width for metadata
   and the always-visible description. Artwork size never follows text height. */
.detail-hero-header.detail-hero-header--album {
    grid-template-columns: clamp(180px, 18vw, 240px) minmax(0, 1fr);
    grid-template-areas: "cover meta";
    gap: 1.75rem;
    min-height: 0;
    padding: 1.5rem;
    border-radius: 20px;
}
.detail-hero-header.detail-hero-header--album .detail-hero-cover {
    align-self: start;
}
.detail-hero-header--album .detail-hero-meta {
    align-self: center;
    gap: 0.45rem;
    width: 100%;
    max-width: none;
    margin-block-start: 0;
    padding: 0;
}
.detail-hero-header--album .detail-hero-title-row {
    width: 100%;
    padding-inline-end: 5.5rem;
    box-sizing: border-box;
}
.detail-hero-header--album .detail-hero-title {
    flex: 0 1 auto;
    font-size: clamp(1.4rem, 2.2vw, 2.2rem);
    line-height: 1.15;
    letter-spacing: -0.035em;
}
.detail-hero-header--album .album-detail-count,
.detail-hero-header--album .streaming-detail-facts {
    margin-top: 0.2rem;
    overflow-wrap: anywhere;
}
.detail-hero-header--album .album-detail-artist,
.detail-hero-header--album .streaming-detail-artist {
    overflow-wrap: anywhere;
}
.detail-hero-header--album #tidal-album-about {
    width: 100%;
}
.detail-hero-header--album #tidal-album-about:empty,
.detail-hero-header--album #tidal-album-facts:empty,
.detail-hero-header--album .album-detail-artist:empty,
.detail-hero-header--album .streaming-detail-artist:empty {
    display: none;
}
.detail-hero-header.detail-hero-header--album .album-detail-back {
    position: absolute;
    top: 1.5rem;
    right: 1.5rem;
}
@media (min-width: 601px) and (max-width: 1099px) {
    .detail-hero-header.detail-hero-header--album {
        grid-template-columns: 170px minmax(0, 1fr);
        gap: 1.25rem;
        padding: 1.25rem;
    }
    .detail-hero-header.detail-hero-header--album .album-detail-back {
        top: 1.25rem;
        right: 1.25rem;
    }
}
@media (max-width: 600px) {
    .detail-hero-header.detail-hero-header--album {
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas: "cover back" "meta meta";
        gap: 1.1rem;
        padding: 1rem;
    }
    .detail-hero-header.detail-hero-header--album .detail-hero-cover {
        width: 144px;
        justify-self: start;
        border-radius: 14px;
    }
    .detail-hero-header--album .detail-hero-title-row {
        padding-inline-end: 0;
    }
    .detail-hero-header.detail-hero-header--album .album-detail-back {
        position: relative;
        top: auto;
        right: auto;
        justify-self: end;
    }
}

/* Prefers reduced motion — keep at end. !important is required here: the
   generic star rule must beat every specific animation/transition rule
   (e.g. .content-state--loading::before) without touching the normal
   cascade. These are the only non-utility !important in the stylesheet. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
            animation-duration: 0.01ms !important;
            animation-iteration-count: 1 !important;
            transition-duration: 0.01ms !important;
            scroll-behavior: auto !important;
        }
}
