/**
 * 收藏夹样式 (v32)
 *
 * 涵盖:
 *   - 列表项心形按钮(.li-fav-btn)
 *   - 侧栏"收藏"虚拟分类(.app-nav a.is-favorites)
 *   - 收藏列表顶部工具栏(.fav-toolbar)— 替代原顶栏 ♡ 按钮 + fav-modal 弹窗
 *   - 收藏列表空状态(.fav-empty)
 *   - 弹跳动画
 *   - v32+:最近播放对称样式(.app-nav a.is-recent / .recent-toolbar / .recent-empty)
 */

/* v58+:fav-note-h / fav-note-h-2line 在 :root 正式定义。
   原方案在 3 处用 var(--fav-note-h, 24.75px) 字面兜底,token 实际从未声明,
   改字体/行高时仍需逐处手改。本块让 token 真实生效,3 处
   var(--fav-note-h) / var(--fav-note-h-2line) 自动跟随。 */
:root {
    --fav-note-h: 24.75px;
    --fav-note-h-2line: 36.5px;
}
/* ≤480 屏 2 行换行时高度约 36.5px,与 token 保持同步。
   原块已存在,仅作为不同值覆盖用,这里用同一变量名避免字面量散落。 */
@media (max-width: 480px) {
    :root {
        --fav-note-h: 32px;
        --fav-note-h-2line: 44px;
    }
}

/* ============== 列表项心形按钮 ============== */

.m-music-list-wrap li {
    /* 让绝对定位的心形按钮有参照 */
    position: relative;
    padding-right: 52px;
}

.li-fav-btn {
    position: absolute;
    right: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 34px;
    height: 34px;
    border: none;
    background: transparent;
    color: var(--text-mute);
    cursor: pointer;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    transition:
        color var(--t-fast) var(--ease),
        background var(--t-fast) var(--ease),
        opacity var(--t-fast) var(--ease),
        transform var(--t-fast) var(--ease);
    /* 默认 0.8:桌面有 hover 时变 1.0,但触屏用户没有 hover — 0.55 之前等于不可见。
       收藏后通过 .is-favorite 切换到 accent 色,opacity 维持 1.0。 */
    opacity: 0.8;
    -webkit-tap-highlight-color: transparent;
    z-index: var(--z-thumb);
}

.li-fav-btn:hover {
    opacity: 1;
    color: var(--accent);
    background: var(--accent-soft);
}

.li-fav-btn:active {
    transform: translateY(-50%) scale(0.88);
}

.li-fav-btn svg {
    width: 18px;
    height: 18px;
    stroke: currentColor;
    stroke-width: 1.8;
    fill: none;
    stroke-linejoin: round;
    stroke-linecap: round;
    transition: fill var(--t-fast) var(--ease);
}

/* 已收藏:实心 + 主色 */
.li-fav-btn.is-favorite {
    color: var(--accent);
    opacity: 1;
}
.li-fav-btn.is-favorite svg {
    fill: currentColor;
}

/* 在收藏列表里:始终显示,且 hover 提示移除 */
.m-music-list-wrap.is-favorites-list .li-fav-btn {
    opacity: 1;
}
.m-music-list-wrap.is-favorites-list .li-fav-btn::after {
    content: '移除';
    position: absolute;
    bottom: -22px;
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: var(--text);
    color: var(--bg-elevated);
    font-size: var(--fs-sm);
    padding: 2px 8px;
    /* v29 round 4+: 4px → var(--r-xs) */
    border-radius: var(--r-xs);
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
    font-family: var(--font);
}
.m-music-list-wrap.is-favorites-list .li-fav-btn:hover::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* 心形按钮点过的弹跳反馈 */
@keyframes favBounce {
    0%   { transform: translateY(-50%) scale(1); }
    30%  { transform: translateY(-50%) scale(1.32); }
    60%  { transform: translateY(-50%) scale(0.92); }
    100% { transform: translateY(-50%) scale(1); }
}
.li-fav-btn.is-bouncing {
    animation: favBounce 320ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* ============== 侧栏"收藏"虚拟分类 ============== */

.app-nav a.is-favorites {
    color: var(--text-soft);
    /* v60:用户反馈"我的收藏自动有选中样式标识"——
       之前默认 border-left-color: var(--accent-line) 让收藏按钮
       永远显示一条 3px 紫色左边线,视觉上跟 .active 的 var(--accent)
       主色边线非常接近,容易被误判为"默认选中"。
       改为 transparent 与其他分类(以及 is-recent)对齐,
       仅在 .active 时才显示主色边线。 */
    border-left-color: transparent;
}
.app-nav a.is-favorites:hover {
    color: var(--accent);
}
.app-nav a.is-favorites.active {
    color: var(--accent);
    background: var(--accent-soft);
    border-left-color: var(--accent);
}

.app-nav a.is-favorites .nav-fav-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-mute);
    transition: color var(--t-fast) var(--ease);
}
.app-nav a.is-favorites .nav-fav-icon svg {
    width: 14px;
    height: 14px;
    stroke: currentColor;
    fill: none;
    stroke-width: 2;
    stroke-linejoin: round;
}
.app-nav a.is-favorites:hover .nav-fav-icon,
.app-nav a.is-favorites.active .nav-fav-icon {
    color: var(--accent);
}

/* ============== 侧栏"最近播放"虚拟分类(平行收藏) ============== */

.app-nav a.is-recent {
    color: var(--text-soft);
    border-left-color: transparent;
}
.app-nav a.is-recent:hover {
    color: var(--accent);
}
.app-nav a.is-recent.active {
    color: var(--accent);
    background: var(--accent-soft);
    border-left-color: var(--accent);
}

.app-nav a.is-recent .nav-recent-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-mute);
    transition: color var(--t-fast) var(--ease);
}
.app-nav a.is-recent .nav-recent-icon svg {
    width: 14px;
    height: 14px;
    stroke: currentColor;
    fill: none;
    stroke-width: 2;
}
.app-nav a.is-recent:hover .nav-recent-icon,
.app-nav a.is-recent.active .nav-recent-icon {
    color: var(--accent);
}

/* 收藏分类与上面 11 个分类之间加一道细分隔 */
.app-nav a.is-favorites + .app-nav-divider,
.app-nav .app-nav-divider {
    height: 1px;
    background: var(--border);
    margin: 8px 14px;
    list-style: none;
}

