/* ============================================
   SoulSync Mobile Responsive Styles
   Loaded after style.css - overrides for ≤768px
   ============================================ */

/* ======================================
   HAMBURGER BUTTON (hidden on desktop)
   ====================================== */

.hamburger-btn {
    display: none;
    position: fixed;
    top: 16px;
    left: 16px;
    z-index: 9999;
    width: 44px;
    height: 44px;
    background: rgba(20, 20, 20, 0.9);
    backdrop-filter: blur(20px);
    border: 1px solid var(--white-a15);
    border-radius: var(--radius-lg);
    cursor: pointer;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    padding: 0;
}

.hamburger-line {
    display: block;
    width: 20px;
    height: 2px;
    background: #fff;
    border-radius: 2px;
    transition: transform 0.3s ease, opacity 0.3s ease;
}

/* Animated X state */
.hamburger-btn.active .hamburger-line:nth-child(1) {
    transform: translateY(7px) rotate(45deg);
}

.hamburger-btn.active .hamburger-line:nth-child(2) {
    opacity: 0;
}

.hamburger-btn.active .hamburger-line:nth-child(3) {
    transform: translateY(-7px) rotate(-45deg);
}

/* ======================================
   MOBILE OVERLAY (hidden on desktop)
   ====================================== */

.mobile-overlay {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, 0.6);
    z-index: 10000;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

.mobile-overlay.active {
    opacity: 1;
    pointer-events: auto;
}

/* ======================================
   MOBILE BREAKPOINT (≤768px)
   ====================================== */

