/* ============================================================
   音乐页移动端（≤768px）  css/music-mobile.css
   ------------------------------------------------------------
   为什么单独一个文件、为什么排在 app.css 之后：
     1. music.html 的 <link> 顺序是
          style → sidebar → all.min → music.css → anim → mobile.css → app.css
        本文件排在 app.css 之后，成为 music.html 的最后一个样式表。
        因此同特异性下本文件的规则恒胜 —— 不需要靠 !important 取胜。
        （mobile.css 文件头那句「app.css 才是最后加载的那个」是全站的说法；
          就 music.html 而言，最后一个现在是本文件，那边的注释已同步更新。）
     2. 本文件只被 music.html 引用，改它不可能波及其它页面。
     3. 全部规则都包在 @media (max-width:768px) 里 —— 桌面端（>768px）
        一行都不命中。这是本仓库 mobile.css 文件头立下的硬约定。

   阶段一 T1.2 配套改动（都在 css/music.css 里，同一次提交）：
     摘掉了 .blog-title / .subhead 的字号、.player-card 的内边距、
     .vinyl 的尺寸、.controls-row 的外边距这几处的 !important，
     交给本文件接管。本文件**没有新增任何 !important**。

   390×844 实测纵向预算（本文件的所有数字都来自这张表）：
     .music-container  padding-top 12
     .music-header     60 → 136.5   (76.5)  = h1 37.2 + 间距 8 + subhead 31.3
     .page-tabs        168.5 → 224.5 (56)   margin-bottom 16
     .po-searchbar     240.5 → 286.5 (46)   margin-bottom 16（与卡片 margin-top 8 折叠）
     .player-card      302.5 → 812.4 (509.9)
       ├ .player-left   317.9 → 465.1 (147.2) = disc-zone 108 + 间距 13.2 + spectrum 38(含 -14 负边距)
       └ .player-right  476.3 → 797   (320.8)
                        = song-details 50.2 + lyric 106 + progress 16.3
                          + controls 78.8 + extra 27.1
   ============================================================ */

