/* music-mobile.css — every @media (max-width: 720px) and
   html.ios rule that overrides earlier modules. Loaded
   LAST in the Music.cshtml @section Styles so its rules
   win the source-order tie-break against equally-specific
   default rules above. */

/* ===================== Responsive ===================== */
/* Collapsed sidebar — icon-only chip layout. Triggered either by the
   user toggle (`.sidebar-collapsed` class added by music.js) OR
   automatically at the tablet-ish viewport range. Both selectors share
   the same rules so the layout is identical in either case. */
.music-app.sidebar-collapsed {
    --sidebar-w: 72px;
}
.music-app.sidebar-collapsed .ms-sidebar { padding: 2.4rem 0 0.6rem; }
.music-app.sidebar-collapsed .ms-sidebar-toggle {
    /* Centre the toggle horizontally so it lines up with the icon chips
       below it, instead of sitting off in the right corner. */
    right: auto;
    left: 50%;
    transform: translateX(-50%) rotate(180deg);
}
.music-app.sidebar-collapsed .ms-nav-item { align-self: center; }
.music-app.sidebar-collapsed .ms-playlist-list,
.music-app.sidebar-collapsed .ms-divider,
.music-app.sidebar-collapsed .ms-nav-item > span { display: none; }
.music-app.sidebar-collapsed .ms-nav {
    padding: 0;
    gap: 0;
    align-items: center;
}
.music-app.sidebar-collapsed .ms-nav-item {
    justify-content: center;
    align-items: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border-radius: 8px;
}
.music-app.sidebar-collapsed .ms-nav-item[aria-current="page"] {
    background: color-mix(in srgb, var(--accent) 14%, transparent);
}

/* Auto-collapse at tablet-ish widths if the user hasn't explicitly
   expanded. Mirrors the .sidebar-collapsed rules above; JS will add
   .sidebar-collapsed in this range too, but the @media here is a
   CSS-only fallback to avoid a flash on initial page load. */
@media (max-width: 900px) and (min-width: 721px) {
    .music-app:not(.sidebar-expanded) { --sidebar-w: 72px; }
    .music-app:not(.sidebar-expanded) .ms-sidebar { padding: 2.4rem 0 0.6rem; }
    .music-app:not(.sidebar-expanded) .ms-sidebar-toggle {
        right: auto;
        left: 50%;
        transform: translateX(-50%) rotate(180deg);
    }
    .music-app:not(.sidebar-expanded) .ms-nav-item { align-self: center; }
    .music-app:not(.sidebar-expanded) .ms-playlist-list,
    .music-app:not(.sidebar-expanded) .ms-divider,
    .music-app:not(.sidebar-expanded) .ms-nav-item > span { display: none; }
    .music-app:not(.sidebar-expanded) .ms-nav {
        padding: 0;
        gap: 0;
        align-items: center;
    }
    .music-app:not(.sidebar-expanded) .ms-nav-item {
        justify-content: center;
        align-items: center;
        width: 34px;
        height: 34px;
        padding: 0;
        border-radius: 8px;
    }
    .music-app:not(.sidebar-expanded) .ms-nav-item[aria-current="page"] {
        background: color-mix(in srgb, var(--accent) 14%, transparent);
    }
}

/* Tablet-ish with the sidebar MANUALLY expanded: the 240px sidebar leaves
   ~480-860px for the main area, not enough for the full-label topbar.
   Drop the labels on the action buttons (icons only) so everything
   still fits on a single row alongside the search field. */
@media (min-width: 721px) and (max-width: 1100px) {
    .music-app.sidebar-expanded .ms-topbar-actions .ms-btn span { display: none; }
}

/* Phone (≤ 720 px): the desktop left sidebar disappears entirely.
   Its three nav destinations (Library / Search / Playlists) live in
   the player row's embedded nav pill instead — one nav surface, not
   two. The previous right-edge floating half-pills + `nav-side-left`
   left-handed override are gone in this rev. */