/* ============== 数据存储提示行(收藏/最近播放共用) ==============
   v52.6:用户在 categories.config.js 里给收藏/最近播放虚拟分类新增 storageNote 字段,
   JS 在 updateEmptyState() 里把该字段渲染成 .fav-storage-note 行,插入到
   .app-list-area 内 .m-list-search-wrap 之后、.m-music-list-wrap 之前。
   视觉上一道浅浅的横向提示条 + 数据库图标,提示"数据只在本机浏览器缓存里,
   清除缓存或换浏览器就会丢"。text 内容(含 <strong> 加粗)完全来自配置,可改不改码。 */

.fav-storage-note {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 5px 14px;
    margin: 0;
    /* v55+:固定 min-height — 与填充内容高度匹配(实测 1280/720 屏单行 24.75px,
       ≤480 屏 2 行 36.5px),fill 内容前后高度不变,CLS = 0。
       fill 后若文本换行到更多行,note 高度自动增长;空状态用
       calc(61px + var(--fav-storage-note-h, 24.75px) + 4px) 自动适配,
       后续高度变化不会再次触发视觉跳动。
       v58+:--fav-note-h 在 :root 真实定义(原 var(..., 24.75px) 字面兜底删)。
       ≤480 块重定义为 --fav-note-h=32px / --fav-note-h-2line=44px。 */
    min-height: var(--fav-note-h);
    font-size: var(--fs-sm);
    color: var(--text-mute);
    background: color-mix(in srgb, var(--text-mute) 6%, var(--bg));
    border-bottom: 1px solid var(--border);
    text-align: center;
    line-height: var(--lh-snug);
    user-select: none;
    flex-shrink: 0;
    /* v54+:note 整体断行策略。
       word-break: keep-all 让中文不被单字切到下一行(CJK 默认就是 keep-all,
       但显式声明防御某些 OS / 浏览器组合),避免 ≤320 屏出现"览"单字孤立的视觉。
       overflow-wrap: anywhere 仅在长 URL / 长英文词(超出 1 行)时强制断行,
       不影响正常中文断行。
       实测:360 屏单行紧凑;320 屏"本机浏览器" 整体保留,剩余文字按
       语义断行(逗号、空格、中英边界)而非单字孤立。 */
    word-break: keep-all;
    overflow-wrap: anywhere;
    /* v52.7:删 transition: opacity 死代码 — JS 用 remove()/appendChild() 而非
       toggle display,opacity transition 永远无法触发(节点被移除就没元素了)。
       原注释"让分类切换进出时平滑淡入淡出"只是愿景,实现走的是另一条路。 */
}
.fav-storage-note[hidden] {
    display: none;
}
/* v56.1:首帧占位 — HTML 预创建的 <div class="fav-storage-note-pre">。
   默认 display:none(完全折叠到 0 高度)→ 普通分类下列表顶部无 24.75px
   空白,listWrap 在 y=125(搜索框 57px + 搜索框下边缘)。其他分类(中文/
   精选/AI/文件时间顺序/随机/外文/串烧/乐器/古典/网络/长时)本来就没显示
   storage note 文案,自然也不需要为它预留 layout 空间。

   虚拟分类(收藏/最近播放)首帧:head 同步脚本(见 index.html:83)给 <html>
   加 data-storage-note-active="true",CSS 见到该标记立即让占位展开到
   24.75px(visibility:hidden 保留布局),与 JS upgrade 后的 .fav-storage-note
   高度一致 → 首帧 CLS = 0。

   in-page 切分类:smusic.enhance.js syncListWrapClasses() 同步切换 html
   上的标记(虚拟分类加上、普通分类移除),CSS 跟着切换占位 div 高度
   (0 ↔ 24.75px)→ listWrap 在 y=125 ↔ y=149.75 切换。这会引入 24.75px
   CLS(与 v55.1 等价,远低于 0.1 的"Good"门槛)— 用户已明确接受此
   权衡以换取"普通分类无 24.75px 空白"的视觉体验。

   v55.2 让占位永久保留 24.75px 修掉了这个切分类 CLS,但代价是普通分类
   下顶部多了 24.75px 空白,被用户反馈"没这行字就没必要留空"否决。

   v56+:占位默认 display:none,只在标记下展开。fold 状态由 html 上的
   data-storage-note-active 标记 + aria-hidden 双信号控制:
     - 普通分类:无标记 + aria-hidden=true → display:none(完全折叠)
     - 虚拟分类首帧:有标记 + 无 aria-hidden → display:flex + 24.75px
     - 虚拟分类已升级:.fav-storage-note 类生效(不受 pre 规则约束),
       visibility:visible + 内容 */
.fav-storage-note-pre {
    display: none;
}
/* v56.1:虚拟分类首帧(普通首屏 + head 预判命中虚拟分类)→ 展开 24.75px。
   visibility:hidden 保留布局(用户看不到),与 JS upgrade 后的 .fav-storage-note
   高度对齐。JS upgrade 仅切 visibility:hidden → visible,fill 内容,高度不
   变 → CLS = 0。 */