@media (max-width: 768px) {

    /* --- Phase 0: Foundation --- */

    body {
        overflow: hidden;
        height: 100vh;
    }

    .main-container {
        flex-direction: column;
        height: 100vh;
        width: 100%;
    }

    .dashboard-container {
        gap: 15px;
        margin: 15px;
        padding: 15px;
    }

    .dashboard-header {
        margin: -15px -15px 15px -15px;
        padding: 15px;
        border-top-left-radius: 20px;
        border-top-right-radius: 20px;
    }

    #artist-hero-section #artist-detail-image {
        width: 100% !important;
        max-width: none !important;
    }

    #media-player {
        min-height: 110px;
        flex-shrink: 0;
    }

    .tool-help-button {
        height: 35px;
        width: 35px;
    }

    .discover-carousel,
    #genre-tabs {
        width: 100%;
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: center;
    }

    .sidebar-header {
        text-align: right;
        /* The header is already `position: sticky; z-index: 1`, which should put
           it above the scrolling nav buttons (positioned, z-index auto). It
           doesn't, and raising the z-index changes nothing — the giveaway that
           these aren't being arbitrated in the same stacking context.
           `backdrop-filter` promotes the header to its own compositing layer,
           where z-index no longer decides the order, so nav items scroll over
           it and stay clickable. Same root cause as #1040, which the opaque
           base only half-fixed.

           That opaque base is why dropping the blur here is nearly invisible:
           the bottom of the gradient is already solid. Handled at the mobile
           breakpoint only, so the desktop frosted look is untouched. */
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }

    .main-content {
        width: 100%;
        flex: 1;
        min-height: 0;
        overflow-y: auto;
        overflow-x: hidden;
    }

    /* --- Phase 1: Sidebar → Off-canvas --- */

    .hamburger-btn {
        display: flex;
    }

    .mobile-overlay {
        display: block;
    }

    .sidebar {
        position: fixed;
        top: 0;
        left: 0;
        width: 280px;
        height: 100vh;
        /* dvh tracks the visible viewport when the mobile browser chrome
           (URL bar) shows/hides — 100vh alone can size the drawer taller
           than the visible area in landscape, pushing the nav off-screen. */
        height: 100dvh;
        z-index: 10001;
        transform: translateX(-100%);
        transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        border-radius: 0;
        border-top-right-radius: 24px;
        border-bottom-right-radius: 24px;
        /* The drawer itself does not scroll — .sidebar-scroll does (base
           rule in style.css). Leaving overflow-y:auto here would re-arm the
           old single-scroll-box behaviour at mobile widths only. */
        overflow: hidden;
    }

    .sidebar-scroll {
        /* Without this a drag inside the open drawer chains its scroll to the
           page underneath: the list itself does not move, so the browser
           resolves the gesture as a tap on whatever nav link is under the
           finger — every scroll attempt navigates. */
        overscroll-behavior: contain;
        -webkit-overflow-scrolling: touch;
    }

    .sidebar.mobile-open {
        transform: translateX(0);
    }

    /* Set for one frame while the viewport crosses the breakpoint. Without it
       the desktop -> mobile flip animates the drawer across the page, which is
       what a resized desktop context caught mid-slide sitting on the content. */
    .sidebar.sidebar-no-transition {
        transition: none !important;
    }

    /* init.js has always put this class on <body> when the drawer opens, but
       nothing ever consumed it, so the page behind the drawer stayed live and
       scrollable. `.main-content` is the real scroller on mobile, so locking
       <body> alone is not enough. */
    body.mobile-nav-open {
        overflow: hidden;
    }

    body.mobile-nav-open .main-content {
        overflow: hidden;
    }

    .page {
        /* Bottom padding clears the fixed floating search bar / FAB buttons
           (~50px band) so the last row of content stays visible & tappable. */
        height: auto;
        min-height: 0;
        overflow: visible;
        flex-shrink: 0;
    }

    .page.active {
        display: block;
    }

    /* ── Minor tap-target enlargements for touch ── */
    #watchlist-select-all-cb {
        width: 18px;
        height: 18px;
    }
    .watchlist-select-all-label {
        min-height: 32px;
    }
    .td-close {
        width: 36px;
        height: 36px;
    }
    .bp-info-toggle {
        width: 28px;
        height: 28px;
        font-size: 14px;
    }

    .nav-button {
        width: 100%;
    }

    /* --- Phase 2: Dashboard --- */

    .dashboard-content {
        flex-direction: column;
        height: auto;
        gap: 20px;
    }

    .header-actions {
        flex-wrap: wrap;
        width: 100%;
    }

    /* MusicBrainz tooltip - reposition for mobile */
    .musicbrainz-tooltip {
        left: 0;
        right: auto;
        transform: translateY(-5px);
    }

    .musicbrainz-button:hover+.musicbrainz-tooltip {
        transform: translateY(0);
    }

    /* AudioDB tooltip - reposition for mobile */
    .audiodb-tooltip {
        left: 0;
        right: auto;
        transform: translateY(-5px);
    }

    .audiodb-button:hover+.audiodb-tooltip {
        transform: translateY(0);
    }

    /* Deezer tooltip - reposition for mobile */
    .deezer-tooltip {
        left: 0;
        right: auto;
        transform: translateY(-5px);
    }

    .deezer-button:hover+.deezer-tooltip {
        transform: translateY(0);
    }

    .tooltip-content {
        min-width: auto;
        width: calc(100vw - 60px);
        max-width: 280px;
    }

    .tooltip-content::before,
    .tooltip-content::after {
        left: 24px;
        transform: none;
    }

    .tools-grid {
        grid-template-columns: 1fr;
    }

    .tool-card {
        padding: 20px 16px;
    }

    .tool-card-header {
        flex-wrap: wrap;
        gap: 8px;
    }

    .tool-card-title {
        font-size: 15px;
    }

    .tool-card-info {
        font-size: 12px;
        word-wrap: break-word;
        overflow-wrap: break-word;
    }

    .tool-card-controls {
        flex-direction: column;
        gap: 8px;
    }

    .tool-card-controls select,
    .tool-card-controls button {
        width: 100%;
        min-height: 44px;
        box-sizing: border-box;
    }

    /* --- Phase 3: Downloads (Search) --- */

    .downloads-content {
        grid-template-columns: 1fr;
        height: auto;
        padding: 0 12px 16px 12px;
        overflow: hidden;
    }

    .downloads-main-panel {
        min-width: 0;
        max-width: 100%;
        overflow: hidden;
    }

    .search-bar-container {
        flex-direction: column;
        gap: 12px;
        padding: 12px 16px;
    }

    .search-bar-container button {
        width: 100%;
        min-height: 44px;
    }

    .sort-order-btn {
        min-width: 44px;
        min-height: 44px;
        width: 44px;
        height: 44px;
    }

    .enhanced-dropdown {
        position: relative;
        margin-top: 12px;
        border-radius: 0;
        z-index: 1;
        overflow: visible;
        max-height: none;
    }

    /* Album cards — wrap and fill space, 2 per row */

    .enh-compact-item.album-card {
        width: calc(50% - 8px);
        flex-shrink: 0;
    }

    .enh-compact-item.album-card .enh-item-name {
        font-size: 12px;
    }

    .enh-compact-item.album-card .enh-item-meta {
        font-size: 11px;
    }

    /* --- Enhanced Search Results --- */

    .track-result-card {
        padding: 14px;
        margin: 8px 4px;
        gap: 12px;
        flex-wrap: wrap;
    }

    .track-icon {
        width: 36px;
        height: 36px;
        font-size: 14px;
    }

    .track-info {
        flex: 1;
        min-width: 0;
    }

    .track-result-card .track-title {
        font-size: 13px;
        white-space: normal;
        word-break: break-word;
    }

    .track-details {
        white-space: normal;
        word-break: break-word;
    }

    .track-result-card .track-actions {
        width: 100%;
        display: flex;
        justify-content: flex-end;
    }

    .album-result-card {
        padding: 16px;
        margin: 8px 4px;
    }

    .album-card-header {
        gap: 12px;
        flex-wrap: wrap;
    }

    .album-icon {
        width: 44px;
        height: 44px;
        font-size: 22px;
    }

    .album-info {
        min-width: 0;
        flex: 1;
    }

    .album-title {
        font-size: 14px;
        white-space: normal;
        word-break: break-word;
    }

    .album-details {
        white-space: normal;
        word-break: break-word;
    }

    .album-actions {
        width: auto;
    }

    .album-track-list {
        margin-top: 12px;
        padding-top: 12px;
    }

    /* Standard search results */
    .search-result-item {
        padding: 12px;
        flex-wrap: wrap;
        gap: 10px;
    }

    /* Enhanced search — tablet/mobile responsive */

    .enh-compact-item.artist-card {
        width: calc(50% - 8px);
        height: 200px;
    }

    .enh-compact-item.artist-card .enh-item-info {
        padding: 10px;
    }

    .enh-compact-item.artist-card .enh-item-name {
        font-size: 13px;
    }

    /* Track items — larger touch targets */
    .enh-compact-item.track-item {
        padding: 10px 12px;
        min-height: 56px;
    }

    .enh-item-image.track-cover,
    .enh-item-image-placeholder.track-placeholder {
        width: 44px;
        height: 44px;
    }

    /* Always show play button on touch devices */
    .enh-item-play-btn {
        opacity: 1 !important;
        transform: translateY(-50%) !important;
        position: static !important;
        transform: none !important;
        padding: 6px 10px;
        flex-shrink: 0;
    }

    .enh-item-duration {
        font-size: 12px;
        gap: 8px;
    }

    /* --- Phase 4: Sync --- */

    .sync-tabs {
        flex-wrap: wrap;
    }

    /* Keep the icon-chip shape on mobile too (was a 50%-width pill for the
       old labeled-tab design) so the strip stays uniform and reflow-free. */
    .sync-tab-button {
        min-width: 0;
        padding: 0;
    }

    /* Spotify playlist cards - stack vertically on mobile */
    .playlist-card {
        padding: 16px;
        margin: 8px 4px;
        border-radius: 14px;
    }

    .playlist-card-main {
        flex-direction: column;
        align-items: stretch;
        gap: 12px;
    }

    .playlist-card-content {
        min-width: 0;
        width: 100%;
    }

    .playlist-card-name {
        font-size: 15px;
        margin-bottom: 6px;
    }

    .playlist-card-info {
        font-size: 13px;
    }

    .playlist-card-actions {
        margin-left: 0;
        display: flex;
        gap: 8px;
    }

    .playlist-card-actions button {
        flex: 1;
        padding: 10px 14px;
        font-size: 12px;
    }

    .beatport-tabs {
        flex-wrap: wrap;
        gap: 4px;
    }

    .beatport-tab-button {
        flex: 0 0 calc(50% - 4px);
        padding: 10px 12px;
        font-size: 12px;
    }

    .beatport-genre-grid {
        grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    }

    .beatport-top10-container {
        grid-template-columns: 1fr;
        gap: 20px;
    }

    .beatport-top10-title {
        font-size: 24px;
    }

    .beatport-top10-card,
    .beatport-hype10-card {
        padding: 12px;
        min-height: 70px;
        max-height: none;
    }

    .beatport-top10-card-rank,
    .beatport-hype10-card-rank {
        font-size: 16px;
        min-width: 30px;
        margin-right: 10px;
    }

    .beatport-top10-card-artwork,
    .beatport-hype10-card-artwork {
        width: 44px;
        height: 44px;
        margin-right: 10px;
    }

    .beatport-top10-card-title,
    .beatport-hype10-card-title {
        font-size: 13px;
    }

    /* --- Beatport rebuild hero slider --- */
    .beatport-rebuild-slider {
        height: 280px;
    }

    .beatport-rebuild-slider-container {
        padding: 12px;
    }

    .beatport-rebuild-slide-content {
        padding: 16px 12px;
    }

    .beatport-rebuild-track-title {
        font-size: 20px;
    }

    .beatport-rebuild-artist-name {
        font-size: 14px;
    }

    .beatport-rebuild-slider-nav {
        display: none;
    }

    /* --- Beatport card sliders: convert from absolute stacking to show/hide --- */

    /* All slider tracks: auto height */
    .beatport-releases-slider-track,
    .beatport-hype-picks-slider-track,
    .beatport-charts-slider-track,
    .beatport-dj-slider-track {
        height: auto;
        min-height: auto;
    }

    /* All slides: position relative, hidden by default */
    .beatport-releases-slide,
    .beatport-hype-picks-slide,
    .beatport-charts-slide,
    .beatport-dj-slide {
        position: relative;
        top: auto;
        left: auto;
        width: 100%;
        height: auto;
        display: none;
        opacity: 0;
        transform: none;
    }

    /* Active slide: visible */
    .beatport-releases-slide.active,
    .beatport-hype-picks-slide.active,
    .beatport-charts-slide.active,
    .beatport-dj-slide.active {
        display: block;
        opacity: 1;
        transform: none;
    }

    /* Prev/next slides: hidden */
    .beatport-releases-slide.prev,
    .beatport-releases-slide.next,
    .beatport-hype-picks-slide.prev,
    .beatport-hype-picks-slide.next,
    .beatport-charts-slide.prev,
    .beatport-charts-slide.next,
    .beatport-dj-slide.prev,
    .beatport-dj-slide.next {
        display: none;
    }

    /* All slider containers: reduced padding */
    .beatport-releases-slider-container,
    .beatport-hype-picks-slider-container,
    .beatport-charts-slider-container,
    .beatport-dj-slider-container {
        padding: 12px;
    }

    /* All card grids: 2 columns, auto rows */
    .beatport-releases-grid,
    .beatport-hype-picks-grid,
    .beatport-charts-grid {
        grid-template-columns: repeat(2, 1fr);
        grid-template-rows: auto;
        gap: 10px;
        padding: 10px;
    }

    .beatport-dj-grid {
        grid-template-columns: 1fr;
        grid-template-rows: auto;
        gap: 10px;
        padding: 10px;
    }

    /* Card heights: auto instead of fixed */
    .beatport-chart-card {
        height: auto;
        min-height: 120px;
        max-height: none;
    }

    .beatport-dj-card {
        height: auto;
        min-height: 120px;
        max-height: none;
    }

    /* Release/hype card compact */
    .beatport-release-card,
    .beatport-hype-pick-card {
        padding: 10px;
    }

    .beatport-release-artwork,
    .beatport-hype-pick-artwork {
        width: 50px;
        height: 50px;
    }

    .beatport-release-title,
    .beatport-hype-pick-title {
        font-size: 12px;
    }

    .beatport-release-artist,
    .beatport-hype-pick-artist {
        font-size: 11px;
    }

    /* Slider nav buttons (prev/next arrows) */
    .beatport-releases-slider-nav,
    .beatport-hype-picks-slider-nav,
    .beatport-charts-slider-nav,
    .beatport-dj-slider-nav {
        position: relative;
        top: auto;
        display: flex;
        justify-content: center;
        gap: 16px;
        padding: 10px 0;
        z-index: 1;
    }

    /* Slider indicators */
    .beatport-releases-slider-indicators,
    .beatport-hype-picks-slider-indicators,
    .beatport-charts-slider-indicators,
    .beatport-dj-slider-indicators {
        position: relative;
        bottom: auto;
        left: auto;
        transform: none;
        display: flex;
        justify-content: center;
        padding: 8px 0;
    }

    /* Section titles */
    .beatport-releases-title,
    .beatport-hype-picks-title,
    .beatport-charts-title {
        font-size: 20px;
    }

    /* Nav buttons */
    .beatport-nav-buttons-container {
        flex-direction: column;
        gap: 12px;
    }

    .beatport-nav-button {
        max-width: none;
        width: 100%;
    }

    /* --- Phase 5A: Artists --- */

    .artists-search-state {
        min-height: auto;
        padding: 20px 16px;
        gap: 20px;
    }

    .artist-card {
        width: 100%;
        max-width: 280px;
        height: 300px;
    }

    .album-cards-container,
    .singles-cards-container {
        grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
        gap: 10px;
    }

    .album-card-content {
        padding: 10px;
    }

    .album-card-name {
        font-size: 12px;
    }

    /* Artists page hero — mobile */
    .artists-hero-section {
        border-radius: var(--radius-lg);
    }

    .artists-hero-name {
        font-size: 1.5em;
    }

    .artists-hero-stats {
        justify-content: center;
    }

    /* --- Phase 5B: Library --- */

    .library-container {
        height: auto;
        padding: 16px;
    }

    .library-controls {
        flex-direction: column;
    }

    .library-search-container {
        max-width: 100%;
    }

    .watchlist-filter {
        flex-wrap: wrap;
    }

    .library-watchlist-all-btn {
        font-size: 12px;
        padding: 5px 12px;
    }

    .watch-all-modal { max-width: 95vw; width: 95vw; }
    .watch-all-grid { grid-template-columns: 1fr; }
    .watch-all-stats { flex-wrap: wrap; gap: 8px; padding: 12px 14px; }
    .watch-all-stat-card { padding: 8px 12px; }
    .watch-all-stat-value { font-size: 18px; }
    .watch-all-cell { padding: 6px 8px; }
    .watch-all-cell-img, .watch-all-cell-placeholder { width: 32px; height: 32px; }
    .watch-all-header { padding: 16px 18px; }
    .watch-all-search-wrap { padding: 8px 14px 4px; }

    .alphabet-selector-inner {
        flex-wrap: wrap;
        min-width: 0;
        gap: 4px;
    }

    .alphabet-btn {
        min-width: 32px;
        min-height: 32px;
    }

    .library-artists-grid {
        grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    }

    /* Artist Detail (Library) — Hero section */
    .artist-hero-section {
        margin: 10px;
        padding: 16px;
        border-radius: var(--radius-lg);
    }

    .artist-hero-content {
        flex-direction: column;
        align-items: center;
        text-align: center;
        gap: 16px;
    }

    .artist-image,
    .artist-image-fallback {
        width: 100px;
        height: 100px;
    }

    .artist-hero-section .artist-name {
        font-size: 1.6em;
        text-align: center;
        display: block;
    }

    .artist-hero-badges {
        justify-content: center;
        flex-wrap: wrap;
        gap: 4px;
    }

    .artist-hero-badge {
        width: 22px;
        height: 22px;
    }

    .artist-genres-container {
        justify-content: center;
        flex-wrap: wrap;
    }

    .artist-hero-bio {
        font-size: 12px;
        -webkit-line-clamp: 3;
        max-height: fit-content;
    }

    .artist-hero-numbers {
        justify-content: center;
        gap: 20px;
    }

    .hero-stat-value {
        font-size: 18px;
    }

    .hero-stat-label {
        font-size: 10px;
    }

    .collection-overview {
        gap: 6px;
    }

    .category-label {
        font-size: 0.65em;
        min-width: 42px;
    }

    .category-stats {
        font-size: 0.65em;
    }

    /* Top tracks sidebar — stack below on mobile */
    .artist-hero-right {
        width: 100%;
        border-left: none;
        border-top: 1px solid var(--white-a06);
        padding-top: 12px;
    }

    .hero-top-tracks {
        max-height: 200px;
        overflow-y: auto;
    }

    .releases-grid {
        grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    }

    /* --- Phase 6: Discover --- */

    .discover-hero-content {
        padding: 16px;
    }

    .discover-hero-bottom-actions {
        bottom: 12px;
        right: 12px;
        gap: 6px;
    }

    /* On a narrow hero the centered carousel indicators and the bottom-right
       action buttons both pin to the bottom edge and collide — lift the
       indicators above the action row so the dots stay usable. */
    .discover-hero-indicators {
        bottom: 62px;
    }

    .discover-hero-watch-all,
    .discover-hero-view-all {
        padding: 6px 12px;
        font-size: 11px;
    }

    /* Recommended Artists Modal - Mobile */
    .recommended-modal {
        max-width: 100vw;
        width: 100vw;
        max-height: 100vh;
        border-radius: 0;
    }

    .recommended-artists-grid {
        grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
        gap: 12px;
        padding: 12px 16px;
    }

    .recommended-actions-bar {
        padding: 12px 16px 0;
        flex-wrap: wrap;
    }

    .recommended-add-all-btn {
        width: 100%;
        text-align: center;
        padding: 10px;
    }

    .recommended-card-watchlist-btn {
        opacity: 1;
    }

    .discover-section-header {
        flex-direction: column;
        gap: 12px;
    }

    .discover-section-actions {
        width: 100%;
        flex-wrap: wrap;
    }

    .discover-section-actions .action-button {
        flex: 1;
        min-height: 44px;
        justify-content: center;
    }

    .discover-card {
        width: 45%;
    }

    /* Horizontal scroll tabs */
    .decade-tabs,
    .genre-tabs,
    .listenbrainz-tabs {
        overflow-x: auto;
        flex-wrap: nowrap;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    .decade-tabs::-webkit-scrollbar,
    .genre-tabs::-webkit-scrollbar,
    .listenbrainz-tabs::-webkit-scrollbar {
        display: none;
    }

    .discover-download-sidebar {
        width: 60px;
        top: auto;
        bottom: 16px;
        right: 16px;
        height: auto;
        border-radius: var(--radius-xl);
        border: 1px solid var(--white-a10);
    }

    /* --- Phase 7: Settings --- */

    .settings-columns {
        flex-direction: column;
    }

    .settings-left-column,
    .settings-right-column,
    .settings-third-column {
        min-width: 0;
        width: 100%;
    }

    .page-header {
        flex-direction: column;
        gap: 12px;
        align-items: stretch;
    }

    .page-header button {
        width: 100%;
        min-height: 44px;
    }

    .api-test-buttons {
        flex-direction: column;
    }

    .api-test-buttons .test-button {
        width: 100%;
        min-width: 0;
    }

    .server-toggle-btn {
        flex: 1;
        min-height: 44px;
    }

    .path-input-group {
        flex-direction: column;
    }

    .path-input-group input {
        width: 100%;
    }

    .preset-button {
        flex: 1;
    }

    /* --- Phase 8: All Modals Responsive --- */

    .modal-overlay {
        padding: 8px;
        align-items: flex-start;
        overflow-y: auto;
    }

    .version-modal {
        width: 95vw;
    }

    .add-to-wishlist-modal {
        width: 100%;
        max-width: 100%;
    }

    .download-missing-modal-content {
        width: 100%;
        max-width: 100%;
        height: 95vh;
        max-height: 95vh;
        border-radius: var(--radius-xl);
    }

    /* Download modal hero - compact */
    .download-missing-modal-hero {
        padding: 12px 14px;
        gap: 10px;
        min-height: auto;
    }

    .download-missing-modal-hero-content {
        gap: 10px;
    }

    .download-missing-modal-hero-images {
        gap: 8px;
    }

    .download-missing-modal-hero-image {
        width: 48px;
        height: 48px;
    }

    .download-missing-modal-hero-image.artist {
        width: 44px;
        height: 44px;
    }

    .download-missing-modal-hero-image.album {
        width: 48px;
        height: 48px;
    }

    .download-missing-modal-hero-icon {
        width: 48px;
        height: 48px;
        font-size: 24px;
    }

    .download-missing-modal-hero-title {
        font-size: 15px;
        white-space: normal;
        line-height: 1.2;
    }

    .download-missing-modal-hero-subtitle {
        font-size: 12px;
        white-space: normal;
    }

    .download-missing-modal-hero-details {
        gap: 6px;
        flex-wrap: wrap;
    }

    .download-missing-modal-hero-detail {
        font-size: 10px;
        padding: 2px 5px;
    }

    .download-missing-modal-header-actions {
        padding: 10px 14px 0 0;
    }

    /* Download modal body */
    .download-missing-modal-body {
        padding: 10px 12px 14px 12px;
        gap: 12px;
    }

    /* Download stats grid */
    .download-dashboard-stats {
        grid-template-columns: repeat(4, 1fr);
        gap: 8px;
        padding: 12px;
    }

    .dashboard-stat-number {
        font-size: 20px;
    }

    .dashboard-stat-label {
        font-size: 10px;
    }

    /* Download tracks table - compact on mobile */
    .download-tracks-header {
        padding: 10px 12px;
    }

    .download-tracks-title {
        font-size: 13px;
    }

    .track-selection-count {
        font-size: 10px;
    }

    .download-tracks-table {
        table-layout: auto;
    }

    .download-tracks-table th,
    .download-tracks-table td {
        padding: 6px 4px;
        font-size: 10px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Checkbox column sizing on mobile */
    .track-select-header,
    .track-select-cell {
        width: auto;
        padding: 6px 4px !important;
    }

    .track-select-header input[type="checkbox"],
    .track-select-cell input[type="checkbox"] {
        width: 14px;
        height: 14px;
    }

    /* Hide # and Duration columns on mobile */
    .download-tracks-table td.track-number {
        display: none;
    }

    .download-tracks-table td.track-duration {
        display: none;
    }

    /* Hide matching th headers — different positions depending on checkbox column */
    .download-tracks-table:has(.track-select-header) th:nth-child(2),
    .download-tracks-table:not(:has(.track-select-header)) th:nth-child(1) {
        display: none;
    }

    .download-tracks-table:has(.track-select-header) th:nth-child(5) {
        display: none;
    }

    .track-name {
        width: auto;
        max-width: 120px;
        font-size: 11px;
    }

    .track-artist {
        width: auto;
        max-width: 80px;
        font-size: 11px;
    }

    .track-match-status {
        width: auto;
        font-size: 10px;
    }

    .track-download-status {
        width: auto;
        font-size: 10px;
    }

    .download-tracks-table .track-actions {
        width: auto;
        font-size: 10px;
    }

    .cancel-track-btn {
        padding: 3px 6px;
        font-size: 10px;
    }

    /* Download modal footer - stack everything vertically */
    .download-missing-modal-footer {
        padding: 12px;
        flex-direction: column;
        gap: 10px;
        align-items: stretch;
    }

    .download-phase-controls {
        width: 100%;
        flex-direction: column;
        gap: 8px;
        align-items: stretch;
    }

    /* Toggle container - stack vertically, prevent overflow */
    .force-download-toggle-container {
        width: 100%;
        padding: 8px 12px;
        box-sizing: border-box;
    }

    .force-download-toggle {
        gap: 8px;
    }

    .force-download-toggle span {
        font-size: 11px;
        line-height: 1.3;
        word-break: break-word;
    }

    .force-download-toggle input[type="checkbox"] {
        width: 40px;
        height: 20px;
        flex-shrink: 0;
    }

    .force-download-toggle input[type="checkbox"]:before {
        width: 14px;
        height: 14px;
    }

    .force-download-toggle input[type="checkbox"]:checked:before {
        transform: translateX(20px);
    }

    /* All download control buttons - full width stacked */
    .download-control-btn {
        width: 100%;
        min-width: 0;
        max-width: none;
        padding: 10px 14px;
        font-size: 12px;
        text-align: center;
        box-sizing: border-box;
    }

    .modal-close-section {
        width: 100%;
        flex-direction: column;
        gap: 8px;
    }

    .modal-close-section .download-control-btn {
        width: 100%;
    }

    .youtube-discovery-modal {
        width: 100%;
        max-width: 100%;
    }

    .artist-download-modal-content {
        width: 100%;
        max-width: 100%;
    }

    .genre-browser-modal-container {
        width: 100%;
        max-width: 100%;
    }

    .tool-help-modal-content {
        width: 95vw;
        max-width: 95vw;
    }

    /* Wishlist & Watchlist modals (playlist-modal based) */
    .playlist-modal {
        width: 100%;
        max-width: 100%;
        max-height: 95vh;
        border-radius: var(--radius-xl);
        overflow: hidden;
        display: flex;
        flex-direction: column;
    }

    .playlist-modal-header {
        padding: 16px;
        flex-wrap: wrap;
        gap: 8px;
        flex-shrink: 0;
    }

    .playlist-header-content h2 {
        font-size: 18px;
    }

    .playlist-quick-info {
        flex-direction: column;
        gap: 4px;
    }

    /* Critical fix: allow modal body to scroll */
    .playlist-modal-body {
        padding: 0 16px;
        overflow-y: auto;
        overflow-x: hidden;
        flex: 1;
        min-height: 0;
    }

    /* Tracks scroll container - fit within modal */
    .playlist-tracks-scroll {
        max-height: none;
        overflow-y: visible;
        flex: none;
    }

    /* Album grid needs to be able to grow */
    .wishlist-album-grid {
        overflow: visible;
    }

    .playlist-modal-footer {
        padding: 16px;
        flex-direction: column;
        gap: 10px;
        flex-shrink: 0;
    }

    .playlist-modal-footer-left,
    .playlist-modal-footer-right {
        width: 100%;
        flex-direction: column;
        gap: 8px;
    }

    /* Footer/action buttons - full width stacked */
    .playlist-modal-footer .playlist-modal-btn,
    .watchlist-actions .playlist-modal-btn {
        width: 100%;
        min-height: 44px;
        text-align: center;
    }

    /* Watchlist card grid on mobile */
    .watchlist-artists-grid {
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
        gap: 16px;
        padding: 16px;
    }

    .watchlist-card-info {
        padding: 0 12px 6px;
        margin-top: -28px;
    }

    .watchlist-card-name {
        font-size: 13px;
    }

    .watchlist-card-meta {
        font-size: 10px;
    }

    /* Show checkbox, remove, and gear always on mobile (no hover) */
    .watchlist-card-checkbox,
    .watchlist-artist-card .watchlist-card-remove,
    .watchlist-artist-card .watchlist-card-gear {
        opacity: 1;
    }

    .watchlist-detail-hero {
        flex-direction: column;
        text-align: center;
    }

    .watchlist-detail-hero-stats {
        justify-content: center;
    }

    .watchlist-detail-hero-genres {
        justify-content: center;
    }

    .watchlist-detail-actions {
        flex-direction: column;
    }

    .watchlist-detail-actions button {
        width: 100%;
    }

    .watchlist-search-container {
        padding: 0 16px;
    }

    /* Retag modal on mobile */

    .retag-modal-header {
        padding: 16px;
        flex-wrap: wrap;
        gap: 8px;
    }

    .retag-modal-body {
        padding: 16px;
    }

    .retag-batch-bar {
        margin: 0 16px 12px;
    }

    .retag-group-header {
        padding: 12px;
        gap: 10px;
    }

    .retag-group-image,
    .retag-group-image-placeholder {
        width: 44px;
        height: 44px;
    }

    .retag-group-album {
        font-size: 13px;
    }

    /* Watchlist live activity - stack on mobile */
    #watchlist-live-activity {
        flex-direction: column;
        align-items: center;
    }

    /* Wishlist category grid */

    .wishlist-category-card {
        min-height: 140px;
    }

    /* Wishlist track items */
    .wishlist-track-item {
        padding: 10px 12px;
        padding-right: 50px;
        gap: 8px;
    }

    .wishlist-track-number {
        width: 24px;
        font-size: 12px;
    }

    .wishlist-track-name {
        font-size: 13px;
    }

    .wishlist-track-artists {
        font-size: 12px;
    }

    .wishlist-back-btn {
        min-height: 36px;
        font-size: 13px;
    }

    /* Modal footer buttons */
    .modal-footer button,
    .modal-actions button {
        flex: 1;
        min-height: 44px;
    }

    /* --- Phase 9: Touch & Hover Adaptations --- */

    /* Global touch targets - only standalone/action buttons, not inline.
       Round icon buttons (fixed-size circles) are excluded so the min-height
       can't stretch them into vertical ellipses. The video dashboard's Studios
       halves (.vst-half) are excluded because this chain's specificity beats
       their own min-height: 208px — their content is absolutely positioned, so
       "winning" here collapses each half to a 38px sliver on phones.
       Segmented-control pills and fixed-size swatches are excluded for the
       same reason: they are designed shorter than 38px to sit inside a track
       (.watchlist-filter-btn is 28px in a 36px track; .dash-qs-swatch is a
       16px circle) and this rule stretched them into ovals / made them
       protrude from their track (mobile CSS batch #2, RC1). The import
       page's pills are a CSS module (hashed class), so they are hooked by
       data attribute like the other import-page exclusions. */
    button:not(.watchlist-card-remove):not(.wishlist-delete-btn):not(.wishlist-delete-album-btn):not(.wishlist-delete-btn-small):not(.wishlist-back-btn):not(.alphabet-btn):not(.filter-btn):not(.playlist-modal-close):not(.notif-bell-btn):not(.helper-float-btn):not(.hero-indicator):not(.discover-blacklist-btn):not(.tool-help-button):not(.vst-half):not([data-import-page-result-row]):not([data-import-page-inline-action]):not([data-import-page-pill]):not(.modal-track-play-btn):not(.cancel-track-btn):not(.dash-qs-swatch):not(.watchlist-filter-btn):not(.play-button):not(.stop-button):not(.mini-nav-btn):not(.mini-toggle-btn):not(.expand-hint):not(.sync-tab-button):not(.sync-tab-close) {
        min-height: 38px;
    }

    /* Range slider thumbs */
    input[type="range"]::-webkit-slider-thumb {
        width: 24px;
        height: 24px;
    }

    input[type="range"]::-moz-range-thumb {
        width: 24px;
        height: 24px;
    }

    input[type="range"] {
        min-height: 12px;
    }

    /* --- Phase 10: Typography & Spacing --- */

    /* Prevent iOS zoom on focus */
    input,
    select,
    textarea {
        font-size: 16px;
    }

    /* Font size floors */
    .app-subtitle,
    .stat-label,
    .stat-value-small {
        font-size: 12px;
    }

    /* Scale down oversized headings */
    .discover-hero-title {
        font-size: 32px;
    }

    .page-header h2 {
        font-size: 22px;
    }

    /* Spacing reductions */
    .page {
        padding: 70px 16px 72px 16px;
    }

    /* Nested wrappers each add horizontal padding, which compounds on a phone
       into more chrome than content (~136px of a 375px screen). Trim the
       biggest offender — the global .page-shell card (margin 20 + padding 24 =
       44px/side) — and drop the settings content wrappers' inner gutters so
       controls get the width back. Global, so all 8 .page-shell pages benefit
       (X4). */
    .page-shell {
        margin: 10px;
        padding: 24px 16px 26px;
    }
    #settings-page .settings-content {
        padding-left: 0;
        padding-right: 0;
    }
    #settings-page .settings-columns {
        padding-left: 0;
        padding-right: 0;
    }

    .activity-section {
        padding: 16px;
    }

    /* --- Chart slideshow grids (fixed 4-col → responsive) --- */
    .new-charts-grid,
    .dj-charts-grid,
    .featured-charts-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 12px;
    }

    /* --- Media player compact --- */
    .media-player {
        padding: 14px;
        border-radius: var(--radius-lg);
        min-height: 100px;
        flex-shrink: 0;
    }

    .media-header {
        gap: 10px;
        margin-bottom: 6px;
    }

    .media-player .track-title {
        font-size: 13px;
    }

    .media-player .artist-name {
        font-size: 11px;
    }

    .media-expanded {
        margin-top: 6px;
        padding-top: 6px;
    }

    .volume-control {
        gap: 6px;
    }

    .volume-slider {
        width: 80px;
    }

    /* --- Settings form inputs full width --- */
    .form-group select {
        width: 100%;
    }

    .form-group input[type="number"] {
        width: 100%;
    }

    .form-group input[type="text"],
    .form-group input[type="url"],
    .form-group input[type="password"] {
        width: 100%;
        box-sizing: border-box;
    }

    /* --- Toast container mobile adjustment --- */
    .toast-container {
        transform: none;
        width: auto;
        z-index: 10003;
    }

    .toast {
        max-width: 100%;
    }
}