@media (max-width: 720px) {
    /* Mobile musiced layout:
       [ main      ]   ← scrollable view (full width, no sidebar overlap)
       [ player    ]   ← persistent player bar with embedded nav pill
       The grid template itself is now the default in music-base.css
       (mobile-first); desktop adds the sidebar column at min-width:
       721px. The override here just swaps the cover-tile token to
       its mobile size. */
    .music-app {
        --cover-tile: var(--cover-tile-mobile);
    }
    /* Sidebar visibility is handled in music-sidebar.css via a
       mobile-first inversion: hidden by default, shown only at
       `min-width: 721px`. The redundant `display: none` that used
       to live here was racy on iOS Safari's initial-load viewport
       evaluation (see § 15 entry "Sidebar appeared on initial cold
       load until reload"). */

    .ms-topbar {
        /* Mobile topbar shrunken to 32 px control height (matching the
           player chrome's modifier buttons) + a tight symmetric
           padding (5.6 px top + bottom) so the row reads as a compact
           single strip between the site header and the library
           content. Vertical padding MUST stay symmetric — any
           top-vs-bottom mismatch (even ~0.8 px) drifts the controls
           off-center enough to be noticeable. */
        padding: 0.35rem 1rem;
        gap: 0.45rem;
    }
    .ms-topbar-actions { gap: 0.25rem; margin-left: 0; flex-shrink: 0; }
    .ms-topbar-actions .ms-btn span { display: none; }   /* icons-only on mobile */

    /* Topbar title visibility is handled in music-topbar.css via a
       mobile-first inversion: hidden by default, the per-view show
       rules are wrapped in `min-width: 721px`. Same race-prevention
       reason as the sidebar (see music-sidebar.css comment). */
    /* Get Musiced Desktop link — removed entirely on mobile.
       Musiced Desktop is a Windows/macOS app; the GitHub releases
       page is a dead-end from a phone. The selector matches the
       music-topbar.css per-view show rule so it overrides on the
       /search view (same specificity, later in source order). */
    .music-app[data-view="search"] .ms-topbar-get-musiced,
    .ms-topbar-get-musiced { display: none; }
    /* New playlist button: hide text label, keep + icon. */
    .ms-topbar-new-playlist span { display: none; }

    /* Topbar extras (#ms-topbar-new-playlist on /playlists,
       #ms-topbar-get-musiced on /search) sit OUTSIDE
       .ms-topbar-actions, so the action-button mobile rule doesn't
       reach them via its scoped selector. Pin them to the same
       32 × 32 icon-only square as the action cluster so the whole
       row sits on one baseline. `min-width: 0` cancels the desktop
       11rem floor (which makes both buttons share a 11rem slot for
       end-of-search-bar alignment) — on mobile the buttons are
       icon-only squares, no text, so the wide-slot floor doesn't
       apply. */
    .music-app[data-view="playlists"] .ms-topbar-new-playlist,
    .music-app[data-view="search"] .ms-topbar-get-musiced {
        width: 32px;
        height: 32px;
        min-width: 0;
        padding: 0;
        justify-content: center;
        box-sizing: border-box;
    }
    /* The mobile-only `font-size: 16 px` override for the search inputs
       (suppresses iOS Safari focus-zoom) used to live here but lost to
       the base `.ms-discover-search input` rule further down the file
       on source-order alone. Same override now lives at the END of the
       file so it wins regardless of where the base rule is declared.
       See "Search-input iOS zoom + topbar overflow follow-ups". */
    .ms-view { padding: 0.25rem 1rem 1.5rem; }
    .ms-playlist-hero { flex-direction: column; align-items: flex-start; gap: 1rem; }
    .ms-playlist-hero-cover { width: 160px; height: 160px; }
    .ms-playlist-hero-meta h1 { font-size: 1.4rem; }

    /* The sidebar collapse chevron doesn't apply on mobile — the
       "sidebar" here is the bottom nav, not the side panel. Hide it
       so it doesn't float into the corner of every view. */
    .ms-sidebar-toggle { display: none; }

    /* Controls-only compact mobile player. Cover + title + artist text
       are GONE from the chrome — the "what's playing" indicator now
       lives on the active library row/tile (the cyan ring + the title
       marquee). The chrome is purely playback control:

         [Library|Search|Playlists]   [⏮][▶][⏭]   [🔀][🔁][≡]
            nav pill (LEFT)         transport (CENTER)   right cluster

       Layout: flex row with two `margin-left: auto` items carving the
       free space into three regions (nav-pill left-anchored,
       transport centered, right cluster right-anchored). The progress
       scrubber sits along the top edge via absolute positioning;
       volume + timestamps stay removed (hardware volume buttons +
       the scrubber bubble cover their purpose).

       Wrapper elements (.mpb-controls, .mpb-buttons, .mpb-right)
       collapse via `display: contents` so every transport / modifier
       button becomes a direct flex child of .ms-player and the
       `order` properties below sort them per the spec.

       Target row height 56 px — the same chrome on every Musiced
       view (library / playlists / playlist:N / search) so swapping
       between them doesn't jump the layout. */
    .ms-player {
        position: relative;        /* anchor for absolute progress + bubble */
        display: flex;
        grid-template-rows: none;
        grid-template-columns: none;
        grid-template-areas: none;
        align-items: center;
        column-gap: 4px;
        row-gap: 0;
        /* No top padding and no border-top on mobile — the absolute
           progress bar at top: 0 must sit flush against the visible
           top edge of the player card. With box-sizing: border-box,
           any padding-top would offset the absolute child's `top: 0`
           into the card; a border-top would do the same. The 3 px
           accent line serves as the player's top divider instead. */
        padding: 0 12px;
        /* Chrome stays 56 px — compact, controls sit tight against
           the top of the bar (the absolute progress strip lives in
           the first 16 px so there's no headroom to spare). Visual
           parity with the cross-page mini-player on / + /clipped is
           achieved by the .music-app's bottom padding-floor
           (`html.android` rule below file end), NOT by inflating the
           bar height — bumping height to match the mini-player just
           dropped dead vertical space inside the chrome above the
           centered controls, which read as a gap instead of as
           lift. Keep the gap OUTSIDE the chrome, not inside. */
        height: 56px;
        border-top: none;
    }

    /* (The iOS Safari Liquid Glass lift rule used to live here inside
       the `@media (max-width: 720px)` wrapper. Moved out so iPad
       Safari at its wider portrait widths (768–1024 px) also picks
       up the floor — previously the rule didn't fire and the player
       got clipped under the home-indicator zone. See the
       `html.iphone-safari .music-app` rule near the end of this
       file for the actual declaration + its history note.) */
    /* `.mpb-controls` and `.mpb-right` collapse via `display: contents`
       so every transport / modifier button becomes a direct flex
       child of .ms-player and the `order` properties below sort
       them per the spec. `.mpb-buttons` is the ONE wrapper that
       stays a real flex container — see the "dead-center transport"
       rule a few lines down. */
    .mpb-controls,
    .mpb-right { display: contents; }

    /* Cover + title + artist removed from the mobile chrome entirely.
       These nodes stay in the DOM so desktop's renderNowPlaying can
       keep writing to them (and a viewport resize back to desktop
       picks up the existing track), but at mobile they take no space
       and never paint. */
    .mpb-track,
    .mpb-cover,
    .mpb-meta { display: none; }

    /* Flex order: nav pill (1), prev/play/next transport (2/3/4),
       shuffle/repeat (5/6), queue (7). The two `margin-left: auto`
       items carve the row into three regions; multiple auto-margins
       on the same flex line share positive free space equally, so
       transport ends up centered between the nav pill on the left
       and the right cluster pinned to the right edge. When the row
       is crowded (very narrow viewport), the auto margins collapse
       to 0 and the chrome packs flush left.

       flex-shrink: 0 on every item — the default flex-shrink: 1
       lets the browser silently squash buttons below their declared
       32 px under crowding, which drops them under the iOS tap-
       target floor. With shrink: 0 the chrome keeps its declared
       sizes; anything that doesn't fit clips at the right edge
       (caught by body's overflow:hidden) rather than distorting. */
    /* Dead-center transport on the VIEWPORT (not on the leftover
       space between the nav pill and the right cluster). The
       previous `margin-left: auto` pair split free-space equally,
       which placed transport between the two clusters — but the
       nav pill (96 px) and the right cluster (~104 px) are
       different widths, so the play button ended up a few pixels
       left of the actual page center.
       Lifting `.mpb-buttons` out of the flex flow with
       `position: absolute; left: 50%; transform: translateX(-50%)`
       pins the play button to the exact horizontal centre of the
       chrome regardless of cluster widths. The nav pill still
       anchors the left edge (order 1) and the right cluster
       anchors the right edge (shuffle uses `margin-left: auto`
       to absorb the leftover flex space). */
    .mpb-nav-pill  { order: 1; flex-shrink: 0; margin-left: 0; }
    .mpb-buttons {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        display: flex;
        align-items: center;
        gap: 4px;
    }
    #mpb-shuffle   { order: 5; flex-shrink: 0; margin-left: auto; }
    #mpb-repeat    { order: 6; flex-shrink: 0; }
    #mpb-queue-btn { order: 7; flex-shrink: 0; }

    /* Mobile transport sizing — 32 px modifier buttons, 36 px play.
       Below the 44 px iOS HIG floor but inside the accepted ~32 px
       compact-player density (Spotify, Apple Music both use this). */
    .mpb-btn { width: 32px; height: 32px; }
    .mpb-btn-primary { width: 36px; height: 36px; }
    .mpb-btn .icon { width: 16px; height: 16px; }
    .mpb-btn-primary .icon.icon-lg { width: 20px; height: 20px; }

    /* Removed on mobile entirely — volume controls + static timestamps.
       Selectors are ID-form for the same reason as the order rules
       above (volume-icon is a .mpb-btn with id #mpb-volume-icon, no
       matching class). Timestamps use the class .mpb-time, which DOES
       match — kept as-is. */
    #mpb-volume-icon,
    #mpb-volume,
    .mpb-vol-slider,
    #mpb-vol-pct,
    .mpb-vol-pct,
    .mpb-time { display: none !important; }

    /* Active-state dot (defined in music-player.css for desktop)
       carries over to mobile too. The desktop offset of
       `bottom: -4px` looks too distant from the icon on mobile —
       the mobile button is 32 px tall but the centered icon is
       only 16 px, leaving ~8 px of empty space below the icon
       BEFORE the dot's 4 px gap kicks in. Pulling the dot back
       up to `bottom: 0` puts it at the button's bottom edge so
       the visual gap from the icon to the dot matches desktop
       (~5 px in both). */
    .mpb-btn[aria-pressed="true"]::after { bottom: 0; }

    /* Progress scrubber becomes the top edge of the player card. The
       .mpb-seek wrapper is absolute-positioned along the top with a
       16 px hit area; the <input type="range"> inside fills it. Only
       the 3 px track is visible (no idle playhead). When the user
       touches/drags, music-player.js adds `.is-scrubbing` to the
       input which reveals the 12 px circular thumb; the bubble
       (.mpb-progress-bubble) appears above the player card showing
       the current time and slides with the playhead. */
    .mpb-seek {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 16px;            /* hit area extending into the chrome */
        display: block;
        max-width: none;
        gap: 0;
        z-index: 2;
        pointer-events: none;    /* children claim their own */
    }
    .music-app input[type=range].mpb-progress {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        width: 100%;
        height: 16px;
        margin: 0;
        padding: 0;
        background: transparent;
        flex: none;
        min-width: 0;
        pointer-events: auto;
    }
    /* Custom track. The runnable-track is full 16 px tall (matching the
       input) so it can host the 16 px hit area, but the VISIBLE track
       is a 3 px-tall linear-gradient background-image positioned at
       the TOP of the runnable-track (`top / 100% 3px no-repeat`).
       Without this trick the browser centres the visible track inside
       the input, leaving a ~6.5 px gap between the player's top edge
       and the visible bar. Webkit + Moz pseudo-elements have to be
       declared in separate rules — combining them with `,` invalidates
       the whole rule for browsers that don't recognise both pseudos. */
    .mpb-progress::-webkit-slider-runnable-track {
        height: 16px;
        background:
            linear-gradient(to right,
                var(--accent) var(--progress, 0%),
                var(--panel-border) var(--progress, 0%))
            top / 100% 3px no-repeat;
        background-color: transparent;
        border-radius: 0;
        border: none;
    }
    .mpb-progress::-moz-range-track {
        height: 16px;
        background:
            linear-gradient(to right,
                var(--accent) var(--progress, 0%),
                var(--panel-border) var(--progress, 0%))
            top / 100% 3px no-repeat;
        background-color: transparent;
        border-radius: 0;
        border: none;
    }
    /* Playhead — hidden when idle, revealed during scrubbing via
       :active or .is-scrubbing (the class persists slightly longer
       than :active so the thumb stays visible through pointerup).
       margin-top centres the 12 px thumb on the visible 3 px track at
       the top of the 16 px runnable-track: (input-centre = 8) shifted
       up by 6.5 px puts the thumb-centre at y = 1.5, the middle of
       the visible 3 px track. */
    /* Specificity note: every mobile thumb selector below is prefixed
       with `.music-app input[type=range]` so it OUTRANKS the desktop
       thumb rule (`.music-app input[type=range]::-webkit-slider-thumb`,
       in music-player.css, specificity 0,2,2). Without the prefix the
       mobile rules sat at 0,1,1 and silently lost — leaving the thumb
       centered in the 16 px runnable-track at y=8 instead of on the
       3 px visible track at y=1.5 (~6.5 px below the line) and
       always-visible instead of fade-on-scrub. */
    .music-app input[type=range].mpb-progress::-webkit-slider-thumb {
        -webkit-appearance: none;
        appearance: none;
        width: 12px;
        height: 12px;
        margin-top: -6.5px;
        border-radius: 50%;
        background: var(--accent);
        border: none;
        opacity: 0;
        transition: opacity var(--dur-fast) var(--ease-smooth);
    }
    .music-app input[type=range].mpb-progress::-moz-range-thumb {
        width: 12px;
        height: 12px;
        border-radius: 50%;
        background: var(--accent);
        border: none;
        opacity: 0;
        transition: opacity var(--dur-fast) var(--ease-smooth);
    }
    .music-app input[type=range].mpb-progress:active::-webkit-slider-thumb,
    .music-app input[type=range].mpb-progress.is-scrubbing::-webkit-slider-thumb { opacity: 1; }
    .music-app input[type=range].mpb-progress:active::-moz-range-thumb,
    .music-app input[type=range].mpb-progress.is-scrubbing::-moz-range-thumb { opacity: 1; }

    /* Floating timestamp bubble. Positioned above the player card via
       bottom: 100% + a small negative gap; horizontal `left` is set in
       JS as a percentage of the scrubber width, then `translateX(-50%)`
       centres the bubble on the playhead. Stays clear of the device
       notch / Dynamic Island because it's anchored to the PLAYER, not
       the viewport top. */
    .mpb-progress-bubble {
        display: block;
        position: absolute;
        bottom: calc(100% + 4px);
        left: 0;
        transform: translateX(-50%);
        padding: 3px 8px;
        background: var(--bg-elevated);
        color: var(--fg);
        border: 1px solid var(--rule);
        border-radius: 6px;
        font-size: var(--text-xs);
        font-variant-numeric: tabular-nums;
        pointer-events: none;
        opacity: 0;
        transition: opacity var(--dur-fast) var(--ease-smooth);
        z-index: 3;
        white-space: nowrap;
        box-shadow: var(--shadow-md);
    }
    .mpb-progress-bubble.is-visible { opacity: 1; }

    /* Embedded nav pill — three segments visually fused into one
       rounded rectangle that mirrors the library's grid/list toggle
       (`.ms-mode-toggle`, 6 px radius, 1 px border, accent fill on
       the active segment). Container holds the shared background +
       outer radius + `overflow: hidden` so the active segment's
       accent background gets clipped to the container's rounded
       corners. No internal dividers between segments — the active
       accent background carries all the visual distinction. */
    .mpb-nav-pill {
        display: inline-flex;
        align-items: stretch;
        background: var(--btn-bg);
        border: 1px solid var(--btn-border);
        border-radius: 6px;
        overflow: hidden;          /* clips active-segment accent bg */
        padding: 0;
        gap: 0;
        flex-shrink: 0;
    }
    .mpb-nav-seg {
        width: 32px;
        height: 26px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        background: transparent;
        border: none;
        border-radius: 0;          /* container clips outer corners */
        color: var(--fg-muted);
        cursor: pointer;
        padding: 0;
        transition: background var(--dur-fast) var(--ease-smooth),
                    color var(--dur-fast) var(--ease-smooth);
    }
    .mpb-nav-seg:hover { color: var(--fg); }
    .mpb-nav-seg[aria-current="page"] {
        background: var(--accent);
        color: var(--bg);
    }
    .mpb-nav-seg .icon { width: 16px; height: 16px; }

    /* Very narrow phones — 380 px and below. Tighten the inter-button
       gap one more notch so everything still fits. The controls-only
       chrome math works out at ~320 px of content (nav 96 + transport
       108 + right 100 + 16 padding), so even on a 320 px iPhone SE
       there's no overflow — no more shuffle/repeat → queue-panel
       fallback was needed. */
    @media (max-width: 380px) {
        .ms-player { column-gap: 2px; padding: 0 8px; }
    }

    .ms-list {
        grid-template-columns: var(--cover-thumb) minmax(0, 1fr) 3.5rem;
    }
    /* cell-artist is NOT hidden here — it's repurposed as the stacked
       meta line by the rules further down. cell-album merges into
       the meta line via ::after. cell-more stays visible on mobile
       list rows so users can open the per-track context menu without
       a long-press (there's no hover on touch, so the desktop
       hover-reveal pattern doesn't work). */
    .ms-list-head .cell-album,
    .ms-list-head .cell-artist,
    .ms-list-row .cell-album { display: none; }

    /* Queue panel: no mobile-specific overrides — the base rule in
       music-queue.css already pins `top: 0 / bottom: 0 / width: 300px
       / max-width: 85vw`, which mirrors `.site-drawer` exactly so
       both panels are visually the same primitive at every width. */
}