html[data-storage-note-active="true"] .fav-storage-note-pre {
    display: flex;
    visibility: hidden;
    color: transparent;
    background: transparent;
    border-bottom-color: transparent;
    /* v58+:var(--fav-note-h) 已在 :root 定义。 */
    min-height: var(--fav-note-h);
}
.fav-storage-note svg {
    width: 13px;
    height: 13px;
    flex-shrink: 0;
    stroke: var(--text-mute);
    fill: none;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.fav-storage-note strong {
    color: var(--text-soft);
    font-weight: var(--fw-semibold);
    /* v54+:删 margin: 0 1px(几乎不可见)改 padding: 0 3px。
       早期 markup 写 `<strong>本机浏览器</strong>缓存中`(strong 后没空格),
       1px margin 在中文字体下视觉上仍"挤"成"本机浏览器缓存中"密不透风。
       改 3px 双向 padding,左右各 ~3px ≈ 半个中文字宽,既不破坏"高亮短语"
       视觉一体性,又给前后文留呼吸空间。 */
    padding: 0 3px;
    /* v54+:给 strong 一个略深一档的底色 + 圆角,与正文色阶分层 —
       之前仅靠字重 + 字色 var(--text-soft) 加深,在 low-contrast 主题
       (如 sepia/forest)与正文区分度不够。背景用 accent-soft 6% 透明,
       跨 6 主题都是色相一致(主题强调色低饱和),与 storage note 整体
       灰底氛围不冲突。 */
    background: color-mix(in srgb, var(--text-mute) 10%, transparent);
    border-radius: 3px;
    /* v54+:防止 strong 内文本在窄屏(≤320)被单字断行孤立。
       overflow-wrap: anywhere 仍允许长 URL / 长英文词断行,
       但 white-space: nowrap 仅约束 strong 自身,不影响外层 text 流。
       强 nowrap 后,"本机浏览器"永远整体保留,下一行若有断字会落在
       后续中文"缓存中..."段。 */
    white-space: nowrap;
}

/* ============== 收藏/最近播放列表空状态(共享样式) ==============
   v37:P2-9 合并 .fav-empty 与 .recent-empty 完全相同的 9 行声明,减少约 40 行重复 CSS。
   两个空状态视觉一致,只是类名前缀不同(供 JS 单独识别/动画)。 */

.fav-empty,
.recent-empty {
    /* v52.6:JS 把空状态 append 到 .app-list-area 里,在 .m-list-search-wrap 之后。
       .m-list-search-wrap flex:1 会先占满空间,空状态被挤到下方剩余区域,
       视觉上变成"大块空白 + 底部一颗心"的别扭布局。
       用 absolute 定位让空状态直接覆盖在 list-wrap 区域上,
       占据列表区(不含顶部工具栏 + 存储提示行),跟正常列表填充时一样居中显示。
       inset: 顶 = 工具栏高度(61px) + 存储提示行(实测 25-28px) + buffer = 90px,其他 = 0,
       配合 .app-list-area position:relative (app.css:889 — 实测位置,v52.7 修正原 647 行号),不会溢出。 */
    position: absolute;
    /* v52.6 r2:用 CSS 变量 --fav-storage-note-h(由 JS 写)+ 4px buffer 动态算 top,
       替代 r1 的 fixed 90px。窄屏 2 行换行 / 旋转 / 字号变化由 ResizeObserver 自动同步。
       61px = .m-list-search-wrap 的 min-height (smusic.enhance.css:61) — 实测恰好对齐。 */
    top: calc(61px + var(--fav-storage-note-h, 24.75px) + 4px);
    right: 0;
    bottom: 0;
    left: 0;
    padding: 60px 32px;
    text-align: center;
    color: var(--text-soft);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    background: var(--bg);
    /* z-index 高于 list-wrap(0/auto),确保覆盖在上面。
       不写 pointer-events:none,空状态下用户仍可点击 icon (虽然当前没绑定) */
    z-index: var(--z-track);
}
.fav-empty svg,
.recent-empty svg {
    width: 64px;
    height: 64px;
    stroke: var(--text-mute);
    fill: none;
    stroke-width: 1.5;
    opacity: 0.5;
    /* v56+:与 .m-list-empty-icon 一致的轻微脉冲,
       scale(1)↔scale(1.06)+opacity 0.85↔1,2.4s 一个周期,
       让空状态"在等用户操作"的呼吸感,6 主题通用(只改 stroke + opacity)。
       prefers-reduced-motion 在下方兜底禁用。 */
    animation: emptyPulse 2.4s var(--ease-in-out) infinite;
    transform-origin: center;
}

/* v58+:emptyPulse 关键帧已统一在 smusic.enhance.css 定义。
   原 favorites.css 版本 opacity=0.85 与 enhance.css 版本 opacity=0.92
   不一致;加载顺序后者胜,本文件版本成死代码且未来若调 CSS 加载顺序
   会让 .fav-empty / .recent-empty 动画瞬间变化(0.85 ↔ 0.92)。
   保留 animation: emptyPulse ... 与 prefers-reduced-motion 兜底,
   关键帧本体统一走 enhance.css 的权威值。 */

@media (prefers-reduced-motion: reduce) {
    .fav-empty svg,
    .recent-empty svg { animation: none; }
}
.fav-empty-title,
.recent-empty-title {
    /* v37:font-size 16px → var(--fs-2xl) token 化 */
    font-size: var(--fs-2xl);
    font-weight: var(--fw-semibold);
    color: var(--text);
}
.fav-empty-desc,
.recent-empty-desc {
    /* v37:font-size 13px → var(--fs-md) token 化 */
    font-size: var(--fs-md);
    color: var(--text-soft);
    /* v37:line-height 1.6 → var(--lh-relaxed) token 化 */
    line-height: var(--lh-relaxed);
    max-width: 320px;
}

/* ============== 收藏列表顶部管理工具栏(v32+:替代 fav-modal 弹窗) ============== */

/* v29: 心形按钮焦点环 — 之前完全没有 :focus-visible 规则,
   键盘用户从列表 tab 时无视觉反馈。 */
.li-fav-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    color: var(--accent);
}

/* ============== 收藏列表顶部工具栏(v32 round 2:细线性文字按钮) ==============
   设计原则:工具栏与搜索框同行,作为 .m-list-search-wrap 的第一个子节点;
   三个文字按钮(导出/导入/清空)无边框/无底色/无图标,仅在 hover 时显示浅底色;
   与现有 .app-overflow-item 视觉语言一致 — 像"面包屑式"操作。 */

.fav-toolbar {
    display: flex;
    align-items: center;
    gap: 4px;
    /* flex-shrink: 0 让工具栏保持完整不被搜索框挤压;
       搜索框 m-list-search 是 flex:1,自适应剩余宽度 */
    flex-shrink: 0;
    /* 工具栏与搜索框之间一道细分隔(避免视觉粘连) */
    padding-right: 12px;
    margin-right: 4px;
    border-right: 1px solid var(--border);
}

/* v37:P3-1 合并 .fav-toolbar-btn / .recent-toolbar-btn 共享样式 —
   两组按钮 9 行声明逐字相同,合并后减约 40 行。
   :hover / :active / .danger:hover / :focus-visible 4 个状态规则也合并。 */
.fav-toolbar-btn,
.recent-toolbar-btn {
    border: none;
    background: transparent;
    color: var(--text-soft);
    font-size: var(--fs-md);
    font-weight: var(--fw-medium);
    font-family: inherit;
    cursor: pointer;
    padding: 6px 10px;
    border-radius: var(--r-sm);
    transition:
        color var(--t-fast) var(--ease),
        background var(--t-fast) var(--ease);
    -webkit-tap-highlight-color: transparent;
    min-height: 32px; /* 桌面尺寸;触摸设备:hover:none 块里再扩展 */
    position: relative;
    white-space: nowrap;
}

.fav-toolbar-btn:hover,
.recent-toolbar-btn:hover {
    color: var(--accent);
    background: var(--accent-soft);
}

.fav-toolbar-btn:active,
.recent-toolbar-btn:active {
    transform: scale(0.96);
}

