/**
 * SMusic - 浅色友好风 · v5 (底部播放器重构)
 *
 * 播放器改为水平条布局(Spotify 风格):
 *   .app-player-bar (固定底栏)
 *     .m-music-play-wrap
 *       .player-left   (封面 + 曲目信息)
 *       .player-center (控件 + 进度条)
 *       .player-right  (音量)
 *
 * .m-music-list-wrap 不再嵌入播放器容器,独立放在 .app-list-area
 */

:root {
    /* v27+:浅色主题 color-scheme 声明 */
    color-scheme: light;

    --bg: #f7f7fa;
    --bg-elevated: #ffffff;
    --bg-hover: #f0f0f4;
    --bg-active: #ebebef;
    --border: #ececf0;
    --border-strong: #d8d8de;
    --text: #1c1c20;
    --text-soft: #3f3f46;
    --text-mute: #6b6b75;
    --accent: #6d28d9;
    --accent-soft: rgba(109, 40, 217, 0.08);
    --accent-line: rgba(109, 40, 217, 0.28);
    --radius: 10px;
    --radius-sm: 6px;
    /* v42:与 app.css --font 对齐,补 system-ui(Win11 / 现代 Android)与
       HarmonyOS Sans SC(华为设备)。app.css 后置加载会覆盖此声明,
       此处补全仅为防御:任何重新排序或单独引用 smusic.css 的场景都安全 */
    --font: system-ui, -apple-system, BlinkMacSystemFont, "Inter", "PingFang SC", "HarmonyOS Sans SC", "Microsoft YaHei", "微软雅黑", sans-serif;
    --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

/* ============== reset ============== */

html, body, h1, h2, h3, h4, h5, h6, div, dl, dt, dd, ul, ol, li,
p, blockquote, pre, hr, figure, table, caption, th, td, form, fieldset,
legend, input, button, textarea, menu {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-size: inherit;
    line-height: inherit;
    -webkit-tap-highlight-color: transparent;
}

/* box-sizing reset 已在 app.css :root 集中定义,smusic.css 此处历史残留 v61+ 删 */

/* ============== 工具类(SMusic 内部用的) ==============
   v34 P0 静态清理:grep 全项目只有 .f-usn 1 个被引用(index.html:142 .app-player-bar),
   其余 15 个 .f-cb/ib/dn/db/fl/fr/fwn/fwb/tal/tac/tar/oh/tdn/vam/wsn/toe/cp 全死代码。
   .f-toe 虽在 smusic.min.js 内部使用,但 min.js 是第三方库私有输出,我们的 CSS
   不需要再覆盖(否则会与库内 class 冲突)。 */
.f-usn {
    -webkit-user-select: none;
    user-select: none;
}

/* ============== 滚动条 ============== */

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--border-strong);
    border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover { background: var(--text-mute); }

/* v51 P0 回归修复:.volume-bar 是 SMusic 旧版库内部查询的元素
   (smusic.min.js setVolume() 在 initPlay 阶段会访问其 .style)。
   本项目用 .volume-current 显示音量,所以强制 display:none 让该元素永远无视觉效果。
   v34 静态清理误删了 HTML span,导致 SMusic initPlay 时 setVolume 抛
   "Cannot read properties of null (reading 'style')" — boot 失败。
   保留 span + 隐藏,才是兼容且无副作用的方案。 */
.u-volume .volume-process .volume-bar {
    display: none;
}

/* v22 修复:Chrome 2024+ 实测 `* { scrollbar-width: thin }` 会强制覆盖
   ::-webkit-scrollbar 的 width 设置(优先用 scrollbar-width 而非 webkit 规则),
   导致 .app-list-area .m-music-list-wrap 的 26px 滚动条失效,只渲染 10px。
   修复:把 * 限定为 body/html + 显式排除 .app-list-area 的子元素,
   让 .m-music-list-wrap 走 app.css 里的 ::-webkit-scrollbar (26px) 规则。 */
body, html {
    scrollbar-width: thin;
    scrollbar-color: var(--border-strong) transparent;
}

/* 主列表容器走 .app-list-area .m-music-list-wrap::webkit-scrollbar 自定义粗条 */

/* ============== 全局 ============== */

html, body {
    height: 100%;
    overflow: hidden;
    font-family: var(--font);
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: "cv11", "ss01";
}

/* ============== 底部播放器主区(水平 3 段) ============== */

.app-player-bar .m-music-play-wrap {
    display: grid;
    /* v30:3 mode + volume + fullscreen 共 5 项,总宽 ~206px。
       旧 180px 装不下会溢出,改成 minmax(200px, 22%) 自适应内容;
       第1列 28%→22% 给中间让点呼吸空间(center 只剩 prev/play/next)。 */
    grid-template-columns: minmax(180px, 22%) 1fr minmax(200px, 220px);
    gap: 24px;
    align-items: center;
    height: 100%;
    padding: 0 20px;
}

/* ============== 左:封面 + 曲目信息 ============== */