/* The old .ms-sidebar-fab (a small button that opened a slide-in
   sidebar drawer in an earlier mobile design) is fully removed in
   this revision — the embedded nav pill in the mobile player row is
   the single nav surface now. */

/* ===================== Mobile list view (≤720px) =====================
   Stacked two-line track row: cover · (title / artist · album) · duration.
   Information-dense like the Spotify/Apple Music mobile pattern; replaces
   the single-line "cover · title · duration" sparse layout. Covers the
   full mobile breakpoint so resizing across the 640–720px range doesn't
   visibly snap between two list shapes. */
@media (max-width: 720px) {
    .ms-list-head,
    .ms-list-head-rule { display: none; }
    .ms-list { gap: 0; }

    .ms-list-row {
        /* 4-column grid: cover · title/meta · duration · ⋮. The ⋮
           cell is mobile-only — desktop's auto-show-on-hover doesn't
           work on touch, so the button needs to be visible-by-default
           to remain reachable. */
        grid-template-columns: 48px minmax(0, 1fr) auto 32px;
        grid-template-rows: auto auto;
        grid-template-areas:
            "cover title    duration more"
            "cover meta     duration more";
        column-gap: 0.6rem;
        row-gap: 2px;
        padding: 0.5rem 0.5rem 0.5rem 0.75rem;
        min-height: 64px;       /* good thumb target */
    }
    .ms-list-row > * { padding: 0; }

    .ms-list-row .cell-cover { grid-area: cover; align-self: center; }
    .ms-list-row .cell-cover img,
    .ms-list-row .cell-cover svg {
        width: 48px;
        height: 48px;
        border-radius: 4px;
    }

    .ms-list-row .cell-title {
        grid-area: title;
        font-size: var(--text-base);
        font-weight: 600;
        color: var(--fg);
        align-self: end;
    }
    /* Un-hide cell-artist (the ≤720px rule hides it) and reuse it as the
       sublabel slot. The ::after pulls the album text in from data-album
       so we get "Artist · Album" composed via CSS — no row HTML change
       required for desktop. */
    .ms-list-row .cell-artist {
        display: block;
        grid-area: meta;
        color: var(--fg-muted);
        font-size: var(--text-xs);
        font-weight: 400;
        align-self: start;
    }
    .ms-list-row .cell-artist[data-album]:not([data-album=""])::after {
        content: " · " attr(data-album);
    }
    .ms-list-row .cell-album { display: none; }

    .ms-list-row .cell-duration {
        grid-area: duration;
        color: var(--fg-muted);
        font-size: var(--text-sm);
        align-self: center;
    }
    .ms-list-row .cell-more {
        grid-area: more;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 0;
    }
    /* Touch surfaces have no `:hover` to trigger the desktop reveal —
       pin the ⋮ button to always-visible on mobile so it's actually
       reachable. */
    .ms-list-row .cell-more .ms-icon-btn { visibility: visible; }
}