/* ======================================
   EXTRA SMALL SCREENS (≤480px)
   ====================================== */

@media (max-width: 480px) {

    .page {
        padding: 70px 12px 72px 12px;
    }

    /* Even tighter card gutters on the smallest phones (X4). */
    .page-shell {
        margin: 6px;
        padding: 20px 12px 22px;
    }

    .stats-grid-dashboard {
        grid-template-columns: 1fr;
    }

    .discover-card {
        width: 140px;
    }

    .discover-hero-title {
        font-size: 26px;
    }

    .artist-card {
        width: 100%;
        max-width: 280px;
    }

    .header-button {
        font-size: 13px;
        padding: 10px 14px;
    }

    .sync-tab-button {
        min-width: 0;
    }

    /* Tool cards tighter on small screens */
    .tool-card {
        padding: 16px 12px;
    }

    .tool-card-title {
        font-size: 14px;
    }

    /* Enhanced search — small phone */

    .enh-compact-item.artist-card {
        width: calc(50% - 6px);
        height: 170px;
    }

    .enh-compact-item.artist-card .enh-item-info {
        padding: 8px;
    }

    .enh-compact-item.artist-card .enh-item-name {
        font-size: 11px;
    }

    .enh-compact-item.album-card {
        width: calc(50% - 6px);
    }

    .enh-compact-item.album-card .enh-item-name {
        font-size: 11px;
    }

    .enh-compact-item.album-card .enh-item-info {
        padding: 8px 10px 10px;
    }

    .enh-compact-item.track-item {
        padding: 10px 8px;
        gap: 10px;
    }

    .enh-compact-item.track-item .enh-item-name {
        font-size: 13px;
    }

    .enh-compact-item.track-item .enh-item-meta {
        font-size: 11px;
    }

    .enh-item-image.track-cover,
    .enh-item-image-placeholder.track-placeholder {
        width: 38px;
        height: 38px;
    }

    /* Beatport tighter */
    .beatport-tab-button {
        flex: 0 0 100%;
        font-size: 12px;
    }

    .beatport-rebuild-slider {
        height: 220px;
    }

    .beatport-rebuild-track-title {
        font-size: 16px;
    }

    .beatport-rebuild-artist-name {
        font-size: 12px;
    }

    .beatport-top10-card,
    .beatport-hype10-card {
        padding: 10px;
    }

    .beatport-top10-card-artwork,
    .beatport-hype10-card-artwork {
        width: 36px;
        height: 36px;
    }

    /* Beatport card grids: single column at 480px */
    .beatport-releases-grid,
    .beatport-hype-picks-grid,
    .beatport-charts-grid,
    .beatport-dj-grid {
        grid-template-columns: 1fr;
        gap: 8px;
        padding: 8px;
    }

    .beatport-release-card,
    .beatport-hype-pick-card {
        padding: 8px;
    }

    .beatport-release-artwork,
    .beatport-hype-pick-artwork {
        width: 40px;
        height: 40px;
    }

    .beatport-chart-card,
    .beatport-dj-card {
        min-height: 100px;
    }

    /* Playlist modal footer tighter */
    .playlist-modal-header {
        padding: 12px;
    }

    .playlist-modal-footer {
        padding: 12px;
    }

    .playlist-modal-footer .playlist-modal-btn {
        padding: 10px 16px;
        font-size: 13px;
    }

    /* Watchlist cards — tighter grid on small screens */
    .watchlist-artists-grid {
        grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
        gap: 12px;
        padding: 12px;
    }

    .watchlist-card-name {
        font-size: 12px;
    }

    .watchlist-card-info {
        padding: 0 10px 4px;
        margin-top: -24px;
    }

    .watchlist-pill {
        font-size: 8px;
        padding: 2px 5px;
    }

    .watchlist-card-pills {
        padding: 2px 10px 8px;
    }

    .watchlist-detail-content {
        padding: 20px 16px;
    }

    .watchlist-detail-hero img {
        width: 80px;
        height: 80px;
    }

    .watchlist-detail-hero-name {
        font-size: 22px;
    }

    .watchlist-detail-releases {
        grid-template-columns: 1fr;
    }

    /* Download modal - even more compact */
    .download-missing-modal-hero {
        padding: 10px 12px;
    }

    .download-missing-modal-hero-image,
    .download-missing-modal-hero-image.artist,
    .download-missing-modal-hero-image.album {
        width: 40px;
        height: 40px;
    }

    .download-missing-modal-hero-icon {
        width: 40px;
        height: 40px;
        font-size: 20px;
    }

    .download-missing-modal-hero-title {
        font-size: 14px;
    }

    .download-missing-modal-hero-subtitle {
        font-size: 11px;
    }

    .download-missing-modal-body {
        padding: 8px 10px 12px 10px;
    }

    /* Hide Library Match column too at 480px */
    .download-tracks-table td.track-match-status {
        display: none;
    }

    .download-tracks-table:has(.track-select-header) th:nth-child(6),
    .download-tracks-table:not(:has(.track-select-header)) th:nth-child(4) {
        display: none;
    }

    .track-name {
        max-width: 100px;
    }

    .track-artist {
        max-width: 70px;
    }

    .download-tracks-table th,
    .download-tracks-table td {
        padding: 5px 3px;
        font-size: 9px;
    }

    .download-control-btn {
        padding: 8px 10px;
        font-size: 11px;
    }

    .force-download-toggle span {
        font-size: 10px;
    }

    .download-missing-modal-footer {
        padding: 10px;
    }

    .dashboard-stat-number {
        font-size: 18px;
    }

    /* Chart grids single column at small screens */
    .new-charts-grid,
    .dj-charts-grid,
    .featured-charts-grid {
        grid-template-columns: 1fr;
        gap: 10px;
    }

    /* Media player even more compact */
    .media-player {
        margin: 6px 8px;
        padding: 10px;
        min-height: 90px;
        flex-shrink: 0;
    }

    .media-player .track-title {
        font-size: 12px;
    }

    .volume-slider {
        width: 60px;
    }
}

/* ======================================
   TOUCH DEVICE ADAPTATIONS
   ====================================== */

@media (hover: none) {

    /* Disable alphabet-btn scale hover effect for touch */
    .alphabet-btn:hover {
        transform: none;
    }

    /* Active feedback states */
    button:active,
    .nav-button:active,
    .filter-btn:active,
    .header-button:active {
        opacity: 0.7;
        transition: opacity 0.1s ease;
    }
}