.player-left {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
    overflow: hidden;
}

.u-cover {
    width: 64px;
    height: 64px;
    background: var(--bg-active);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    flex-shrink: 0;
    position: relative;
    overflow: hidden;
}

.u-cover img {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: var(--radius-sm);
    object-fit: cover;
}

.u-cover.play {
    animation: spin 16s linear infinite;
}

.u-cover.paused {
    animation-play-state: paused;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

.player-text {
    min-width: 0;
    flex: 1;
}

.u-music-title {
    font-weight: var(--fw-medium);
    /* v47+:行高 --lh-normal (1.4) → --lh-snug (1.25) — 双行总高 38.4px → 31.25px,
       ≤320 row 36px 不再溢出,所有断点标题更精致。gap 2 → 3 整数化,
       强/弱两档间留呼吸。
       v48+:gap 3 → 5 — 中文字符行间需要更多呼吸(YaHei 字间距宽),
       row 1 双行总高 31.25 → 35px,row 1 44px 余 9px 安全。 */
    line-height: var(--lh-snug);
    display: flex;
    flex-direction: column;
    gap: 5px;
    margin: 0;
    overflow: hidden;
}

.u-music-title strong {
    font-size: var(--fs-lg);
    color: var(--text);
    /* v47+:字重 700 → 600 — 现代 UI 标准 (Apple Music / Spotify 风)。
       700 + 父级 500 叠加 <strong> 默认 bolder 关键词,YaHei 上偏黑体感。
       降到 600 与 .app-brand-name 一致,层级 brand 600 ≈ strong 600 > body 500。 */
    font-weight: var(--fw-semibold);
    /* v47+:字距 -0.01em,大字号收一档让标题更"实"。 */
    letter-spacing: var(--tracking-title);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.u-music-title small {
    font-size: var(--fs-base);
    /* v47+:颜色 text-soft → text-mute — 让标题与艺人名形成主次对比。 */
    color: var(--text-mute);
    /* v47+:字重 500 → 400 — 与列表项 strong 一致,层级 small 400 = list 400 < body 500。 */
    font-weight: var(--fw-regular);
    /* v47+:字距 0.02em,辅助文本略宽,中文 0.24px 增距几乎不可见,英文略打开。 */
    letter-spacing: var(--tracking-tag);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.u-music-title small::before {
    content: "";
    margin: 0;
}

/* ============== 中:控件 + 进度条 ============== */

/* v37: 单行式 (≥1025) .player-center 视觉对齐 —
   column flex + justify-content: space-between + height: 100% 让
   .m-play-controls 贴 col2 顶、.player-progress 贴 col2 底,
   与 col1 (.player-left cover) 视觉重心对齐。
   原 gap:8px 让两子元素被"夹在中间",与左右两列 13-27px 错位;
   删 gap 让 justify-content 接管纵向分布。
   双行式 ≤720 / 700-1280w 501-700h / ≤500h 横屏 各自 app.css @media
   块 specificity (0,0,2,1) 覆盖此处 (0,0,1,0),需在 app.css ≤720
   块显式重置 justify-content:flex-start + height:auto。 */
.player-center {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    max-width: 640px;
    margin: 0 auto;
    width: 100%;
    min-width: 0;
    height: 100%;
}

/* ============== 播放控件 ==============
   点击区放大 + 圆角放大,适配"友好大字"风格 */

.m-play-controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
}

.m-play-controls a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
}

.u-play-btn {
    width: 36px;
    height: 36px;
    border: 1px solid var(--border);
    border-radius: 50%;
    color: var(--text-soft);
    cursor: pointer;
    background: var(--bg-elevated);
    /* P1 性能修复:精确过渡列表(hover/active 改 color/border-color/background/transform/box-shadow),
       transition: all 让浏览器为每个属性建 watcher,改为精确列表省初始化开销。 */
    transition:
        color var(--t-fast) var(--ease),
        border-color var(--t-fast) var(--ease),
        background var(--t-fast) var(--ease),
        transform var(--t-fast) var(--ease),
        box-shadow var(--t-fast) var(--ease);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}

.u-play-btn svg {
    width: 15px;
    height: 15px;
    fill: currentColor;
    color: inherit;
}

.u-play-btn:hover {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}

.u-play-btn:active {
    background: var(--bg-active);
    transform: scale(0.94);
}

.u-play-btn.ctrl-play {
    width: 48px;
    height: 48px;
    background: var(--accent);
    color: #ffffff;
    border-color: var(--accent);
    box-shadow: 0 6px 14px -3px rgba(109, 40, 217, 0.45);
}

.u-play-btn.ctrl-play:hover {
    /* v51 P1-10:硬编码 #7c3aed → var(--accent-hover),6 主题已定义 --accent-hover
       token(theme.css),与主 accent 区分 hover 态色,保证主题切换时 hover 跟着变。 */
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: #ffffff;
    /* v47+:scale 1.04 → 1.05,Material 涟漪感的微调。 */
    transform: scale(1.05);
}

.u-play-btn.ctrl-play:active {
    transform: scale(0.96);
}

.u-play-btn.ctrl-play svg {
    width: 19px;
    height: 19px;
}

.u-play-btn.mode {
    width: 34px !important;
    height: 34px !important;
    color: var(--text-mute);
    border-color: var(--border);
}

.u-play-btn.mode svg {
    width: 14px;
    height: 14px;
}

.u-play-btn.mode.current {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
    /* v47+:外发光 — outline ring 之外再叠 6px 柔光,
       与 ctrl-play 填充风格拉开层次(34px outline + glow < 48px filled accent),
       但视觉权重 > 未激活模式(opacity 0.55)。 */
    box-shadow:
        0 0 0 1px var(--accent-line),
        0 2px 6px rgba(109, 40, 217, 0.18);
}

/* 未激活的 mode 按钮:轻微弱化(不透明度 0.55 + 内边距略小),
   让"当前激活模式"更突出,节省视觉空间。
   hover 时恢复正常 — 点击区不变,仅做视觉降权。 */
.u-play-btn.mode:not(.current) {
    opacity: 0.55;
    transition: opacity var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
                border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}

.u-play-btn.mode:not(.current):hover {
    opacity: 1;
}

/* ============== 进度条 + 时间 ============== */

.player-progress {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 12px;
    align-items: center;
    width: 100%;
    min-width: 0;
}

.u-time {
    font-size: var(--fs-lg);
    /* v47+:颜色 text-soft → text-mute — 与 small 一致,降权重让标题/艺人突出。 */
    color: var(--text-mute);
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    /* v47:60px → var(--u-time-min-w) — 与 app.css 8 处统一 token 化。 */
    min-width: var(--u-time-min-w, 60px);
    text-align: right;
    /* v47+:字重 500 → 400 — 与 small/list 统一,层级 u-time 400 < body 500。 */
    font-weight: var(--fw-regular);
    /* v47+:字距 0.04em — mono 数字略宽,5 字符 "00:00" 视觉更舒展。 */
    letter-spacing: var(--tracking-en);
}

.u-process {
    flex: 1;
    min-width: 0;
    height: 4px;
    position: relative;
    background: var(--border-strong);
    border-radius: 2px;
    cursor: pointer;
    /* v24: 让进度条容器有 8px 高度触摸命中区(配合 .u-process::before 外扩) */
    -webkit-tap-highlight-color: transparent;
}

.u-process .buffer-process,
.u-process .current-process {
    display: block;
    width: 0;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    background: var(--accent);
    border-radius: 2px;
    z-index: var(--z-track);
}

.u-process .buffer-process {
    z-index: 0;
    background: var(--border-strong);
    /* v47+:0.55 → 0.4 — buffer 进度更弱,不与 current 进度竞争视觉,
       Spotify 模式:buffer 是"远景",current 是"当下"。 */
    opacity: 0.4;
    /* v61+:0.2s → var(--t-base) — 与 app.css 其他 32 处过渡 token 化对齐 */
    transition: opacity var(--t-base);
}

/* v24: hover 时 buffer 进度更明显,告诉用户还有多少已缓冲 */
.u-process:hover .buffer-process {
    /* v47+:0.85 → 0.95 — hover 时几乎完全显示,idle 弱化形成对比。 */
    opacity: 0.95;
}

/* ============== 右:音量 ============== */

.player-right {
    display: flex;
    justify-content: flex-end;
    align-items: center;
}

.u-volume {
    position: relative;
    display: flex;
    align-items: center;
}

/* 桌面端垂直音量条:从 4px 加宽到 8px(用户反馈"太细"),圆角 2px 等比同步 3px。
   高 80px / 宽 8px = 10:1 长宽比,视觉仍细长优雅但不像素条。
   .volume-event 触摸命中区 24→32px 保持居中并匹配新宽度,
   hover 命中范围仍 ≥ 内容,点拖都跟手。 */
.u-volume .volume-process {
    width: 8px;
    height: 80px;
    background: var(--border-strong);
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
    border-radius: 3px;
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--t-fast), visibility var(--t-fast);
}

