/* ── Narrow screens ───────────────────────────────────────────
   Loaded last so these override the base rules without needing weight.

   The breakpoint is not a guess. The reference was measured at nine widths
   between 600 and 1024: it keeps its 256px rail down to 768px and swaps to a
   docked 70px bar of four below that, with nothing in between. So there is one
   breakpoint here, at 768px, and no tablet state — matching what it does
   rather than what a framework's default scale suggests.

   The shell is driven by --sidebar-w and --player-h, so most of the layout
   follows from retargeting those two rather than from rewriting rules. */

/* The docked bar exists only below the breakpoint. */
.tab-bar {
  display: none;
}

/* ── Safe-area insets (all widths) ──────────────────────────
   Portrait phones need bottom (home indicator) and, with a notch,
   top/left/right; landscape phones (844×390 is wider than the 768px
   breakpoint, so they get the desktop shell) need left/right for the
   camera notch and bottom for the home indicator most of all. These
   land here rather than in the phone block so both shells get them.
   env() is 0 without a notch, so this is a no-op on plain screens.
   The main column shifts for top/left/right; the viewport-fixed player
   carries its own three sides (the tab bar is phone-only and sets its
   own inside the phone block). */
.main {
  inset-block-start: env(safe-area-inset-top, 0px);
  inset-inline-start: calc(var(--sidebar-w) + env(safe-area-inset-left, 0px));
  inset-inline-end: env(safe-area-inset-right, 0px);
}

.player {
  inset-inline-start: env(safe-area-inset-left, 0px);
  inset-inline-end: env(safe-area-inset-right, 0px);
  inset-block-end: env(safe-area-inset-bottom, 0px);
}

/* ── Narrow desktop ───────────────────────────────────────────
   Between the breakpoint and about 1100px the player's three columns —
   1fr / up to 560px / 1fr — could not all be paid for: the centre took its
   560 and the right zone its intrinsic 280, leaving the left column exactly
   0px wide. The cover, title and artist were simply not drawn, so nothing on
   screen said what was playing. Nothing was clipped, so no overflow check
   could see it.

   Giving the left column a floor and letting the scrubber give up width
   instead resolves it in the direction that keeps information on screen. */
@media (min-width: 768px) and (max-width: 1099.98px) {
  .player {
    grid-template-columns: minmax(140px, 1fr) minmax(0, 400px) auto;
  }
}

/* Four quick-link columns need ~135px each before the 56px cover plus
   padding leaves the label under half its text (measured: 844px with
   notch-magnitude insets gives 50px labels showing four characters).
   Below 992px there are two roomy columns instead of four clipped ones —
   the same direction the phone rule takes it, one step later. */