@media (max-width: 768px) {
    /* Profile Picker - Mobile */
    .profile-picker-grid {
        gap: 20px;
    }

    .profile-avatar {
        width: 64px;
        height: 64px;
        font-size: 26px;
    }

    .profile-manage-content {
        width: calc(100vw - 32px);
        max-width: 400px;
    }

    .profile-pin-content {
        width: calc(100vw - 32px);
        max-width: 340px;
    }

    /* Enhanced Library Management - Mobile */
    .enhanced-artist-meta-grid {
        grid-template-columns: 1fr;
    }
    .enhanced-meta-field.wide {
        grid-column: span 1;
    }
    .enhanced-manual-match-modal {
        width: 95vw;
    }
    .enhanced-bulk-bar {
        left: 10px;
        right: 10px;
        padding: 8px 12px;
    }
    /* above the full-width mobile player (bottom:62px, 110px tall) */
    .enhanced-bulk-bar.visible {
        bottom: 184px;
    }
    .enhanced-bulk-modal {
        width: calc(100vw - 32px);
    }

    /* Discography filter bar */
    .discography-filters {
        gap: 6px;
        padding: 8px 0 12px;
    }
    .filter-group {
        gap: 4px;
        flex-wrap: wrap;
    }
    .filter-label {
        font-size: 10px;
        width: 100%;
    }
    .discography-filter-btn {
        padding: 4px 10px;
        font-size: 11px;
    }
    .filter-divider {
        display: none;
    }
    .enhanced-view-toggle-btn {
        padding: 5px 12px;
        font-size: 11px;
    }

    /* Enhanced view — artist card */
    .enhanced-artist-meta-header {
        flex-direction: column;
        align-items: stretch;
        padding: 16px;
        gap: 12px;
    }
    .enhanced-artist-meta-header-left {
        width: 100%;
        gap: 12px;
        flex-basis: auto;
    }
    .enhanced-artist-meta-image {
        width: 56px;
        height: 56px;
    }
    .lib-artist-initial {
        font-size: 22px;
    }
    .enhanced-artist-meta-name {
        font-size: 20px;
        white-space: normal;
    }
    .enhanced-artist-meta-actions {
        width: 100%;
        justify-content: flex-start;
        gap: 6px;
    }
    .enhanced-artist-meta-actions .lib-btn {
        flex: 1 1 auto;
        justify-content: center;
        min-width: 0;
        padding: 0 10px;
        font-size: 12px;
    }
    .lib-artist-foot {
        padding: 12px 16px 14px;
        gap: 12px;
    }
    .lib-quality {
        max-width: none;
        flex-basis: 100%;
    }
    .enhanced-artist-meta-form {
        padding: 0 16px 16px;
    }

    /* Enhanced view — album rows */
    .enhanced-album-row {
        gap: 12px;
        padding: 8px 12px 8px 8px;
    }
    .enhanced-album-art-wrap {
        width: 48px;
        height: 48px;
    }
    /* no hover on a phone: the play overlay is always there, quietly */
    .enhanced-album-play-btn {
        opacity: 1;
        background: rgba(0, 0, 0, 0.35);
    }
    .enhanced-album-title {
        font-size: 14px;
    }
    .enhanced-album-meta-line {
        font-size: 11.5px;
        white-space: normal;
    }
    .lib-album-side .enhanced-format-badge {
        display: none;
    }

    /* Enhanced view — expanded album */
    .enhanced-tracks-panel.visible > .enhanced-tracks-panel-inner {
        padding: 16px 12px 12px;
    }
    .enhanced-expanded-header {
        flex-direction: column;
        gap: 14px;
    }
    .enhanced-expanded-art-wrap {
        width: 120px;
        height: 120px;
        align-self: center;
    }
    .enhanced-expanded-info {
        width: 100%;
        align-items: center;
        text-align: center;
    }
    .enhanced-expanded-title {
        font-size: 20px;
        white-space: normal;
    }
    .enhanced-expanded-genres,
    .enhanced-expanded-info .lib-sources {
        justify-content: center;
    }
    .enhanced-expanded-actions {
        justify-content: center;
        width: 100%;
    }
    .enhanced-expanded-actions .lib-btn {
        flex: 1 1 auto;
        justify-content: center;
    }
    .enhanced-expanded-actions .lib-btn.icon {
        flex: 0 0 34px;
    }
    .enhanced-album-meta-row {
        grid-template-columns: 1fr !important;
        gap: 8px;
        padding: 12px;
    }
    .enhanced-album-meta-input {
        font-size: 12px;
    }
    .enhanced-album-save-btn {
        width: 100%;
    }

    /* Enhanced view — track table */
    .enhanced-track-table {
        table-layout: auto;
        font-size: 12px;
    }
    .enhanced-track-table th,
    .enhanced-track-table td {
        font-size: 12px;
    }
    .enhanced-track-table .col-num {
        width: 24px;
    }
    .enhanced-track-table .col-title {
        white-space: normal;
    }

    /* Mobile actions popover */
    .enhanced-mobile-actions-popover {
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        background: rgba(20, 20, 20, 0.98);
        backdrop-filter: blur(20px);
        border-top: 1px solid var(--white-a10);
        border-radius: 16px 16px 0 0;
        padding: 16px;
        z-index: 10001;
        display: flex;
        flex-direction: column;
        gap: 4px;
        animation: slideUpPopover 0.25s ease-out;
    }
    .enhanced-mobile-actions-popover .popover-title {
        font-size: 13px;
        font-weight: 600;
        color: var(--white-a50);
        padding: 0 4px 8px;
        border-bottom: 1px solid var(--white-a06);
        margin-bottom: 4px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .enhanced-mobile-actions-popover button {
        display: flex;
        align-items: center;
        gap: 12px;
        width: 100%;
        padding: 14px 16px;
        background: none;
        border: none;
        border-radius: 10px;
        color: var(--white-a85);
        font-size: 14px;
        cursor: pointer;
        transition: background 0.15s;
    }
    .enhanced-mobile-actions-popover button:active {
        background: var(--white-a08);
    }
    .enhanced-mobile-actions-popover button .popover-icon {
        font-size: 16px;
        width: 24px;
        text-align: center;
    }
    .enhanced-mobile-actions-popover button.popover-delete {
        color: rgba(255, 80, 80, 0.8);
    }
    .enhanced-mobile-actions-popover button.popover-cancel {
        color: var(--white-a40);
        border-top: 1px solid var(--white-a06);
        margin-top: 4px;
    }
    .mobile-popover-overlay {
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: 10000;
    }

    @keyframes slideUpPopover {
        from { transform: translateY(100%); }
        to { transform: translateY(0); }
    }

    /* Bulk bar */
    .enhanced-bulk-bar {
        flex-wrap: wrap;
        gap: 8px;
    }
    .enhanced-bulk-bar .enhanced-bulk-btn {
        font-size: 11px;
        padding: 6px 10px;
    }
    /* Now Playing Modal */
    .np-modal {
        width: 100vw;
        max-width: none;
        max-height: none;
        height: 100vh;
        border-radius: 0;
    }
    .np-body {
        flex-direction: column;
        overflow-y: auto;
        max-height: 100vh;
    }
    .np-track-info {
        width: 100%;
    }
    .np-track-title {
        font-size: 18px;
    }
    .np-volume-slider-container {
        width: 120px;
    }
}

/* ======================================
   ARTIST ENRICHMENT RINGS — Mobile
   ====================================== */

@media (max-width: 768px) {
    .artist-enrichment-coverage {
        margin-top: 12px;
    }

    .artist-enrich-grid {
        grid-template-columns: repeat(5, 1fr);
        gap: 8px 4px;
    }

    .artist-enrich-ring {
        width: 36px;
        height: 36px;
    }

    .artist-enrich-ring svg {
        width: 36px;
        height: 36px;
    }

    .artist-enrich-ring .ring-pct {
        font-size: 8px;
    }

    .artist-enrich-label {
        font-size: 0.5em;
    }
}

@media (max-width: 480px) {
    .artist-enrich-grid {
        grid-template-columns: repeat(3, 1fr);
        gap: 10px 8px;
    }
}

/* ======================================
   AUTOMATIONS PAGE — Mobile
   ====================================== */

@media (max-width: 768px) {
    .automations-container {
        padding: 16px;
    }

    .automations-header {
        flex-direction: column;
        align-items: flex-start;
        gap: 12px;
    }

    .automations-stats {
        flex-wrap: wrap;
    }

    /* Builder view */
    .builder-header {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
        padding: 12px;
    }

    .builder-name-input,
    .builder-group-input {
        width: 100%;
        font-size: 14px;
    }

    .builder-header-actions {
        width: 100%;
        display: flex;
        gap: 8px;
    }

    .builder-header-actions button {
        flex: 1;
        font-size: 12px;
        padding: 8px;
    }

    .builder-sidebar {
        border-right: none;
        border-bottom: 1px solid var(--white-a06);
    }

    .builder-canvas {
        width: 100%;
        flex: 1;
    }

    .block-item {
        padding: 10px;
    }

    .condition-builder {
        flex-direction: column;
        gap: 6px;
    }

    .condition-builder select,
    .condition-builder input {
        width: 100%;
    }

    /* Automation cards */
    .automation-card {
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
    }

    .automation-card-actions {
        width: 100%;
        justify-content: flex-end;
    }
}

/* ======================================
   HYDRABASE PAGE — Mobile
   ====================================== */

@media (max-width: 768px) {
    .hydrabase-container {
        flex-direction: column;
        height: auto;
        overflow-y: auto;
    }

    .hydrabase-panel {
        width: 100%;
        min-height: 200px;
    }

    .hydrabase-card {
        padding: 12px;
    }

    .hydrabase-card > div {
        flex-direction: column;
        gap: 8px;
    }

    .hydrabase-card input,
    .hydrabase-card select {
        width: 100%;
        box-sizing: border-box;
    }

    .hydra-payload {
        width: 100%;
        min-height: 80px;
    }

    .hydrabase-response-area {
        max-height: 250px;
        font-size: 12px;
    }
}

/* ======================================
   WATCHLIST / ENHANCE BUTTONS — Mobile
   ====================================== */

@media (max-width: 768px) {
    .library-artist-radio-btn,
    .library-artist-watchlist-btn,
    .library-artist-enhance-btn {
        padding: 8px 14px;
        font-size: 12px;
        gap: 6px;
    }

    .library-artist-radio-btn .radio-icon,
    .library-artist-watchlist-btn .watchlist-icon,
    .library-artist-enhance-btn .enhance-icon {
        font-size: 12px;
    }
}

/* ======================================
   API RATE MONITOR — MOBILE
   ====================================== */

@media (max-width: 768px) {
    .rate-monitor-grid {
        grid-template-columns: repeat(2, 1fr) !important;
        gap: 8px;
    }

    .gauge-unit {
        font-size: 8px !important;
    }

    /* Rate modal */
    .rate-modal {
        width: 95vw !important;
        max-height: 90vh;
        border-radius: 14px;
    }

    .rate-modal-header h3 {
        font-size: 14px;
    }

    .rate-modal-body {
        padding: 14px 16px;
    }

    .rate-modal-ep-name {
        width: 100px;
        font-size: 11px;
    }

    .rate-modal-ep-value {
        font-size: 10px;
        width: 50px;
    }
}

@media (max-width: 480px) {
    .rate-monitor-grid {
        grid-template-columns: repeat(2, 1fr) !important;
        gap: 6px;
    }
}

/* ======================================
   NOTIFICATION SYSTEM — MOBILE
   ====================================== */

@media (max-width: 768px) {
    /* Toast */
    .toast-container {
        bottom: 72px;
        right: 12px;
        left: 12px;
    }

    .toast-compact {
        max-width: 100%;
        font-size: 12px;
        padding: 10px 12px;
        gap: 8px;
    }

    /* Bell button */
    .notif-bell-btn {
        bottom: 16px;
        right: 60px;
        width: 38px;
        height: 38px;
        font-size: 16px;
    }

    .notif-bell-badge {
        font-size: 9px;
        min-width: 14px;
        height: 14px;
    }

    /* Notification panel */
    .notif-panel {
        /* JS positions this inline from the bell's rect (right/bottom), which on
           mobile pushes it off-screen (the bell isn't flush right). Override the
           inline styles with !important and anchor both sides so it always fits. */
        left: 12px !important;
        right: 12px !important;
        width: auto !important;
        max-width: none !important;
        bottom: 62px !important;
        max-height: 55vh;
        border-radius: 14px;
    }

    .notif-panel-header {
        padding: 12px 14px 10px;
    }

    .notif-panel-title {
        font-size: 13px;
    }

    /* Helper button */
    .helper-float-btn {
        bottom: 16px;
        right: 12px;
        width: 38px;
        height: 38px;
        font-size: 16px;
    }

    /* Server Activity button — match the bell/helper row (it kept its desktop
       44px @ bottom 24 / right 136, so it floated bigger and higher than the
       other two on phones). Same size, same baseline, next slot leftward. */
    .activity-float-btn {
        bottom: 16px;
        right: 108px;
        width: 38px;
        height: 38px;
    }

    .activity-float-badge {
        font-size: 9px;
        min-width: 14px;
        height: 14px;
    }

    /* Global search bar */
    .gsearch-bar {
        width: calc(100vw - 160px);
        bottom: 16px;
        height: 38px;
    }

    .gsearch-bar.active {
        width: calc(100vw - 24px);
    }

    .gsearch-input {
        font-size: 13px;
    }

    .gsearch-results {
        max-height: 50vh;
        width: calc(100vw - 24px);
        left: 12px;
        right: 12px;
        transform: none;
        bottom: 60px;
    }

    .gsearch-item {
        padding: 6px;
    }

    .gsearch-item-art {
        width: 36px;
        height: 36px;
    }

    .gsearch-item-title {
        font-size: 12px;
    }

    .gsearch-item-sub {
        font-size: 10px;
    }
}

@media (max-width: 480px) {
    .notif-bell-btn {
        bottom: 12px;
        right: 54px;
        width: 34px;
        height: 34px;
    }

    .helper-float-btn {
        bottom: 12px;
        right: 10px;
        width: 34px;
        height: 34px;
    }

    .activity-float-btn {
        bottom: 12px;
        right: 96px;
        width: 34px;
        height: 34px;
    }

    .gsearch-bar {
        width: calc(100vw - 130px);
        bottom: 12px;
        height: 34px;
    }

    .gsearch-bar.active {
        width: calc(100vw - 20px);
    }

    .toast-container {
        bottom: 56px;
        right: 8px;
        left: 8px;
    }

    .notif-panel {
        left: 8px !important;
        right: 8px !important;
        width: auto !important;
        bottom: 54px !important;
    }
}

/* ─────────────────────────────────────────────────────────────
   Source picker row — Search page + global widget responsive.
   Chips shrink on tablet, labels drop on phone so the full row
   of 8 sources remains scannable without hijacking the screen. */
@media (max-width: 768px) {
    .enh-source-row {
        padding: 8px 8px;
        margin: 8px 0 10px;
        gap: 6px;
        border-radius: var(--radius-lg);
    }
    .enh-source-icon {
        min-width: 72px;
        padding: 8px 10px;
        gap: 4px;
        font-size: 10.5px;
    }
    .enh-source-icon-glyph,
    .enh-source-icon-glyph img {
        width: 24px;
        height: 24px;
    }
    .enh-source-icon-label { font-size: 10.5px; }
    .enh-fallback-banner {
        font-size: 11px;
        padding: 6px 10px;
    }

    /* Global widget source row (inside the popover) */
    .gsearch-source-row {
        padding: 10px 10px 6px;
        gap: 4px;
    }
    .gsearch-source-icon {
        min-width: 62px;
        padding: 6px 8px;
        gap: 3px;
    }
    .gsearch-source-icon-glyph,
    .gsearch-source-icon-glyph img {
        width: 20px;
        height: 20px;
    }
    .gsearch-fallback-banner {
        font-size: 10px;
        padding: 5px 10px;
    }

    /* Ambient glow under the global search — trim size so it doesn't
       dominate a short mobile viewport. */
    .gsearch-aura {
        height: 180px;
        background:
            radial-gradient(ellipse 440px 160px at 50% 100%,
                rgba(var(--accent-rgb), 0.20) 0%,
                rgba(var(--accent-rgb), 0.08) 35%,
                rgba(var(--accent-rgb), 0.02) 65%,
                transparent 85%);
    }
    .gsearch-aura.active {
        background:
            radial-gradient(ellipse 540px 200px at 50% 100%,
                rgba(var(--accent-rgb), 0.34) 0%,
                rgba(var(--accent-rgb), 0.14) 28%,
                rgba(var(--accent-rgb), 0.04) 58%,
                transparent 85%);
    }

    /* Library empty-state hand-off CTA — allow wrap on narrow screens
       so long artist queries don't overflow. */
    .library-empty-search-cta {
        flex-wrap: wrap;
        justify-content: center;
        padding: 10px 14px;
        font-size: 13px;
        max-width: 100%;
    }
    .library-empty-search-cta-text {
        white-space: normal;
        text-align: center;
    }
}

/* Very narrow phones — drop the icon labels entirely and show just the
   glyphs. Tap target stays big enough, row compacts dramatically. */
@media (max-width: 480px) {
    .enh-source-row {
        padding: 6px 6px;
        gap: 4px;
        border-radius: 10px;
    }
    .enh-source-icon {
        min-width: 44px;
        padding: 6px 8px;
    }
    .enh-source-icon-label { display: none; }

    .gsearch-source-row {
        padding: 8px 8px 5px;
        gap: 4px;
    }
    .gsearch-source-icon {
        min-width: 40px;
        padding: 5px 7px;
    }
    .gsearch-source-icon-label { display: none; }

    .gsearch-aura { height: 140px; }

    .library-empty-search-cta {
        font-size: 12px;
        padding: 9px 12px;
    }
}

/* ============================================================================
   Mobile fixes (v2) — phone-only, all inside max-width:768px. Desktop untouched.
   ============================================================================ */
@media (max-width: 768px) {
    /* Center the artist hero action buttons + match-status chips on phone
       (moved here from the base rule so desktop stays left-aligned). */
    .artist-hero-actions { justify-content: center; }
    .enhanced-match-status-row { justify-content: center; }

    /* #8 Page-container heroes carry desktop-sized padding/margins that waste
       space and look off on a phone. Tighten them up. */
    .tools-maintenance-hero,
    .watchlist-artist-config-hero,
    .watchlist-detail-hero,
    .discover-hero {
        padding: 14px 14px;
        margin-bottom: 16px;
    }

    /* #9 Sync page header: title + the three action buttons (Auto-Sync / Library
       Match / Sync History) don't fit side-by-side. Stack the header and let the
       buttons wrap so all three are reachable. */
    .sync-header-row {
        flex-direction: column;
        align-items: stretch;
        gap: 12px;
    }
    .sync-header-row > div:last-child {
        flex-wrap: wrap;
    }
    .sync-header-row .sync-history-btn {
        flex: 1 1 auto;
    }
}

@media (max-width: 768px) {
    /* #6 Enhanced-view track table: a 6+ column table can't fit a phone and the
       panel clips the overflow, so only the first column showed. Drop table
       layout entirely and make each row a single flex line: play · title (takes
       the space) · duration · the ⋯ actions button. Secondary columns hidden. */
    .enhanced-track-table,
    .enhanced-track-table thead,
    .enhanced-track-table tbody,
    .enhanced-track-table tr,
    .enhanced-track-table td,
    .enhanced-track-table th {
        display: block;
        width: auto;
    }
    .enhanced-track-table thead { display: none; }
    .enhanced-track-table tr {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 8px 6px;
        border-bottom: 1px solid var(--white-a05);
    }
    .enhanced-track-table td,
    .enhanced-track-table th {
        padding: 0;
        border: none;
        white-space: normal;
        /* the desktop row height would stretch each block cell to 42px and
           float the checkbox above the title */
        height: auto;
    }
    .enhanced-track-table .col-play {
        flex: 0 0 auto;
        width: auto;
        line-height: 0;
    }
    /* no hover on a phone, so the play glyph cannot stay dim */
    .enhanced-track-table .enhanced-play-btn:not(:disabled) {
        color: var(--white-a75);
    }
    .enhanced-track-table .col-title {
        flex: 1 1 auto;
        min-width: 0;
        word-break: break-word;
        font-size: 13px;
    }
    .enhanced-track-table .col-duration {
        flex: 0 0 auto;
        width: auto;
        font-size: 11px;
        opacity: 0.65;
    }
    .enhanced-track-table .col-mobile-actions {
        display: block;
        flex: 0 0 auto;
        width: auto;
        text-align: right;
    }
    /* Everything else folds into the ⋯ actions sheet — hide on the row. */
    .enhanced-track-table .col-num,
    .enhanced-track-table .col-disc,
    .enhanced-track-table .col-format,
    .enhanced-track-table .col-bitrate,
    .enhanced-track-table .col-bpm,
    .enhanced-track-table .col-path,
    .enhanced-track-table .col-match,
    .enhanced-track-table .col-queue,
    .enhanced-track-table .col-writetag,
    .enhanced-track-table .col-delete,
    .enhanced-track-table .col-track-actions,
    .enhanced-track-table .col-report,
    .enhanced-track-table tr > th:first-child {
        display: none;
    }
}

@media (max-width: 768px) {
    /* #7 Mini media player: on desktop it's a 340px widget pinned bottom-right
       (right:132px) — that overflows a phone and overlaps the bottom search.
       Make it a full-width bar that sits just ABOVE the global search bar
       (which is at bottom:16px, height:38px on mobile). */
    .media-player {
        left: 10px;
        right: 10px;
        width: auto;
        bottom: 62px;
        margin: 0;
    }
}

@media (max-width: 768px) {
    /* ── Now Playing modal — full responsive pass ──
       Desktop is a two-column (art | controls) layout with heavy 40-48px
       padding. Existing mobile rules made it full-screen + stacked the body but
       left the panels' desktop padding and the controls/queue/lyrics untouched. */
    .np-body {
        padding: 24px 16px 28px;
        gap: 20px;
    }
    .np-left,
    .np-right {
        width: 100%;
    }
    /* Album art scales with the screen instead of a fixed 220px. */
    .np-album-art-container {
        width: min(220px, 66vw);
        height: auto;
        aspect-ratio: 1 / 1;
        margin: 0 auto;
    }
    .np-track-info { text-align: center; }
    .np-action-buttons { justify-content: center; }
    .np-util-row { justify-content: center; flex-wrap: wrap; }
    /* Playback controls: tighten the gap so the row fits a phone. */
    .np-controls-row { gap: 12px; justify-content: center; }
    /* Queue + lyrics panels: drop the 40px desktop side padding that crushed
       content on a narrow screen; give them a bit more vertical room. */
    .np-queue-panel { padding: 0 16px 16px; }
    .np-lyrics-panel { padding: 0 16px; }
    .np-queue-body { max-height: 240px; }
    .np-lyrics-body { max-height: 300px; }
}

/* When the expanded Now Playing modal is open, hide the floating mini-player —
   it has a higher z-index (99998) than the modal overlay (10001), so it would
   otherwise float on top of the modal's content. Both are body-level siblings
   (#media-player follows #np-modal-overlay), and the overlay drops its .hidden
   class when open. Not width-scoped — applies on desktop too. */
.np-modal-overlay:not(.hidden) ~ #media-player {
    display: none !important;
}