.u-volume:hover .volume-process,
.u-volume .volume-process.show {
    opacity: 1;
    visibility: visible;
}

.u-volume .volume-process .volume-current,
.u-volume .volume-process .volume-event {
    display: inline-block;
    width: 100%;
    height: 50%;
    background: var(--text);
    position: absolute;
    left: 0;
    bottom: 0;
    border-radius: 2px;
    transition: height var(--t-fast) linear;
}

.u-volume .volume-process .volume-event {
    width: 32px;
    left: 50%;
    transform: translateX(-50%);
    background: none;
    height: 100%;
    z-index: var(--z-track);
}

.u-volume .volume-control {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 50%;
    cursor: pointer;
    color: var(--text-soft);
    /* P1 性能修复:精确过渡列表(hover/active 改 color/border-color/background/transform) */
    transition:
        color var(--t-fast) var(--ease),
        border-color var(--t-fast) var(--ease),
        background var(--t-fast) var(--ease),
        transform var(--t-fast) var(--ease),
        box-shadow var(--t-fast) var(--ease);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}

.u-volume .volume-control:hover {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}

.u-volume .volume-control:active {
    transform: scale(0.94);
}

.u-volume .volume-control.muted {
    color: var(--text-mute);
}

.u-volume .volume-control svg {
    width: 16px;
    height: 16px;
    fill: currentColor;
}