/* 危险按钮(清空)hover 用警示色而非主题强调色。
   v38: 硬编码 #c2410c 在 dark/night 下 13px 文字 3.22/3.38:1,失败 AA。
   改用 var(--danger) / var(--danger-soft),6 主题各自定义:
   light/sepia/ocean/forest 沿用 #c2410c;dark/night 用 #f97316 (5.7:1)。 */
.fav-toolbar-btn-danger:hover,
.recent-toolbar-btn.danger:hover {
    color: var(--danger);
    background: var(--danger-soft);
}

.fav-toolbar-btn:focus-visible,
.recent-toolbar-btn:focus-visible {
    color: var(--accent);
    background: var(--accent-soft);
    outline: none;
}

/* 隐藏的文件选择 input(挂在 toolbar 容器下,detach 时一起带走) */
.fav-toolbar-file-input {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    opacity: 0;
}

/* v47: ≤360 折叠用的"管理"按钮 — 默认隐藏,≤360 块下显示并隐藏 3 个独立按钮。
   视觉与 .fav-toolbar-btn 同款(细线性、无边框、hover 浅底),尺寸略大以暗示有下拉。 */
.fav-toolbar-overflow-btn {
    display: none;  /* 默认隐藏,≤360 块下切到 inline-flex */
    align-items: center;
    border: none;
    background: transparent;
    color: var(--text-soft);
    font-size: var(--fs-md);
    font-weight: var(--fw-medium);
    font-family: inherit;
    cursor: pointer;
    padding: 6px 10px;
    border-radius: var(--r-sm);
    transition:
        color var(--t-fast) var(--ease),
        background var(--t-fast) var(--ease);
    -webkit-tap-highlight-color: transparent;
    min-height: 32px;
    white-space: nowrap;
    position: relative;
}
.fav-toolbar-overflow-btn::after {
    /* 向下小箭头,暗示 popover */
    content: '';
    display: inline-block;
    width: 0;
    height: 0;
    margin-left: 4px;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 4px solid currentColor;
    opacity: 0.7;
    transition: transform var(--t-fast) var(--ease);
}
.fav-toolbar-overflow-btn[aria-expanded="true"]::after {
    transform: rotate(180deg);
}
.fav-toolbar-overflow-btn:hover,
.fav-toolbar-overflow-btn[aria-expanded="true"] {
    color: var(--accent);
    background: var(--accent-soft);
}
.fav-toolbar-overflow-btn:focus-visible {
    color: var(--accent);
    background: var(--accent-soft);
    outline: none;
}

/* v47: popover 菜单 — 仿 .app-overflow-menu(app.css:1006-1145)模式,
   position absolute + z-index: --z-overlay,阴影/圆角/边框 token 化。
   菜单挂在 toolbar 下,fixed/absolute 兼容 toolbar 滚出视口。 */
.fav-toolbar-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    /* v58+:var(--z-overlay) 已在 :root 定义,删冗余兜底。 */
    z-index: var(--z-overlay);
    min-width: 110px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
    padding: 4px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    opacity: 0;
    transform: translateY(-4px);
    transition:
        opacity var(--t-fast) var(--ease),
        transform var(--t-fast) var(--ease);
}
.fav-toolbar-menu[hidden] {
    display: none !important;
}
.fav-toolbar-menu:not([hidden]) {
    opacity: 1;
    transform: translateY(0);
}
.fav-toolbar-menuitem {
    appearance: none;
    -webkit-appearance: none;
    border: none;
    background: transparent;
    color: var(--text);
    font-size: var(--fs-md);
    font-family: inherit;
    font-weight: var(--fw-medium);
    text-align: left;
    cursor: pointer;
    padding: 8px 12px;
    border-radius: var(--r-sm);
    transition:
        background var(--t-fast) var(--ease),
        color var(--t-fast) var(--ease);
    -webkit-tap-highlight-color: transparent;
    min-height: 36px;  /* 触摸友好 */
    white-space: nowrap;
}
.fav-toolbar-menuitem:hover,
.fav-toolbar-menuitem:focus-visible {
    background: var(--bg-hover);
    color: var(--accent);
    outline: none;
}
.fav-toolbar-menuitem.fav-toolbar-menuitem-danger:hover,
.fav-toolbar-menuitem.fav-toolbar-menuitem-danger:focus-visible {
    color: var(--danger);
    background: var(--danger-soft);
}

/* ============== 最近播放列表顶部工具栏(v32+:平行 .fav-toolbar) ==============
   与 .fav-toolbar 共享"细线性文字按钮"语言,挂在 .m-list-search-wrap 内做兄弟节点;
   但布局不同 — 左侧 meta 计数 + 右侧清空按钮(justify-content: space-between),
   而不是连续按钮组。 */

.recent-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    /* 工具栏与搜索框之间一道细分隔(与 fav-toolbar 一致) */
    padding-right: 12px;
    margin-right: 4px;
    border-right: 1px solid var(--border);
    flex-shrink: 0;
    min-width: 0;
}