@media (max-width: 720px) {
    .ms-discover-head { padding: 0 0.25rem; }
    /* 2-col grid on every mobile width — going to 1 col at ≤480px made
       cards balloon to ~600px tall (full-width aspect-ratio:1 cover +
       meta) which felt like "three displays per video" on iPhone. */
    .ms-discover-cards {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0.5rem;
    }
    .ms-discover-card { padding: 0.45rem; gap: 0.4rem; }
    .ms-discover-title { font-size: var(--text-xs); }
    .ms-discover-sub  { font-size: var(--text-xs); }
    /* Source badge runs out of room fast on the 2-col mobile grid;
       trim padding and shrink the text slightly. */
    .ms-discover-source-badge {
        top: 0.3rem;
        left: 0.3rem;
        padding: 0.14rem 0.35rem;
        font-size: 10px;
    }
    /* Per-card download button is a desktop-only affordance — Musiced
       Desktop doesn't install on mobile and the lucyna://download
       deep link has nothing to hand off to. (The topbar Get Musiced
       link is hidden separately, further up this file.) */
    .ms-discover-dl { display: none; }
}


/* ============================================================
   Search-input iOS zoom + topbar overflow follow-ups (Batch 1.5)
   Lives at end-of-file on purpose: needs to win source-order over
   the base `.ms-discover-search input { font-size: var(--text-sm); }`
   rule which sits further up the file. CSS @media adds no specificity,
   so the only reliable way to override an equally-specific later rule
   is to come even later.
   ============================================================ */