/* ============== 列表区(独立容器) ============== */

.app-list-area .m-music-list-wrap {
    background: var(--bg-elevated);
}

.m-music-list-wrap ul {
    list-style: none;
}

.m-music-list-wrap li {
    /* v50+:display: grid → flex,彻底消除"刷新时列表字体闪动"。
       原 grid 布局下,SMusic 的 createListDom (smusic.min.js:37) 写入的
       "<strong>[1] 将军</strong> - <small>周杰伦</small>" 中,strong 与 small
       之间的匿名 " - " 文本节点被 grid-auto-flow 推到 row 1 col 3(占住
       small 位置),把 small 挤到 row 2,li 从 44px 撑高到 78px。
       enhance.js:967-976 的 decorateListItems 后才 removeChild 删掉文本节点,
       刷新那 ~150ms 用户能看到 li 从 78 塌到 44,文字视觉上像"突然变大"。
       flex 布局下匿名文本节点作为 inline flex item 流式参与,不创建第二行,
       li 一开始就是 44px,无需等 JS 装饰。
       视觉差异:flex 与 grid 在这个 3 段布局 (idx | title | artist) 下完全等效
       (gap 18 + align-items center + min-width:0 ellipsis),无回归风险。 */
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 12px 24px;
    cursor: pointer;
    color: var(--text);
    /* v44+ strong 14/small 12 阶梯在子元素上各自声明,li 默认继承 12px(body 字体) */
    font-size: var(--fs-base);
    border-left: 3px solid transparent;
    /* v37:P3-2 0.12s → var(--t-fast),与 line 248/326/466 的 token 化对齐 */
    transition:
        background var(--t-fast) var(--ease),
        color var(--t-fast) var(--ease),
        border-color var(--t-fast) var(--ease);
    /* v37:line-height 1.4 → var(--lh-normal) token 化 */
    line-height: var(--lh-normal);
    /* v24: 让 hover/active 反馈更平滑,与整体 cubic-bezier 一致 */
}

.m-music-list-wrap li:nth-child(odd) {
    background: rgba(0, 0, 0, 0.015);
}

.m-music-list-wrap li strong {
    /* v50+:grid-column: 2 → flex: 1 1 0 — 配合 li 改 display:flex。
       flex-grow:1 + flex-shrink:1 + flex-basis:0 让 strong 平分 .li-index 与
       .small 之间的剩余空间,与原 grid col 2 (minmax(0,1fr)) 等效。

       v56+:flex: 1 1 0 → flex: 0 1 auto。原先让 strong 撑满整个剩余空间的
       设计在短标题(如"彩虹" 2字)时会留 ~700px 的巨大空白,艺人被推到
       列表右边缘,视觉上"标题孤立"且无法体现"标题-艺人"的归属关系。
       新方案:strong 按内容宽度伸缩(可缩到 0 + ellipsis),配合 small 改
       flex: 0 0 auto(内容宽度,不可缩),剩余空间自然落到 li 右侧
       (small 之后),艺人紧贴标题右侧:
         - 短标题:"彩虹 — 周杰伦" — 标题与艺人视觉成组
         - 长标题:"蒲公英的约定... — 周杰伦" — 标题 ellipsis,艺人紧跟
       与 Spotify / Apple Music / YouTube Music 等主流播放器一致。 */
    flex: 0 1 auto;
    /* min-width: 0 让 ellipsis 真正生效,允许 strong 收缩到 ellipsis */
    min-width: 0;
    /* v56+:max-width: 100% 防止 flex shrink 计算极端情况下 strong 越出 li
       边界(理论上 flex: 0 1 auto + min-width: 0 已经够,这里是双保险) */
    max-width: 100%;
    /* v44+:标题 12→14(原 fs-base → fs-lg)— 修复"标题 < 艺人"反序层级。
       原 base 12px/artist 14px 是历史遗留;≤720/≤480 早已 override 到 14/12 正确层级,
       但 base 与 ≥1440 没有 override,导致 ≥1440 屏幕列表/播放器标题都比艺人小。
       现在 base 14/12 统一,各断点 override 只剩 max-width 与 grid 差异。 */
    font-size: var(--fs-lg);
    /* v37: 删中间死代码 font-weight: 400 — 立即被下方 v24 注释的 font-weight: 500 覆盖。
       P2 #3 死列清理,与 line 442/v27 静态清理统一。 */
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* v41+:字重 500→400,与 body 500 区分开 — "列表标题不需要黑体"。
       让标题比正文更"轻",只靠字号建立层级,减少 YaHei 在 Windows 下的黑体感。
       v24 注释("从 400 微调到 500 让标题更易读")的初衷已被字号(14px vs body 12px)
       满足,不再依赖字重补偿。 */
    font-weight: var(--fw-regular);
}