.recent-toolbar-meta {
    font-size: var(--fs-md);
    color: var(--text-mute);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* v37:P3-1 合并后,.recent-toolbar-btn 共享 .fav-toolbar-btn 同款样式
   (上面合并规则已覆盖 base/hover/active/danger/focus-visible 全部 5 组状态)。
   此处不再单独声明,避免特异性竞争 */

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

@media (max-width: 720px) {
    .li-fav-btn {
        right: 8px;
        width: 32px;
        height: 32px;
    }
    .m-music-list-wrap li {
        padding-right: 46px;
    }
    /* v32 round 2:窄屏工具栏压紧字号与 padding */
    .fav-toolbar {
        padding-right: 8px;
        margin-right: 2px;
        gap: 2px;
    }
    .fav-toolbar-btn {
        padding: 5px 8px;
        font-size: var(--fs-base);
        min-height: 30px;
    }
    /* 最近播放工具栏:窄屏同步缩 */
    .recent-toolbar {
        padding-right: 8px;
        margin-right: 2px;
        gap: 8px;
    }
    .recent-toolbar-btn {
        padding: 5px 8px;
        font-size: var(--fs-base);
        min-height: 30px;
    }
}

/* v27 round 4: 低高度横屏(iPhone SE 横屏 568x320 等)工具栏紧凑。
   3 个文字按钮保持水平布局,整体压小避免撑爆视口高度。
   v60+:max-height: 480 → 500 — 与 app.css 横屏规则统一(app.css 5 处用 500);
   481-500h 横屏(如 1024×490、1280×490)下工具栏原本按竖屏高布局,
   可能与底部播放器产生 16-20px 视觉冲突。 */
@media (max-height: 500px) and (orientation: landscape) {
    .fav-toolbar-btn {
        padding: 4px 7px;
        font-size: var(--fs-sm);
        min-height: 28px;
    }
    .recent-toolbar-btn {
        padding: 4px 7px;
        font-size: var(--fs-sm);
        min-height: 28px;
    }
}

/* v32 round 2:平板 721-1024 工具栏加宽 padding,与搜索框更协调 */
@media (min-width: 721px) and (max-width: 1024px) {
    .fav-toolbar {
        padding-right: 14px;
        margin-right: 6px;
    }
    .recent-toolbar {
        padding-right: 14px;
        margin-right: 6px;
    }
}

@media (max-width: 480px) {
    /* 列表项:更紧凑的内边距,防止拥挤 */
    .m-music-list-wrap li {
        padding: 9px 14px 9px 16px;
        padding-right: 42px;
        gap: 12px;
        grid-template-columns: 36px 1fr;
    }
    .li-fav-btn {
        right: 6px;
        width: 32px;
        height: 32px;
    }
    .li-fav-btn svg {
        width: 16px;
        height: 16px;
    }

    /* 收藏工具栏:窄屏紧凑布局(细线性,字号略缩) */
    .fav-toolbar {
        padding-right: 6px;
        margin-right: 2px;
        gap: 2px;
    }
    .fav-toolbar-btn {
        padding: 5px 7px;
        font-size: var(--fs-base);
    }

    /* 最近播放工具栏:同样窄屏紧凑 */
    .recent-toolbar {
        padding-right: 6px;
        margin-right: 2px;
        gap: 6px;
    }
    .recent-toolbar-btn {
        padding: 5px 7px;
        font-size: var(--fs-base);
    }

    /* 空状态:小屏下更紧凑 */
    .fav-empty { padding: 40px 20px 32px; }
    .fav-empty svg { width: 48px; height: 48px; }
    .fav-empty-title { font-size: var(--fs-xl); }
    .fav-empty-desc { font-size: var(--fs-base); }

    .recent-empty { padding: 40px 20px 32px; }
    .recent-empty svg { width: 48px; height: 48px; }
    .recent-empty-title { font-size: var(--fs-xl); }
    .recent-empty-desc { font-size: var(--fs-base); }

    /* v52.6:数据存储提示行 — 小屏压紧 padding,
       紧凑档避免挤压曲目列表可视区。字号保持 var(--fs-sm) 不再缩,
       因为已经够小(<14px),再缩屏读吃力。
       v55+:min-height 24.75 → 36.5 适配 2 行换行(实测 ≤480 屏单行 → 2 行)。
       v55.2+:占位 .fav-storage-note-pre 也用 36.5px,切到虚拟分类时 CLS = 0
       (之前占位 24.75px + note 36.5px 切分类时 listWrap 下移 12px,实测 CLS 0.06-0.12)。
       padding 也对齐,保持高度一致。 */
    .fav-storage-note,
    .fav-storage-note-pre {
        padding: 4px 10px;
        /* v58+:var(--fav-note-h-2line) 已在 :root 定义(原字面兜底 36.5px 删)。 */
        min-height: var(--fav-note-h-2line);
    }
}

/* v47: ≤360 折叠(主流移动端最窄档:iPhone SE 1 代 320、Pixel 360、小米 360 等)。
   3 个细线性按钮 + 文件 input 一起塞进搜索框旁边,即使 padding 6+7+10+gap 5px
   也装不下(导出/导入/清空 + 字数 8+8+8 = 24 字符,横排绝对溢出)。
   解决方案:隐藏 3 个独立按钮 + 文件 input,显示单一"管理"按钮,点开 popover
   暴露同样的 3 个动作。注:popover 内的 menuitem 永远保留触控友好的 36px 触摸区。 */
@media (max-width: 360px) {
    /* 收藏工具栏:3 个按钮 + file input 隐藏,改用 overflow button。
       隐藏用 display:none 而不是 hidden 属性,避免破坏 buildToolbar 的元素创建顺序 */
    .fav-toolbar-btn,
    .fav-toolbar-file-input {
        display: none;
    }
    .fav-toolbar-overflow-btn {
        display: inline-flex;
    }
    /* 工具栏自身去掉 padding-right,节省 6px 给管理按钮 */
    .fav-toolbar {
        padding-right: 0;
        margin-right: 0;
        gap: 0;
    }
}

/* v11: 兜底压缩(≤320px,iPhone 5 / SE 1 代)
   列表项 padding 与 grid 列宽再压,序号列 36→32、padding-right 42→38,
   让中等长度歌名("等你下课(with 杨瑞代)")能完整显示。
   注意:favorites.css 在 app.css 之后加载,故 fav 相关规则(fav-btn / meta)
   需在本文件声明才能覆盖 app.css 中的对应 ≤320 规则。 */
@media (max-width: 320px) {
    /* 工具栏:超窄屏进一步压紧(细线性只缩字号,不改布局) */
    .fav-toolbar-btn {
        padding: 4px 6px;
        font-size: var(--fs-sm);
    }

    /* v40 P0 修复:触摸区加大(35.6 → 47+pt,符合 iOS HIG 44pt);当年还同步覆盖过
       .is-virtual-list 的 grid 列定义(grid 时代 li-no-num 与 strong 同列重叠)。
       v74:grid-* 属性自 v50 列表 flex 化后即死代码,已删;本块仅保留 padding/gap
       等仍生效的压缩规则。虚拟分类 ≤320 行内布局完全继承 flex 自然流 + .li-no-num。 */
    .m-music-list-wrap li {
        padding: 11px 10px 11px 12px;
        padding-right: 38px;
        gap: 10px;
    }
    .m-music-list-wrap li .li-index { font-size: var(--fs-sm); }
    .m-music-list-wrap li strong { font-size: var(--fs-md); }
    /* v37:P2-4 删 li small font-size/max-width — small 在窄屏被隐藏后永不渲染,
       字号规则失效。v74:隐藏条件从"≤480"收紧为"≤360"(smusic.css),
       本 ≤320 块仍落在隐藏区间内,结论不变。 */
    /* 心形按钮视觉缩,触摸区由 hover:none 块的 inset:-8px 保 */
    .li-fav-btn {
        right: 4px;
        width: 30px;
        height: 30px;
    }
    .li-fav-btn svg { width: 15px; height: 15px; }
}

/* ============== 收藏列表拖动排序(v41+) ==============
   设计原则:
   - 拖动手柄(⠿ 六点)绝对定位在 li 左侧,默认 opacity:0,
     仅 li:hover / li:focus-within / 手柄自身:focus-visible 时淡入,
     与项目"极简"风格一致(用户要求:悬停/聚焦才显示)
   - 触屏(hover:none)下手柄常驻但淡灰 0.35,触屏用户无需 hover
     即可看到/操作,符合"发现性"与"可触达性"平衡
   - 拖动源:opacity 0.4 + scale(0.98),与全局 cubic-bezier(--ease)/--t-fast
     对齐,prefers-reduced-motion 块关闭 transform
   - 拖放指示:用 box-shadow inset(不占盒模型空间)2px accent 线,
     不影响 grid 列宽
   - 键盘移动模式:源 li outline dashed + accent-soft 底色,
     与 .is-suggestion(搜索激活态)视觉分级,避免与 .current 撞色
   - li 自身 draggable="true" + data-src 由 JS 注入,CSS 不参与 */

/* 拖动手柄 — 在收藏列表里常驻(opacity 0.45),hover/focus 提到 1。
   v56+:位置 left: 8px → right: 54px(与 .li-fav-btn 同侧分组放右侧)。
   修复"hover 时手柄盖 strong 标题左 6-12px"的视觉重叠问题
   (实测 1280 屏 handle right=244 vs strong left=236 overlap 8px,
   720 屏 overlap 12px,360 屏 overlap 6px)。
   移到右侧后 strong 不被任何东西盖住,标题完整可读;
   触屏 (hover:none) 手柄常显也仍清晰分组在 li 右侧,不挤压 strong。
   与 .li-fav-btn (right:14px + width:34 = 14-48px) 分组:
   handle 在 right:54px + width:24 = 54-78px,fav-btn 与 handle 间 6px gap。

   v57:用户反馈"我的收藏顺序调整存在问题",根因是桌面端默认 opacity:0
   让手柄完全不可见,用户根本不知道可以拖动。改为收藏列表里常驻 0.45:
   - 非收藏列表:仍隐藏(其他分类无此功能,隐藏避免误读)
   - 收藏列表:0.45 常驻 + 浅色背景,鼠标悬停/聚焦时升到 1.0,
     让"拖动手柄"作为视觉锚点持续提示"此处可拖动"
   - 触屏 (hover:none) 保持 0.5 + 更明显背景(原 @media 块不动),
     与桌面常驻逻辑互补,跨设备一致 */
.li-drag-handle {
    position: absolute;
    right: 54px;
    top: 50%;
    transform: translateY(-50%);
    width: 24px;
    height: 24px;
    border: none;
    background: transparent;
    color: var(--text-mute);
    cursor: grab;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--r-xs);
    opacity: 0;
    pointer-events: none;
    z-index: var(--z-thumb);
    -webkit-tap-highlight-color: transparent;
    transition:
        opacity var(--t-fast) var(--ease),
        color var(--t-fast) var(--ease),
        background var(--t-fast) var(--ease);
}