/* Same story for the nav drawer (Oct 13 batch, M-05): the mini player is
   z-index 99998, the drawer 10001, so with the drawer open the player
   floated on top of it and covered its Podcasts row (measured live:
   elementFromPoint at the player's centre returned a player button while
   the drawer was open). init.js already stamps mobile-nav-open on <body>
   for exactly this state; the player defers to the drawer the same way it
   defers to the Now Playing modal. */
body.mobile-nav-open #media-player {
    display: none !important;
}

/* Same deferral for the Year in Listening story (Oct 13 fold, M-17): the
   portalled overlay sits at z-9000 at body level, but #media-player is
   z-99998 and full-width at the bottom on mobile — whenever anything was
   playing (the normal case for a listening story) the player sat on top
   of the story's Back / counter / Done row. The floating button stack
   covered Done the same way. The story is a takeover; both defer to it
   for exactly its lifetime (the overlay only exists while it is open). */
body:has([data-year-story-overlay]) #media-player,
body:has([data-year-story-overlay]) .activity-float-btn,
body:has([data-year-story-overlay]) .helper-float-btn {
    display: none !important;
}

@media (max-width: 768px) {
    /* ── Downloads page (.adl-*) ──
       The redesign is single-column already; the phone pass is about row
       anatomy. Desktop rows are art + text + a right-hand status column,
       which squeezed titles to ~10 chars (and review rows to NOTHING).
       On a phone the text owns line one and everything else wraps under it. */

    .adl-hero {
        gap: 10px 14px;
    }
    .adl-hero-stats {
        gap: 18px;
        width: 100%;
        justify-content: space-between;
    }
    .adl-stat { min-width: 0; }
    .adl-stat-num { font-size: 1.4rem; }
    .adl-hero-actions {
        width: 100%;
    }
    .adl-cancel-all-btn,
    .adl-clear-btn { flex: 1 1 auto; padding: 8px 13px; }

    /* view tabs spread across the full width; status chips scroll */
    .adl-view-tabs {
        width: 100%;
    }
    .adl-view-tab {
        flex: 1 1 auto;
        padding: 9px 6px 11px;
        font-size: 0.82rem;
    }
    .adl-status-chips {
        width: 100%;
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
        padding-bottom: 9px;
    }
    .adl-status-chips::-webkit-scrollbar { display: none; }
    .adl-pill { flex-shrink: 0; padding: 5px 12px; }

    /* row: art + info on line one, status chip + chevron wrap to line two,
       indented under the text instead of amputating the title */
    .adl-row {
        flex-wrap: wrap;
        row-gap: 6px;
    }
    .adl-row-info {
        /* wide enough to stay beside the art (rail included), narrow enough
           that the status chip can't fit on line one and wraps below */
        flex: 1 1 180px;
        min-width: 180px;
    }
    .adl-row-status {
        margin-left: 52px;
    }
    .adl-row-chevron { display: none; }

    /* review rows had it worst: badges + five buttons ate the entire width
       and the title rendered zero chars. Same cure: actions wrap below. */
    .verif-quar-row .verif-actions {
        flex-basis: 100%;
        margin-left: 52px;
        flex-wrap: wrap;
        row-gap: 6px;
    }
    .adl-deleted-header {
        flex-wrap: wrap;
        gap: 8px;
    }

    /* group headers: drop the stat line (900px already does) and the source
       tag; keep name, phase, progress and the actions tappable */
    .adl-group-header {
        padding: 10px 8px 10px 14px;
        gap: 10px;
    }
    .adl-group-source { display: none; }
    .adl-group-act,
    .adl-group-chevron { width: 36px; height: 36px; }

    /* the banners (batch filter, review sub-views, clients tabs) wrap;
       nothing may clip off the right edge */
    .adl-batch-filter-banner {
        flex-wrap: wrap;
        row-gap: 6px;
    }
    .verif-banner-spacer { display: none; }
}