@media (max-width: 720px) {
    /* iOS Safari triggers focus-zoom when an <input> has computed
       font-size < 16 px. 16 px is the exact threshold. */
    .ms-search-input,
    .ms-discover-search input {
        font-size: 16px;
    }

    /* Topbar action cluster — with span hidden the buttons were still
       carrying 0.4rem 0.85rem padding (~50 px each), pushing the row
       past the viewport on iPhone (Add folder + Select were clipping
       off-screen). Make each ms-btn a 36×36 square so the whole
       cluster fits next to the search input on a 390 px viewport.

       Heights are explicitly aligned across all three element types
       (search input, mode toggle, action buttons) to 36 px so the
       topbar row reads as a single horizontal strip. Mode toggle stays
       narrower (28 px wide per button) since the two buttons read as a
       paired group and a 56-px total width balances the 32-px squares
       beside it without bloating the action cluster horizontally. */
    .ms-search-wrap {
        padding: 0.25rem 0.85rem;
        min-height: 32px;
    }
    .ms-topbar-actions .ms-btn {
        padding: 0;
        width: 32px;
        height: 32px;
        justify-content: center;
    }
    /* Mobile parity: wrapper height matches the new 32 px topbar
       control-h so the whole row sits on one baseline. Buttons inside
       inherit `height: 100%` from the desktop rule. */
    .ms-mode-toggle {
        height: 32px;
    }
    .ms-mode-toggle button {
        width: 28px;
    }

    /* Topbar action buttons + per-view extras (#ms-topbar-new-playlist,
       #ms-topbar-get-musiced) + select-mode bar buttons all go
       BORDERLESS on mobile — they read as icon-only ghost buttons
       inside the compact 32 px chrome. The .ms-btn default `border:
       1px solid var(--btn-border)` was visually heavy at this size.
       Color from .ms-btn-primary (+ New playlist accent) and
       .ms-btn-danger (Delete red) still carries the icon hue.
       Hover/active still flashes a subtle bg.
       Search bar (.ms-search-wrap) keeps its border — it's a text
       input, not a ghost-icon button, and reads as an input field. */
    .ms-topbar-actions .ms-btn,
    .ms-topbar-new-playlist,
    .ms-topbar-get-musiced,
    .ms-select-bar .ms-btn {
        background: transparent;
        border-color: transparent;
    }
    .ms-topbar-actions .ms-btn:hover:not(:disabled),
    .ms-topbar-new-playlist:hover:not(:disabled),
    .ms-topbar-get-musiced:hover:not(:disabled),
    .ms-select-bar .ms-btn:hover:not(:disabled) {
        background: var(--row-hover);
        border-color: transparent;
    }

    /* Select-mode topbar polish — the .ms-select-bar replaces
       .ms-topbar-actions while the user has tracks selected. Its
       buttons (Cancel / Add to playlist / Delete) weren't picked up by
       the rule above (different parent class), so they kept the default
       .ms-btn padding + size. That made the row reshape every time you
       entered select-mode AND on iPhone they overflowed the viewport.
       Fix in three parts. */

    /* (1) Search input is hidden during select-mode on mobile — it has
       no meaningful interaction with an active selection and removing
       it frees enough horizontal room for the longer "Add N to
       playlist" / "Delete N" labels to fit at 390 px. Desktop keeps
       both visible because it has room. */
    .music-app[data-selecting="true"] .ms-search-wrap { display: none; }

    /* (2) Tighten the bar's own gap + font so the four pieces (count +
       three buttons) read as one compact strip. */
    .ms-select-bar {
        gap: 0.4rem;
        font-size: 0.78rem;
        flex: 1;
    }
    .ms-select-count {
        font-size: 0.75rem;
        white-space: nowrap;
        flex-shrink: 0;
        margin-right: 0.1rem;
    }

    /* (3) Match the 32 px height of every other topbar element so the
       whole row sits on a single baseline. Padding shrinks to keep the
       label visible without making the button look squat. */
    .ms-select-bar .ms-btn {
        padding: 0 0.5rem;
        height: 32px;
        font-size: 0.78rem;
        white-space: nowrap;
    }

    /* Critical flex-shrink fix: a flex item's default min-width is
       `auto`, which is its intrinsic content width. For the search
       input that's its placeholder text (~210 px) — wider than what's
       available next to the 188 px action cluster on a 390 px iPhone.
       Forcing min-width:0 lets the search-wrap shrink past its
       placeholder so the action cluster always has room and the
       Select button stops clipping off the right edge. The placeholder
       text just truncates inside the input. */
    .ms-search-wrap { min-width: 0; }
    .ms-search-input { min-width: 0; }

    /* (The mobile 3-column library/playlist grid moved to music-library.css as the
       MOBILE-FIRST base of `.ms-grid` — so the phone column count lives in the same
       always-loaded file as the grid itself and can't be lost to a stale mobile cache.
       Desktop widens it via `@media (min-width: 721px)` there. Nothing needed here now.) */
}