/* 收藏列表:常驻 0.45 + 8% accent 浅底,让用户一眼看到"此处可拖动"。
   pointer-events: auto 让 handle 始终可点击(无 hover 也能触发),
   与悬停/focus 升 1 视觉叠加,符合用户期望。 */
.m-music-list-wrap.is-favorites-list .li-drag-handle {
    opacity: 0.45;
    pointer-events: auto;
    background: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
}

/* 显形触发:悬停 / 列表项聚焦 / 手柄自身键盘聚焦 — 升到 1 + 更明显 accent 底 */
.m-music-list-wrap.is-favorites-list li:hover .li-drag-handle,
.m-music-list-wrap.is-favorites-list li:focus-within .li-drag-handle,
.li-drag-handle:focus-visible {
    opacity: 1;
    background: var(--accent-soft);
}

.li-drag-handle:hover {
    color: var(--accent);
    background: var(--accent-soft);
}

.li-drag-handle:active {
    cursor: grabbing;
    transform: translateY(-50%) scale(0.92);
}

/* 键盘聚焦环(用户从 Tab 进入 li 内部时) */
.li-drag-handle:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* ⠿ 六点图标:6 个圆点两列三行,用 SVG circle 绘制,
   跟随 currentColor,主题切换自动适配 */
.li-drag-handle svg {
    width: 14px;
    height: 14px;
    fill: currentColor;
}

/* 拖动源 — 半透叠加 + 微缩,被拖走时仍占位让用户感知"来源"。
   v55:背景加一抹 accent-soft(透明版)比单纯 opacity 更明确"被选走了"。
   v55+:opacity 0.5 + 12% accent 底 双半透在亮主题几乎看不到染色;
   改 transform: scale(0.98) + 单一 14% accent 底,scale 提供"被拖走"物理感,
   颜色单一来源更醒目。 */
.m-music-list-wrap.is-favorites-list li.is-dragging {
    transform: scale(0.98);
    background: color-mix(in srgb, var(--accent) 14%, var(--bg-elevated));
    transition:
        transform var(--t-fast) var(--ease),
        background var(--t-fast) var(--ease);
}

/* 拖动源手柄 — 抓取姿态 */
.m-music-list-wrap.is-favorites-list li.is-dragging .li-drag-handle {
    cursor: grabbing;
    opacity: 1;
    pointer-events: auto;
    color: var(--accent);
}

/* 拖放指示线 — 用 box-shadow inset,不破坏 grid 盒模型。
   v55:从单线升级为 2px 实线 + 浅底色"目标区域",比单线更醒目且更易理解
   "拖到这里",用户在快速操作中不会错过插入位置。
   不影响 li 高度(grid / flex 盒模型),只用 background 叠加。
   v55+:background 加 !important — 防御 app.css / smusic.css 中可能存在的
   `.is-favorites-list li:hover` 或 `.li-X:hover` 规则 specificity > (0,0,3,0),
   覆盖 drop 浅底(实测当前文件内 specificity 刚好够,但跨文件无法 grep 验证)。 */
.m-music-list-wrap.is-favorites-list li.is-drop-before {
    box-shadow: inset 0 2px 0 0 var(--accent);
    background: color-mix(in srgb, var(--accent) 6%, var(--bg-elevated)) !important;
}
.m-music-list-wrap.is-favorites-list li.is-drop-after {
    box-shadow: inset 0 -2px 0 0 var(--accent);
    background: color-mix(in srgb, var(--accent) 6%, var(--bg-elevated)) !important;
}
/* v55+:drop 目标 li 在:hover 也保持浅底优先(避免 hover:bg-hover 覆盖 drop 浅底)。
   !important 同步,与 base 一致。 */