@media (min-width: 768px) and (max-width: 991.98px) {
  .quick-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 767.98px) {
  :root {
    --sidebar-w: 0px;
    /* The tab band is 5px of air plus a 65px pill, and the player floats a
       further 28px above it — which is where its measured 98px offset comes
       from. Naming both keeps that arithmetic visible instead of leaving 98
       as a number nobody can derive. */
    --tab-bar-h: 70px;
    --tab-bar-gap: 28px;
    --player-h: 64px;
  }

  /* ── The rail goes away entirely ─────────────────────────── */
  .sidebar {
    display: none;
  }

  /* Collapsing is meaningless with no rail; the control would be a dead end. */
  .top-bar__btn--expand,
  .top-bar__btn--collapse,
  .sidebar__collapse {
    display: none !important;
  }

  /* Both bars float clear of the edge, so the content has to clear the taller
     stack: the player's own 98px offset plus its height, plus a little air.
     Top/left/right insets ride on the global rule above (at this width
     --sidebar-w is 0, so it reduces to the bare env()); only the bottom
     needs the floating-stack arithmetic. */
  .main {
    inset-block-end: calc(var(--tab-bar-h) + var(--tab-bar-gap) + var(--player-h) + 8px
                          + env(safe-area-inset-bottom, 0px));
  }

  /* ── The docked bar ──────────────────────────────────────────
     Measured off the reference at 390, not designed: it is not an edge-to-edge
     bar but a floating pill — 12px inset, 65px tall, 28px radius, 6px padding,
     sitting 5px off the bottom, over rgba(18,20,28,0.44) and a heavy blur.
     The glass is the same recipe used elsewhere here: a bright inset top edge,
     a dark inset bottom edge, and one deep outer shadow.

     The reference keeps a fifth control to the right of its pill, which is why
     its own pill stops 80px short. We have no counterpart, so ours spans the
     full inset width rather than leaving a gap for something absent. */
  .tab-bar {
    position: fixed;
    /* 12px float plus the notch side on each edge — inset-inline cannot hold
       two different env() sides, so start/end are spelled out. */
    inset-inline-start: calc(12px + env(safe-area-inset-left, 0px));
    inset-inline-end: calc(12px + env(safe-area-inset-right, 0px));
    inset-block-end: calc(5px + env(safe-area-inset-bottom, 0px));
    z-index: 40;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    block-size: 65px;
    padding: 6px;
    border-radius: 28px;
    background: rgba(18, 20, 28, 0.44);
    backdrop-filter: blur(44px) saturate(2.2) brightness(1.12);
    -webkit-backdrop-filter: blur(44px) saturate(2.2) brightness(1.12);
    box-shadow:
      inset 0 1px 0 0 rgba(255, 255, 255, 0.2),
      inset 0 -1px 0 0 rgba(0, 0, 0, 0.2),
      0 18px 40px rgba(0, 0, 0, 0.7);
  }

  .tab-bar__item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    text-decoration: none;
    color: var(--text-muted);
    font-size: 11px;
    line-height: 11px;
    font-weight: 600;
    letter-spacing: -0.176px;
    -webkit-tap-highlight-color: transparent;
    transition: color 0.18s var(--ease-out);
  }

  .tab-bar__item svg {
    inline-size: 22px;
    block-size: 22px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  /* The rail tints only the icon; this bar tints the whole item and thickens
     the icon stroke to 2.5. Both were read off the running site. */
  .tab-bar__item--selected {
    color: var(--accent);
  }

  .tab-bar__item--selected svg {
    stroke-width: 2.5;
  }

  .tab-bar__item:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -3px;
    border-radius: 22px;
  }

  /* ── The player bar ──────────────────────────────────────────
     It docks above the tab bar rather than at the foot of the screen.

     Its three columns are 1fr / up-to-560px / 1fr, which at 390 resolved to
     0px / 78px / 280px: the track info vanished entirely and two transport
     buttons sat at negative x, off the left edge. The scrubber is what wants
     the 560, so it goes — it is in the now-playing view, one tap away through
     the expand control, which lives in the left zone and stays.

     Cast, Volume, Mini player and Fullscreen all describe a desktop or a
     second screen. Queue does not, so it is the one that stays.

     The reference floats this too: 12px inset, 64px tall, 36px radius, 12px
     padding, 98px off the bottom — which is 28px of air above the tab pill. */
  .player {
    inset-inline-start: calc(12px + env(safe-area-inset-left, 0px));
    inset-inline-end: calc(12px + env(safe-area-inset-right, 0px));
    inset-block-end: calc(var(--tab-bar-h) + var(--tab-bar-gap) + env(safe-area-inset-bottom, 0px));
    block-size: 64px;
    border-radius: 36px;
    border-top: none;
    padding: 12px;
    grid-template-columns: minmax(0, 1fr) auto auto;
    column-gap: 8px;
    background: rgba(18, 20, 28, 0.44);
    backdrop-filter: blur(44px) saturate(2.2) brightness(1.12);
    -webkit-backdrop-filter: blur(44px) saturate(2.2) brightness(1.12);
    box-shadow:
      inset 0 1px 0 0 rgba(255, 255, 255, 0.2),
      inset 0 -1px 0 0 rgba(0, 0, 0, 0.2),
      0 18px 40px rgba(0, 0, 0, 0.7);
  }

  .player__scrubber,
  .player__time,
  .player__vol-bar,
  /* By id. These were matched on aria-label, and syncMuted rewrites the volume
     button's to "Mute" at module load, so the rule never applied and the mute
     icon stayed on screen below 768px. Fullscreen's label happens to be static
     today, which is not a reason to key on it. */
  #player-vol-btn,
  #player-fullscreen-btn {
    display: none;
  }

  .player__cover {
    inline-size: 44px;
    block-size: 44px;
  }

  .player__left {
    gap: 8px;
  }

  .player__centre,
  .player__transport {
    gap: 4px;
  }

  /* ── Room ────────────────────────────────────────────────── */
  .content-frame__inner {
    padding-inline: 16px;
  }

  /* Measured on the reference at 390: the row wraps rather than squeezing,
     and the greeting itself drops from 36/40 to 30/36. Without the wrap the
     Library/Folders pill was pushed off the right edge — present, tappable
     nowhere. */
  .greeting-row {
    padding-block: 16px;
    flex-wrap: wrap;
    gap: 12px;
  }

  .greeting-row__text {
    font-size: 30px;
    line-height: 36px;
    letter-spacing: -0.75px;
  }

  /* Four columns leaves 80px a card, which is narrower than the 56px cover
     plus a word: every label rendered as a single letter and a full stop.
     The reference goes to two here (grid-cols-2, 10px), and so do we. */
  .quick-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
  }

  /* ── Touch targets ───────────────────────────────────────────
     These control sizes are the reference's, matched deliberately, and they
     are sized for a cursor: the top-bar arrows are 32x32, the segmented pill
     28 tall, the hero card's share button 20 wide. A fingertip wants about 44.

     The first attempt gave each an invisible 44px hit area through ::after,
     which measured beautifully and did not work: elementFromPoint showed the
     expanded areas being clipped by scrolling ancestors and covered by the
     floating bars. Growing the controls themselves is a visible change on
     phones, but it is one that can be verified. */
  .top-bar__btn,
  .top-bar__avatar {
    inline-size: 44px;
    block-size: 44px;
  }

  /* 50 on the pill leaves each segment at exactly 44 once padding is taken. */
  .seg-pill {
    block-size: 50px;
  }

  .seg-pill__seg--sort {
    block-size: 44px;
  }

  /* Not a sizing choice: shell.css says 48x48 and it renders 20 wide,
     because as a flex item it was free to shrink. Same defect as the sync
     pill, same fix — and holding its real width puts the row 5px past a
     390px screen, so the play button's 22px of side padding gives some back.
     The label is what that padding is around, and it has room to spare.
     The min sizes below make the 44px guarantee structural in every
     header variant (hero, album, artist, playlist, liked): the rows wrap,
     so nothing squeezes today, but flex-shrink:1 would let any of these
     collapse below a fingertip the moment a row stops wrapping. */
  .hero-card__share {
    flex-shrink: 0;
    min-inline-size: 44px;
    min-block-size: 44px;
  }

  .album-btn--shuffle,
  .album-btn--like,
  .album-btn--queue,
  .album-btn--share,
  .album-btn--more {
    flex-shrink: 0;
    min-inline-size: 44px;
    min-block-size: 44px;
  }

  .album-btn--play,
  .artist-follow-btn {
    flex-shrink: 0;
    min-block-size: 44px;
  }

  .hero-card__play {
    padding-inline: 16px;
  }

  .shelf__see-all {
    padding-block: 10px;
  }

  .settings-btn {
    block-size: 44px;
  }

  /* ── Now playing ─────────────────────────────────────────────
     The desktop view is two columns — art and transport at the left, lyrics
     down the right — held apart by 96px of side padding. At 390 that padding
     alone is half the screen, so the columns stack: art and controls first,
     lyrics taking the rest of the height and scrolling within it.

     The cover was a hard 279px square, which is wider than the content box
     here; it now tracks the viewport and keeps its own aspect rather than
     being squashed by the flex row. */
  .now-playing__top {
    padding: 16px 20px;
  }

  .now-playing__body {
    flex-direction: column;
    padding: 0 20px 20px;
    gap: 16px;
  }

  .now-playing__left {
    flex: 0 0 auto;
  }

  .now-playing__cover {
    inline-size: min(70vw, 279px);
    block-size: auto;
    aspect-ratio: 1;
    margin-block-end: 16px;
  }

  .now-playing__right {
    flex: 1 1 0;
    min-block-size: 0;
  }

  .now-playing__lyrics {
    padding-block: 8px;
    padding-inline: 0;
  }

  /* 48px of side padding is most of a phone; the sync pill needs the room. */
  .np-sync-row {
    padding-inline: 0;
  }

  /* ── Now-playing utility row ───────────────────────────────
     Measured at 390: device (101) + gap + group (220) fits its 350px box,
     but only just, and the lyrics/queue 44px ::after hit areas overlap by
     4px (24px paints on 40px centres). Shrink, not wrap or demote: the
     volume slider gives up 28px and the group gaps go 16→20, so icon
     centres sit exactly 44 apart with zero hit overlap and ~29px of air.
     Nothing is demoted — every control stays on screen and tappable. */
  .np-utility-row__group {
    gap: 20px;
  }

  .np-vol-slider {
    inline-size: 72px;
  }

  /* ── Album header ────────────────────────────────────────────
     Same shape of problem: a 304px cover with 91px beneath it, sized for a
     page three times this wide. */
  .album-header {
    padding-block-start: 28px;
    padding-block-end: 24px;
  }

  .album-header__cover {
    inline-size: min(64vw, 304px);
    block-size: auto;
    aspect-ratio: 1;
    margin-block-end: 24px;
  }

  /* The action row ran 419px wide inside a 390px screen and the header clips
     its overflow, so the outer controls were cut off rather than pushed to a
     scrollbar — invisible unless measured. Wrapping keeps every control
     reachable, which matters more here than holding them to one line. */
  .album-header__controls {
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
    max-inline-size: 100%;
  }

  /* ── Liked and playlist headers ──────────────────────────────
     A row whose 232px art will not shrink, beside a text column that will:
     the column collapsed to 38px and the 48px title, having nothing to break
     on, ran 56px past the screen. Stacking gives the title the full width,
     and at that width 48px is too large for the line anyway. */
  .liked-header {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 16px;
    padding: 24px 16px 0;
  }

  .liked-header__art {
    inline-size: min(52vw, 232px);
    block-size: auto;
    aspect-ratio: 1;
  }

  .liked-header__meta {
    align-items: center;
    inline-size: 100%;
  }

  .liked-header__title {
    font-size: 32px;
    line-height: 36px;
    letter-spacing: -0.8px;
  }

  .liked-header__controls {
    justify-content: center;
    flex-wrap: wrap;
  }

  /* ── Artist header ─────────────────────────────────────────
     Had no phone rules at all: the 208px photo and the text column stayed
     side by side, and the nowrap 398px action row ran 256px past a 390px
     screen behind the header's own overflow:hidden — shuffle and play
     visible, follow/share/more cut off with no way to reach them. Same
     stacking treatment as the liked header above: art on top, full-width
     centred text, wrapping controls. The photo keeps its circle through
     the aspect ratio. */
  .artist-header {
    block-size: auto;
    padding: 24px 16px 0;
  }

  .artist-header__content {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }

  .artist-header__photo {
    inline-size: min(52vw, 208px);
    block-size: auto;
    aspect-ratio: 1;
  }

  .artist-header__text {
    align-items: center;
    inline-size: 100%;
  }

  .artist-header__name {
    font-size: 32px;
    line-height: 36px;
    letter-spacing: -0.8px;
  }

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

  /* ── Narrow phone (< 480px) ──────────────────────────────────
     At 390px the player bar is overcrowded with all transport and utility
     controls visible. Demote secondary controls so only: cover, title,
     expand, play/pause, and next remain. This keeps every visible button
     at ≥ 44px touch target and prevents overflow. */
  @media (max-width: 479.98px) {
    /* Hide secondary left-zone controls */
    #player-like-btn,
    #player-share-btn {
      display: none;
    }

    /* Hide secondary centre transport */
    #player-shuffle-btn,
    #player-repeat-btn,
    /* Previous button: no id, use aria-label */
    .player__centre button[aria-label="Previous"] {
      display: none;
    }

    /* Hide right-zone utility button */
    #player-queue-btn {
      display: none;
    }

    /* Tighten left-zone gap now that two buttons are gone */
    .player__left {
      gap: 4px;
    }

    /* Centre only has play + next; tighten */
    .player__centre,
    .player__transport {
      gap: 2px;
    }

    /* ── Survivors hit 44px for real ─────────────────────────
       Cover is already 44; expand, play and next grow to 44 here
       (expand included, not just play/next: a 44px pin around its
       centre lands on the title text to its left if the paint stays
       32, so the ::after overlay alone cannot pass elementFromPoint).
       The budget holds one row: 44 cover + 4 + ~156 title + 4 + 44
       expand left, 44 play + 2 + 44 next centre, of 342 content px.
       Paint IS the hit area now, so the desktop ::after overlays are
       switched off — they would overlap the neighbours by 6px. */
    .player__left .player__icon-btn,
    .player__transport .player__icon-btn,
    .player__play-btn {
      inline-size: 44px;
      block-size: 44px;
    }

    .player__left .player__icon-btn::after,
    .player__transport .player__icon-btn::after,
    .player__play-btn::after {
      content: none;
    }

    /* The title block is the fifth survivor: tall enough that a 44px
       box around its centre still lands on it, text centred in it — and
       growing to fill the row (flex-grow was 0, so a short title left the
       info at its 39px content width with 117px of slack beside it). Long
       titles still truncate on the existing ellipsis. */
    .player__track-info {
      flex: 1 1 auto;
      min-block-size: 44px;
      justify-content: center;
    }
  }
}