/* ============================================================
   Mobile double-tap-to-play "picked" state
   ============================================================
   Single tap on a library or playlist row/tile at ≤ 720 px marks it
   as picked rather than playing immediately. A second tap on the
   same picked row plays. Picked rows scale up slightly + grow an
   accent outline so it's obvious which row would play next. Pinned
   to mobile only — desktop keeps single-click-to-play. See the
   `attachRowBehavior` click handler in music-library.js. */
@media (max-width: 720px) {
    /* Tactile feedback for touch: a small scale on the picked tile
       or row so the finger gets visible confirmation that the tap
       registered. The accent border + text colour live in the
       universal "chosen" indicator block in music-library.css
       (applies to both .picked and .playing, both views, both
       viewports). This block adds the scale ON TOP for mobile only
       — desktop doesn't need it (cursor users get hover feedback +
       single-click-to-play, so there's no picked-but-not-yet-playing
       intermediate state to indicate). */
    .ms-tile.picked,
    .ms-list-row.picked {
        transform: scale(1.02);
        transition: transform var(--dur-fast) var(--ease-smooth);
    }
    /* Tile hover already does scale(1.03); selecting `.picked` after
       `:hover` in the cascade keeps the picked-scale winning when the
       finger is held down on the tile. */
    .ms-tile.picked:hover { transform: scale(1.02); }
}