.m-music-list-wrap.is-favorites-list li.is-drop-before:hover,
.m-music-list-wrap.is-favorites-list li.is-drop-after:hover {
    background: color-mix(in srgb, var(--accent) 10%, var(--bg-elevated)) !important;
}

/* v56+:drop 目标 = 正在播放曲目的复合规则 — 保留 .current 的 accent-soft 强调,
   只加 box-shadow 顶/底边线指示插入位置。不覆盖 background,让用户一眼
   看到"在播曲目 = drop 目标"两件事同时成立。 */
.m-music-list-wrap.is-favorites-list li.is-drop-before.current,
.m-music-list-wrap.is-favorites-list li.is-drop-after.current {
    background: var(--accent-soft) !important;
    box-shadow: inset 0 2px 0 0 var(--accent);
}
.m-music-list-wrap.is-favorites-list li.is-drop-before.current {
    box-shadow: inset 0 2px 0 0 var(--accent);
}
.m-music-list-wrap.is-favorites-list li.is-drop-after.current {
    box-shadow: inset 0 -2px 0 0 var(--accent);
}

/* 键盘移动模式 — 源 li 高亮,与其他状态区分
   v55:左右各加 2px accent-soft 条 + 微妙的左边框,
   比纯 outline dashed 视觉更"稳",且不与 :focus 冲突。
   "稳态"(Enter/Esc 之外)用 static 样式,鼠标 hover 不会覆盖。
   v55+:加 :not(:focus-visible) 守卫 — li 自身被 Tab 聚焦时,
   outline dashed 会盖掉默认焦点环(让键盘焦点视觉丢失),
   守卫让 outline 只在非焦点状态显示。 */
.m-music-list-wrap.is-favorites-list li.is-reorder-source:not(:focus-visible) {
    background: color-mix(in srgb, var(--accent) 14%, var(--bg-elevated));
    outline: 2px dashed var(--accent);
    outline-offset: -2px;
    box-shadow:
        inset 3px 0 0 0 var(--accent),
        inset -3px 0 0 0 var(--accent);
}

/* v56+:键盘移动源 = 正在播放曲目的复合规则 — 保留 .current 的 accent-soft 强调,
   让用户知道"自己正在拖的就是当前在播的曲目"。outline 保留 dashed 标识"选中态"。 */
.m-music-list-wrap.is-favorites-list li.is-reorder-source.current:not(:focus-visible) {
    background: var(--accent-soft) !important;
    outline: 2px dashed var(--accent);
    outline-offset: -2px;
    box-shadow:
        inset 3px 0 0 0 var(--accent),
        inset -3px 0 0 0 var(--accent);
}

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

/* ≤720 触摸密集区:手柄略缩,沿用 base 块的 right: 54px 不变(只缩尺寸)。
   v56+:从 left 改 right — 修"hover 手柄盖 strong 标题左 6-12px"重叠问题。 */
@media (max-width: 720px) {
    .li-drag-handle {
        width: 22px;
        height: 22px;
    }
    .li-drag-handle svg { width: 12px; height: 12px; }
}

/* ≤480 进一步压紧 */
@media (max-width: 480px) {
    .li-drag-handle {
        width: 20px;
        height: 20px;
    }
    .li-drag-handle svg { width: 11px; height: 11px; }
}

/* ≤320:手柄常驻(opacity 0.35)+ 进一步缩,
   即使触屏用户也能看到操作入口;键盘用户仍可 Tab + Space
   v71+: 删掉 left: 2px — 基础规则是 right: 54px 定位(LTR 下 left/right/width
   同时固定时 right 被忽略…但这里 left 会覆盖解析顺序把手柄左拉到序号列上方),
   只保留宽高收缩,定位仍跟随基础 right。 */
@media (max-width: 320px) {
    .li-drag-handle {
        width: 18px;
        height: 18px;
    }
    .li-drag-handle svg { width: 10px; height: 10px; }
}

/* 触摸设备:扩大手柄触摸区(同 .li-fav-btn ::before 模式,
   inset 拉到 -8 让命中区 ≥44pt 满足 iOS HIG);
   手柄常驻但淡灰,触屏用户不需要 hover 就能发现。
   v55:0.35 → 0.5 + 加 accent-soft 微底,触屏用户对"按钮"的识别依赖
   形状/底色而非颜色对比,纯透明灰在亮主题里几乎"消失"。 */
@media (hover: none) {
    .li-drag-handle::before {
        content: "";
        position: absolute;
        inset: -8px;
        border-radius: var(--r-sm);
    }
    /* v57:选择器带 .m-music-list-wrap.is-favorites-list 让 specificity 与
       上面"收藏列表常驻 0.45"块齐平(都是 0,2,0),且后写覆盖先写,
       在触屏设备上保持 0.5 + 18% accent 强反馈。
       原版 .li-drag-handle (0,1,0) 会被新增的 (0,2,0) 块压住 → 触屏
       反而只看到 0.45 + 8% accent,弱于桌面,反向阶梯。 */
    .m-music-list-wrap.is-favorites-list .li-drag-handle {
        opacity: 0.5;
        /* v55+:12% accent × transparent 在亮主题几乎消失(亮主题 accent
           本身浅紫,12% 透明后约 96% 透明,几乎等于 transparent)。
           改 var(--bg-elevated) 当底色,12% accent 与 li 实际背景混合,
           跨主题都能看出"此处是触摸可拖动手柄"。 */
        background: color-mix(in srgb, var(--accent) 18%, var(--bg-elevated));
        pointer-events: auto;
    }
    .m-music-list-wrap.is-favorites-list li:hover .li-drag-handle,
    .m-music-list-wrap.is-favorites-list li:focus-within .li-drag-handle,
    .li-drag-handle:focus-visible {
        opacity: 1;
        background: var(--accent-soft);
    }
    /* 触屏清 hover sticky(同 .li-fav-btn 策略) */
    .li-drag-handle:hover {
        color: var(--text-mute);
        background: transparent;
    }
}

/* v59 触屏拖动期间:阻止 native scroll / Safari callout / 文本选择。
   只在 .is-dragging 期间生效,不影响列表日常滚动与点击播放。 */
.m-music-list-wrap.is-favorites-list li.is-dragging {
    touch-action: none;
    -webkit-touch-callout: none;
    user-select: none;
    -webkit-user-select: none;
}