@media (max-width: 768px) {

  /* ============================================================
     1. 首屏纵向预算（T1.4）
     ------------------------------------------------------------
     问题：屏幕短于约 800px 时，用户进页面第一眼看不到播放键。
     实测「bot-tab 顶边 − 播放键底边」：
       320×568 −233 | 360×740 −61 | 375×667 −134 | 390×844 +43 | 430×932 +171
     做法分两档：
       · 1a 所有 ≤768 生效：收紧标题区与各处间距，约省 80px。高屏手机上
         观感基本不变（留白本来就有富余）。
       · 1b 仅短屏（≤800px 高）生效：再压封面与歌词，把播放键抬进首屏。
         375×667 / 360×740 必须通过；320×568 做不到（见文件末尾说明）。
     注意：H1 一律保留，只压间距 —— mobile.css:584 写明手机网页必须保住
     H1（搜索引擎是移动优先索引），这里不能 display:none。
     ============================================================ */

  /* ---- 1a. 基础收紧 ---- */
  .music-header {
    margin: 0 0 14px;   /* 原 32 */
    padding: 0;
  }
  .music-header .blog-title {
    margin: 0;
    font-size: 22px;    /* 原 24.8（1.55rem） */
    line-height: 1.15;  /* 原 37.2px 行高 */
  }
  .music-header .subhead {
    margin: 4px 0 0;    /* 原 8 */
    padding: 2px 6px;   /* 原 4.8 */
    font-size: 12.5px;  /* 原 13.6（0.85rem） */
    line-height: 1.35;
  }
  .page-tabs {
    margin-bottom: 10px;    /* 原 16 */
  }
  .po-searchbar {
    margin-bottom: 10px;    /* 原 16，与 .player-card 的 margin-top 8 折叠后取 10 */
  }
  .player-card {
    padding: 10px;          /* 原 14.4（0.9rem）。左右同为 10px，横向反而更宽松 */
  }
  .player-right .song-details {
    margin-bottom: 2px;     /* 原 5.6 */
  }
  .player-right .track-title {
    font-size: 19px;        /* 原 21.6（1.35rem） */
    line-height: 1.25;
  }
  .player-right .progress-area {
    margin: 2px 0;          /* 原 3.2 */
  }
  .player-right .controls-row {
    margin: 8px 0 4px;      /* 原 14.4 / 8 */
    padding: 6px 0 4px;     /* 原 9.6 / 7.2 */
  }

  /* ---- 1b. 短屏加码（≤800px 高）---- */
  @media (max-height: 800px) {
    .music-header {
      margin-bottom: 8px;   /* 基础档 14 → 8 */
    }
    .music-header .blog-title {
      font-size: 20.5px;
    }
    /* 封面：108 → 92。整块 .player-left 是首屏里最"可压"的部分 ——
       桌面端那块留白是唱片机构图需要，手机上不值这个高度。 */
    .player-left .vinyl {
      width: 92px;
      height: 92px;
    }
    .player-left .cover-inner {
      width: 80px;          /* 原 96 */
      height: 80px;
    }
    .disc-zone {
      margin-top: 4px;      /* 原 8 */
      margin-bottom: 2px;   /* 原 5.6 */
    }
    /* 频谱条：38 → 28。它是纯装饰，压掉的 10px 直接还给播放键。 */
    .spectrum-line .spectrum-bars {
      height: 28px;
    }
    .player-left .spectrum-line {
      margin-top: 0.1rem;
      margin-bottom: -10px; /* 原 -14，抵消条形容器下方的固有空白 */
    }
    /* 歌词面板：106 → 72。短屏上它是唯一可以牺牲的区块；
       阶段二会把它并进全屏播放页，这里先保证播放键可见。 */
    .player-right .lyric-panel {
      height: 72px;
      max-height: 72px;
      min-height: 0;
      margin-bottom: 2px;
    }
  }

  /* ============================================================
     2. 触控目标（T1.5）
     ------------------------------------------------------------
     实测不达标的控件（44×44 是下限）：
       .mode-chip          30×27 / 61×27      （≤420 时 .mc-txt 被隐藏，只剩图标）
       .progress-bar-bg    239×7              （app.css 已给 ::before 28px 命中区，仍不够）
       .glass-icon（抽屉）  32×32
       .filter-tab         ×40
     ============================================================ */

  /* mode-chip：补齐到 44。视觉上只是更疏朗，不影响一行排布，
     因为高度不会撑宽这一行（没有改 padding/字号）。 */
  .player-right .extra-actions .mode-chip {
    min-height: 44px;
    min-width: 44px;
    /* min-width 撑开图标型 chip 之后，"歌单 128 首" 里的数字会被挤成两行
       （实测 390 宽下 "128" / "首" 分家）。禁止换行，溢出交给 3 节的换行规则兜。 */
    white-space: nowrap;
  }

  /* 进度条：7px 的视觉高度保持不变，把 app.css 那条 28px 的透明命中区
     提到 44px。命中区是绝对定位的 ::before，不占布局，不会把控制行顶下去。
     （与下方 .controls-row 有不到 1px 的重叠，控制行在 DOM 里靠后、
       绘制在其之上，点击不会被这条透明层截走。） */
  .progress-area .progress-bar-bg {
    position: relative;
  }
  .progress-area .progress-bar-bg::before {
    height: 44px;
    margin-top: -22px;
  }

  /* 歌单抽屉右上角三颗图标（只看收藏 / 上传 / 关闭） */
  .pl-drawer-tools .glass-icon {
    width: 44px;
    height: 44px;
    border-radius: 22px;
  }

  /* 作品分类 chip。app.css:1371 用的是 `html.has-appbar .filter-tab`
     （0,2,1），比单纯的 .filter-tab 更具体，所以这里必须把选择器写到同一级，
     靠"本文件最后加载"取胜 —— 而不是靠 !important。 */
  .filter-tab,
  html.has-appbar .filter-tab {
    min-height: 44px;
  }

  /* ============================================================
     3. 极窄屏：控制行不再横向溢出（T1.6）
     ------------------------------------------------------------
     实测 320px 宽下 .extra-actions 溢出到 R=331（视口 320）：
     该行是 flex + 不换行，6 个控件（循环 / 随机 / 倍速 / 音量 / 歌单）
     的最小内容宽之和超过了卡片内宽。T1.5 把 chip 撑到 44px 后会更容易溢出。
     做法：≤360 时允许换行，把音量条整条挪到第二行。
     换行发生在 .controls-row **之后**，所以不会影响播放键的首屏位置。
     ============================================================ */
  @media (max-width: 360px) {
    .player-right .extra-actions {
      flex-wrap: wrap;
      row-gap: 8px;
    }
    .player-right .extra-actions .mixer {
      flex: 1 1 100%;
      margin-left: 0;
      justify-content: flex-start;
    }
  }
}

/* ============================================================
   阶段二 · 首屏三态：内容页 + 迷你条 + 全屏播放页
   ------------------------------------------------------------
   参照 Spotify Mobile UI Kit 的首页：区块标题 +「全部」入口 + 横向卡片行，
   下面接纵向列表。桌面端这些类名一个都不存在（HTML 里的 .mm-* 由本文件的
   媒体查询整块隐藏），所以 >768px 零影响。
   ============================================================ */