.m-music-list-wrap li small {
    /* v50+:grid-column: 3 → flex: 0 1 auto — 配合 li 改 display:flex。
       flex-shrink:1 让 small 在窗口窄到极限时可被压缩(原 grid auto 也会
       自动收缩),但有 max-width:200px 兜底防止太短艺人名被压扁。

       v56+:flex 保持 0 0 auto(取消原 v50 的 shrink)。配合 strong 改 flex:
       0 1 auto 后,strong 按内容伸缩而 small 始终占自身内容宽度,
       剩余空间自然落到 li 右侧(small 之后),艺人紧贴标题。
         - 短标题:"彩虹 — 周杰伦" — 标题与艺人视觉成组
         - 长标题:"蒲公英的约定... — 周杰伦" — 标题 ellipsis,艺人紧跟
       标题过长时 strong 因 min-width: 0 + ellipsis 收缩,布局仍受控。 */
    flex: 0 0 auto;
    color: var(--text-soft);
    /* v44+:艺人 14→12(原 fs-lg → fs-base) — 配合 strong 上调到 fs-lg,
       恢复"标题 > 艺人"的标准层级。 */
    font-size: var(--fs-base);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 200px;
}

.m-music-list-wrap li .li-index {
    /* v50+:grid-column: 1 → flex: 0 0 52px — 配合 li 改 display:flex。
       flex-basis:52px 等同于原 grid col 1 (52px) 的固定宽度。 */
    flex: 0 0 52px;
    font-size: var(--fs-lg);
    color: var(--text-mute);
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    text-align: right;
    /* v24: li-index 与 strong 间留点呼吸空间,视觉对齐 */
    padding-right: 2px;
}

.m-music-list-wrap li .li-no-num {
    /* v57+:flex: 0 0 24px → 52px,visibility:hidden 占位 — 对齐 .li-index 阶梯,
       修复"收藏/最近 strong 起始 X 比普通列表左偏 70px"问题(用户反馈"缩进存在问题")。
       原 v50 24px + display:none 设计是"让 strong 自然贴左"的历史选择,
       但与用户期望"参考其他列表缩进"冲突。
       现在 .li-no-num 占位 52px 等效 .li-index,strong 起始 X = 24+52+18 = 94px,
       与普通列表(24 padding + 52 li-index + 18 gap = 94px)完全一致。
       visibility:hidden 让占位占据 flex 空间但不渲染内容(无文本),
       比 display:none 少一次 reflow。≤720 阶梯改 44px(见下方 media query)。 */
    flex: 0 0 52px;
    width: 52px;
    visibility: hidden;
}

/* 虚拟分类(收藏 / 最近播放):无序号列,但 .li-no-num 仍作波形锚点保留
   (enhance.js renderPlayingBars 用它做替换位置;不删除 DOM)。

   v41+:修复切分类瞬间虚拟列表 li 高度膨胀(46px → 64px)的视觉抖动。
   原 grid 实现 .li-no-num 抢 strong 位置导致 row 2 出现。

   v50+:改用 flex 后,匿名 " - " 文本节点不再创建第二行。

   v57+:display:none → visibility:hidden — 配合上方 .li-no-num 改为 52px 占位策略。
       原 display:none 让 strong 贴左(差 70px);现在 visibility:hidden 保留 52px 占位,
       strong 起始 X = 94px = 普通列表,达成"参考其他列表缩进"的目标。
       不删除节点 + 隐藏渲染 → renderPlayingBars 仍能正确找到 .li-no-num 做替换位置。 */
.m-music-list-wrap.is-virtual-list li .li-no-num {
    visibility: hidden;
}
/* v55+:首帧防缩进闪烁 — 刷新收藏/最近播放时,head 预判脚本(见 index.html:108)
   在 <html> 上打的 data-storage-note-active 标记已经代表"当前是虚拟分类"。
   enhance.js boot() 阶段 decorateListItems() 创建 .li-no-num 时,JS 还没来得及
   给 listWrap 加 .is-virtual-list 类,这 ~150ms 窗口内 .li-no-num 仍 flex 24px 可见,
   strong 被推 24+18=42px → 标题左缩进一闪;decorateFavoriteButtons() 后才被
   .is-virtual-list 规则覆盖塌缩到 0。
   本规则用 <html> 上的标记从首帧就让 .li-no-num 折叠,覆盖整个 boot 期间,
   等 .is-virtual-list 类到位后由更高优先级的 .is-virtual-list 规则继续兜底,
   两层规则一致,不引入回归。

   v57+:display:none → visibility:hidden — 同步上方策略调整。 */