@media (max-width: 768px) {
    /* the sidebar visualizer is a desktop thing. on phones it floated over the
       page with the drawer closed, and with the drawer open it was just a thin
       violet line down the drawer's edge that read as a bug. hide it in every
       state. the .viz-* rules set display with 2-class specificity, so this
       needs !important to win. */
    .sidebar-visualizer {
        display: none !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
   TOOLS PAGE REDESIGN — phone + tablet
   Health hero, findings inbox, operation tiles, recent runs, tool containers.
   The base rules live in style.css; everything responsive lives here, on the
   house 768/480 breakpoints.
   ═══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 1024px) {
    /* Tablet: two tile columns at most, so a tile never gets so narrow that
       its cadence editor and action row fight for the same line. */
    .repair-family-grid {
        grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
    }
}

@media (max-width: 768px) {
    /* THE important one. The hero is its own scroll container on desktop so
       the section nav can stick to it — on a phone that is a scroll-within-a-
       scroll, and the findings list nests a THIRD one inside it. Release both
       and let the page scroll like a page. */
    .tools-maintenance-hero {
        max-height: none;
        overflow: visible;
    }
    /* The hero clipped its own 3px top edge to the rounded corner. Released,
       nothing clips it, so it rounds itself. */
    .tools-maintenance-hero::before {
        border-radius: 16px 16px 0 0;
    }

    .repair-inbox-body {
        max-height: none;
        overflow: visible;
        padding: 0 10px 12px 10px;
    }

    /* Sticky needs a scroll container to stick to; with the hero released it
       would pin against the app chrome instead. Let it scroll away — it is
       four buttons and the sections are a swipe apart. */
    .repair-section-nav {
        position: static;
        overflow-x: auto;
        scrollbar-width: none;
        padding: 6px 0;
    }
    .repair-section-nav::-webkit-scrollbar { display: none; }
    .repair-section-link { flex-shrink: 0; }

    /* ── Health hero ── */
    .repair-health {
        gap: 14px;
        padding: 14px;
    }
    .repair-health-score-block {
        min-width: 0;
        flex-direction: row;
        align-items: baseline;
        gap: 10px;
    }
    .repair-health-score { font-size: 42px; }
    .repair-health-band { margin-top: 0; }
    .repair-health-body { flex: 1 1 100%; }
    .repair-health-actions-note { flex-basis: 100%; }
    .repair-health-fix-safe { min-height: 40px; }

    /* ── Filters ── */
    .repair-findings-toolbar { gap: 8px; }
    .repair-status-segments {
        display: flex;
        width: 100%;
        overflow-x: auto;
        scrollbar-width: none;
    }
    .repair-status-segments::-webkit-scrollbar { display: none; }
    .repair-status-seg { flex: 1 0 auto; justify-content: center; min-height: 38px; }
    .repair-findings-search { flex: 1 1 100%; min-height: 38px; }
    .repair-findings-filters { flex: 1 1 100%; }
    .repair-findings-filters select { flex: 1 1 45%; min-height: 38px; }
    .repair-clear-btn { flex: 1 1 100%; min-height: 38px; }

    /* ── Findings inbox ── */
    .repair-inbox-head {
        flex-wrap: wrap;
        row-gap: 6px;
        padding: 11px 12px;
    }
    .repair-inbox-blurb { white-space: normal; }
    .repair-inbox-actions {
        width: 100%;
        justify-content: flex-end;
        flex-wrap: wrap;
    }
    .repair-inbox-btn { min-height: 36px; }
    .repair-list-controls { gap: 8px; }
    .repair-list-controls select { flex: 1 1 45%; min-height: 36px; }

    /* ── Operation tiles ── */
    .repair-family { padding: 12px 11px 13px 11px; }
    .repair-family-head { flex-wrap: wrap; row-gap: 4px; }
    .repair-family-summary { flex-basis: 100%; order: 3; white-space: normal; }
    .repair-family-grid { grid-template-columns: 1fr; }

    /* Number + unit + Save + Cancel do not fit one line in a full-width
       tile on a phone, and a clipped Save is a schedule you cannot change. */
    .repair-tile-schedule { row-gap: 6px; }
    .repair-tile-cadence-edit { flex-wrap: wrap; row-gap: 6px; }
    .repair-tile-cadence,
    .repair-tile-cadence-save,
    .repair-tile-cadence-cancel { min-height: 34px; }
    .repair-tile-cadence-edit input,
    .repair-tile-cadence-edit select { min-height: 34px; }

    /* ── Recent runs ── */
    .repair-runs-toolbar { flex-direction: column; align-items: stretch; }
    .repair-runs-tools { justify-content: flex-end; }
    .repair-runs-chip,
    .repair-runs-toggle { min-height: 32px; }
    .repair-run-head { flex-wrap: wrap; row-gap: 3px; padding: 10px 12px; }
    .repair-run-name { min-width: 0; }
    /* Order 3 drops the summary onto its own line UNDER the row, leaving the
       clock, name, age and chevron together on the first — without it the
       summary splits the row and pushes age + chevron onto a third line. */
    .repair-run-summary {
        order: 3;
        white-space: normal;
        flex-basis: 100%;
        padding-left: 29px;
    }
    .repair-run-age { margin-left: auto; }
    .repair-run-detail { padding: 4px 12px 13px 12px; }
    .repair-run-counters { gap: 14px; }
    .repair-run-foot { flex-direction: column; align-items: flex-start; gap: 6px; }

    /* ── Tool containers ── */
    .tools-container { padding: 12px 11px 13px 11px; }
    .tools-container-head { gap: 6px; }
    .tools-container-blurb { flex-basis: 100%; }
}

@media (max-width: 480px) {
    /* The trend line is the first thing to go: it is context, and the score
       and the bar underneath it are the point. */
    .repair-health-trend { display: none; }
    .repair-health-score { font-size: 36px; }
    .repair-health-actions { gap: 8px; }

    .repair-section-link { padding: 6px 11px; }

    .repair-inbox-count { min-width: 44px; font-size: 20px; }
    .repair-inbox-head { gap: 9px; }
    .repair-inbox-label { font-size: 13px; flex-wrap: wrap; row-gap: 4px; }
    /* Two lines of explanation beats one line of ellipsis. */
    .repair-inbox-blurb { font-size: 11px; }

    .repair-tile { padding: 11px; }
    .repair-tile-desc { -webkit-line-clamp: 3; }
    .repair-tile-foot { flex-wrap: wrap; row-gap: 8px; }
    .repair-tile .repair-job-actions { margin-left: auto; }

    .repair-run-clock { min-width: 40px; }
    .repair-run-counter-value { font-size: 15px; }
    /* A stack trace does not need to eat the screen on a phone. */
    .repair-run-error-text { max-height: 120px; font-size: 10px; }
}

@media (hover: none) {
    /* Icon-only controls at desktop sizes are a miss on a fingertip. */
    .repair-run-btn,
    .repair-stop-btn,
    .repair-settings-btn,
    .repair-help-btn,
    .repair-inbox-expand,
    .repair-runs-refresh,
    .repair-finding-expand-btn {
        min-width: 34px;
        min-height: 34px;
    }

    /* The cadence pill reads as editable on hover; on touch there is no
       hover, so it carries its affordance all the time. */
    .repair-tile-cadence {
        border-style: solid;
        border-color: rgba(var(--tile-glow), 0.35);
    }

    /* Same for the health bar segments — they are buttons. */
    .repair-health-seg { min-width: 10px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   AUTOMATIONS REDESIGN — phone + tablet
   Verdict strip, family containers, and the builder palette.
   ═══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 768px) {
    /* The verdict chips are buttons now, so they need thumb-sized targets and
       have to wrap rather than push the master toggle off the row. */
    .automations-stats { padding: 12px 13px; gap: 8px; }
    .automations-stats .auto-stat { padding: 7px 11px; min-height: 38px; }
    .automations-stats .auto-master-toggle {
        order: -1; margin-left: 0; width: 100%; justify-content: center; min-height: 42px;
    }

    .automations-section { padding: 11px 11px 12px; }
    .automations-section-header { flex-wrap: wrap; row-gap: 4px; }
    .automations-section-header .section-line { display: none; }
    .automations-section-header .section-action-btn { min-width: 34px; min-height: 34px; }

    /* One card per row: the grid's 430px floor is wider than a phone. */
    .automations-section .automations-grid { grid-template-columns: 1fr; }
    .automation-card { padding: 12px 12px 11px 15px; }
    .automation-card .automation-actions { flex-wrap: wrap; }

    /* The tile's foot is a two-up row on desktop. On a phone the meta line
       alone eats the width, so the controls take their own row underneath
       rather than being squeezed to one button per line. */
    .automation-card.automation-tile .auto-tile-foot {
        flex-direction: column; align-items: stretch; gap: 8px;
    }
    .automation-card.automation-tile .automation-actions { justify-content: flex-end; }
    /* Thumb targets: these were 28px squares built for a mouse. */
    .automation-card.automation-tile .automation-actions button {
        width: 38px; height: 38px; font-size: 14px;
    }
    /* The cadence editor is three controls in a chip-sized row — let it wrap
       instead of overflowing the card. */
    .automation-card.automation-tile .auto-cadence-edit { width: 100%; }
    .automation-card.automation-tile .auto-cadence-edit input,
    .automation-card.automation-tile .auto-cadence-edit select { min-height: 34px; }
    .automation-card.automation-tile .auto-cadence-save,
    .automation-card.automation-tile .auto-cadence-cancel { min-height: 34px; }

    /* The builder is two columns on desktop; stack them, and cap the palette
       so the canvas is reachable without scrolling past 100 blocks. */
    .builder-content { flex-direction: column; }
    .builder-sidebar {
        width: 100%; max-width: none;
        max-height: 45vh; overflow-y: auto;
    }
}

@media (max-width: 480px) {
    .automations-stats .auto-stat strong { font-size: 16px; }
    .automation-card .automation-flow { flex-wrap: wrap; row-gap: 4px; }
    .automation-card .auto-meta-fail { max-width: 100%; white-space: normal; }
    /* The name and the runs badge stop competing for one line. */
    .automation-card.automation-tile .auto-tile-head { flex-wrap: wrap; row-gap: 4px; }
    .automation-card.automation-tile .automation-name { font-size: 13.5px; }
    .automation-card.automation-tile .flow-trigger,
    .automation-card.automation-tile .flow-action,
    .automation-card.automation-tile .flow-notify { max-width: 100%; }
    .builder-sidebar { max-height: 40vh; }
}

@media (hover: none) {
    /* Drawer headers and block rows are the builder's whole interaction. */
    .builder-sidebar .block-drawer-head { min-height: 38px; }
    .builder-sidebar .block-item { min-height: 46px; }
    .automations-stats .auto-stat-lens:hover { transform: none; }
    .automation-card:hover { transform: none; }
    /* No hover to reveal the tile's controls with, and the editable trigger
       chip must be tappable rather than hover-hinted. */
    .automation-card.automation-tile .automation-actions { opacity: 1; }
    .automation-card.automation-tile .auto-flow-editable { min-height: 30px; }
    .automation-card.automation-tile .auto-tile-badge { min-height: 30px; }
}

/* #1227: shared by playlist, album, artist-album and wishlist download dialogs.
   Dynamic viewport sizing also covers Safari with its browser bars visible. */
html.download-modal-open,
html.download-modal-open body {
    overflow: hidden;
    overscroll-behavior: none;
}
.download-missing-modal {
    height: 100vh;
    height: 100dvh;
    overscroll-behavior: contain;
}
.download-missing-modal-content {
    max-height: 95vh;
    max-height: 95dvh;
}
@media (max-width: 768px) {
    /* One outer scroll area keeps the hero, rows and all footer controls reachable.
       The bounded inner table scroll still works for very long playlists. */
    .download-missing-modal .download-missing-modal-content {
        height: 95vh;
        height: 95dvh;
        overflow-y: auto;
        overscroll-behavior-y: contain;
        -webkit-overflow-scrolling: touch;
    }
    .download-missing-modal-header,
    .download-missing-modal .download-missing-modal-body,
    .download-missing-modal-footer {
        flex: 0 0 auto;
    }
    .download-missing-modal .download-missing-modal-body {
        overflow: visible;
    }
    .download-missing-modal .download-tracks-section {
        flex: 0 0 auto;
        min-height: 280px;
    }
    .download-missing-modal .download-tracks-table-container {
        flex: 0 0 auto;
        min-height: 220px;
        max-height: 50vh;
        max-height: max(220px, 50dvh);
        overflow: auto;
        /* The inner list must chain its scroll to the outer modal when it hits
           top/bottom — `contain` here traps the gesture, so reaching the end
           of the tracklist dead-ends instead of scrolling the modal. The outer
           .download-missing-modal-content keeps `contain` to stop the chain
           at the modal (the page behind must not scroll). */
        overscroll-behavior: auto;
    }
    .download-missing-modal-footer {
        padding-bottom: max(12px, env(safe-area-inset-bottom));
    }
}

/* download modal rows on a phone: a table can't fit eight columns in 390px, so
   each row becomes a little card. title on top, artist under it, the two
   statuses stacked on the right. the cells keep their ids so the live
   updaters still find them. */
@media (max-width: 768px) {
    .download-missing-modal-content .download-tracks-table,
    .download-missing-modal-content .download-tracks-table thead,
    .download-missing-modal-content .download-tracks-table tbody {
        display: block;
        width: 100%;
    }

    /* the header keeps select-all and the track label, the rest is said by the rows */
    .download-missing-modal-content .download-tracks-table thead tr {
        display: flex;
        align-items: center;
    }
    .download-missing-modal-content .download-tracks-table thead th {
        display: none;
    }
    .download-missing-modal-content .download-tracks-table thead th.track-select-header,
    .download-missing-modal-content .download-tracks-table:has(.track-select-header) thead th:nth-child(3),
    .download-missing-modal-content .download-tracks-table:not(:has(.track-select-header)) thead th:nth-child(2) {
        display: block;
        background: none;
        border: none;
        text-align: left;
    }
    .download-missing-modal-content .download-tracks-table thead tr {
        background: linear-gradient(180deg, rgba(28,28,28,0.95), rgba(22,22,22,0.95));
        border-bottom: 1px solid var(--white-a08);
    }

    .download-missing-modal-content .download-tracks-table tbody tr {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr) auto auto;
        grid-template-areas:
            "sel name   match    act"
            "sel artist download act";
        align-items: center;
        column-gap: 10px;
        row-gap: 3px;
        padding: 10px 12px 10px 4px;
        border-bottom: 1px solid rgba(255, 255, 255, 0.045);
    }
    .download-missing-modal-content .download-tracks-table tbody tr:last-child {
        border-bottom: none;
    }
    .download-missing-modal-content .download-tracks-table tbody td {
        display: block;
        padding: 0;
        border: none;
        max-width: none;
        width: auto;
        min-width: 0;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .download-missing-modal-content .download-tracks-table tbody td.track-select-cell {
        grid-area: sel;
        align-self: center;
    }
    .download-missing-modal-content .download-tracks-table tbody td.track-number,
    .download-missing-modal-content .download-tracks-table tbody td.track-duration {
        display: none;
    }
    .download-missing-modal-content .download-tracks-table tbody td.track-name {
        grid-area: name;
        font-size: 14px;
        line-height: 26px;
    }
    /* the artist lines up under the title, past the play + add buttons (26px + 8px each) */
    .download-missing-modal-content .download-tracks-table tbody td.track-artist {
        grid-area: artist;
        font-size: 12.5px;
        text-align: left;
        padding-left: 68px;
    }
    .download-missing-modal-content .download-tracks-table tbody td.track-match-status,
    .download-missing-modal-content .download-tracks-table tbody td.track-download-status {
        display: block;
        font-size: 10px;
        text-align: right;
        overflow: visible;
    }
    .download-missing-modal-content .download-tracks-table tbody td.track-match-status {
        grid-area: match;
    }
    .download-missing-modal-content .download-tracks-table tbody td.track-download-status {
        grid-area: download;
    }
    .download-missing-modal-content .download-tracks-table tbody td.track-actions {
        grid-area: act;
        overflow: visible;
    }
    /* the pill sits behind the status text; sized to the cell now that the
       cell is only as wide as its text */
    .download-missing-modal-content .download-tracks-table tbody td.track-download-status[data-state] {
        padding: 4px 10px;
    }
    .download-missing-modal-content .download-tracks-table tbody td.track-download-status[data-state]::before {
        width: 100%;
        height: 100%;
    }
    /* a bare "-" means no action, it doesn't need a column */
    .download-missing-modal-content .download-tracks-table tbody td.track-actions:not(:has(*)) {
        display: none;
    }

    /* the two progress cards stack; side by side they ran off the right edge */
    .download-missing-modal-content .download-progress-section {
        grid-template-columns: minmax(0, 1fr);
        gap: 8px;
        padding: 10px 0;
    }
    .download-missing-modal-content .progress-item {
        padding: 10px 14px;
    }
    .download-missing-modal-content .progress-label {
        margin-bottom: 7px;
    }
    .download-missing-modal-content .progress-item .progress-bar {
        margin-bottom: 0;
    }

    /* four stat tiles in a row only fit "downloaded" once the tiles and labels
       stop padding so wide */
    .download-missing-modal-content .download-dashboard-stats {
        gap: 6px;
        padding: 12px 8px;
    }
    .download-missing-modal-content .dashboard-stat {
        padding: 10px 2px;
    }
    .download-missing-modal-content .dashboard-stat-label {
        font-size: 9px;
        letter-spacing: 0.02em;
    }
}

/* discover mix modal on a phone: the art shrinks beside the title, the header
   actions wrap and share the width, the floating selection bar wraps instead of
   running off the edge, and the rows drop the number and album columns so the
   title and artist get the width. */
@media (max-width: 768px) {
    .mix-modal {
        width: 100%;
        max-width: calc(100vw - 16px);
        max-height: 90vh;
        max-height: 90dvh;
    }
    /* a grid with the heading's children lifted into it: art beside the
       words, the actions on their own full-width row underneath. inside the
       heading they only got the narrow column and Sync wrapped alone. */
    .mix-modal-header {
        display: grid;
        grid-template-columns: 76px minmax(0, 1fr);
        /* row-gap 0: the desktop gap: 24px would land between every text line */
        gap: 0 14px;
        align-items: start;
        padding: 18px 16px 16px;
    }
    .mix-modal-heading {
        display: contents;
    }
    .mix-modal-cover {
        grid-row: 1 / span 4;
        align-self: center;
        width: 76px;
        height: 76px;
        border-radius: 10px;
    }
    .mix-modal-eyebrow,
    .mix-modal-title,
    .mix-modal-subtitle,
    .mix-modal-meta {
        grid-column: 2;
        padding-right: 30px;
    }
    .mix-modal-title {
        font-size: 22px;
    }
    .mix-modal-actions {
        grid-column: 1 / -1;
        margin-top: 14px;
        flex-wrap: wrap;
    }
    .mix-modal-actions .btn {
        flex: 1 1 0;
        justify-content: center;
    }
    .mix-modal-close {
        top: 10px;
        right: 10px;
    }

    .mix-modal-selbar {
        flex-wrap: wrap;
        justify-content: center;
        row-gap: 8px;
        column-gap: 6px;
        width: calc(100% - 24px);
        bottom: 12px;
        padding: 10px 12px;
        border-radius: 18px;
        white-space: normal;
    }
    .mix-sel-count {
        flex: 1 1 auto;
    }
    .mix-modal-selbar .btn {
        flex: 1 1 0;
        justify-content: center;
        white-space: nowrap;
    }
    .mix-modal.has-selection .mix-modal-body {
        padding-bottom: 120px;
    }

    .mix-modal-colhead {
        margin: 0 8px;
    }
    .mix-modal-body {
        padding: 4px 8px 16px;
    }

    .discover-playlist-track-compact,
    .mix-modal .discover-playlist-track-compact,
    .mix-modal-colhead {
        grid-template-columns: 40px minmax(0, 1fr) auto 32px;
        gap: 10px;
        padding: 8px;
    }
    .discover-playlist-track-compact.has-select,
    .mix-modal .discover-playlist-track-compact.has-select,
    .mix-modal-colhead.has-select {
        grid-template-columns: 22px 40px minmax(0, 1fr) auto 32px;
    }
    .discover-playlist-track-compact .track-compact-number,
    .discover-playlist-track-compact .track-compact-album,
    .mix-colhead-num,
    .mix-colhead-album {
        display: none;
    }
    .track-compact-name {
        font-size: 14px;
    }
    .track-compact-artist {
        font-size: 12px;
    }
}

/* --- Landscape phones: compact the drawer header so the nav can scroll ---
   In landscape the viewport is ~360px tall. The sidebar header (brand +
   Audio/Video toggle + profile) eats ~200px of that, leaving almost no room
   for .sidebar-scroll — the nav items pile up below the fold with nothing to
   scroll. This compacts the header at short heights so the scroll area gets
   real space. */
@media (max-height: 500px) {
    .sidebar-header {
        min-height: 0;
        padding: 12px 16px;
        gap: 6px;
    }
    .sidebar-header .app-subtitle {
        display: none;
    }
    .sidebar-header .sidebar-logo {
        width: 28px;
        height: 28px;
    }
    .sidebar-header .app-name {
        font-size: 18px;
    }
    .sidebar-header .side-toggle {
        margin-top: 2px;
    }
    .sidebar-header .side-toggle-btn {
        padding: 6px 10px;
        font-size: 12px;
    }
    #profile-indicator {
        margin-top: 2px;
    }
}

/* --- Mobile tab/pill bars: never overlap, scroll instead of clipping ---
   Thibs' screenshots show pill tab groups (Audiobooks genres, Watchlist
   tabs, Settings Library tabs) either cut off at the viewport edge or —
   worse — rendering on top of each other ("AudiobookPodcasts"). On small
   screens these groups become horizontal scrollers: items keep their size
   (flex-shrink: 0) and the group scrolls instead of overflowing. */
@media (max-width: 768px) {
    .genre-pills,
    .genre-tabs,
    .watchlist-tabs,
    .settings-tabs,
    .pill-group,
    .tab-group,
    [role="tablist"] {
        display: flex;
        flex-wrap: nowrap;
        overflow-x: auto;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .genre-pills::-webkit-scrollbar,
    .genre-tabs::-webkit-scrollbar,
    .watchlist-tabs::-webkit-scrollbar,
    .settings-tabs::-webkit-scrollbar,
    .pill-group::-webkit-scrollbar,
    .tab-group::-webkit-scrollbar,
    [role="tablist"]::-webkit-scrollbar {
        display: none;
    }
    .genre-pills > *,
    .genre-tabs > *,
    .watchlist-tabs > *,
    .settings-tabs > *,
    .pill-group > *,
    .tab-group > *,
    [role="tablist"] > * {
        flex-shrink: 0;
        white-space: nowrap;
    }
}

/* --- Hide hamburger behind open modals ---
   The hamburger is position:fixed with a high z-index so it's always
   reachable. When a modal opens (e.g. the Deezer service setup), the
   hamburger paints above the modal's own header and overlaps its title.
   Modals get their own close control, so the hamburger is redundant while
   one is open.
   Batch #2: the original rule waited for modal-open / download-modal-open,
   which almost nothing sets. What actually signals an open modal, and what
   this rule keys off:
   - body classes the app toggles: src-modal-open (settings service/source
     modals — the Deezer one), pf-modal-open (profile layers), np-modal-open
     (the player).
   - overlay roots via :has(), for the React modals that set no body class —
     the pattern style.css already uses for the vanilla modals. Each family
     below was checked: its overlay is either mounted only while open, or
     stays mounted and carries its open class (.visible / .active) only
     while open, so the hamburger never hides with nothing open.
   - the audiobook overlays (AudiobookOverlay) portal a backdrop whose
     class is a hashed CSS module, unnameable here — the component stamps
     data-audiobook-overlay on it instead, and that attribute is the hook.
   Modal families NOT listed either stack above the hamburger already
   (z-index ≥ 10000: download, mirrored, repair-help, server-search) or
   are covered by the body classes above.
   Oct 13 batch: the old assumption that the generic .modal-overlay
   "stacks above the hamburger already" is FALSE for anything mounted
   inside #webui-react-root (position:relative; z-index:1) — at body level
   the whole React root stacks at 1, below the hamburger's 9999, whatever
   the overlay's own z-index says (measured live: elementFromPoint at the
   hamburger's centre returned the hamburger over a z-10000
   .modal-overlay). So the generic overlay is listed below, generalised
   (fold): EVERY .modal-overlay family is trapped the same way (playlist
   detail, mix, playlist-preview, your-artists, artist-info, blacklist,
   station, sync discovery, sources, artist-detail modals, watchlist
   modals, …), not just the playlist one. closed overlays don't all use
   .hidden: some vanilla ones (automation run history, the spotify and
   deezer arl playlist details) close with style.display='none' and stay
   in the dom, which hid the hamburger for good after one open. so an
   inline display:none counts as closed too. Hiding the hamburger behind
   the account modal also keeps the nav drawer from being opened over it
   (the drawer is z-10001, one rung above it). The Artist Map / Artist Web
   container joins the list for the same reason — it is z-index 100, far
   BELOW the hamburger, and only exists while a map is open. */
html.download-modal-open .hamburger-btn,
html.modal-open .hamburger-btn,
body.modal-open .hamburger-btn,
body.src-modal-open .hamburger-btn,
body.pf-modal-open .hamburger-btn,
body.np-modal-open .hamburger-btn,
body:has(.auto-sync-overlay) .hamburger-btn,
body:has(.confirm-modal-overlay) .hamburger-btn,
body:has(.discog-modal-overlay.visible) .hamburger-btn,
body:has(.arec-overlay.visible) .hamburger-btn,
body:has(.art-picker-overlay.visible) .hamburger-btn,
body:has(.watchadd-modal-overlay.visible) .hamburger-btn,
body:has(.server-disambig-overlay.visible) .hamburger-btn,
body:has(.genre-browser-modal-overlay.active) .hamburger-btn,
body:has([data-audiobook-overlay]) .hamburger-btn,
body:has(.modal-overlay:not(.hidden):not([style*="display: none"]):not([style*="display:none"])) .hamburger-btn,
body:has(.artist-map-container) .hamburger-btn,
body:has([data-year-story-overlay]) .hamburger-btn {
    display: none !important;
}

/* The map/web container is a full-viewport takeover, but the shell's
   floating stack renders above it (.activity-float-btn is z-index 999999)
   and parks exactly where the stacked island nav lands (bottom-right):
   in the visual harness the Server Activity button intercepted every
   click on the island nav's current-genre button, and the mini player
   (z-index 99998, a full-width bottom bar) covers the genre strip the
   same way. Both defer for the container's lifetime — it only exists
   while a map or web is open. Same deferral shape as the year-story
   rule above and the watchlist overlay rules. */
body:has(.artist-map-container) #media-player,
body:has(.artist-map-container) .activity-float-btn,
body:has(.artist-map-container) .helper-float-btn,
body:has(.artist-map-container) #notif-bell-btn,
body:has(.artist-map-container) #gsearch-bar {
    display: none !important;
}

/* --- Page titles must clear the fixed hamburger ---
   The hamburger is position:fixed at left:16px, 44px wide (ends at 60px).
   Page headers starting at the left edge slide under it — gzetk's screenshot
   shows "Au" of "Auto-Sync Manager" hidden behind the button. Give page
   headers left padding on mobile so titles start clear of the button. */
@media (max-width: 768px) {
    .page-header,
    .page-title,
    h1.page-title {
        padding-left: 56px;
    }

    /* Settings sub-pages title their pane with .stg-active-title-text, not
       .page-title, so they slid under the hamburger too ("…brary",
       "…wnloads", "…ality" in the batch #2 screenshots). The title sits in
       the detail pane, right of the category rail; indent the title block
       itself so the Save button on the same row is untouched. */
    #settings-page .stg-active-section-title {
        padding-left: 56px;
    }
}