/* ============================================================
   iOS-only: folder import doesn't work (Safari ignores
   webkitdirectory). Hiding both the topbar "Add folder" button
   and the empty-state secondary "or import an entire folder"
   link so users aren't tricked into tapping something that
   silently no-ops. The `html.ios` class is added pre-paint by
   _Layout.cshtml's user-agent sniff (covers Safari + Chrome iOS
   + Opera GX iOS + every iPad Safari WebKit-based browser).
   ============================================================ */
html.ios label[for="ms-folder-input"] { display: none; }


/* ============================================================
   iOS Safari Liquid Glass lift for /musiced. NOT inside any
   media query — `.iphone-safari` is the gate (set only on
   iPhone + iPad Safari by the multi-gate detector in
   _Layout.cshtml), and the rule needs to apply at every viewport
   width because iPad Safari is wider than the 720 px mobile
   breakpoint. Previously this rule lived inside `@media
   (max-width: 720px)` which excluded iPad entirely, so iPad
   users saw the player clipped under the home-indicator strip.

   .music-app is `height: 100%` + `box-sizing: border-box`, so
   padding-bottom shrinks the grid's available space and the
   player (auto-sized / fixed bottom row) ends up `padding-bottom`
   above the viewport bottom. The 1fr main row shrinks by the
   same amount, which the album grid absorbs via its own scroll.

   `max(env, 2.75rem)` instead of `env + 2.75rem`: iPhone Safari's
   Liquid Glass URL bar has two heights — full on cold load
   (env ≈ 85 px) and minimized after user interaction (env ≈
   34 px). The old `env + 2.75rem` stacked the buffer on top of
   the URL-bar inset, so the player floated ~126 px above the
   viewport bottom on cold load and snapped down to ~75 px after
   the first interaction shrank the bar — a visible "jump" the
   user noticed. `max()` collapses both cases to a stable
   2.75 rem (URL-bar minimized) / 85 px (URL-bar full) without
   stacking, so the only jump is the natural URL-bar animation
   itself, no longer compounded by the buffer. The translucent
   URL pill happily sits over the player at the minimized state;
   the home indicator is cleared by the 2.75 rem floor. On iPad
   Safari the URL bar lives at the top, so env tends to be just
   the home-indicator inset (~21 px); the 2.75 rem floor adds a
   bit of extra gap below the player on iPad but reads cleanly
   and matches the iPhone treatment.

   Layered on top of the base `padding-bottom: env(safe-area-
   inset-bottom)` in music-base.css — which covers Android, iPad,
   and non-Safari iOS. This rule overrides for iPhone/iPad Safari
   specifically.
   ============================================================ */