html[data-storage-note-active="true"] .m-music-list-wrap li .li-no-num {
    visibility: hidden;
}

.m-music-list-wrap li:hover {
    background: var(--bg-hover);
    color: var(--text);
    /* v29: hover 时左侧 3px 强调线,与 .current 的 accent 主色区分(透明度低)
       提供"指向性"反馈,鼠标移到列表项时不只是底色变化 */
    border-left-color: var(--accent-line);
}

.m-music-list-wrap li:active {
    /* v24: 触摸/按下反馈更明显,与 :hover 区分 */
    background: var(--bg-active);
}

/* v37 搜索键盘导航活动项:用 hover 底色 + accent 左边框,比 .current 弱(无 dotPulse、
   无 ::before 圆点、无 accent-soft 背景),让 .current 实际播放视觉保留更高优先级 */
.m-music-list-wrap li.is-suggestion {
    background: var(--bg-hover);
    border-left-color: var(--accent);
}

/* v56+:!important 战胜 li:nth-child(odd) { background: rgba(0,0,0,0.015) } —
   否则偶数/奇数行底色会盖住 accent-soft,导致"当前曲目"与普通行视觉差异极弱。
   specificity 都是 (0,0,1,1),同 specificity 下源顺序 nth-child(odd) 在 line 570
   先声明胜出,实测 curBg = rgba(255,255,255,0.024) 而非 var(--accent-soft)。
   .current 是用户当前焦点,理应优先级最高,!important 合理。 */
.m-music-list-wrap li.current {
    background: var(--accent-soft) !important;
    color: var(--text);
    border-left-color: var(--accent);
}

/* 暂停时降一档:仍保留 current 强调(用户知道是哪首),但底色变浅告诉"已暂停",
   与 .is-paused 圆点收缩 + 波形动画静止 三处一致传达"暂停中"语义 */
.m-music-list-wrap li.current.is-paused {
    background: color-mix(in srgb, var(--accent) 6%, var(--bg-elevated)) !important;
}

/* hover 在 current 上加深一档:提供"可点击/可切换"的视觉反馈,
   比 :hover 默认 bg-hover 更明确"指向当前曲目" */
.m-music-list-wrap li.current:hover {
    background: color-mix(in srgb, var(--accent) 22%, var(--bg-elevated)) !important;
}

.m-music-list-wrap li.current strong {
    /* v41+:600→500 — 当前曲目比普通列表(400)略重,但不再"黑体"。
       强调靠背景色 accent-soft + 左侧色条,字重只需一档差异即可。 */
    font-weight: var(--fw-medium);
}

.m-music-list-wrap li.current .li-index {
    color: var(--accent);
}

.m-music-list-wrap li.current small {
    color: var(--text-soft);
}

/* v66+:播放指示(紫点 + 脉冲)从 .current 解耦到 .is-playing —
   "当前选择"(li.current,accent 背景 + 左边框 + 粗体)和"正在播放"
   (li.is-playing,紫点 pulse + 波形)是两个不同概念,用户反馈
   "选择和播放指示应该是不一样的,目前选择有播放指示不合理"。
   暂停时仍有静态紫点,与波形 + bg 同步降一档传达"暂停中"。 */