/* --- Auto-Sync Manager header on phones ---
   The header is a flex row: title/blurb, the summary strip (a grid of
   minmax(150px,1fr) tiles) passed in as an aside, and the actions. The
   title div is the only shrinkable child, so on a phone it was crushed
   toward min-content (~90px — the one-word-per-line blurb in gzetk's
   screenshot) while the second stat pill clipped at the modal's edge
   (batch #2, RC4). Wrap: title + actions share the first row, the summary
   takes a full-width row of its own below. */
@media (max-width: 768px) {
    .auto-sync-header {
        flex-wrap: wrap;
    }
    .auto-sync-header > div {
        min-width: 0;
    }
    .auto-sync-header .auto-sync-summary {
        flex: 1 1 100%;
        order: 3;
    }
}

/* --- Auto-Sync Manager on phones: the whole modal, not just its header ---
   The header wrap above was batch #2; the rest of the modal never got a
   phone layout at all (Boulder's screenshot, Oct 13). Measured in Chromium
   at 390px against the real stylesheets, replica markup:
   - The <=1100px block in style.css tries to stack .auto-sync-body into
     one column (280px sidebar over lanes), but the streamlined board rules
     are scoped .auto-sync-modal .auto-sync-body (0,2,0) and beat it — so
     the sidebar kept 280px, the lanes got the leftover 90px, filled lanes
     (365px of content) clipped off the modal's right edge, and the grid's
     second row stood empty: the board area rendered 150px tall in a 421px
     slot, over half the modal dead space.
   - The four tabs total 454px in a 370px modal with no scroll or wrap:
     Run History clipped at the edge, mid-word.
   - Header + idle monitor + tabs + board intro ate 403px of the 844px
     screen before the first playlist appeared.
   - At <=1100px the source list becomes a horizontal flex strip (groups
     min-width 220px side by side), so the playlist list was a 69px tall
     sideways scroller showing one group at a time.
   The rules below are scoped to match the selectors they override
   (.auto-sync-modal …) and this file loads after style.css, so they win
   ties. Desktop is untouched: everything sits inside max-width: 768px. */
@media (max-width: 768px) {
    /* The modal takes the screen instead of floating in it. dvh so the
       phone browser chrome doesn't crop the bottom; vh first as fallback. */
    .auto-sync-modal {
        width: calc(100vw - 12px);
        height: calc(100vh - 12px);
        height: calc(100dvh - 12px);
        border-radius: 18px;
    }

    /* Header: one compact block. Title + actions share the first row, the
       summary chips split the second row evenly instead of sizing to
       their text and clipping. */
    .auto-sync-modal .auto-sync-header {
        padding: 14px 16px 12px;
        gap: 8px 12px;
        align-items: flex-start;
    }
    .auto-sync-modal .auto-sync-header h3 {
        font-size: 19px;
    }
    /* The blurb goes on phones: style.css already hides it on short
       screens (max-height: 760px) for the same reason — the board is the
       content, and two lines of explanation cost two playlist rows.
       Without it the title shrinks to its text and the actions share
       its row again instead of wrapping onto a row of their own. */
    .auto-sync-modal .auto-sync-header p {
        display: none;
    }
    .auto-sync-modal .auto-sync-header > div:first-child {
        flex: 1 1 auto;
        min-width: 0;
    }
    .auto-sync-modal .auto-sync-header .auto-sync-header-actions {
        margin-left: auto;
    }
    .auto-sync-modal .auto-sync-close {
        width: 38px;
        height: 38px;
        flex: 0 0 auto;
    }
    .auto-sync-modal .auto-sync-refresh {
        padding: 8px 10px;
    }
    .auto-sync-modal .auto-sync-header .auto-sync-summary {
        flex-wrap: wrap;
        gap: 6px;
        margin-left: 0;
        padding: 0;
    }
    .auto-sync-modal .auto-sync-header .auto-sync-summary > div {
        flex: 1 1 0;
        min-width: 0;
        padding: 6px 10px;
    }
    .auto-sync-modal .auto-sync-header .auto-sync-summary span {
        font-size: 15px;
    }
    .auto-sync-modal .auto-sync-header .auto-sync-summary small {
        font-size: 9px;
        letter-spacing: 0.2px;
    }

    /* Idle monitor: kicker + state on one line. The detail sentence is
       hidden only while idle — it repeats what the board intro says, and
       the board needs the room more. A running monitor keeps it. */
    .auto-sync-modal .auto-sync-monitor {
        padding: 10px 16px;
    }
    .auto-sync-modal .auto-sync-monitor.auto-sync-monitor--idle {
        padding: 8px 16px;
    }
    .auto-sync-monitor--idle .auto-sync-monitor-head small {
        display: none;
    }
    .auto-sync-monitor-list {
        grid-template-columns: 1fr;
    }

    /* Tabs: a scroll strip, every tab reachable, nothing wraps mid-word
       and nothing clips. */
    .auto-sync-tabs {
        padding: 0 8px;
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
    }
    .auto-sync-tabs::-webkit-scrollbar {
        display: none;
    }
    .auto-sync-tabs button {
        flex: 0 0 auto;
        height: 44px;
        padding: 0 12px;
        white-space: nowrap;
    }

    .auto-sync-modal .auto-sync-board-intro,
    .auto-sync-automation-intro,
    .auto-sync-history-intro {
        padding: 10px 16px;
    }

    /* The board stacks: playlists on top (capped, own scroll), lanes
       below filling what's left (own scroll). display:flex replaces the
       grid outright, which is what finally retires the 280px column and
       the phantom second row. */
    .auto-sync-modal .auto-sync-body {
        display: flex;
        flex-direction: column;
        flex: 1;
        min-height: 0;
    }
    .auto-sync-modal .auto-sync-sidebar {
        flex: 0 0 auto;
        width: auto;
        max-height: 40%;
        border-right: 0;
        border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    }
    .auto-sync-sidebar-title {
        padding: 10px 16px 6px;
    }
    .auto-sync-sidebar-filter {
        padding: 2px 12px 8px;
    }
    .auto-sync-sidebar-search {
        height: 36px;
        font-size: 13px;
    }
    /* Undo the <=1100px horizontal strip: back to a vertical list that
       scrolls inside the sidebar's cap. */
    .auto-sync-modal .auto-sync-source-list {
        display: block;
        flex: 1;
        min-height: 0;
        overflow-y: auto;
        overflow-x: hidden;
        padding: 0 12px 12px;
    }
    .auto-sync-modal .auto-sync-source-group {
        min-width: 0;
        margin-bottom: 12px;
    }

    /* Lanes: one column. A filled lane is a header strip (interval +
       cadence + count) over full-width cards; an empty lane is a
       full-width dashed row that says what it's for, not a 59px sliver
       of a chip at the screen's edge. */
    .auto-sync-modal .auto-sync-lanes {
        flex: 1;
        min-height: 0;
        flex-direction: column;
        flex-wrap: nowrap;
        align-content: stretch;
        overflow-y: auto;
        overflow-x: hidden;
        padding: 12px;
        gap: 8px;
    }
    .auto-sync-modal .auto-sync-lane.filled {
        flex: 0 0 auto;
        flex-direction: column;
        gap: 8px;
        padding: 10px;
    }
    .auto-sync-modal .auto-sync-lane.filled .auto-sync-lane-badge {
        flex: 0 0 auto;
        flex-direction: row;
        align-items: baseline;
        gap: 8px;
        padding: 0 2px 6px;
        border-right: 0;
        border-bottom: 1px solid rgba(255, 255, 255, 0.07);
    }
    .auto-sync-modal .auto-sync-lane.filled .auto-sync-lane-badge b {
        font-size: 16px;
    }
    .auto-sync-modal .auto-sync-lane.filled .auto-sync-lane-track {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
        padding: 0;
    }
    .auto-sync-modal .auto-sync-lane .auto-sync-scheduled-card {
        width: 100%;
        min-width: 0;
        max-width: none;
        margin: 0;
    }
    .auto-sync-modal .auto-sync-lane.empty {
        flex: 0 0 auto;
        width: auto;
        border-radius: 12px;
    }
    .auto-sync-modal .auto-sync-lane.empty .auto-sync-lane-badge {
        flex: 1;
        flex-direction: row;
        align-items: center;
        gap: 8px;
        padding: 10px 12px;
    }
    .auto-sync-modal .auto-sync-lane.empty .auto-sync-lane-badge span {
        display: inline;
    }

    /* The automation intro is a bare strong + span in a flex row, so on a
       phone the heading was crushed into a 140px column beside its own
       explanation. Stack them. The history intro has the same shape
       (text block + filter controls) and stacks the same way. */
    .auto-sync-automation-intro,
    .auto-sync-history-intro {
        flex-direction: column;
        align-items: flex-start;
        gap: 4px;
    }

    /* The read-only panels ride the same panel column; give their lists
       the leftover height and phone padding. */
    .auto-sync-automation-list,
    .auto-sync-history-list {
        flex: 1;
        min-height: 0;
        padding: 12px;
    }
    .auto-sync-automation-card {
        flex-wrap: wrap;
    }

    /* Bulk popover + weekly editor: stay on screen, real tap targets. */
    .auto-sync-bulk-menu {
        max-width: calc(100vw - 16px);
    }
    .auto-sync-bulk-menu button {
        min-height: 40px;
    }
    .auto-sync-weekly-editor-backdrop {
        padding: 12px;
    }
    .auto-sync-weekly-editor {
        padding: 18px;
    }
}

/* playlist play row + add songs on a phone: the controls stay one thumb row,
   the add panel drops the duration so the title keeps its width */
@media (max-width: 768px) {
    .mm-play-row { gap: 8px; margin-top: 12px; }
    .mm-play { width: 46px; height: 46px; }
    .mm-round { width: 38px; height: 38px; }
    .mm-pill { height: 38px; padding: 0 13px; }
    .mm-play-gap { display: none; }
    .mm-cover { width: 120px; height: 120px; }
    .mm-sortbar { padding: 8px 12px 0; flex-wrap: wrap; }
    .as-panel { margin: 10px 8px 4px; padding: 14px 12px 8px; max-height: 52vh; }
    .as-row { grid-template-columns: 40px minmax(0, 1fr) auto; gap: 10px; }
    .as-art { width: 40px; height: 40px; }
    .as-dur { display: none; }
    .as-add { min-width: 64px; padding: 0 12px; }
}