html.iphone-safari .music-app {
    padding-bottom: max(env(safe-area-inset-bottom), 2.75rem);
}

/* ============================================================
   Android lift — sits the player chrome the same distance above
   the bottom edge as iPhone Safari's `.iphone-safari` rule does
   (2.75rem floor over env). Originally tuned to clear a Custom
   Tab action bar I thought was overlapping; the actual purpose
   ended up being visual parity with the cross-page mini-player
   on / and /clipped, which sits well above the gesture bar at
   its natural padded height. Keeping the player flush with the
   bottom looked cramped and inconsistent with the rest of the
   site's bottom-chrome rhythm.
   ============================================================ */
html.android .music-app {
    padding-bottom: max(env(safe-area-inset-bottom), 3.75rem);
}
/* Firefox Android tunes a hair higher than Chrome — its `100dvh`
   resolves to a slightly larger value (URL-bar-hidden state) even
   when the URL bar is visible, so the body overflows the visible
   viewport by ~12 px and the player chrome at the grid bottom paints
   into the overflow. 4.5rem floor compensates so the chrome sits at
   the same Y the Chrome Custom Tab path reaches with 3.75rem.
   Source-order WINS the specificity tie (.android-firefox .music-app
   and .android .music-app both compute to 0,2,1). */
html.android-firefox .music-app {
    padding-bottom: max(env(safe-area-inset-bottom), 4.5rem);
}

/* ============================================================
   DuckDuckGo iOS — force the bottom inset to 0 on EVERY device.
   DuckDuckGo's bottom toolbar is separate chrome below the web viewport
   (it shrinks the viewport; it never overlays content, and the home
   indicator sits below the toolbar in native chrome), so the page needs
   no bottom inset at all. The base `.music-app { padding-bottom:
   env(safe-area-inset-bottom) }` is wrong for it: env is 0 on an iPhone
   Pro Max (so it looked fixed there) but NON-ZERO on smaller iPhones,
   which reopened the player gap. Pin it to 0 regardless of env.
   `(0,2,1)` beats the base `.music-app` `(0,1,0)`, and DuckDuckGo never
   carries `.iphone-safari`/`.android`, so there's no specificity fight.
   ============================================================ */
html.ios-ddg .music-app {
    padding-bottom: 0;
}



/* ----------------------------------------------------------------------
   Touch: pin the ⋮ options buttons visible.
   ----------------------------------------------------------------------
   On desktop the per-track / per-playlist ⋮ buttons are hover-revealed
   (opacity:0 until `:hover` under `@media (hover:hover) and (pointer:fine)`).
   Touch devices have no hover, so without this they're unreachable — which
   on a phone/iPad blocks the track menu entirely in GRID view (and the
   sidebar playlist menu), and with it "Set album cover…". Gated on
   `hover: none` so it covers BOTH phones and iPads (a width-only query
   would miss the iPad). The list-row equivalent lives in the
   max-width:720px block above; this also re-pins it for wider touch
   screens (iPad in list view). */
@media (hover: none) {
    .ms-tile-more { opacity: 1; }
    .ms-playlist-more { opacity: 1; }
    .ms-list-row .cell-more .ms-icon-btn { visibility: visible; }
}