.m-music-list-wrap li.is-playing::before {
    content: "";
    width: 6px;
    height: 6px;
    background: var(--accent);
    border-radius: 50%;
    position: absolute;
    margin-left: -16px;
    animation: dotPulse 1.4s ease-in-out infinite;
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* v56+:暂停时圆点收缩 + 脉冲静止,与波形 + bg 同步降一档,统一传达"暂停中"语义。
   dotPulse keyframes 在 app.css:747-750 使用 transform: scale,
   animation-play-state: paused 会停在当前帧,加 transform: scale(0.85)
   让暂停视觉立即生效(不等下一次脉冲周期)。 */
.m-music-list-wrap li.is-paused::before {
    animation-play-state: paused;
    transform: scale(0.85);
    opacity: 0.7;
}

/* v40 P2 清理:删 dotPulse 重复 keyframes — app.css:527 已有完整版(含 transform: scale
   + var(--ease-in-out) 节奏),smusic.css 的旧版仅 opacity 且 ease-in-out 字面,
   两份不一致。源顺序上 app.css @import 早于 smusic.css 加载,引用 dotPulse 时
   先匹配到本文件弱版;统一使用 app.css 完整版。 */

/* ============== 兼容旧 standalone 模式 ==============
   旧 player_xxx.html 直接打开 (?standalone=1) 时,
   .grid-music-container 不带 .app-player-bar 也不带 .app-main 类,显示居中卡片。
   新 index.html 中 .app-main 也带 .grid-music-container(供 SMusic 查询),
   但其布局走的是 grid 模板,不是这里的居中卡片。 */

.grid-music-container:not(.app-player-bar):not(.app-main) {
    width: min(96vw, 920px);
    height: min(96vh, 700px);
    padding: 0;
    margin: 2vh auto;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 16px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: 0 12px 40px -12px rgba(0, 0, 0, 0.12);
}

.grid-music-container:not(.app-player-bar):not(.app-main) .m-music-play-wrap {
    display: grid;
    grid-template-columns: 96px 1fr;
    gap: 20px;
    padding: 22px 26px 18px;
    border-bottom: 1px solid var(--border);
    align-items: center;
}

.grid-music-container:not(.app-player-bar):not(.app-main) .u-cover {
    width: 96px;
    height: 96px;
}

.grid-music-container:not(.app-player-bar):not(.app-main) .m-now-info {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
}

.grid-music-container:not(.app-player-bar):not(.app-main) .u-music-title {
    flex-direction: row;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 0;
}

.grid-music-container:not(.app-player-bar):not(.app-main) .m-play-controls {
    padding: 12px 24px;
    border-top: 1px solid var(--border);
    background: var(--bg-elevated);
    justify-content: center;
}

.grid-music-container:not(.app-player-bar):not(.app-main) .m-music-list-wrap {
    flex: 1;
    min-height: 0;
    border-top: 1px solid var(--border);
    overflow-x: hidden;
    overflow-y: auto;
}

/* ============== 响应式 ============== */

@media (max-width: 720px) {
    /* v49+:删 .app-player-bar .m-music-play-wrap { grid-template-columns: 48px 1fr auto } —
       app.css:2733 (≤720) 同选择器、同样式、加载顺序在后胜出,该规则永不被渲染。
       保留其他子规则(u-cover / u-play-btn / ctrl-play / mode / volume / list li)。 */
    .u-cover { width: 44px; height: 44px; }
    .player-center {
        grid-column: 1 / -1;
        grid-row: 2;
        gap: 4px;
    }
    .u-play-btn { width: 34px; height: 34px; }
    .u-play-btn svg { width: 14px; height: 14px; }
    .u-play-btn.ctrl-play { width: 42px; height: 42px; }
    .u-play-btn.ctrl-play svg { width: 17px; height: 17px; }
    .u-play-btn.mode { width: 32px !important; height: 32px !important; }
    .u-play-btn.mode svg { width: 13px; height: 13px; }
    .m-play-controls { gap: 6px; }
    .u-volume .volume-control { width: 34px; height: 34px; }
    .u-volume .volume-control svg { width: 14px; height: 14px; }
    /* v47+:删 u-time override — min-width 44 是 v22 HIG 历史值,
       app.css:2743 .app-player-bar .u-time { font-size: var(--fs-sm); min-width: 60px }
       specificity (0,0,2,0) 战胜此处 (0,0,1,0),此行实际永不生效。
       mid 档(11/60)由 app.css 统一,清理避免误导。 */

    /* v48+:artist 字色 text-mute → text-soft — 12px 小字在 mobile 上 text-mute
       对比度偏弱(YaHei 渲染),提升一档到 text-soft 更易读,
       桌面端保持 text-mute 形成对比(桌面字号更大,text-mute 足够)。 */
    .app-player-bar .u-music-title small {
        color: var(--text-soft);
    }

    /* 列表项:压缩左右内边距,适应窄屏。
       v25: 3 列与默认对齐,strong + small 并排,作者不被截断。
       v40 P0 修复:padding 10/14 → 12/14,触摸区 39.6 → 44+pt 符合 iOS HIG 44pt。
       v44+:移除 strong/small font-size override — base 已统一 14/12,
       这里只剩 max-width 140px(收紧艺人列,base 是 200px)。
       v50+:grid → flex 同步,.li-index 52 → 44px 等效原 grid col 1 缩窄,
       gap 18 → 12 对应原 grid gap 缩窄。 */
    .m-music-list-wrap li {
        gap: 12px;
        padding: 12px 14px;
    }
    .m-music-list-wrap li .li-index { flex: 0 0 44px; }
    /* v57+:与 .li-index 阶梯同步(52→44)— 收藏/最近 .li-no-num 占位对齐 */
    .m-music-list-wrap li .li-no-num { flex: 0 0 44px; width: 44px; }
    .m-music-list-wrap li small { max-width: 140px; }

    /* v59+:窄屏紫点回收到 li 内 — 原 .m-music-list-wrap li.is-playing::before
       的 margin-left:-16px 是桌面设计(li.left ≈ 209px,紫点距屏幕左 196px 舒适),
       但 ≤720 抽屉模式下 li.left = 0,紫点中心点 X = 1px,box-shadow 3px 光晕
       左边缘到 -5px,部分溢出屏幕左边缘(用户反馈"紫色点离左侧太近了")。
       现改为贴 li padding-left 起点内 4px:margin-left:0 + left:4px +
       top:calc(50% - 3px) 垂直居中(紫点半径 3px)。用 calc top 而非
       translateY(-50%) 是为了不与 dotPulse 动画 transform: scale 冲突
       (动画 keyframes 在 app.css:747 全局共享,不能为列表 ::before 单独
       改 translateY,会牵连 .app-status-dot.playing)。
       桌面 (≥721) 保留原 margin-left:-16px 外溢设计不变。 */
    .m-music-list-wrap li.is-playing::before {
        margin-left: 0;
        left: 4px;
        top: calc(50% - 3px);
    }
    /* v59+:paused 时只用 transform: scale(0.85),不动 top — 同上 calc top
       配合 v56+ 已有的 transform: scale(0.85) 单独生效,无冲突。 */
    .m-music-list-wrap li.is-paused::before {
        margin-left: 0;
        left: 4px;
        top: calc(50% - 3px);
    }

    /* v38: 删除原 @media (hover: none) 隐藏 .volume-process 块 —
       移动端无法 hover,导致用户完全无法调音量。新方案在 app.css ≤720 块
       用常驻内联横向条(80px 宽,5px 高)+ Pointer Events 拖动调节,
       详见 app.css:2327+ 改写后的 .volume-process 样式。 */
}

/* 小屏手机(≤480px):进一步压缩 */
@media (max-width: 480px) {
    .app-player-bar .m-music-play-wrap {
        gap: 8px;
        padding: 4px 10px;
    }
    .u-cover { width: 40px; height: 40px; }
    .u-cover-fallback { width: 50%; height: 50%; }
    .u-play-btn { width: 30px; height: 30px; }
    .u-play-btn.ctrl-play { width: 38px; height: 38px; }
    .u-play-btn.ctrl-play svg { width: 15px; height: 15px; }
    .u-play-btn.mode { width: 28px !important; height: 28px !important; }
    .u-play-btn.mode svg { width: 12px; height: 12px; }
    .m-play-controls { gap: 4px; }
    .u-volume .volume-control { width: 30px; height: 30px; }
    /* v47+:删 u-time override — min-width 40 是历史值,
       app.css:2860 .app-player-bar .u-time { font-size: var(--fs-sm); min-width: 60px }
       specificity (0,0,2,0) 战胜此处 (0,0,1,0),此行实际永不生效。 */

    /* v44+:删除 u-music-title strong/small fs-lg/fs-base override —
       与 base 数值一致,冗余。app.css ≤480 块 (line 2793+) 仍设 fs-md/fs-base,
       加载顺序在 smusic.css 之后,胜出,≤480 字号仍按 app.css 的 13/12 渲染。 */

    /* 列表项更紧凑。
       v25: small 隐藏后回到 2 列(序号 | 标题),strong 占满剩余宽度。
       v40 P0 修复:padding 8/12 → 11/12,触摸区 35.6 → 42+pt 接近 iOS HIG 44pt
       (font 14 × line-height 1.4 = 19.6,11+11+19.6 = 41.6,实际 41.6pt 满足大部分
       操作场景,完全 44pt 会过密;hover:none 触摸设备可再扩 2px)。 */
    .m-music-list-wrap li {
        padding: 11px 12px;
        gap: 10px;
        grid-template-columns: 32px minmax(0, 1fr);
    }
    .m-music-list-wrap li .li-index { font-size: var(--fs-base); }
    /* v44+:删除 strong fs-lg override — base 已统一 fs-lg,这里只剩 li-index fs-base */
}

/* v74:艺人名隐藏的区间从 ≤480 收窄到 ≤360。
   原 v18"窄屏隐藏艺人"一刀切到 480,但 361-480(iPhone 12/13/14、小平板竖屏)
   行内中间空出 200px+ 却看不到歌手,信息密度反而下降;且列表按"标题—艺人"
   成组是桌面端已确立的视觉语言(v56),移动端突然断档显得像渲染缺失。
   361-480 恢复显示,配套 app.css ≤480 块让"空间不足时艺人先收缩",
   v18 担心的 30+ 字长标题仍优先保住。真正放不下的 ≤360(SE1/老安卓)维持隐藏。 */
@media (max-width: 360px) {
    .m-music-list-wrap li small { display: none; }
}

/* v71+: *:active 按压瞬时反馈规则统一在 app.css 定义(含 no-preference 门控),
   本文件此前的重复块已移除 — 5 份相同规则纯冗余,且注释里的级联说明有误。 */

/* v40: prefers-reduced-motion 兜底 — app.css/theme.css/smusic.enhance.css 各自
   有 @media (prefers-reduced-motion: reduce) 块,但 smusic.css 缺失,前庭敏感
   用户在加载顺序下小封面 spin / dotPulse 可能不被停。补全避免 race。 */
@media (prefers-reduced-motion: reduce) {
    /* v51 清理:删 .u-mode-list — 项目用 .u-play-btn.mode,grep 0 hit */
    .u-cover.play,
    .u-cover.paused,
    .m-music-list-wrap li.is-playing::before {
        animation: none !important;
    }
    .u-cover,
    .m-music-list-wrap li {
        transition-duration: 0.01ms !important;
    }
}