/* --- Oct 13 mobile batch (Boulder's phone screenshots + videos) ---
   Every mechanism below was measured live in Chromium against the real
   stylesheets (harness replicas + the real pages at 390 / 360 / 412px)
   before fixing. M-numbers are the issue ids from that pass. */
@media (max-width: 768px) {
    /* M-01 — the video detail Back pill is sticky at top:14px with a 22px
       left margin, i.e. directly under the fixed hamburger (16..60px on
       both axes), which ate its left end. Push it clear of the button.
       The page-class prefixes raise specificity: video-side.css loads
       after this file. The same pill renders on the person (.vp-page)
       and studio (.vst-page) pages with the same geometry (fold: the
       first pass only covered .vd-page), so all three are listed. */
    .vd-page .vd-back,
    .vp-page .vd-back,
    .vst-page .vd-back {
        margin-left: 76px;
    }

    /* M-08 — Playlist Explorer empty state. .explorer-tree keeps desktop
       canvas geometry on phones (min-width: max-content, 58px side
       padding), so the scrollable stage measured wider than its own
       viewport (410px in a 388px viewport at 390px wide) and the empty
       state, sized from 100vw, centred on that wide stage instead of the
       screen — its heading and copy clipped on both sides. On phones the
       tree hugs the viewport and the empty state fills its container.
       Fold: scoped to the EMPTY state only (the tree's only child is
       .explorer-empty then). The populated tree is designed the other
       way — centred nowrap tiers wider than the viewport inside an
       overflow:auto stage — and clamping its min-width made wide tiers
       overflow both sides with the left half unreachable, and changed
       what the zoom transform scales. */
    .explorer-tree:has(> .explorer-empty) {
        min-width: 0;
        padding: 24px 12px 48px;
    }
    .explorer-empty {
        width: 100%;
        min-height: 280px;
        padding: 32px 16px;
        box-sizing: border-box;
    }

    /* M-09 — the global loading overlay's message is a bare single-line
       string: "Loading playlist: Hearthstone Soundtrack…" ran straight
       off the right edge of the phone (V2 frames). Cap and centre it. */
    .loading-message {
        max-width: min(88vw, 480px);
        text-align: center;
        overflow-wrap: anywhere;
    }

    /* M-10 — "Your Artists" cards. discover-premier pins .ya-card at a
       fixed 148px flex basis (!important) while this file wraps
       .discover-carousel into a centred stack: at 360px only one 148px
       card fits a row and it sits centred with dead space both sides
       (measured: every card at x=106 in a 360px viewport). Make this one
       carousel a fluid 2-up grid — cards share the row and shrink with
       it. The !importants match the pinning rules they override. */
    #your-artists-carousel {
        flex-wrap: wrap;
        /* discover-premier pins .discover-carousel at overflow-x:auto
           !important + scroll-snap-type:x mandatory !important, and it
           loads after this file — the plain declarations in the first
           pass lost both fights and only misled. Say it with !important
           or not at all (fold, M-10). */
        overflow-x: visible !important;
        scroll-snap-type: none !important;
        justify-content: flex-start;
    }
    #your-artists-carousel > .ya-card {
        flex: 1 1 calc(50% - 9px) !important;
        width: auto !important;
        max-width: calc(50% - 9px) !important;
    }

    /* M-11 — Artist Map never had a phone layout (this file contained
       zero artmap rules). The desktop surface is a 200px genre sidebar
       beside the canvas inside a fixed full-screen container; measured
       at 390px the canvas ran 200..1702px because the sidebar would not
       shrink and the canvas would not either. Stack them: the genre
       list becomes a capped strip above the canvas, the canvas takes
       what is left and may shrink to it (min-width: 0 — a canvas is a
       replaced element, so its automatic minimum is its intrinsic
       width). The island nav already caps at 100vw-32px; in the
       stacked layout it anchors to the canvas's bottom-right instead of
       floating over the genre strip.
       Fold: the first pass capped the sidebar's BOX but the sidebar is
       display:block in style.css, so its list's flex:1 was inert and a
       real ~40-genre list painted straight over the canvas, unreachable
       past the row's overflow:hidden. The sidebar must be a flex column
       for the cap to mean anything, and the list must be the scroller.
       The canvas sizing in JS is layout-aware too — see
       artist-map-overlay.tsx (measureFor / artMapHandleResize). */
    .artmap-content-row {
        flex-direction: column;
    }
    .artmap-genre-sidebar {
        display: flex;
        flex-direction: column;
        width: auto;
        flex: 0 1 auto;
        max-height: 38%;
        min-height: 0;
        border-right: 0;
        border-bottom: 1px solid var(--white-a06);
    }
    .artmap-genre-sidebar-list {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
    }
    #artist-map-canvas {
        flex: 1 1 auto;
        min-width: 0;
        min-height: 0;
        width: 100%;
    }
    .artmap-island-nav {
        /* Its desktop anchor (top of the canvas, beside the sidebar)
           lands on the genre strip once the layout stacks; park it over
           the canvas's bottom-right instead. */
        top: auto;
        bottom: 12px;
        left: auto;
        right: 12px;
        max-width: calc(100vw - 24px);
    }
    .artmap-island-menu {
        /* The menu's desktop anchor reads --artmap-menu-top /
           --artmap-chrome-left, both measured from the row layout — in
           the stacked layout they put the menu right of and below the
           viewport, so genre-jump was dead (fold, M-11c). Anchor it to
           the nav it belongs to: above the bottom-right nav, right edge
           aligned, opening upward. */
        top: auto;
        bottom: 76px;
        left: auto;
        right: 12px;
        max-width: calc(100vw - 24px);
    }

    /* M-11 fold — Artist Web (shot 202453) shares .artist-map-container
       and the toolbar, but its toolbar carries far more than the map's:
       two lens toggles alone are wider than a 390px row, and the nav-right
       cluster (toggles + Path/Edges/Filter + zoom + help) never wrapped,
       so it overflowed the right edge and canvas labels clipped under it.
       Give the right cluster its own full-width row and let it wrap; the
       search row drops below it. The genre sidebar is the shared class
       above, so the web's filter sidebar stacks and scrolls the same way. */
    #artist-web-container .artist-map-toolbar {
        flex-wrap: wrap;
    }
    #artist-web-container .artmap-nav-right {
        order: 3;
        flex: 1 1 100%;
        flex-wrap: wrap;
        justify-content: flex-end;
        row-gap: 6px;
    }
    #artist-web-container .artmap-nav-center {
        order: 4;
    }
    #artist-web-container .artweb-lens-toggle {
        max-width: 100%;
    }
    #artist-web-container .artweb-lens-btn {
        padding: 5px 8px;
        font-size: 11px;
        white-space: nowrap;
    }
    #artist-web-container .artweb-legend {
        max-width: calc(100vw - 28px);
    }

    /* M-13 — sync tab chips and their close button. The global 38px
       touch-target rule stretched the chips to 32x38 and the chip's
       close button (designed 18x18) to an 18x38 dark oval overlapping
       the Spotify chip (Boulder's circled screenshot). Both classes are
       now excluded from that rule (see the chain above). The close
       button also gets its designed size restated ON ITSELF (fold): the
       first pass relied entirely on the :not chain, so a chain refactor
       would silently re-oval it. The chips' 38x38 circle lives in the
       ≤720px block below — that is the band where they are icon chips;
       at 721-768px the labelled pill design wins and stays a pill. */
    .sync-tab-close {
        width: 18px;
        height: 18px;
        flex: 0 0 auto;
    }

    /* M-13 family — the mirrored tab's source filter pills are the same
       squeeze shape (a flex row whose children could shrink): keep them
       whole and let the row scroll instead. */
    .library-sources {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
    }
    .library-sources::-webkit-scrollbar {
        display: none;
    }
    .library-source {
        flex-shrink: 0;
        white-space: nowrap;
    }

    /* M-14 — the mini player's transport row. Removing the player
       buttons from the 38px touch-target chain (above) restores their
       designed round/square shapes (measured before: play 28x38 oval,
       stop 24x38 tall rectangle, every other control x38 tall). The row
       still has to fit: art + info + seven controls measured the info
       column at 84px (390px) / 54px (360px), truncating titles to a few
       characters. The expand chevron goes — the whole bar already opens
       Now Playing on tap — the controls tighten, and the info column
       keeps the rest. */
    .media-player .sidebar-album-art {
        width: 44px;
        height: 44px;
        flex: 0 0 auto;
    }
    .mini-player-body {
        gap: 8px;
        padding: 8px 10px 10px;
    }
    .mini-player-body .media-info {
        flex: 1 1 auto;
        min-width: 0;
    }
    .mini-player-controls {
        gap: 4px;
    }
    .mini-player-controls .play-button {
        width: 36px;
        height: 36px;
    }
    .mini-player-controls .expand-hint {
        display: none;
    }
}

/* M-13 in the icon-chip band (fold): at ≤720px the sync tabs are icon
   chips (mobile.css's Phase 4 block zeroes their padding there); give
   them their round shape back at a real tap size. Above 720px the
   labelled pills keep their designed shape. */
@media (max-width: 720px) {
    .sync-tab-button {
        width: 38px;
        height: 38px;
        flex: 0 0 auto;
    }
}

/* M-10 in the tablet band (fold): the ≤768px 2-up grid yields ~357px-wide
   cards at 721-768px — phone cards stretched across a tablet. Three up
   keeps them card-sized there; phones keep the 2-up above. */
@media (min-width: 561px) and (max-width: 768px) {
    #your-artists-carousel > .ya-card {
        flex-basis: calc(33.333% - 12px) !important;
        max-width: calc(33.333% - 12px) !important;
    }
}

/* M-14 at genuinely small widths only (fold): the first pass dropped the
   shuffle/repeat toggles below 400px, which took them from standard
   390/393px iPhones too — the staged design keeps the FULL transport at
   390px and drops the toggles only below 340px (small Androids / SE-class
   widths), where even tightened, art + info + seven controls leave the
   info column ~62px. The toggles are the droppable pair — both live in
   the Now Playing view the bar opens — so there the transport is prev /
   play / next / stop and the title gets the freed ~48px. */
@media (max-width: 340px) {
    .mini-player-controls .mini-toggle-btn {
        display: none;
    }
}

/* --- Mirrored playlist detail modal on phones: every action reachable ---
   Tacobell444's screenshot (#1691): on a phone the modal's action bar ran
   off the right edge — "Sync & download", Close and Identify were past
   the modal's clipped edge with no way to reach them, and the track rows
   squeezed the title into a few characters ("i wan…").

   What was wrong (measured in Chromium, replica markup against the real
   stylesheets, before this section):
   - .mm-actions-right is a no-wrap flex row holding five controls whose
     nowrap buttons measure ~596px together. style.css's <=640px block
     stacks .mm-actions into a column but never wraps the right group, and
     .mirrored-modal clips with overflow:hidden — so at 390px the Sync &
     download button's box started at x=342 on a 390px viewport and ran
     past the panel, and Close / Identify rendered entirely off-screen.
     Between 641-768px the bar did not even stack.
   - The track grid kept its six desktop columns (34+40+56+28px fixed,
     70px of gaps, 36px of row padding): the title element measured
     36px wide at 390px, 18px at 360px, 0px at 320px.
   After this section, same replica (and the vanilla modal's markup,
   and the editable grid): every action button is fully inside the
   modal at 390 / 360 / 320px with its label inside its button, and
   the title element measures 170 / 140 / 100px (its full text fits
   unclipped at 390px). Nothing
   above 768px changes; the 641-768px band deliberately takes the phone
   layout too (it is this app's mobile breakpoint) even though its
   album column would have fit — the stacked action bar would not.
   This file loads after style.css, so it wins ties. */
@media (max-width: 768px) {
    /* More of the phone for the modal: the panel measured 328px wide
       on a 390px phone before, 355px after (replica-measured). */
    .mirrored-modal-overlay {
        padding: 10px;
    }
    .mirrored-modal {
        max-height: calc(100vh - 20px);
        max-height: calc(100dvh - 20px);
    }
    /* Track rows: the album column goes (the title needs the room more,
       the same call the download / discover modals made), the fixed
       columns and gaps shrink, and the title takes the remaining space.
       The position column keeps 26px so a 3-digit track number still
       fits on one line. The
       head's album label is its 4th span; a hidden grid child leaves no
       gap, so head and rows stay in step, editable grid included. */
    .mm-list-head,
    .mm-row {
        grid-template-columns: 26px 36px minmax(0, 1fr) 48px 28px;
        gap: 8px;
        padding: 0 10px;
    }
    .mm-list--editable .mm-list-head,
    .mm-list--editable .mm-row {
        grid-template-columns: 26px 36px minmax(0, 1fr) 48px 28px 28px;
    }
    .mm-list-head > span:nth-child(4),
    .mm-row-album {
        display: none;
    }
    .mm-row {
        margin: 1px 4px;
    }
    /* Head labels sit over the row cells: rows are inset by their 4px
       margin, so the head's padding grows by the same 4px. */
    .mm-list-head {
        padding: 0 14px;
    }
    .mm-row-art {
        width: 36px;
        height: 36px;
    }
    /* #1721: no room for the status words beside the artist, so a row
       keeps just the dot. the line at the top names and filters them. */
    .mm-row-st {
        font-size: 0;
        gap: 0;
    }
    .mm-row-st::before {
        width: 7px;
        height: 7px;
    }

    /* Actions: stack, then wrap. The two captioned actions (Refresh,
       Sync & download) take a full row each — their buttons are the
       longest labels and their captions finally fit under them — and
       the bare buttons share what rows remain, growing evenly instead
       of sizing to their text and pushing each other off-screen.
       flex-basis 30% (not 0) on the bare buttons: a 0-basis button
       would share a line with a 100%-basis wrap and end up 0px wide. */
    .mm-actions {
        flex-direction: column;
        align-items: stretch;
        padding: 14px 16px;
    }
    .mm-actions-right {
        flex-wrap: wrap;
    }
    .mm-actions-right > .mm-btn {
        flex: 1 1 30%;
        min-width: 0;
    }
    /* No markup uses .mm-btn-wrap / .mm-btn-caption since the made-over
       playlist detail modal (b968b3445), but mirrored-modal-mobile.test.ts
       still pins these three rules, so they stay until that test moves. */
    .mm-btn-wrap {
        flex: 1 1 100%;
        min-width: 0;
        align-items: stretch;
    }
    .mm-btn-wrap > .mm-btn {
        width: 100%;
    }
    .mm-btn-caption {
        white-space: normal;
        text-align: center;
    }
    /* Button labels wrap inside their buttons instead of spilling out
       of them: .mm-btn is nowrap, and the shrinkable boxes above go
       narrower than "Edit Source" / "Auto-Sync" at <=390px in the
       vanilla modal, whose four bare buttons lay out 3-across + 1. */
    .mm-actions .mm-btn {
        white-space: normal;
    }
}

/* The stacked hero (style.css stacks .mm-hero-content only at <=640px):
   the close button then floats over empty hero padding, not over the
   info column, so the info takes its full width back. Scoped to <=640px
   on purpose — at 641-768px the hero is still a row and the 44px
   padding-right is the close button's clearance. */
@media (max-width: 640px) {
    .mm-hero-content {
        padding-right: 0;
    }
}