/* 桌面端必须先把这两块藏掉 —— 它们的样式全部写在下面的媒体查询里，
   不藏的话 .mm-home 会以「无样式 div」的形态出现在桌面版首屏。
   （.mm-mini 自带 hidden 属性兜底，这里一并写明白。） */
.mm-home,
.mm-mini {
  display: none;
}

@media (max-width: 768px) {

  /* ============================================================
     4. 播放器大卡片退出首屏（T2.1）
     ------------------------------------------------------------
     卡片仍然留在 DOM 里 —— 全屏播放页靠 AppShell.adopt() 把
     #coverInner / #trackName / #trackArtist / #lyricBox / .progress-area /
     .controls-row / .extra-actions 这些**真实节点**搬进 .fs-* 层。
       · display:none 不影响 adopt：节点被搬走后就脱离了本卡片，在别处正常渲染
       · display:none 也不影响 element.click()：迷你条正是靠它触发 openFull()
     首屏的控制入口改为：点迷你条 → 全屏播放页。
     ============================================================ */
  .player-card {
    display: none;
  }

  /* ============================================================
     5. 首屏内容区（T2.1）
     ============================================================ */
  .mm-home {
    display: block;
    /* 给固定在底部的迷你条 + 底部 tab 让出空间。
       不直接改 .music-container 的 padding —— 它在 mobile.css 里带 !important
       （html.has-appbar 那条），跟它较劲不如把留白加在新元素上。 */
    padding-bottom: 84px;
  }

  .mm-section {
    margin: 0 0 22px;
  }
  .mm-sec-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin: 0 2px 10px;
  }
  .mm-sec-title {
    margin: 0;
    font-size: 17px;
    font-weight: 700;
    color: #a14563;
    letter-spacing: 0.01em;
  }
  .mm-sec-more {
    flex: 0 0 auto;
    min-height: 44px;
    padding: 0 6px;
    border: 0;
    background: none;
    color: #c4567a;
    font-size: 12.5px;
    font-family: inherit;
    cursor: pointer;
  }
  .mm-sec-more i {
    font-size: 10px;
  }

  /* ---- 5a. 横向卡片行 ---- */
  .mm-row {
    display: flex;
    gap: 12px;
    /* 横向滚动条隐藏（和 UI Kit 一样只靠手势），两端各留 2px 呼吸位 */
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding: 2px 2px 6px;
  }
  .mm-row::-webkit-scrollbar {
    display: none;
  }
  .mm-card {
    flex: 0 0 auto;
    width: 116px;
    padding: 0;
    border: 0;
    background: none;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    scroll-snap-align: start;
  }
  .mm-card-art {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 116px;
    height: 116px;
    border-radius: 14px;
    color: rgba(255, 255, 255, 0.9);
    font-size: 30px;
    box-shadow: 0 4px 14px rgba(203, 106, 128, 0.16);
  }
  .mm-card-name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: 7px;
    font-size: 12.5px;
    line-height: 1.3;
    color: #8a5567;
    word-break: break-word;
  }
  .mm-card:active .mm-card-art {
    transform: scale(0.96);
  }

  /* ---- 5b. 我的歌单：从抽屉搬来的真实节点 ---- */
  .mm-list-host .pl-views {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 12px;
  }
  .mm-list-host .pl-views .pl-view {
    flex: 0 0 auto;
    min-height: 44px;
    padding: 0 14px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12.5px;
  }
  /* 列表在内容页里不再跟着整页无限拉长 —— 128 首 × 71px = 9081px，
     整页会变成一条长龙，页脚等于消失。这里给它一个有界高度 + 自己的滚动。
     嵌套滚动是刻意接受的：手势落在列表上时由列表接管，落在别处就是整页滚。 */
  .mm-list-host .playlist-scroll {
    flex: none;
    max-height: 62vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding-right: 2px;
  }
  /* 搬出抽屉后 .pl-drawer 的后代选择器全部失效，这里把行版式补回来 */
  .mm-list-host .track-item {
    border-radius: 14px;
    margin-bottom: 8px;
  }

  /* ============================================================
     6. 页内迷你播放条（T2.1）
     ------------------------------------------------------------
     z-index 取 9970：在 .bot-tab(9998) 之下、正文之上；
     抽屉 mask(10005)/抽屉(10006)/二级页(9999) 打开时它自然被盖住。
     ============================================================ */
  .mm-mini {
    position: fixed;
    left: 10px;
    right: 10px;
    bottom: calc(var(--tab-h, 56px) + var(--sab, 0px) + 8px);
    z-index: 9970;
    display: flex;
    align-items: center;
    gap: 10px;
    height: 56px;
    padding: 0 10px;
    box-sizing: border-box;
    border: 1px solid #ffd6e0;
    border-radius: 14px;
    background: rgba(255, 250, 252, 0.97);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow: 0 6px 22px rgba(200, 120, 150, 0.24);
    cursor: pointer;
    overflow: hidden;
  }
  .mm-mini[hidden] {
    display: none;
  }
  /* 在 shell（index.html）里运行时，本页自己的 .bot-tab 被
     html.in-shell 隐藏（app.css:2514），迷你条要跟着落到底部，
     否则会在底栏原来的位置留一条空白。 */
  html.in-shell .mm-mini {
    bottom: calc(var(--sab, 0px) + 8px);
  }
  .mm-mini-cover {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    object-fit: cover;
    background: #ffe9ef;
  }
  .mm-mini-meta {
    flex: 1 1 auto;
    min-width: 0;
  }
  .mm-mini-title {
    font-size: 13px;
    font-weight: 600;
    color: #a14563;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .mm-mini-artist {
    font-size: 11px;
    color: #b5768c;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .mm-mini-btn {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    border: 0;
    border-radius: 12px;
    background: transparent;
    color: #e85d86;
    font-size: 1.05rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
  }
  .mm-mini-btn:active {
    background: #ffeaf1;
  }
  /* 进度条贴在迷你条底边，2px 高，纯指示不接收点击 */
  .mm-mini-bar {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: rgba(255, 182, 193, 0.35);
    pointer-events: none;
  }
  .mm-mini-bar-fill {
    height: 100%;
    width: 0;
    background: linear-gradient(90deg, #ff8fab, #e85d86);
  }

  /* ============================================================
     7. 全屏播放页（T2.4）
     ------------------------------------------------------------
     这块补的是 app.css 里一段**悬空选择器**本该做的事：那边 374-382 行挂着
       .detail-view .fs-modes .extra-actions / .mode-strip / .mixer /
       .mixer .volume-slider / .pl-drawer-trigger b
     一串选择器，注释写着「音量条给到 88px，歌单胶囊保持一行」，
     但 { … } 声明块缺失 —— CSS 解析器一路吃到下一个 {（.disc-zone），
     三条版式声明从来没生效过。所以 .fs-modes 在 390 宽下折成三行，
     「歌单 128 首」被压成「歌 128 / 单 首」。那段悬空列表已在 app.css 里删除。

     实测改前 390×844：.fs-cover 236 / .fs-lyrics 174 / .fs-controls 93 /
     .fs-modes 101（三行，底边 830，视口 844，几乎没有余量）。
     ============================================================ */

  /* ---- 7a. 顶栏：收起 / 提示 / 歌词 / 更多 / 歌单 排成一行 ---- */
  .fs-top {
    gap: 6px;
  }
  .fs-hint {
    flex: 1 1 auto;
    min-width: 0;
    text-align: center;
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .fs-icon {
    flex: 0 0 auto;
  }

  /* ---- 7b. 纵向节奏：省出余量，别让 .fs-modes 贴到视口底边 ---- */
  .fs-wrap {
    gap: 6px;
    padding: 6px 16px calc(10px + var(--sab, 0px));
  }

  /* ---- 7c. 封面：圆形黑胶，按屏宽自适应 ---- */
  .fs-cover {
    padding: 2px 0;
  }
  .fs-cover .vinyl {
    width: min(60vw, 236px);
    height: min(60vw, 236px);
  }
  .fs-cover .cover-inner {
    width: min(50vw, 196px);
    height: min(50vw, 196px);
  }

  /* ---- 7d. 曲目信息 ---- */
  .fs-meta #trackName {
    font-size: 19px;
    font-weight: 700;
    color: #a14563;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .fs-meta #trackArtist {
    margin-top: 2px;
    font-size: 13px;
    color: #b5768c;
  }

  /* ---- 7e. 歌词区：封面/歌词二选一，歌词模式独占剩余高度 ---- */
  .fs-lyrics {
    min-height: 0;
    flex: 1 1 auto;
    padding: 10px 12px;
  }
  /* 没有歌词时（js/music-mobile.js 挂的 mm-no-lyric）：
     歌词区收成一条居中的提示，省下的高度全部让给封面 ——
     否则就是 300 多像素的大色块中间飘着一行字。 */
  .fs-wrap.mm-no-lyric .fs-lyrics {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 58px;
    text-align: center;
  }
  .fs-wrap.mm-no-lyric .fs-cover .vinyl {
    width: min(68vw, 264px);
    height: min(68vw, 264px);
  }
  .fs-wrap.mm-no-lyric .fs-cover .cover-inner {
    width: min(58vw, 224px);
    height: min(58vw, 224px);
  }

  /* ---- 7f. 进度条：7px 视觉高度不变，加一个可见把手 + 44px 触控区 ---- */
  .fs-progress .progress-bar-bg {
    position: relative;
    overflow: visible;
  }
  .fs-progress .progress-fill {
    position: relative;
  }
  .fs-progress .progress-fill::after {
    content: '';
    position: absolute;
    right: -7px;
    top: 50%;
    width: 14px;
    height: 14px;
    margin-top: -7px;
    border-radius: 50%;
    background: #ff8fab;
    box-shadow: 0 1px 5px rgba(200, 90, 130, 0.42);
    pointer-events: none;
  }
  .fs-progress .progress-bar-bg::before {
    height: 44px;
    margin-top: -22px;
  }

  /* ---- 7g. 次级控制：三行收到一行 ---- */
  .fs-modes {
    padding-bottom: 0;
  }
  .fs-modes .extra-actions {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    width: 100%;
    margin: 0;
  }
  .fs-modes .extra-actions .mode-strip {
    flex: 0 0 auto;
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: 6px;
    margin: 0;
  }
  .fs-modes .extra-actions .mode-chip {
    flex: 0 0 auto;
    padding: 0 10px;
    white-space: nowrap;
  }
  /* 图标 + 数值就够；文字标签挤掉的是音量条的位置 */
  .fs-modes .extra-actions .mc-txt {
    display: none;
  }
  .fs-modes .extra-actions .mixer {
    flex: 0 1 auto;
    min-width: 0;
    margin-left: 0;
    padding: 0;
    gap: 4px;
  }
  /* 主页面里 .volume-slider 的宽度是 `.player-right …` 前缀的 !important，
     节点搬进 .fs-modes 后那几条自然不再命中，这里用普通声明就够。 */
  .fs-modes .extra-actions .mixer .volume-slider {
    flex: 0 1 auto;
    width: 64px;
    min-width: 40px;
  }
  .fs-modes .extra-actions .pl-drawer-trigger b {
    font-size: 11px;
    white-space: nowrap;
  }

  /* ============================================================
     8. 第三方音乐页（T3.1–T3.4）
     ------------------------------------------------------------
     实测 390×844：
       #nsPlatformChips  w=362  scrollWidth=662   → 可横滑，但没有任何"右边还有"的提示
       .filter-tabs      w=362  scrollWidth=6626  → 128 个分类 chip
       .unlock-sub       w=229  scrollWidth=232，overflow-x:hidden → 格式列表被截断
       .stats-bar        h=77，.stat-item 106×56，"作品总数""总时长"折成两行
     ============================================================ */

  /* ---- 8a. 横向 chip 条：右端渐隐，提示可横滑 ----
     只做右端。两端都做的话，未滚动时左边第一个 chip 会被吃掉一截。
     用 mask 而不是盖一层渐变 div：这些容器本身就是滚动容器，
     没有额外的定位父节点可以挂伪元素。 */
  .ns-chips,
  .filter-tabs {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent 100%);
    mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent 100%);
  }

  /* ---- 8b. 「本地音乐解锁」折叠头：标题与格式说明分两行 ----
     选择器必须写到 `.unlock-section > summary.unlock-summary` 这一级：
     music.css:2012 用的就是这个（0,2,1），比单类选择器更具体，
     光靠"本文件后加载"是压不过去的。 */
  .unlock-section > summary.unlock-summary {
    flex-wrap: wrap;
    row-gap: 2px;
    min-height: 56px;
    padding: 8px 10px;
    box-sizing: border-box;
  }
  .unlock-summary .unlock-title {
    flex: 0 0 auto;
    order: 1;
  }
  /* 折叠箭头必须留在第一行右侧：DOM 顺序是 标题 → 格式说明 → 箭头，
     而格式说明被撑成整行（flex-basis 100%），不重排的话箭头会被挤到第三行。 */
  .unlock-summary .unlock-caret {
    order: 2;
    margin-left: auto;
  }
  .unlock-summary .unlock-sub {
    order: 3;
    flex: 1 1 100%;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    font-size: 11px;
    line-height: 1.35;
  }

  /* ---- 8c. 统计栏：三个指标各自不折行 ---- */
  .stats-bar .stat-item {
    white-space: nowrap;
    font-size: 11px;
    gap: 3px;
    padding: 8px 4px;
  }
  .stats-bar .stat-item > i {
    font-size: 12px;
  }
  .stats-bar .stat-number {
    font-size: 15px;
  }

  /* ---- 8d. 子页签（在线搜歌 / 作品卡片）视觉降一档 ----
     页面里已经有一层 .page-tabs（音乐盒 / 第三方音乐），再叠一层同尺寸的
     分段控件会让人分不清层级。这里把子页签做轻：去掉实心底，只留文字与下划线。
     选择器必须带 html.has-appbar —— app.css:1427-1445 那一组就是这个前缀
     （0,2,1），比单类选择器更具体，靠"后加载"压不过去。 */
  html.has-appbar .ns-subtabs {
    gap: 4px;
    padding: 0 2px;
    margin-bottom: 12px;
    border: 0;
    border-bottom: 1px solid #ffe2ec;
    border-radius: 0;
    background: none;
  }
  html.has-appbar .ns-subtab {
    flex: 1 1 0;
    min-width: 0;
    min-height: 44px;
    padding: 0 8px;
    border-radius: 0;
    background: none;
    color: #b5768c;
    font-size: 13.5px;
    position: relative;
  }
  html.has-appbar .ns-subtab.active {
    background: none;
    color: #c4567a;
    font-weight: 700;
    box-shadow: none;
  }
  .ns-subtab.active::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 6px;
    width: 28px;
    height: 3px;
    margin-left: -14px;
    border-radius: 2px;
    background: linear-gradient(90deg, #ff8fab, #e85d86);
  }

  /* ============================================================
     9. 作品卡片（T3.3）
     ------------------------------------------------------------
     实测 .work-card 176×270（阶段一已恢复两列）：
       .card-cover 174×174（自带渐变底 + 唱片图标，不是坏图）
       .card-body  174×94  ← 偏高，收紧
     ============================================================ */
  .work-card .card-body {
    padding: 8px 9px 9px;
  }
  .work-card .card-title {
    font-size: 13px;
    line-height: 1.3;
    margin-bottom: 2px;
  }
  .work-card .card-artist {
    font-size: 11px;
    line-height: 1.3;
  }
  /* 卡片在等数据/等图时不至于是"一块纯色"：给封面一个不刺眼的骨架底 */
  .work-card .card-cover {
    background-color: #fff2f7;
  }

  /* ============================================================
     10. 歌单行（T4.2 / T4.3）
     ------------------------------------------------------------
     阶段二把 #plViews 与 .playlist-scroll 搬进了内容页首屏，所以：
       · 移动端抽屉已经空掉（658px 里只剩头部与提示）→ 整块退场
       · 列表行不再受 .pl-drawer 后代选择器影响，可以在内容页里重做
     实测行高 67px（pill 圆角、无封面缩略图）。
     ============================================================ */

  /* 移动端不再需要抽屉：歌单就在首屏，「上传」入口也搬到了区块标题行。
     全屏播放页里那颗「歌单」chip 改由 js/music-mobile.js 拦下来变成
     「收起播放页 · 回到歌单」，不再打开这个抽屉。 */
  .pl-drawer,
  .pl-drawer-mask {
    display: none;
  }

  .mm-list-host .track-item {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 64px;
    padding: 8px 10px;
    margin-bottom: 7px;
    border: 1px solid #ffe6ee;
    border-radius: 14px;
    background: rgba(255, 250, 252, 0.94);
    box-sizing: border-box;
  }
  /* 行首那颗音符图标撑成 40px 圆角方块，当作没有真封面时的封面位。
     注意：保持 .track-info 为块级 + 图标 inline-flex —— 行名是裸文本节点，
     一旦把 .track-info 变成 flex，文本会变成匿名 flex 项，ellipsis 就失效了。 */
  .mm-list-host .track-info {
    flex: 1 1 auto;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 13.5px;
    line-height: 1.3;
    color: #8a5567;
  }
  .mm-list-host .track-info > i {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin-right: 10px;
    vertical-align: middle;
    border-radius: 10px;
    background: linear-gradient(140deg, #ffd9e6, #ffb0ca);
    color: #fff;
    font-size: 15px;
  }
  .mm-list-host .track-duration {
    flex: 0 0 auto;
    font-size: 11.5px;
    color: #b5768c;
    font-variant-numeric: tabular-nums;
  }
  .mm-list-host .track-fav,
  .mm-list-host .track-del {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: #d8a2b6;
    font-size: 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .mm-list-host .track-fav.on {
    color: #e85d86;
  }
  .mm-list-host .track-del {
    color: #e0b6c4;
    font-size: 12px;
  }

  /* ---- T4.3 当前播放：左侧粉色条 + 底色 + 文字加粗 ---- */
  .mm-list-host .track-item.active {
    background: linear-gradient(100deg, #fff0f5, #ffe6ee);
    border-color: #ffc2d4;
  }
  .mm-list-host .track-item.active .track-info {
    color: #a14563;
    font-weight: 700;
  }
  .mm-list-host .track-item.active .track-info > i {
    background: linear-gradient(140deg, #ff8fab, #e85d86);
  }
  .mm-list-host .track-item.active::before {
    content: '';
    flex: 0 0 auto;
    width: 3px;
    height: 28px;
    margin-right: -4px;
    border-radius: 2px;
    background: linear-gradient(180deg, #ff8fab, #e85d86);
  }

  /* ============================================================
     11. 二级页集合（阶段五）
     ------------------------------------------------------------
     全部由 js/music-pages.js 经 AppShell.openDetail() 开层，
     所以这里的 .detail-view 就是它们的容器。
     行版式尽量复用 app.css 已有的 .mp-item / .mp-row，只补缺失的部分。
     ============================================================ */

  /* ---- 11a. 区块标题行右侧的多个动作（设置 / 上传） ---- */
  .mm-sec-actions {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 2px;
  }

  /* ---- 11b. 列表行的渐变封面位（替代没有真封面的 img） ---- */
  .mp-art {
    flex: 0 0 auto;
    width: 48px;
    height: 48px;
    border-radius: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 17px;
    box-shadow: 0 3px 10px rgba(203, 106, 128, 0.18);
  }
  .mp-art-round {
    border-radius: 50%;
    font-size: 20px;
    font-weight: 700;
  }
  .mp-arrow {
    flex: 0 0 auto;
    color: #d3a3b4;
    font-size: 13px;
    padding: 0 4px;
  }
  .detail-view .mp-list {
    padding: 2px 0 12px;
  }
  .detail-view .mp-item {
    min-height: 64px;
    border-radius: 14px;
    margin-bottom: 7px;
    padding: 8px 10px;
    box-sizing: border-box;
    background: rgba(255, 250, 252, 0.94);
    border: 1px solid #ffe6ee;
  }

  /* ---- 11c. 艺人详情：英雄区 ---- */
  .mp-artist {
    padding-bottom: 12px;
  }
  .mp-hero {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 18px 16px;
    margin-bottom: 14px;
    border-radius: 20px;
    box-shadow: 0 6px 22px rgba(203, 106, 128, 0.22);
  }
  .mp-hero-art {
    flex: 0 0 auto;
    width: 88px;
    height: 88px;
    border-radius: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 34px;
    color: rgba(255, 255, 255, 0.95);
    background: rgba(255, 255, 255, 0.26);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5);
  }
  .mp-hero-meta {
    flex: 1 1 auto;
    min-width: 0;
  }
  .mp-hero-name {
    margin: 0;
    font-size: 20px;
    font-weight: 700;
    color: #7a3f52;
    line-height: 1.25;
    word-break: break-word;
  }
  .mp-hero-sub {
    margin: 4px 0 10px;
    font-size: 12px;
    color: rgba(122, 63, 82, 0.72);
  }
  .mp-hero-play {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 44px;
    padding: 0 18px;
    border: 0;
    border-radius: 999px;
    background: #fff;
    color: #d9547d;
    font-family: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 3px 12px rgba(160, 70, 100, 0.2);
  }
  .mp-hero-play:active {
    transform: scale(0.96);
  }

  /* ---- 11d. 设置页 ---- */
  .mp-settings {
    padding-bottom: 16px;
  }
  .mp-group {
    margin-bottom: 18px;
  }
  .mp-group-title {
    margin: 0 0 8px 4px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: #c4567a;
  }
  .detail-view .mp-settings .mp-row {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 52px;
    padding: 6px 12px;
    margin-bottom: 6px;
    border-radius: 14px;
    background: rgba(255, 250, 252, 0.94);
    border: 1px solid #ffe6ee;
    box-sizing: border-box;
  }
  .detail-view .mp-settings .mp-row-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 14px;
    color: #7a3f52;
  }
  .detail-view .mp-settings .mp-row-note {
    flex: 0 0 auto;
    font-size: 11px;
    color: #b5768c;
  }
  .detail-view .mp-settings .mp-row-btn {
    cursor: pointer;
    position: relative;
    padding-right: 34px;
  }
  .detail-view .mp-settings .mp-row-btn::after {
    content: '\f054';
    font-family: 'Font Awesome 6 Free';
    font-weight: 900;
    position: absolute;
    right: 14px;
    font-size: 11px;
    color: #d3a3b4;
  }
  .detail-view .mp-settings .mp-row-btn.on {
    background: linear-gradient(100deg, #fff0f5, #ffe6ee);
    border-color: #ffc2d4;
  }
  .detail-view .mp-settings .mp-row-btn.on .mp-row-name {
    color: #a14563;
    font-weight: 700;
  }
  .detail-view .mp-settings .mp-row-btn.danger .mp-row-name {
    color: #c4567a;
  }
  .mp-slider {
    flex: 0 0 128px;
    accent-color: #e85d86;
  }
  .mp-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 2px 4px 6px;
  }
  .mp-chip {
    min-width: 56px;
    min-height: 44px;
    padding: 0 14px;
    border: 1px solid #ffe2ec;
    border-radius: 999px;
    background: rgba(255, 250, 252, 0.94);
    color: #b1627d;
    font-family: inherit;
    font-size: 13px;
    cursor: pointer;
  }
  .mp-chip.on {
    background: linear-gradient(145deg, #f4a9c1, #e06a8f);
    border-color: transparent;
    color: #fff;
    font-weight: 700;
  }

  /* ---- 11e. 分享卡片 ---- */
  .mp-share {
    padding: 4px 0 16px;
    text-align: center;
  }
  .mp-share-canvas {
    width: 100%;
    max-width: 340px;
    height: auto;
    border-radius: 18px;
    box-shadow: 0 8px 26px rgba(203, 106, 128, 0.26);
  }
  .mp-share-bar {
    display: flex;
    gap: 10px;
    justify-content: center;
    margin-top: 16px;
  }
  .mp-share-btn {
    flex: 0 1 auto;
    min-height: 48px;
    padding: 0 20px;
    border: 0;
    border-radius: 999px;
    background: linear-gradient(145deg, #f4a9c1, #e06a8f);
    color: #fff;
    font-family: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(203, 106, 128, 0.28);
  }
  .mp-share-btn.ghost {
    background: rgba(255, 250, 252, 0.94);
    color: #c4567a;
    border: 1px solid #ffc2d4;
    box-shadow: none;
  }
  .mp-share-btn:active {
    transform: scale(0.96);
  }
  .mp-share-tip {
    margin: 12px 0 0;
    font-size: 11.5px;
    color: #b5768c;
  }

  /* ---- 11f. 歌词页：把搬进来的歌词面板铺满这一层 ---- */
  .detail-lyric {
    display: flex;
    flex-direction: column;
    min-height: 100%;
    padding: 4px 0 12px;
    box-sizing: border-box;
  }
  .detail-lyric .lyric-panel {
    flex: 1 1 auto;
    min-height: 60vh;
    height: auto;
    max-height: none;
    margin: 0;
    background: rgba(255, 250, 252, 0.72);
    border-radius: 20px;
  }
}

/* ============================================================
   已知未解决 / 后续
   ------------------------------------------------------------
   · 阶段一遗留的「320×568 与 375×667 首屏放不下播放键」在阶段二自动消失 ——
     播放器已经不在内容页首屏了，控制入口是迷你条 + 全屏播放页。
   · .mode-chip 的 min-height 与 music.css 里三条 padding/字号 !important
     并存（1692/1762/1771 等）。本文件改的是高度不是内边距，暂时不冲突；
     但那是三处历史补丁叠出来的，清理它属于另一件事。
   · 首屏「官方推荐」横向卡片用渐变色块 + 音符图标代替真实封面 ——
     实测 data/playlist.json 里官方曲库只有 name/artist/file，**没有封面字段**，
     所以就算改 music-bundle.js 也拿不到官方封面。真封面只存在于用户自己
     通过「在线搜歌 / 上传」加进来的歌（localStorage sakuraUserPlaylist 的
     cover 字段）。要做「有封面就显示、没有就用渐变」需要让 bundle 暴露
     已加载的 playlist 数组，列入后续。
   · 「最近播放」横条已在阶段六整体移除（用户决定不要这个功能）：
     music-plus.js 的 buildRecentStrip() / record() / REC_KEY 与 app.css 的
     .mp-strip* 全部删除，本文件也不再搬运它。
   · 全屏播放页的歌词空状态（无歌词时）仍是一个大色块，只显示一句
     「正在播放: …」。文案来自 music-bundle.js 的 LyricHelper，要做得更好
     需要动那个打包产物。
   ============================================================ */