/* 触摸设备:扩大心形按钮触摸区(用伪元素外扩,不改变按钮自身 position) */
@media (hover: none) {
    .li-fav-btn::before {
        content: "";
        position: absolute;
        inset: -8px;
        border-radius: 50%;
    }

    /* v27+:触摸设备清除 hover 状态 — iOS Safari 点击后 :hover 会粘住,
       心形按钮保持高亮导致用户视觉上分不清"已点"和"未点"。
       强制还原 hover 前的视觉,让 :active 反馈单独负责"按下"状态。 */
    .li-fav-btn:hover {
        opacity: 0.55;
        color: var(--text-mute);
        background: transparent;
    }

    /* v32 round 2:细线性按钮触摸区扩展。
       视觉 30-32 + inset -4 -6 让命中区 ≥44 (iOS HIG),
       同时清 hover sticky 反馈(同 .li-fav-btn 策略)。
       v40 P1 修复:≤720 / ≤320 min-height 30 时 -4 -6 只有 38pt 高不达 44,
       改 -6 -8 → 高度 30+12=42/32+12=44、宽度 30+16=46,真正满足 HIG。 */
    .fav-toolbar-btn::before {
        content: "";
        position: absolute;
        inset: -6px -8px;
        border-radius: var(--r-sm);
    }
    .fav-toolbar-btn:hover {
        /* 触摸设备清除 hover sticky */
        color: var(--text-soft);
        background: transparent;
    }
    .fav-toolbar-btn-danger:hover {
        color: var(--text-soft);
        background: transparent;
    }

    /* v32+:最近播放工具栏按钮触摸区扩展(与 .fav-toolbar-btn 同款策略)
       v40 P1 修复:同步 inset -6 -8 满足 iOS HIG 44pt。 */
    .recent-toolbar-btn::before {
        content: "";
        position: absolute;
        /* v42+:删 v40 P1 残留死代码 inset: -6px -8px — 紧跟的 inset: -4px -6px 立即覆盖,
           看似两个声明实则只有 -4 -6 生效。直接保留一个,避免维护者困惑。 */
        inset: -4px -6px;
        border-radius: var(--r-sm);
    }
    .recent-toolbar-btn:hover {
        /* 触摸设备清除 hover sticky */
        color: var(--text-soft);
        background: transparent;
    }
    .recent-toolbar-btn.danger:hover {
        color: var(--text-soft);
        background: transparent;
    }
}

/* ============== 全局收藏 toast ==============
   点击列表心形按钮 / 按 F 键收藏时,顶部居中浮层短暂提示"已收藏/已取消"。
   独立于弹窗内的 .fav-toast,任何页面状态都能显示。
   z-index 走 --z-toast token(原 2000 硬编码) — 与 app.css --z-* 系统对齐。
   弹窗用原生 <dialog> 的顶层渲染(top layer),CSS z-index 对其无效,
   toast 始终在弹窗之上,与 z 数值无关。 */

/* 节点由 favorites.js 动态创建,初始不挂 DOM */
.fav-global-toast {
    position: fixed;
    top: calc(20px + var(--safe-top, 0px));
    left: 50%;
    transform: translateX(-50%) translateY(-20px);
    /* v58+:var(--z-toast) 已在 :root 定义,删冗余兜底。 */
    z-index: var(--z-toast);
    padding: 10px 16px;
    background: var(--text);
    color: var(--bg-elevated);
    font-size: var(--fs-lg);
    font-weight: var(--fw-medium);
    border-radius: 999px;
    box-shadow: 0 8px 24px -6px rgba(0, 0, 0, 0.25);
    opacity: 0;
    pointer-events: none;
    transition:
        opacity 200ms var(--ease),
        transform 200ms var(--ease);
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font);
    white-space: nowrap;
    -webkit-tap-highlight-color: transparent;
}

.fav-global-toast.visible {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

.fav-global-toast svg {
    width: 16px;
    height: 16px;
    fill: var(--accent);
    stroke: var(--accent);
    stroke-width: 1.5;
    flex-shrink: 0;
}

/* "取消"分支:把心形描边变灰,提示是撤销 */
.fav-global-toast.is-remove svg {
    fill: var(--text-mute);
    stroke: var(--text-mute);
}

/* v38 P2:'success' 紫色实心心(默认就是 accent),无需覆盖。
   'error' 红色描边心 + 红字,提醒用户操作失败。 */
/* v51 P2-8:硬编码 #d44 / rgba(220,60,60,0.35) → var(--danger) + color-mix,
   与 theme.css 6 主题 --danger token 对齐。color-mix(in srgb, var(--danger) 35%, transparent)
   替代硬编码 rgba,不需新增 --danger-line token,主题切换时跟随 accent 变。 */
.fav-global-toast.is-error {
    color: var(--danger);
    border-color: color-mix(in srgb, var(--danger) 35%, transparent);
    background: var(--bg);
}
.fav-global-toast.is-error svg {
    fill: none;
    stroke: var(--danger);
    stroke-width: 1.5;
}

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

@media (prefers-reduced-motion: reduce) {
    .fav-global-toast {
        transition: none;
    }
    /* 拖动排序相关:关闭 transform/opacity 过渡,仅保留静态视觉 */
    .li-drag-handle,
    .m-music-list-wrap.is-favorites-list li.is-dragging {
        transition: none;
    }
}

/* v55+:color-mix() 浏览器兼容兜底。
   文件内 9 处 color-mix()(storage note / drop indicator / drag handle / reorder source /
   toast error 等),Safari ≤ 15.3 / 老 Edge / 部分 WebView 不支持,
   解析为 invalid → 属性降级到无背景,视觉丢失 accent 染色。
   兜底用 --accent-soft / --bg-elevated / --bg-hover / --danger 等
   现有 token,无新依赖;老浏览器看不出 accent 微差,新浏览器走 color-mix 精细效果。 */
@supports not (color-mix(in srgb, red, blue)) {
    .fav-storage-note {
        background: var(--bg-elevated);
    }
    .fav-storage-note strong {
        background: var(--bg-hover);
    }
    .m-music-list-wrap.is-favorites-list li.is-dragging {
        background: var(--accent-soft);
    }
    .m-music-list-wrap.is-favorites-list li.is-drop-before,
    .m-music-list-wrap.is-favorites-list li.is-drop-after {
        background: var(--accent-soft);
    }
    .m-music-list-wrap.is-favorites-list li.is-drop-before:hover,
    .m-music-list-wrap.is-favorites-list li.is-drop-after:hover {
        background: var(--accent-soft);
    }
    .m-music-list-wrap.is-favorites-list li.is-reorder-source {
        background: var(--accent-soft);
    }
    .li-drag-handle {
        background: var(--accent-soft);
    }
    .fav-global-toast.is-error {
        border-color: var(--danger);
    }
}
