/* ===== 在线音频管理系统 · 样式（深色/浅色双主题） ===== */
:root{
  --bg:#14161a; --panel:#1b1e24; --panel2:#21252c; --panel3:#282d35;
  --line:#2c313a; --line2:#363c46;
  --text:#e7eaf0; --sub:#8d95a3; --sub2:#6b7381;
  --accent:#4d8bff; --accent2:#3a75e0;
  --danger:#ff5b5b; --ok:#22b07d; --warn:#f2a33c; --purple:#9b6dff;
  --accent-soft:rgba(77,139,255,.14);
  --accent-text:#a9c6ff;
  --accent-ring:rgba(77,139,255,.28);
  --wave-idle:#3a4048; --wave-bg1:#191d23; --wave-bg2:#15181d;
  --track:#333944; --track-hover:#414859;
  --dot:#4a5160;
  --radius:10px;
  --shadow:0 20px 60px rgba(0,0,0,.45);
  --scrim:rgba(0,0,0,.6);
}
body.theme-light{
  --bg:#f4f6fa; --panel:#ffffff; --panel2:#f4f6fa; --panel3:#e9edf4;
  --line:#e2e7f0; --line2:#d1d8e6;
  --text:#1a1f28; --sub:#5d6573; --sub2:#8b93a2;
  --accent:#2f6fe4; --accent2:#2456bd;
  --danger:#e0454a; --ok:#12a06a; --warn:#e08c0b; --purple:#7c53e8;
  --accent-soft:rgba(47,111,228,.10);
  --accent-text:#1f5fd0;
  --accent-ring:rgba(47,111,228,.25);
  --wave-idle:#c3cbd9; --wave-bg1:#eef1f7; --wave-bg2:#e7ebf3;
  --track:#c9d1de; --track-hover:#aeb8c8;
  --dot:#98a2b3;
  --shadow:0 18px 50px rgba(31,41,60,.13);
  --scrim:rgba(20,26,38,.42);
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{
  background:var(--bg);color:var(--text);
  font:14px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei","PingFang SC",Arial,sans-serif;
  -webkit-font-smoothing:antialiased;overflow:hidden;
}
a{color:inherit;text-decoration:none}
button{font-family:inherit}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:var(--track);border-radius:6px;border:2px solid var(--bg)}
::-webkit-scrollbar-thumb:hover{background:var(--track-hover)}
::-webkit-scrollbar-track{background:transparent}

/* ---------- 登录 ---------- */
.login-body{display:flex;align-items:center;justify-content:center;background:radial-gradient(1200px 600px at 50% -10%,var(--panel2),var(--bg))}
.login-wrap{width:100%;max-width:380px;padding:20px}
.login-box{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:34px 30px 26px;box-shadow:var(--shadow)}
.login-logo{text-align:center;margin-bottom:24px}
.login-logo h1{font-size:19px;margin:12px 0 6px;letter-spacing:.5px}
.login-logo p{color:var(--sub2);font-size:12px;margin:0}
.field{margin-bottom:12px}
.field input,.mini-in,select.sel,textarea.inp{
  width:100%;background:var(--panel2);border:1px solid var(--line);color:var(--text);
  border-radius:8px;padding:10px 12px;font-size:14px;outline:none;transition:.15s;font-family:inherit;
}
/* ★第100轮:外扩 3px 光晕 + 自身 1px border = 同心双框(用户报的登录框问题)。
 * 后台表单/私信框统一改成 inset 内描边,视觉上只剩一个圆角框。
 * 下方 .dm-inp.bad(校验失败)刻意保留外扩——那是整块变红的告警态,和常态描边不冲突。 */
/* ★第100轮：后台/前台里**裸的** .inp / .sel 压根没有聚焦规则，而 .inp 自己又写了
 * outline:none —— 结果是点「搜索用户名 / 昵称」那种输入框一点反馈都没有。
 * 这里给一层 inset 内描边兜底，和登录框同一套观感（外扩会 again 出双框）。
 * 与下面 .field / .modal / .uc / .tiny-sel 同色等值，靠特异性决定谁说话，位置无所谓。 */
.inp:focus,.sel:focus{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.field input:focus,.mini-in:focus,select.sel:focus,textarea.inp:focus{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
/* 注册验证码: 输入框 + 图片并排,点击图片换一张 */
.captcha-field{display:flex;align-items:center;gap:8px}
.captcha-field input{flex:1 1 auto;min-width:0}
.captcha-field img{flex:0 0 auto;height:42px;width:118px;border:1px solid var(--line);border-radius:8px;cursor:pointer;background:var(--panel2)}

/* ★★★第107轮 —— 一次性根治「输入框外面套一个直角矩形框」（用户已两次报修）
 *
 * 【症状】聚焦输入框时，控件外面多出一圈直角矩形：上下边比左右边各窄 8px、四边互不相连。
 * 【实测像素证据】截图放大扫描：上下边 x=39..332、左右边 x=31..340。
 * 【根因】同时画了两个框，且两个框的圆角不一样：
 *   ① 外框 —— 浏览器**默认 focus ring**（outline）。它是直角、不跟随 border-radius，
 *      而且画在 <input> 自己的盒子尺寸上；
 *   ② 内框 —— 站内的 1px border + inset 描边（跟随容器的 border-radius）。
 *   容器 10px 圆角、input 直角 → 两层框必然错位，就是那个矩形。
 * 【为什么反复出现】前两轮（第100轮）只盯着「外扩 box-shadow + border = 双圆角框」，
 *   把描边改成了 inset 就收工 —— 但 outline 这一层压根没参与进来，症状被掩盖了；
 *   一旦某个内核把默认 focus ring 画出来（或 outline-offset 被别处覆盖），老毛病立刻复现。
 * 【根治】三条一起上，任何一条单独都不够：
 *   ① 所有文本类控件统一 outline:0 solid transparent + outline-offset:0，
 *      并额外压掉 old Chromium 的 -webkit-focus-ring（兼容模式的老 360 会画它）；
 *   ② 描边只由**控件自身**承担（它已经有 border-radius），不给 input 留独立圆角；
 *   ③ 键盘可达性不丢：下面这条 :focus-visible 给无障碍留一条真正的可见焦点提示，
 *      用 outline-offset 画在控件外侧 2px，与控件同色同宽 —— 这是**唯一**允许
 *      outline 出现的场景，且方向是「外扩 + 跟随圆角」，不会再和边框错位。 */
input[type=text]:focus-visible,input[type=password]:focus-visible,
input[type=number]:focus-visible,input[type=search]:focus-visible,
input[type=tel]:focus-visible,input[type=email]:focus-visible,
input[type=url]:focus-visible,input[type=date]:focus-visible,select:focus-visible,
textarea:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* ★容器型输入框（图标在框内的那种）：描边交给容器，input 必须彻底「无壳」——
   否则 input 的直角盒子会和容器的圆角框对不上，就是用户看到的那两圈。 */
input[type=text],input[type=password],input[type=number],input[type=search],
input[type=tel],input[type=email],input[type=url],input[type=date]{
  outline:0 solid transparent;outline-offset:0}
input[type=text]::-webkit-focus-ring,input[type=password]::-webkit-focus-ring,
input[type=number]::-webkit-focus-ring,select::-webkit-focus-ring,textarea::-webkit-focus-ring{
  outline:0 solid transparent}
/* ★第107轮：把上面那条 :focus-visible 兜底**显式排除**容器型输入框。
 * 上面 input[type=text]:focus-visible 的权重是 (0,2,1)，容器型选择器
 * `.lg-item input` 只有 (0,1,1) —— 靠层叠「碰巧」压过它并不是可靠做法
 * （不同内核对 :focus-visible 的 UA 层叠处理并不一致，本轮实测就出现过
 *   权重明明更高却没生效的情况）。这里用 :focus-visible 把容器型再压一遍，
 *   权重 (0,3,1) 稳赢，无论哪套实现都不会把那个矩形框放回来。
 * 容器型输入框的聚焦提示由 .lg-item/.am-auth-item 的 inset 描边提供，无障碍不丢。 */
.lg-item input:focus-visible,.am-auth-item input:focus-visible,
#amAuthBox .am-auth-item input:focus-visible,.am-auth-cap input:focus-visible{
  outline:0 solid transparent;outline-offset:0;box-shadow:none}
.login-err{color:var(--danger);font-size:13px;min-height:20px;text-align:center}
/* 字段下方的字符数/格式要求说明(独立注册页与弹窗口径一致) */
.field-hint{margin:5px 0 0;padding-left:2px;font-size:11.5px;line-height:1.6;color:var(--sub2)}
.login-tip{margin-top:16px;text-align:center;color:var(--sub2);font-size:12px}
input[type=range]{accent-color:var(--accent)}

/* ---------- 按钮 ---------- */
.btn{
  background:var(--panel3);color:var(--text);border:1px solid var(--line2);border-radius:8px;
  padding:7px 14px;font-size:13px;cursor:pointer;transition:.15s;white-space:nowrap;
}
.btn:hover{background:var(--track);border-color:var(--track-hover)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}
.btn.primary:hover{background:var(--accent2);border-color:var(--accent2)}
.btn.ghost{background:transparent}
.btn.danger{background:transparent;border-color:#5a3038;color:#ff7b7b}
.btn.danger:hover{background:#3a1f24;border-color:var(--danger)}
.btn.block{width:100%;padding:10px}
.btn.tiny{padding:4px 9px;font-size:12px}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn.x{padding:2px 7px;font-size:16px;line-height:1}

/* ---------- 布局 ---------- */
/* 第120轮：100vh 在「笔记本 1366x768 + 系统缩放 125%/150%」下会按**缩放后的 CSS 像素**
 * 计算，比实际可视高度多出一截，底部播放条/操作区被挤出屏幕；100dvh 用动态视口，
 * 与现代浏览器一致。老浏览器不认 dvh 会忽略第二条，仍用 vh —— 渐进增强，不会回退。 */
.app{display:flex;flex-direction:column;height:100vh;height:100dvh}
/* 第120轮：图片兜底。整站 img 都是具体选择器定死的尺寸，这条只做**最后一道保险**——
 * 富文本（协议正文、公告）里贴的原图常常自带上千像素宽，窄屏/高缩放下会直接撑破容器。
 * 特异性 (0,0,1) 低于任何具名选择器，不会覆盖已定死的头像/封面尺寸，只兜没被管到的。 */
img,svg,video{max-width:100%}
.topbar{height:54px;display:flex;align-items:center;gap:12px;padding:0 14px;background:var(--panel);border-bottom:1px solid var(--line);flex-shrink:0}
.brand{display:flex;align-items:center;gap:8px;font-weight:600;font-size:15px;white-space:nowrap}
.brand span{letter-spacing:.3px}
.search-box{flex:1;max-width:520px;position:relative;display:flex;align-items:center}
.search-box .ico{position:absolute;left:11px;color:var(--sub2);pointer-events:none}
.search-box input{width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:8px 32px;color:var(--text);font-size:13px;outline:none;transition:.15s}
.search-box input:focus{border-color:var(--accent);background:var(--panel3)}
.clear-btn{position:absolute;right:8px;background:none;border:0;color:var(--sub2);font-size:19px;cursor:pointer;line-height:1;padding:0 4px;display:none}
.search-box.has .clear-btn{display:block}
/* 搜索按钮: 不回车就点它,输入过程中不再自动发请求 */
.search-btn{margin-left:8px;flex:none;display:inline-flex;align-items:center;gap:5px;height:32px;padding:0 14px;
  border:1px solid var(--accent);border-radius:9px;background:var(--accent);color:#fff;font-size:13px;cursor:pointer;
  white-space:nowrap;transition:.15s}
.search-btn:hover{filter:brightness(1.08)}
.search-btn:active{transform:translateY(1px)}
.search-btn svg{flex:none}
.topbar-actions{display:flex;align-items:center;gap:8px;margin-left:auto}
/* ---------- 页面底部备案 / 版权（第72轮） ----------
 * 原先是 position:fixed 贴在 left:12px/bottom:84px 的小角标，正好压在素材库左侧文件夹树上
 * （用户反馈挡住列表最后几项），而且脱离文档流、位置和内容没关系。现在改成随内容滚动、
 * 居中的语义化 <footer>，靠 .main 的 margin-top:auto 在内容不足一屏时也贴在底部。 */
.site-foot{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:4px 0;
  margin-top:auto;padding:22px 16px 8px;font-size:12px;line-height:1.9;color:var(--sub2)}
.site-foot .sf-item{white-space:nowrap;padding:0 9px}
/* 分隔线用 1px 竖线而不是文字「·」：复制备案号时不会把分隔符一起复制走 */
.site-foot .sf-item + .sf-item{border-left:1px solid var(--line2)}
.site-foot a.sf-link{color:var(--sub2);text-decoration:none}
.site-foot a.sf-link:hover{color:var(--accent);text-decoration:underline}
/* 窄屏放不下就让它自然换行，换行后竖线分隔符反而是噪声 */
@media (max-width:640px){ .site-foot{gap:2px 0} .site-foot .sf-item + .sf-item{border-left:none} }
select.sel{width:auto;padding:7px 10px;font-size:13px;cursor:pointer;background:var(--panel3)}
select.sel.tiny{padding:3px 6px;font-size:12px}
.seg input[type=range]{width:88px}
.icon-btn{background:var(--panel3);border:1px solid var(--line2);color:var(--text);width:32px;height:32px;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;transition:.15s}
.icon-btn:hover{background:var(--track);border-color:var(--track-hover)}
.user-chip{display:flex;align-items:center;gap:8px;padding:4px 10px 4px 4px;background:var(--panel2);border:1px solid var(--line);border-radius:20px;cursor:pointer}
.user-chip .avatar{width:26px;height:26px;border-radius:50%;background:linear-gradient(135deg,var(--accent),var(--purple));display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;color:#fff}
.user-chip img.avatar{display:block;object-fit:cover}
.user-chip .uname{font-size:12px;line-height:1.25;display:flex;flex-direction:column}
.user-chip .uname em{font-style:normal;color:var(--sub2);font-size:11px}
.admin-entry{background:var(--panel3)}
.admin-entry:hover{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-text)}

.body{flex:1;display:flex;min-height:0;position:relative}

/* ---------- 侧栏 ---------- */
.sidebar{width:250px;background:var(--panel);border-right:1px solid var(--line);overflow-y:auto;flex-shrink:0;padding-bottom:30px}
.smart{padding:10px 8px;border-bottom:1px solid var(--line)}
.smart-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;cursor:pointer;color:var(--sub);font-size:13.5px;transition:.12s}
.smart-item:hover{background:var(--panel2);color:var(--text)}
.smart-item.active{background:var(--accent-soft);color:var(--accent-text);font-weight:600}
.smart-item em{margin-left:auto;font-style:normal;font-size:11.5px;color:var(--sub2);background:var(--panel3);padding:1px 7px;border-radius:9px}
.smart-item.danger:hover{color:var(--danger)}
.ic{width:16px;height:16px;flex-shrink:0;opacity:.85}
.ic-all{background:currentColor;-webkit-mask:radial-gradient(circle 3px at 50% 50%,#000 96%,transparent);mask:radial-gradient(circle 3px at 50% 50%,#000 96%,transparent)}
.ic-fav{background:currentColor;clip-path:polygon(50% 0,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%)}
.ic-time{background:currentColor;-webkit-mask:radial-gradient(circle 7px at 50% 50%,transparent 62%,#000 63%);mask:radial-gradient(circle 7px at 50% 50%,transparent 62%,#000 63%)}
.ic-tag{background:currentColor;clip-path:polygon(0 0,72% 0,100% 50%,72% 100%,0 100%)}
.ic-star{background:currentColor;clip-path:polygon(50% 0,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%)}
.ic-folder{background:currentColor;clip-path:polygon(0 18%,42% 18%,50% 30%,100% 30%,100% 100%,0 100%)}
.ic-trash{background:currentColor;clip-path:polygon(18% 12%,82% 12%,78% 26%,22% 26%,30% 100%,70% 100%)}

.side-sec{padding:12px 12px 4px;border-bottom:1px solid var(--line)}
.side-title{font-size:11.5px;color:var(--sub2);text-transform:uppercase;letter-spacing:.6px;margin-bottom:8px;display:flex;align-items:center}
.filter-pending{margin-left:auto;font-size:10.5px;color:var(--warn);background:rgba(242,163,60,.14);border:1px solid rgba(242,163,60,.35);border-radius:9px;padding:1px 7px;text-transform:none;letter-spacing:0}
.mini-actions{margin-left:auto}
.mini-actions button{background:none;border:0;color:var(--sub);cursor:pointer;font-size:15px;padding:0 4px;line-height:1}
.mini-actions button:hover{color:var(--accent)}
/* 左侧选项卡: 官方分类 / 我的收藏夹 */
.side-tabs{display:flex;gap:4px;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:3px;margin-bottom:10px}
.side-tabs .stab{flex:1;border:0;background:none;color:var(--sub);font:inherit;font-size:12.5px;padding:6px 4px;border-radius:7px;cursor:pointer;white-space:nowrap;transition:.14s}
.side-tabs .stab:hover{color:var(--text)}
.side-tabs .stab.on{background:var(--accent-soft);color:var(--accent-text);font-weight:600}
/* 第89轮：「我上传的 / 回收站」快捷行（第88轮撤出顶栏宫格、第89轮又撤出个人中心侧栏，
 * 入口落在这里）。行式而不是宫格式：左栏本来就窄，两项用图标+文字+计数一行排开刚好。
 * 计数 .sq-n 只在 >0 时显示（JS 负责置 hidden），0 就一个数字都不占。 */
.side-quick{display:flex;gap:6px;margin:-4px 0 10px}
.side-quick .sq{flex:1;min-width:0;display:flex;align-items:center;gap:5px;justify-content:center;
  border:1px solid var(--line);background:var(--panel2);color:var(--sub);font:inherit;font-size:12px;
  padding:6px 4px;border-radius:8px;cursor:pointer;transition:.14s;white-space:nowrap}
.side-quick .sq:hover{border-color:var(--accent);color:var(--text)}
.side-quick .sq.on{background:var(--accent-soft);border-color:transparent;color:var(--accent-text);font-weight:600}
.side-quick .sq svg{flex-shrink:0;opacity:.85}
.side-quick .sq-n{font-size:10.5px;font-weight:700;color:var(--sub2);background:var(--panel);
  border:1px solid var(--line);border-radius:8px;padding:0 5px;line-height:1.5;min-width:16px;text-align:center}
.side-quick .sq.on .sq-n{color:var(--accent-text);border-color:transparent;background:rgba(255,255,255,.55)}
/* 收藏夹列表(复用文件夹树的行式观感) */
.fc-list{font-size:13.5px}
.fc-list .fc-item{display:flex;align-items:center;gap:6px;padding:6px 8px;border-radius:7px;cursor:pointer;color:var(--sub);position:relative}
.fc-list .fc-item:hover{background:var(--panel2);color:var(--text)}
.fc-list .fc-item.active{background:var(--accent-soft);color:var(--accent-text)}
.fc-list .fc-item .fdot{width:8px;height:8px;border-radius:2px;flex-shrink:0;background:var(--dot)}
.fc-list .fc-item .fname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fc-list .fc-item .fcnt{font-size:11px;color:var(--sub2)}
.fc-list .fc-item .fc-more{font-size:14px;line-height:1;color:var(--sub2);padding:0 2px;border-radius:4px}
.fc-list .fc-item .fc-more:hover{color:var(--accent-text);background:var(--panel)}
/* 收藏夹树: 展开箭头(叶子占位保持缩进对齐) */
.fc-list .fc-item .fc-tw{width:12px;flex-shrink:0;text-align:center;font-size:10px;line-height:1;color:var(--sub2);transition:transform .14s}
.fc-list .fc-item .fc-tw.open{transform:rotate(90deg)}
.fc-list .fc-item .fc-tw.leaf{opacity:0}
.fc-list .fc-item .fc-tw:hover{color:var(--text)}
.fc-add{margin-top:8px;width:100%;border:1px dashed var(--line2);background:none;color:var(--sub);font:inherit;font-size:12.5px;padding:6px;border-radius:7px;cursor:pointer}
.fc-add:hover{color:var(--accent-text);border-color:var(--accent);background:var(--accent-soft)}
/* 收藏弹窗里的分类选择 */
.fc-pick{max-height:230px;overflow:auto;margin:10px 0}
.fc-pick .fc-opt{display:flex;align-items:center;gap:8px;padding:7px 9px;border-radius:7px;font-size:12.5px;color:var(--text);cursor:pointer}
.fc-pick .fc-opt:hover{background:var(--panel2)}
.fc-pick .fc-opt.on{background:var(--accent-soft);color:var(--accent-text)}
.fc-pick .fc-opt .fb-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fc-pick .fc-opt .fb-count{font-size:11.5px;color:var(--sub2)}
.fc-pick .fc-opt .fb-dot{width:12px;height:12px;border-radius:50%;border:2px solid var(--line2);flex-shrink:0}
.fc-pick .fc-opt.on .fb-dot{border-color:var(--accent);background:var(--accent)}
.fc-newrow{display:flex;gap:6px}
.fc-newrow .inp{flex:1}
/* 详情面板「⏸ 暂停」态 */
/* 播放中: 蓝底白字(按钮本体是 primary 蓝底,若只改文字色会蓝底配深蓝字,看不清) */
.btn.tiny.playing{background:var(--accent);border-color:var(--accent);color:#fff}
.btn.tiny.playing:hover{background:var(--accent2);border-color:var(--accent2);color:#fff}

.tree{font-size:13.5px}
.tree-sk{padding:8px 10px;color:var(--sub2);font-size:12.5px}
.tree-item{display:flex;align-items:center;gap:6px;padding:6px 8px;border-radius:7px;cursor:pointer;color:var(--sub);position:relative}
.tree-item:hover{background:var(--panel2);color:var(--text)}
.tree-item.active{background:var(--accent-soft);color:var(--accent-text)}
.tree-item .fdot{width:8px;height:8px;border-radius:2px;flex-shrink:0;background:var(--dot)}
.tree-item .fname{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tree-item .fcnt{font-size:11px;color:var(--sub2)}
.tree-children{margin-left:12px;border-left:1px solid var(--line);padding-left:6px}
.drop-hint{background:var(--accent-soft)!important;outline:1px dashed var(--accent)}

.tagcloud{display:flex;flex-wrap:wrap;gap:6px;padding-bottom:8px}
.tag-pill{background:var(--panel2);border:1px solid var(--line);border-radius:20px;padding:3px 10px;font-size:12px;cursor:pointer;color:var(--sub);transition:.12s;white-space:nowrap;max-width:120px;overflow:hidden;text-overflow:ellipsis}
.tag-pill:hover{border-color:var(--accent);color:var(--text)}
.tag-pill.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-text)}
.tag-pill i{font-style:normal;color:var(--sub2);font-size:11px;margin-left:4px}

.filter-line{display:flex;align-items:center;gap:6px;margin-bottom:9px;font-size:12.5px}
.filter-line label{color:var(--sub2);width:56px;flex-shrink:0}
.exts{display:flex;flex-wrap:wrap;gap:4px}
.ext-pill{background:var(--panel2);border:1px solid var(--line);border-radius:5px;padding:2px 7px;font-size:11.5px;cursor:pointer;color:var(--sub)}
.ext-pill.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-text)}
.stars-filter{display:flex;flex-wrap:wrap;gap:3px}
.stars-filter span{background:var(--panel2);border:1px solid var(--line);border-radius:5px;padding:2px 6px;font-size:11px;cursor:pointer;color:var(--sub)}
.stars-filter span.on{background:rgba(242,163,60,.18);border-color:var(--warn);color:var(--warn)}
.mini-in{width:62px;padding:4px 7px;font-size:12px}
.dash{color:var(--sub2)}
.colors{display:flex;flex-wrap:wrap;gap:4px}
.color-dot{width:18px;height:18px;border-radius:50%;cursor:pointer;border:2px solid transparent;transition:.12s}
.color-dot.on{border-color:var(--text);transform:scale(1.12)}
.color-dot.none{background:repeating-linear-gradient(45deg,var(--dot),var(--dot) 4px,var(--panel2) 4px,var(--panel2) 8px)}
.filter-btns{display:flex;gap:8px;margin:10px 0 12px}
.filter-btns .btn{flex:1}

/* ---------- 主区 ---------- */
/* 竖向 flex 只为了两件事：① 底部的 .site-foot 能靠 margin-top:auto 贴底；
 * ② 内容不足一屏时 footer 不会吊在半空。子项全部 flex-shrink:0 —— 否则内容超高时
 * 会被压扁（而不是交给 overflow-y 滚动），网格卡片会被挤变形。 */
.main{flex:1;overflow-y:auto;padding:0 0 40px;position:relative;min-width:0;display:flex;flex-direction:column}
.main>*{flex-shrink:0}
.crumb-bar{position:sticky;top:0;z-index:5;background:var(--bg);padding:12px 16px 8px;display:flex;align-items:center;gap:10px;border-bottom:1px solid var(--line)}
.crumb{font-size:15px;font-weight:600}
.crumb-right{margin-left:auto;display:flex;align-items:center;gap:8px}
.list-stat{color:var(--sub2);font-size:12px}

/* 已生效的筛选条件(可单独移除) */
.active-filters{display:flex;align-items:center;gap:6px;padding:10px 16px 0;flex-wrap:wrap}
.af-label{font-size:11.5px;color:var(--sub2)}
.af-chip{display:inline-flex;align-items:center;gap:5px;background:var(--accent-soft);border:1px solid var(--accent);color:var(--accent-text);border-radius:20px;padding:2px 9px;font-size:11.5px;cursor:pointer}
.af-chip i{font-style:normal;font-size:13px;line-height:1;opacity:.7}
.af-chip:hover i{opacity:1}

.batch-bar{display:flex;align-items:center;gap:12px;margin:10px 16px;padding:8px 12px;background:var(--accent-soft);border:1px solid var(--accent);border-radius:9px;font-size:13px;flex-wrap:wrap}
.batch-actions{display:flex;gap:6px;align-items:center;margin-left:auto;flex-wrap:wrap}
.batch-bar b{color:var(--accent)}

.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--cw,180px),1fr));gap:12px;padding:14px 16px}
.card{background:var(--panel2);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;cursor:pointer;transition:.14s;position:relative;user-select:none}
.card:hover{border-color:var(--line2);transform:translateY(-2px);box-shadow:0 6px 18px rgba(0,0,0,.28)}
.card.sel{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-ring)}
/* 后台文件管理点标题跳转过来时的高亮脉冲 */
.card.focus-hl{border-color:var(--accent);animation:focusPulse 1s ease-in-out 4}
@keyframes focusPulse{0%,100%{box-shadow:0 0 0 3px var(--accent-ring)}50%{box-shadow:0 0 0 7px var(--accent-ring),0 0 30px var(--accent-ring)}}
.card.playing{border-color:var(--ok)}
.card .cwave{display:block;width:100%;height:62px;background:linear-gradient(180deg,var(--wave-bg1),var(--wave-bg2))}
/* 「关闭预览」态(顶栏用户菜单切换): 卡片不画波形,整块换成文件格式文字 */
.card .cfmt{display:none;width:100%;height:62px;align-items:center;justify-content:center;
  background:linear-gradient(180deg,var(--wave-bg1),var(--wave-bg2));color:var(--sub2);
  font:700 19px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;letter-spacing:1.5px}
body.preview-off .card .cwave{display:none}
body.preview-off .card .cfmt{display:flex}
.card .cbar{height:3px;width:100%}
.card .cbody{padding:8px 10px 9px}
/* 卡片标题：最多一行、超框打省略号（第57轮，用户要求由两行收紧到一行）。
 * 原来是 -webkit-line-clamp:2 + 固定 35px 高 —— 标题一长就顶成两行把卡片撑高，
 * 一行内容占两行位置，网格里看着参差不齐。完整标题走 title 悬停，不丢信息。
 * 高度必须写死成 line-height 的整数倍，否则偶发出现半行裁切。 */
.card .ctitle{font-size:13px;line-height:18px;height:18px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.card .cmeta{display:flex;align-items:center;gap:6px;margin-top:5px;font-size:11px;color:var(--sub2)}
.card .cmeta .dur{background:var(--panel3);padding:1px 6px;border-radius:4px;color:var(--sub)}
.card .ctags{display:flex;gap:4px;margin-top:6px;flex-wrap:wrap;height:18px;overflow:hidden}
.card .ctag{font-size:10.5px;background:var(--panel3);color:var(--sub);padding:1px 6px;border-radius:9px;
  max-width:58px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card .cstars{position:absolute;top:6px;left:6px;font-size:11px;color:var(--warn);text-shadow:0 1px 3px rgba(0,0,0,.35)}
/* 五角星: 未收藏 = 置灰(悬停才浮现,提示可收藏);已收藏 = 金色常亮 */
.card .cfav{position:absolute;top:4px;right:4px;color:var(--sub2);font-size:14px;text-shadow:0 1px 3px rgba(0,0,0,.35);opacity:0}
/* 相似素材角标: 精确搜索无命中、展示模糊匹配推荐结果时,卡片左上角标识 */
.card .csim{position:absolute;top:6px;left:6px;z-index:2;font-size:10.5px;line-height:1;padding:3px 7px;border-radius:4px;background:var(--accent);color:#fff;box-shadow:0 1px 4px rgba(0,0,0,.25);pointer-events:none;letter-spacing:.5px}
.card:hover .cfav{opacity:.8}
.card .cfav.on{color:var(--warn);opacity:1}
.card .cinfo{position:absolute;top:4px;right:26px;color:#fff;font-size:13px;text-shadow:0 1px 3px rgba(0,0,0,.5);opacity:0;transition:.12s}
.card:hover .cinfo{opacity:.85}
.card .cinfo:hover{opacity:1}
.card .ccheck{position:absolute;top:6px;right:6px;width:18px;height:18px;border-radius:5px;border:1.5px solid rgba(255,255,255,.45);background:rgba(0,0,0,.35);display:none;align-items:center;justify-content:center;font-size:12px;color:#fff}
.card.sel .ccheck{display:flex;background:var(--accent);border-color:var(--accent)}
.card .cfolder{font-size:10.5px;color:var(--sub2);margin-top:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 「我的自定义标签」角标: 个人颜色 + 自定义标签(仅本人可见,与公共标签/颜色区分开)。
   走文档流跟在官方标签行下面,不再绝对定位 —— 否则两行标签重叠看不清 */
.card .cmymark{display:inline-flex;align-items:center;gap:4px;margin-top:5px;max-width:100%;
  background:var(--panel3);color:var(--sub);border-radius:9px;padding:1px 7px;font-size:10.5px;line-height:16px;pointer-events:none}
.card .cmymark span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:58px;flex-shrink:1;min-width:0}
.card .cmymark .mm-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;box-shadow:0 0 0 1.5px rgba(255,255,255,.45)}

/* 列表模式 */
.grid.list-mode{grid-template-columns:1fr;gap:6px;padding:10px 16px}
.grid.list-mode .card{display:flex;align-items:center;gap:10px;padding:6px 10px 6px 6px;transform:none}
.grid.list-mode .card:hover{transform:none}
.grid.list-mode .card .cwave{width:72px;height:34px;flex-shrink:0;border-radius:5px}
.grid.list-mode .card .cfmt{width:72px;height:34px;flex-shrink:0;border-radius:5px;font-size:12px;letter-spacing:.5px}
.grid.list-mode .card .cbody{padding:0;display:flex;align-items:center;gap:10px;flex:1;min-width:0}
/* 列表模式：基础规则已经是单行省略，这里只放开固定高度并让标题吃掉剩余宽度 */
.grid.list-mode .card .ctitle{height:auto;flex:1;min-width:0}
.grid.list-mode .card .cmeta{margin-top:0;flex-shrink:0}
.grid.list-mode .card .ctags,.grid.list-mode .card .cfolder{display:none}
.grid.list-mode .card .cmymark{flex-shrink:0;margin-top:0}
.grid.list-mode .card .cstars,.grid.list-mode .card .cfav{position:static;text-shadow:none;opacity:1;flex-shrink:0}
.grid.list-mode .card .csim{position:static;flex-shrink:0;order:-1}
.grid.list-mode .card .ccheck{position:static;width:16px;height:16px;display:flex;flex-shrink:0}

.empty{text-align:center;padding:70px 20px;color:var(--sub2)}
.empty p{margin:14px 0 4px;color:var(--sub);font-size:15px}
.empty span{font-size:13px}
.pager{display:flex;justify-content:center;align-items:center;gap:8px;padding:18px}
.pager button{background:var(--panel2);border:1px solid var(--line);color:var(--text);border-radius:7px;padding:5px 12px;cursor:pointer;font-size:13px}
.pager button:hover:not(:disabled){border-color:var(--accent)}
.pager button:disabled{opacity:.4;cursor:not-allowed}
.pager .pinfo{color:var(--sub2);font-size:12.5px}
.load-more{display:flex;justify-content:center;padding:14px 0 6px}
.load-more button{background:var(--panel2);border:1px solid var(--line);color:var(--text);border-radius:8px;padding:7px 22px;cursor:pointer;font-size:13px}
.load-more button:hover{border-color:var(--accent);color:var(--accent)}

/* ---------- 详情 ---------- */
/* 详情面板 = 覆盖式抽屉(绝对定位悬浮在内容右侧):
   以前是 flex 布局里的实体列,每次点预览打开详情都会把网格挤窄(5列→4列,卡片肉眼可见变小,
   用户报"播放预览时素材会逐渐缩小");改悬浮后网格宽度恒定,预览不再引发版面收缩。 */
.detail{position:absolute;top:0;right:0;bottom:0;width:330px;background:var(--panel);border-left:1px solid var(--line);
  overflow-y:auto;display:flex;flex-direction:column;z-index:40;box-shadow:-12px 0 32px rgba(0,0,0,.16)}
/* 第81轮：面板打开时主内容「让位」。
 * 以前是纯悬浮覆盖，会把最右一列的卡片（多半就是你刚点开、正在播的那张）盖掉一半，
 * 反馈"素材详情弹出会遮盖"。现在 main 加 has-detail 后整块内容往左收 330+16，
 * 面板正好落在收出来的空档里，谁也不遮谁 —— 代价是列表可用宽度少 330px（行末可能少一列），
 * 这是用户明确拍的方向（他也不想卡片缩水）。小于 1000px 没有富余空间，仍走原覆盖。 */
main.has-detail{padding-right:calc(330px + 16px);transition:padding-right .18s ease}
@media (max-width:1000px){main.has-detail{padding-right:0}}
.detail-head{position:sticky;top:0;background:var(--panel);padding:12px 14px;border-bottom:1px solid var(--line);display:flex;align-items:center;font-weight:600;font-size:14px;z-index:2}
.detail-head .x{margin-left:auto;background:none;border:0;color:var(--sub);font-size:20px;cursor:pointer;line-height:1;padding:0}
.detail-head .x:hover{color:var(--text)}
.detail-body{padding:14px}
/* 详情标题：最多一行、超出打省略号（第56轮限两行 → 第57轮按用户要求收紧到一行）。
 * 以前只有 word-break:break-all：长标题（尤其「222…」这种无空格长串）会一路往下撑，
 * 每行都顶到面板右边缘，看着就像「文字超出框」。现在单行 + …，完整标题走 title 悬停。
 * 管理员/作者能在线改标题（contenteditable），编辑时必须放开限制，否则改到后半段就看不见了。 */
.d-title{font-size:16px;font-weight:600;line-height:1.4;overflow:hidden;
  white-space:nowrap;text-overflow:ellipsis}
.d-title[contenteditable]:focus{white-space:normal;overflow:visible;outline:none;border-bottom:1px solid var(--accent)}
.d-actions{display:flex;gap:6px;margin:10px 0 14px;flex-wrap:wrap}
/* 详情音频规格速览条: 替代原波形位,时长/格式/大小/比特率/采样率/声道一排小卡 */
.d-spec{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:14px}
.d-spec .spec{flex:1 1 calc(33.33% - 6px);min-width:86px;box-sizing:border-box;background:var(--panel2);
  border:1px solid var(--line);border-radius:8px;padding:7px 9px;display:flex;flex-direction:column;gap:2px}
.d-spec .spec b{font-size:12.5px;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.d-spec .spec em{font-style:normal;font-size:10.5px;color:var(--sub2)}
.d-sec{margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.d-sec h4{margin:0 0 10px;font-size:12px;color:var(--sub2);text-transform:uppercase;letter-spacing:.6px;font-weight:600;display:flex;align-items:center}
.d-sec h4 .d-hint{font-style:normal;text-transform:none;letter-spacing:0;font-weight:400;font-size:11px;margin-left:6px;color:var(--sub2);background:var(--panel3);border-radius:9px;padding:1px 7px}
/* 区块标题右侧的操作按钮(添加标签 / 标签管理),不与标签混排 */
.d-sec h4 .d-sec-t{flex-shrink:0;white-space:nowrap}
.d-sec h4 .d-hint{flex-shrink:0;white-space:nowrap}
.d-sec h4 .d-ops{flex-shrink:0}
.d-ops{margin-left:auto;display:inline-flex;gap:6px;align-items:center}
.d-ops .tag-pill{font-size:11px;padding:2px 8px}
/* 我的自定义标签区: 色板与标签留出呼吸感 */
.d-my .color-row{margin-top:2px;padding-bottom:4px}
/* 标签容器: 独立圆角盒子,标签多时限高滚动,不再把按钮挤进标签流 */
.tag-box{display:flex;flex-wrap:wrap;gap:6px;align-content:flex-start;background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:9px 11px;max-height:126px;overflow-y:auto;margin-top:10px}
.tag-box:empty{display:none}
/* 我的自定义标签 chips(合并版): off=未打(描边置灰,可点) / on=已打(主题色高亮,带 ✕) */
.tag-pill.mine{cursor:pointer;user-select:none;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tag-pill.mine.off{color:var(--sub);background:transparent;border-style:dashed}
.tag-pill.mine.off:hover{border-color:var(--accent);color:var(--text);border-style:solid}
.tag-pill.mine.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-text);font-weight:600}
/* 高亮标签自适应宽度: 不强制每排几个,按文字自然占宽,尽量利用行空间 */
.d-my .tag-box .tag-pill.mine.on{max-width:100%;justify-content:center;box-sizing:border-box}
/* 详情-信息表: 标签列与值列必须垂直居中在同一基线 ——
   否则 dt/dd 各自贴顶,行内还混着 inline-flex(头像)与 inline-block(按钮),
   基线对齐会把按钮往下推 8px(用户反馈的「错位」)。 */
.meta-table{display:grid;grid-template-columns:78px 1fr;gap:6px 10px;font-size:12.5px;align-items:center}
.meta-table dt{color:var(--sub2)}
.meta-table dd{margin:0;color:var(--text);word-break:break-all;display:flex;align-items:center;gap:9px;flex-wrap:wrap;min-width:0}
/* 详情-上传者: 头像+名称,可点击进入 TA 的主页 */
.d-owner{display:inline-flex;align-items:center;gap:7px;color:var(--text);text-decoration:none;border-radius:20px;padding:2px 8px 2px 2px;margin-left:-2px;transition:.12s}
.d-owner:hover{background:var(--panel2)}
.d-owner:hover b{color:var(--accent-text)}
.d-owner b{font-weight:500}
.d-avatar{width:26px;height:26px;border-radius:50%;object-fit:cover;background:var(--panel2);flex-shrink:0;border:1px solid var(--line)}
.d-avatar.lt{display:none;align-items:center;justify-content:center;font-size:13px;font-weight:600;color:#fff;background:var(--accent);border:none}
.star-row{display:flex;gap:3px;font-size:21px;color:var(--wave-idle);cursor:pointer}
.star-row span.on{color:var(--warn)}
.color-row{display:flex;gap:7px;flex-wrap:wrap;margin-top:8px}
.color-row .color-dot{width:22px;height:22px}
.tag-edit{display:flex;flex-wrap:wrap;gap:5px;align-items:center}
.tag-edit .tag-pill{padding:3px 8px}
.tag-edit .add-tag{background:transparent;border:1px dashed var(--line2);color:var(--sub2)}
textarea.inp{min-height:64px;resize:vertical;font-size:13px;line-height:1.5}
.save-row{margin-top:8px;display:flex;gap:6px}

/* ---------- 播放器 ---------- */
.player{height:72px;background:var(--panel);border-top:1px solid var(--line);display:flex;align-items:center;gap:16px;padding:0 16px;flex-shrink:0}
.pl-info{display:flex;align-items:center;gap:12px;width:280px;min-width:180px}
.pl-info canvas{width:220px;height:34px;border-radius:6px;background:var(--wave-bg2);cursor:pointer}
.pl-meta{display:flex;flex-direction:column;overflow:hidden}
.pl-meta b{font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pl-meta span{font-size:11.5px;color:var(--sub2)}
.pl-ctrl{display:flex;align-items:center;gap:10px;flex:1;justify-content:center}
.pl-btn{background:var(--panel3);border:1px solid var(--line);color:var(--text);width:32px;height:32px;border-radius:8px;cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center;transition:.12s}
.pl-btn:hover{background:var(--track)}
.pl-btn.big{width:38px;height:38px;border-radius:50%;background:var(--accent);border-color:var(--accent);color:#fff;font-size:14px}
.pl-btn.big:hover{background:var(--accent2)}
.pl-btn.on{color:var(--accent-text);border-color:var(--accent);background:var(--accent-soft)}.pl-time{font-size:12px;color:var(--sub);min-width:92px;text-align:center;font-variant-numeric:tabular-nums}
.pl-right{display:flex;align-items:center;gap:10px}
.pl-right input[type=range]{width:84px}

/* ---------- 浮层 ---------- */
.drop-mask{position:fixed;inset:0;background:var(--scrim);z-index:100;display:none;align-items:center;justify-content:center;border:3px dashed var(--accent)}
.drop-mask.on{display:flex}
.drop-inner{font-size:20px;color:var(--accent-text)}

.toast-wrap{position:fixed;top:70px;right:18px;z-index:200;display:flex;flex-direction:column;gap:8px;align-items:flex-end}
.toast{background:var(--panel3);border:1px solid var(--line2);border-left:3px solid var(--accent);border-radius:8px;padding:10px 16px;font-size:13px;box-shadow:0 8px 24px rgba(0,0,0,.3);animation:slideIn .22s ease;max-width:340px}
.toast.err{border-left-color:var(--danger)}
.toast.ok{border-left-color:var(--ok)}
@keyframes slideIn{from{transform:translateX(30px);opacity:0}to{transform:none;opacity:1}}

.modal-wrap{position:fixed;inset:0;background:var(--scrim);z-index:150;align-items:center;justify-content:center;backdrop-filter:blur(2px)}
/* 弹窗默认收窄到 520px(信息确认/表单类足够),大内容弹窗手动加 .wide 放宽 */
/* 旧 Chromium(<79,如部分 360 版本)不认 min(): 先给固定宽度兜底,新内核用 min() 覆盖 */
.modal{background:var(--panel);border:1px solid var(--line2);border-radius:14px;width:520px;width:min(520px,92vw);max-height:86vh;overflow:auto;box-shadow:var(--shadow);animation:modalIn .18s ease}
.modal.wide{width:680px;width:min(680px,92vw)}
@keyframes modalIn{from{transform:translateY(10px) scale(.98);opacity:0}to{transform:none;opacity:1}}
.modal-head{display:flex;align-items:center;padding:15px 20px;border-bottom:1px solid var(--line);font-size:15.5px;font-weight:600;position:sticky;top:0;background:var(--panel);z-index:2}
.modal-head .x{margin-left:auto;background:none;border:0;color:var(--sub);font-size:22px;cursor:pointer;line-height:1}
.modal-body{padding:18px 20px}
.modal-foot{padding:13px 20px;border-top:1px solid var(--line);display:flex;gap:8px;justify-content:flex-end;position:sticky;bottom:0;background:var(--panel)}
/* 弹窗内输入控件: 统一高度/圆角/聚焦光圈,更有"官方"质感 */
.modal .inp,.modal .sel,.modal input[type=text],.modal input[type=password],.modal input[type=number],.modal textarea{
  height:38px;padding:0 12px;border:1px solid var(--line2);border-radius:9px;background:var(--panel2);color:var(--text);
  font-size:13px;outline:none;transition:border-color .15s, box-shadow .15s}
.modal textarea{height:auto;padding:10px 12px;line-height:1.7;resize:vertical}
/* ★第100轮:同一控件上「1px border」+「外扩 box-shadow」会形成同心目标的两个圆角框
 * (用户报的登录框双边框就是这个)。这里统一用 inset 内描边吃掉自身 border,不再外扩。 */
.modal .inp:focus,.modal .sel:focus,.modal input:focus,.modal textarea:focus{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.form-row{display:flex;align-items:center;gap:10px;margin-bottom:12px}
/* 只作用于「行首的字段名」——必须用 > 限定直接子级:
   .form-row 里还嵌着别的 label(权限卡 / 选项行 / 下载地址的加密勾选),
   后者被这条 96px 定宽压成细条,文字逐字换行(用户反馈的「后台编辑弹窗很丑」)。 */
.form-row>label{width:96px;color:var(--sub);font-size:13px;flex-shrink:0}
.form-row .val{flex:1;display:flex;gap:8px;align-items:center;flex-wrap:wrap;min-width:0}
/* 表单里要独占一整行的字段块(说明文字 / 权限网格 / 选项行) */
.fld-full{flex:1 1 100%;min-width:0}
/* 多行配置(如「禁止使用的用户名」): 标题一行、控件整宽一行、说明在下方,避免被长文案挤成细条 */
.form-row.stack{flex-direction:column;align-items:stretch;gap:6px}
.form-row.stack label{width:auto;color:var(--text);font-weight:600}
.form-row.stack .val{flex-direction:column;align-items:stretch;gap:6px}
.form-row input[type=text],.form-row input[type=number],.form-row textarea{flex:1;background:var(--panel2);border:1px solid var(--line);border-radius:7px;padding:7px 10px;color:var(--text);font-size:13px;outline:none;font-family:inherit}
.form-row input:focus,.form-row textarea:focus{border-color:var(--accent)}
/* 第64轮：编辑投稿弹窗两列栅格 + 投稿审核列表行压缩 + 锁定标识 */
.fe-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px 22px;margin-bottom:6px}
.fe-grid .form-row{margin-bottom:0}
.fe-grid .col-2{grid-column:1 / -1}
@media(max-width:720px){.fe-grid{grid-template-columns:1fr}.fe-grid .col-2{grid-column:auto}}
/* 第65轮：编辑投稿弹窗 —— 下拉框与文本框对齐 / 标签·推荐等级并排 / 音频数据一行三列 */
/* 必须「锁宽 + 锁高 + 锁圆角」一起做：只写 width:100% 时 select 仍走 .modal .sel(38px 高 / 圆角 9px)，
   而相邻文本框走 .form-row input(padding 7px → 约 32px 高 / 圆角 7px)，
   两者一高一矮、圆角不一，正是「下拉框和文本框没对齐」的成因。 */
.fe-grid .form-row select.sel,
.fe-grid .form-row input[type=text],
.fe-grid .form-row input[type=number]{
  width:100%;height:38px;box-sizing:border-box;padding:0 12px;border-color:var(--line2);border-radius:9px}
.fe-tag-wrap{width:100%;min-width:0}
.fe-tag-inp{position:relative;display:flex;gap:6px;align-items:center}
.fe-tag-inp>input{flex:1;min-width:0}
.fe-tag-sel:empty{display:none}
.fe-meta-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;width:100%}
@media(max-width:560px){.fe-meta-grid{grid-template-columns:1fr 1fr}}
.au-info{font-size:11.5px;line-height:1.6;color:var(--sub);max-height:2.9em;overflow:hidden}
.lock-tag{display:inline-block;padding:2px 8px;border-radius:20px;background:rgba(229,72,77,.14);color:var(--danger);font-size:12px;font-weight:500;white-space:nowrap;vertical-align:middle}
.btn.warn{background:rgba(229,72,77,.12);color:var(--danger);border-color:rgba(229,72,77,.32)}
.btn.warn:hover{background:rgba(229,72,77,.2)}
.hint{color:var(--sub2);font-size:12px;margin-top:4px;line-height:1.6}

.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:10px;margin-bottom:16px}
.stat-box{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:14px;text-align:center}
.stat-box b{display:block;font-size:22px;color:var(--accent);margin-bottom:2px}
.stat-box span{font-size:12px;color:var(--sub2)}
.bar-row{display:flex;align-items:center;gap:10px;margin-bottom:7px;font-size:12.5px}
.bar-row .bl{width:52px;color:var(--sub)}
.bar-row .bar{flex:1;height:8px;background:var(--panel2);border-radius:4px;overflow:hidden}
.bar-row .bar i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--purple));border-radius:4px}
.bar-row .bv{width:56px;text-align:right;color:var(--sub2)}

.browse{background:var(--panel2);border:1px solid var(--line);border-radius:8px;max-height:220px;overflow:auto;padding:6px}
.browse-item{padding:5px 8px;border-radius:6px;cursor:pointer;font-size:13px;color:var(--sub);display:flex;align-items:center;gap:6px}
.browse-item:hover{background:var(--panel3);color:var(--text)}
.browse-up{color:var(--warn)!important}
table.tbl{width:100%;border-collapse:collapse;font-size:13px}
table.tbl th,table.tbl td{padding:7px 10px;border-bottom:1px solid var(--line);text-align:left}
table.tbl th{color:var(--sub2);font-weight:600;font-size:12px}
table.tbl tr:hover td{background:var(--panel2)}

.upload-prog{margin-top:10px;font-size:12.5px;color:var(--sub)}
.prog{height:6px;background:var(--panel2);border-radius:3px;overflow:hidden;margin-top:6px}
.prog i{display:block;height:100%;background:var(--accent);transition:.3s}

.menu{position:fixed;background:var(--panel3);border:1px solid var(--line2);border-radius:9px;padding:5px;z-index:300;box-shadow:0 10px 30px rgba(0,0,0,.4);min-width:150px}
.menu-item{padding:7px 12px;border-radius:6px;cursor:pointer;font-size:13px;color:var(--text);display:flex;align-items:center;gap:8px}
.menu-item:hover{background:var(--accent);color:#fff}
.menu-item.danger{color:var(--danger)}
.menu-item.danger:hover{background:var(--danger);color:#fff}
.menu-sep{height:1px;background:var(--line2);margin:4px 2px}

/* ===== 管理中心 ===== */
.admin-body{overflow:auto}
.admin-body .topbar .logo{display:flex;align-items:center;gap:8px;font-weight:600;font-size:15px}
.admin-body .topbar .badge{font-style:normal;font-size:11px;background:var(--accent-soft);color:var(--accent-text);border:1px solid var(--accent);border-radius:9px;padding:1px 8px;margin-left:6px;font-weight:400}
.admin-body .top-right{margin-left:auto;display:flex;align-items:center;gap:12px;font-size:13px}
.top-link{color:var(--sub);font-size:13px}
.top-link:hover{color:var(--accent)}
.top-user{color:var(--sub2);font-size:12.5px}
/* 第120轮：同 .app，补 dvh 兜底（笔记本 768 高 + 缩放时 vh 会算多，底栏被挤出可视区） */
.admin-layout{display:flex;min-height:calc(100vh - 55px);min-height:calc(100dvh - 55px);align-items:stretch}
/* 侧栏 · 分组式导航(第39轮): 概览 / 内容 / 用户 / 系统 四组, 组内合并同类功能 */
.admin-nav{width:196px;background:var(--panel);border-right:1px solid var(--line);padding:12px 10px 26px;flex-shrink:0;
  position:sticky;top:0;align-self:flex-start;max-height:calc(100vh - 55px);max-height:calc(100dvh - 55px);overflow-y:auto;box-sizing:border-box}
.admin-nav a{display:block;padding:9px 11px;border-radius:9px;color:var(--sub);font-size:13.5px;cursor:pointer;margin-bottom:2px;
  transition:background .14s,color .14s}
.admin-nav a:hover{background:var(--panel2);color:var(--text)}
.admin-nav a.on{background:var(--accent-soft);color:var(--accent-text);font-weight:600}
/* 线性图标(去 emoji,统一描边风格) */
.ai{flex-shrink:0;vertical-align:-2px;opacity:.9}
.admin-nav a{display:flex;align-items:center;gap:9px;position:relative}
.admin-nav a .ai{opacity:.75}
.admin-nav a:hover .ai,.admin-nav a.on .ai{opacity:1}
/* 分组标题: 小号、弱化、字距拉开, 整组都不可见时由 JS 一并隐藏 */
.anav-sec{margin-bottom:4px}
.anav-t{font-size:11px;font-weight:600;color:var(--sub2);letter-spacing:.1em;padding:11px 11px 5px;user-select:none}
.anav-sec:first-child .anav-t{padding-top:2px}
/* 侧栏待办角标(投稿审核 / 站内信未读 / 待升级迁移) */
.admin-nav a .nav-badge{margin-left:auto;min-width:18px;height:18px;padding:0 5px;border-radius:9px;
  background:var(--danger,#e5484d);color:#fff;font-size:11px;line-height:18px;text-align:center;font-weight:600}
/* 顶栏返回链接: 图标+文字,稳重不浮夸 */
.topbar .top-link{display:inline-flex;align-items:center;gap:5px}
.admin-body .top-link .ai{opacity:.8}
.admin-body .top-link:hover .ai{opacity:1;transform:translateX(-1px)}
.admin-body .top-link .ai{transition:transform .15s}
.admin-main{flex:1;padding:20px 22px;min-width:0;overflow-x:auto}
.admin-main h2{margin:0 0 16px;font-size:17px}
.admin-panel{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px 18px;margin-bottom:16px}
.admin-panel h3{margin:0 0 14px;font-size:14px;display:flex;align-items:center;gap:8px}
.admin-panel h3 .sp{margin-left:auto;font-weight:400;font-size:12px;color:var(--sub2)}
.stat-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin-bottom:16px}
.stat-card{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px}
.stat-card .num{font-size:24px;font-weight:600;color:var(--accent);line-height:1.2}
.stat-card .num.g{color:var(--ok)}
.stat-card .lbl{font-size:12px;color:var(--sub2);margin-top:4px}
/* 当前在线：唯一一张「活的」卡片，左侧加一道绿条做区分 */
.stat-card.live{position:relative;border-left:3px solid var(--ok)}
/* 可下钻的统计卡：整张能点进明细（第100轮：数据看板「文件夹」卡点击可增删该分类） */
.stat-card.act{cursor:pointer;transition:border-color .15s,transform .15s,box-shadow .15s}
.stat-card.act:hover{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.stat-card.act:active{transform:translateY(1px)}
.stat-card.act .lbl{display:flex;align-items:center;gap:4px}
.stat-card.act .lbl::after{content:'›';font-size:15px;line-height:1;color:var(--accent);
  transform:translateX(-2px);transition:transform .15s}
.stat-card.act:hover .lbl::after{transform:translateX(2px)}
.stat-card .num.r{color:var(--ok)}
/* ---------- 用户组卡片 / 的成员弹窗 / 权限矩阵（第100轮：用户与权限页重做） ---------- */
.gx-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(272px,1fr));gap:12px}
.gx-card{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px 15px;
  display:flex;flex-direction:column;gap:9px;transition:border-color .15s,box-shadow .15s}
.gx-card:hover{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.gx-top{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.gx-name{font-size:14.5px;font-weight:600;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gx-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.gx-perm{font-size:12.5px;color:var(--text);background:var(--panel2);border:1px solid var(--line);
  border-radius:8px;padding:7px 9px;line-height:1.6;word-break:break-all;min-height:31px}
.gx-perm.empty{color:var(--sub2);font-style:normal}
.gx-note{font-size:12px;color:var(--sub2);line-height:1.55}
.gx-ops{display:flex;gap:7px;margin-top:auto;padding-top:3px}
.gx-ops .btn{flex:1;min-width:0;white-space:nowrap}
/* 成员弹窗里的「搜索加人」行 */
.gm-add{display:flex;align-items:center;gap:8px;margin-bottom:12px;flex-wrap:wrap}
.gm-pick{margin-top:12px}
.gm-pick .adm{margin-top:6px}
/* 行内小下拉（成员换组、批量条） */
.tiny-sel{background:var(--panel2);border:1px solid var(--line);color:var(--text);border-radius:6px;
  padding:4px 6px;font-size:12.5px;cursor:pointer;max-width:100%}
.tiny-sel:focus{outline:none;border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
/* 权限矩阵 */
.mx-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:10px;font-size:12.5px;color:var(--sub2)}
.mx-wrap{max-height:60vh;overflow:auto;border:1px solid var(--line);border-radius:10px}
table.mx{border-collapse:separate;border-spacing:0;font-size:13px;min-width:max-content;width:100%}
table.mx th,table.mx td{border-bottom:1px solid var(--line);border-right:1px solid var(--line);padding:7px 10px;text-align:center;font-weight:400}
table.mx th:last-child,table.mx td:last-child{border-right:none}
table.mx tbody tr:last-child td{border-bottom:none}
table.mx thead th{position:sticky;top:0;z-index:3;background:var(--panel2);min-width:118px;vertical-align:top}
table.mx thead th:first-child{min-width:200px;text-align:left;font-weight:600;color:var(--sub2);font-size:12px;z-index:4}
table.mx td:first-child,table.mx .mx-key{position:sticky;left:0;z-index:2;background:var(--panel);text-align:left;min-width:200px}
table.mx thead th:first-child{z-index:4}
table.mx .mx-gname{font-weight:600;color:var(--text);font-size:13px}
table.mx .mx-colops{display:flex;gap:8px;justify-content:center;margin-top:3px}
table.mx .mx-colops a{color:var(--accent-text);cursor:pointer;font-size:11.5px;opacity:.85}
table.mx .mx-colops a:hover{opacity:1;text-decoration:underline}
table.mx .mx-cat th{background:var(--panel2);color:var(--sub2);font-size:12px;font-weight:600;text-align:left;
  letter-spacing:.4px;padding:6px 10px;position:sticky;left:0}
table.mx .mx-key em{display:block;font-style:normal;font-size:11px;color:var(--sub2);margin-top:1px}
table.mx input[type=checkbox]{width:15px;height:15px;accent-color:var(--accent);cursor:pointer;vertical-align:middle}
table.mx tbody tr:hover td{background:var(--panel2)}
table.mx tbody tr:hover td:first-child,table.mx tbody tr:hover .mx-key{background:var(--panel2)}
.ol-sub{font-size:11.5px;color:var(--sub2);margin-top:5px;line-height:1.5}
.ol-ops{display:flex;gap:6px;margin-top:9px;flex-wrap:wrap}
.ol-ops .btn{font-size:11.5px;padding:2px 8px}
/* 刷新做成右上角小图标：三个按钮挤一行会把卡片顶高，破坏跟其它卡片的对齐 */
.ol-refresh{position:absolute;top:9px;right:9px;width:24px;height:24px;padding:0;display:flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:7px;background:var(--panel2);color:var(--sub2);cursor:pointer;line-height:1}
.ol-refresh:hover{color:var(--accent-text);border-color:var(--line2)}
.ext-bar{display:flex;align-items:center;gap:10px;font-size:12.5px;margin-bottom:6px;color:var(--sub)}
.ext-bar .bar{height:8px;background:linear-gradient(90deg,var(--accent),var(--purple));border-radius:4px}
.maint-tip{font-size:13px;line-height:1.9;color:var(--sub)}
.maint-tip code{background:var(--panel2);border:1px solid var(--line);border-radius:5px;padding:2px 7px;font-size:12px;color:var(--accent-text)}

table.adm{width:100%;border-collapse:collapse;font-size:13px}
table.adm th,table.adm td{padding:8px 10px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}
table.adm th{color:var(--sub2);font-size:12px;font-weight:600;background:var(--panel2);position:sticky;top:0}
table.adm tr:hover td{background:var(--panel2)}
table.adm td.ops{white-space:nowrap}
/* 第72轮：短字段列（时间 / 用户名+ID / 大小·时长…）必须一行显示 ——
 * 列宽够却因为自动换行折成两行，看着像排版 bug（用户截图反馈）。
 * 只给确实需要单行的单元格加 .nw；标题、说明这类长文本列不加，保持正常换行。
 * 注：这里刻意不给表格套 overflow-x:auto 的横向滚动容器 ——
 * 那会把表头 position:sticky 的吸附基准换成新容器，滚动时表头就不再吸顶了。 */
table.adm td.nw,table.adm th.nw{white-space:nowrap}
/* 单元格里的次要信息（#ID、时长）小一号、灰色，跟在主值同一行 */
table.adm td .sub{font-size:11px;color:var(--sub2);font-weight:400}
table.adm .muted{color:var(--sub2)}
/* ---- 第96轮：紧凑表格 ----
 * 用户反馈「文件管理」行距太开，一屏放不下几条。
 * 只改内边距，**不动 font-size / line-height / 边框颜色** ——
 * 字一缩就触发第72轮「折行」的老问题（列宽是按现字号算的）。
 * 竖向 padding 8px→4px 让行高省下 8px，横向 10px→8px 让密集表格少留白。
 * 只给需要密的表格加 .cmp，不改全局 —— 审核/设置这类表单型表格本来就该松。 */
table.adm.cmp th,table.adm.cmp td{padding:4px 8px}
table.adm.cmp th{font-size:11.5px}
table.adm.cmp td.ops .btn{padding:3px 7px;font-size:11.5px}
/* 行内小徽标（试听 .pvl / 存储位置 .sto）字号 12px 会让紧凑行看着仍然偏松，
   这里只降字号、不动 padding（它们本来就没有内边距，写了也是空规则） */
table.adm.cmp .pvl,table.adm.cmp .sto{font-size:11.5px;gap:3px}
.mono{font-family:Consolas,"Courier New",monospace;font-size:12px}
/* ---- 第96轮：在线明细弹窗的「人数 / 设备 / 会话」三口径汇总条 ----
 * 不写汇总条的话管理员只能把行数、会话数、卡片数字对着猜；
 * 有了它，「一个人开 6 个窗口」这件事就被解释清楚了。 */
.ol-sum{display:flex;align-items:stretch;gap:8px;flex-wrap:wrap;margin-bottom:12px}
.ol-sum-i{flex:0 0 auto;min-width:76px;padding:7px 12px;border:1px solid var(--line);
  border-radius:10px;background:var(--panel2)}
.ol-sum-i b{display:block;font-size:19px;font-weight:600;line-height:1.15;color:var(--accent-text)}
.ol-sum-i span{display:block;margin-top:2px;font-size:11.5px;color:var(--sub2)}
.ol-sum-t{flex:1 1 220px;min-width:0;padding:8px 12px;border:1px dashed var(--line);
  border-radius:10px;font-size:12px;line-height:1.7;color:var(--sub2)}
.ol-sum-t b{color:var(--sub)}
/* 同 IP 多行时那行提示：与主行之间留一点缝，但不撑高整行 */
.ol-tb td .muted{margin-top:1px;line-height:1.45}

/* ---- 第96轮：云端文件的「关联素材」列 ----
 * 一格要装下「哪个素材 + 它拿这个文件干什么（源文件/试听版/导入来源）」，
 * 所以做成胶囊 + 小字角色，而不是拼成一串纯文字。 */
.ref-chip{display:inline-flex;align-items:center;gap:4px;max-width:100%;margin:1px 3px 1px 0;
  padding:1px 7px;border:1px solid var(--line);border-radius:10px;background:var(--panel2);
  font-size:11.5px;color:var(--sub);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ref-chip:hover{border-color:var(--accent);color:var(--accent-text)}
.ref-chip i{font-style:normal;color:var(--sub2);font-size:11px}
/* 孤儿行整行淡一点：让「需要整理的」在一屏里自己浮出来 */
#osList tr.os-orphan td{background:rgba(240,176,32,.05)}
#osList tr.os-orphan:hover td{background:rgba(240,176,32,.1)}
/* 跨页跳转到文件管理后的定位高亮，2.6 秒后自动淡掉 */
.row-hl td{background:var(--accent-soft)!important;box-shadow:inset 3px 0 0 var(--accent)}
.b.ok{color:var(--ok)}
.b.warn{color:#b8860b}
/* ---- 第89轮：后台提现审核的「实名资料」列 ----
 * 一格要放下 4~5 项，所以用「标签: 值」的小行堆叠，而不是挤成一串。
 * 缺失项染红（.bad）而不是只写「资料不全」—— 审核员要一眼看到**缺哪一项**，
 * 才能一次性告诉会员补什么；「补不齐」四个字还得再点一次详情才知道缺什么。
 * 宽度给 200px：4 行最短的一行（"性别: 不愿透露"）约 130px，留出照片按钮的位置。 */
.wd-real{min-width:190px;max-width:230px}
.wd-rl{display:flex;gap:6px;align-items:baseline;font-size:12px;line-height:1.7}
.wd-rl>span{flex-shrink:0;width:34px;color:var(--sub2)}
.wd-rl.bad{color:var(--danger)}
.wd-rw{margin-top:3px;font-size:11px;line-height:1.5;color:var(--warn,#f2a33c)}
/* 第90轮：实名单元格多出「状态 + 收款」几行，行数从 4 涨到 8~9。
   原来 230px 的上限会逼着文字换行，现在放宽到 280px 并让标签列从 34px 提到 40px ——
   「收款人」「收款码」这两个标签本来就比 34px 宽，挤着会折成两行。 */
.wd-real.wd-real-wide{min-width:220px;max-width:280px}
.wd-real-wider .wd-rl>span{width:40px}
/* 证件照弹窗：两张并排，各占一半，1.59:1 是身份证标准比例不能压扁 */
.wd-idc{display:flex;gap:14px;flex-wrap:wrap}
.wd-idc figure{margin:0;flex:1;min-width:230px}
.wd-idc img{width:100%;aspect-ratio:1.59/1;object-fit:contain;background:var(--panel2);
  border:1px solid var(--line);border-radius:9px;display:block}
.wd-idc figcaption{font-size:12px;color:var(--sub2);text-align:center;margin-top:6px}
.wd-idc figure.bad img{opacity:.28}
.wd-idc figure.bad figcaption{color:var(--danger)}
@media (max-width:640px){ .wd-idc figure{min-width:100%} }
.role-tag{display:inline-block;border-radius:6px;padding:1px 8px;font-size:11.5px;border:1px solid var(--line2);color:var(--sub)}
.role-tag.role-admin{background:rgba(155,109,255,.16);border-color:var(--purple);color:var(--purple)}
.role-tag.role-editor{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-text)}
.role-tag.role-viewer{background:var(--panel3);color:var(--sub)}
.state-tag{display:inline-block;border-radius:6px;padding:1px 8px;font-size:11.5px}
.state-tag.on{background:rgba(34,176,125,.15);color:var(--ok);border:1px solid rgba(34,176,125,.4)}
.state-tag.off{background:rgba(255,91,91,.12);color:var(--danger);border:1px solid rgba(255,91,91,.35)}
/* 第96轮：warn 态 = 「能删但要当心」（未关联文件）。与 on/off 分开是因为语义不同：
   off 是「不可用」，warn 是「可用，但请确认没有别的系统在用」。 */
.state-tag.warn{background:rgba(240,176,32,.15);color:#b8860b;border:1px solid rgba(240,176,32,.42)}
.empty-row{text-align:center;color:var(--sub2);padding:26px 0;font-size:13px}

/* 回收站概览卡片 */
.rc-stat{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:14px}
.rc-stat-item{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:10px 12px}
.rc-stat-item b{display:block;font-size:18px;color:var(--text);line-height:1.3}
.rc-stat-item span{font-size:11.5px;color:var(--sub2)}

/* 对象存储配置表单 */
.oss-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:10px 16px;margin-bottom:12px}
.oss-field{display:flex;flex-direction:column;gap:5px}
.oss-field label{font-size:12px;color:var(--sub2)}
.oss-field .inp,.oss-field .sel{width:100%;box-sizing:border-box}
.oss-switches{display:flex;flex-wrap:wrap;gap:8px 18px;padding:10px 12px;background:var(--panel2);border:1px solid var(--line);border-radius:9px}
.oss-check{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--sub);cursor:pointer}
.oss-crumbs{font-size:12.5px;color:var(--sub2);margin-bottom:8px;padding:6px 10px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;overflow-x:auto;white-space:nowrap}
.oss-crumbs a{color:var(--accent-text);cursor:pointer}
.oss-crumbs a:hover{text-decoration:underline}
.oss-crumbs .sep{margin:0 6px;opacity:.5}
#osList .os-dir{cursor:pointer}
#osList .os-dir:hover td{background:var(--panel3)}
/* ---- 第97轮：云端的「来源」列 ----
 * 千万别跟「关联素材」那列混：来源说的是**这文件当初是怎么进去的**
 * （管理员传 / 会员传 / 系统自动转的试听版 / 来源不明），关联说的是**现在有没有素材在用**。
 * 两件事分两列，管理员才不会拿「来源不明」当「可以删」。 */
.src-tag{display:inline-block;max-width:100%;padding:1px 8px;border-radius:6px;font-size:11.5px;
  border:1px solid var(--line2);background:var(--panel2);color:var(--sub);vertical-align:middle;
  overflow:hidden;white-space:nowrap;text-overflow:ellipsis;cursor:help;line-height:1.6}
.src-tag.tone-ok{background:rgba(34,176,125,.14);border-color:rgba(34,176,125,.42);color:var(--ok)}
.src-tag.tone-warn{background:rgba(240,176,32,.14);border-color:rgba(240,176,32,.45);color:#b8860b}
.src-tag.tone-bad{background:rgba(255,91,91,.12);border-color:rgba(255,91,91,.38);color:var(--danger)}
.src-g{margin-left:6px;font-size:10.5px;color:var(--sub2);white-space:nowrap;cursor:help}
/* 目录行：名字 + 一排小按钮。默认半透明，hover 才全显 —— 一层里十几个目录全按钮会很吵 */
.os-dir-name{display:inline-flex;align-items:center;gap:6px}
.os-dir-ops{display:inline-block;margin-left:10px;opacity:.72;white-space:nowrap}
#osList .os-dir:hover .os-dir-ops,.os-dir-ops:hover{opacity:1}
/* 第97轮：新建/搬移 的小输入框弹窗。输入框要撑满，路径串长，别让人横向滚 */
.oss-ask .inp{width:100%;box-sizing:border-box}
.oss-ask code{word-break:break-all}
@media (max-width:720px){ .os-dir-ops{display:none} }

/* 后台文件夹树 */
.ftree{border:1px solid var(--line);border-radius:10px;padding:6px;background:var(--panel2)}
.ftree-row{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:7px;font-size:13px}
.ftree-row:hover{background:var(--panel3)}
.ftree-row:hover .ft-ops{opacity:1}
.ftree-row .ft-caret{width:16px;height:16px;line-height:14px;text-align:center;font-size:12px;color:var(--sub);border:1px solid var(--line2);border-radius:4px;background:var(--panel);cursor:pointer;flex-shrink:0;box-sizing:border-box;user-select:none}
.ftree-row .ft-caret:hover{color:var(--accent-text);border-color:var(--accent);background:var(--accent-soft)}
.ftree-row .ft-caret.open{color:var(--accent-text);border-color:var(--accent);background:var(--accent-soft)}
.ftree-row .ft-caret.leaf{border-color:transparent;background:none;cursor:default}
.ftree-row .ft-dot{width:8px;height:8px;border-radius:2px;background:var(--dot);flex-shrink:0}
.ftree-row .ft-name{font-weight:600;color:var(--text);max-width:280px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ftree-row .ft-cnt{font-size:11px;color:var(--sub2);background:var(--panel3);border-radius:20px;padding:1px 8px}
.ftree-row .ft-acc{font-size:11.5px;display:flex;align-items:center;gap:4px}
.ftree-row .ft-ops{margin-left:auto;display:flex;gap:5px;opacity:.25;transition:.12s;flex-shrink:0}
.ftree-row .ft-ops .btn{padding:2px 8px;font-size:11.5px}
.ftree-kids{position:relative}
.filt-chip{display:inline-flex;align-items:center;gap:6px;background:var(--accent-soft);border:1px solid var(--accent);color:var(--accent-text);border-radius:20px;padding:3px 6px 3px 11px;font-size:12px}
.filt-chip i{font-style:normal;cursor:pointer;font-size:14px;line-height:1;opacity:.7}
.filt-chip i:hover{opacity:1}

/* 数据库管理 */
.db-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}
.db-card{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:13px 14px;cursor:pointer;transition:.14s}
.db-card:hover{border-color:var(--accent);background:var(--panel3)}
.db-card .tn{font-size:13.5px;font-weight:600;display:flex;align-items:center;gap:6px}
.db-card .tn em{font-style:normal;font-size:11px;color:var(--sub2);font-weight:400;margin-left:auto}
.db-card .tc{font-size:12px;color:var(--sub2);margin:6px 0 8px;line-height:1.5;min-height:32px}
.db-card .tm{display:flex;gap:10px;font-size:11.5px;color:var(--sub2)}
.db-card .tm b{color:var(--text);font-weight:600}
.db-head{display:flex;align-items:center;gap:10px;margin-bottom:12px;flex-wrap:wrap}
.db-head .back{background:none;border:0;color:var(--accent);cursor:pointer;font-size:13px;padding:0}
.sub-tabs{display:flex;gap:6px;margin-bottom:14px;border-bottom:1px solid var(--line);padding-bottom:8px}
.sub-tabs a{padding:5px 12px;border-radius:7px;font-size:13px;color:var(--sub);cursor:pointer}
.sub-tabs a.on{background:var(--accent-soft);color:var(--accent-text);font-weight:600}
.desc{color:var(--sub);font-size:12.5px;line-height:1.6}
.desc b{color:var(--text);font-weight:600}
.kv{display:grid;grid-template-columns:1fr 1fr;gap:8px 18px;margin-bottom:14px}
.kv div{font-size:12.5px;color:var(--sub2)}
.kv div b{color:var(--text);font-weight:600}
.pager-mini{display:flex;align-items:center;gap:8px;justify-content:flex-end;margin-top:10px;font-size:12.5px;color:var(--sub2)}
.pager-mini button{background:var(--panel2);border:1px solid var(--line);color:var(--text);border-radius:6px;padding:3px 10px;cursor:pointer;font-size:12px}
.pager-mini button:disabled{opacity:.4;cursor:not-allowed}

@media (max-width:1200px){ .detail{width:290px} .sidebar{width:220px} }
@media (max-width:900px){ .detail{display:none!important} .sidebar{width:190px} .search-box{max-width:none} .admin-nav{width:150px} }

/* ===== 比特率筛选 ===== */
.bit-presets{display:flex;flex-wrap:wrap;gap:4px;flex:1}
.bit-pill{font-size:11px;padding:2px 7px;border:1px solid var(--line);border-radius:20px;color:var(--sub);cursor:pointer;user-select:none;transition:.12s;white-space:nowrap}
.bit-pill:hover{border-color:var(--line2);color:var(--text)}
.bit-pill.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-text)}
.ext-pill{display:inline-flex;align-items:center;gap:4px}
.ext-pill i{font-style:normal;font-size:10px;opacity:.55}
.ext-pill.none{opacity:.62}

/* ===== 后台：权限勾选 ===== */
.perm-box{border-top:1px solid var(--line);margin-top:10px;padding-top:12px}
.perm-group{margin-bottom:14px}
.perm-group h5{font-size:12px;color:var(--accent-text);margin:0 0 8px;font-weight:600}
.perm-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:6px}
.perm-item{display:flex;align-items:flex-start;gap:6px;background:var(--panel2);border:1px solid var(--line);border-radius:7px;padding:7px 9px;font-size:12.5px;cursor:pointer;line-height:1.35}
.perm-item:hover{border-color:var(--line2)}
.perm-item input{margin-top:2px;flex-shrink:0}
.perm-item em{display:block;font-style:normal;font-size:11px;color:var(--sub2);margin-top:2px}
/* 「选项行」: 复选框 + 标题 + 说明,整宽单行卡片(区别于权限卡: 用于开关类设置) */
.opt-row{display:flex;align-items:flex-start;gap:9px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:9px 11px;cursor:pointer;transition:.12s}
.opt-row:hover{border-color:var(--line2)}
.opt-row input{margin:2px 0 0;flex-shrink:0}
.opt-row b{display:block;font-weight:600;font-size:12.5px;color:var(--text);line-height:1.45}
.opt-row em{display:block;font-style:normal;font-size:11.5px;color:var(--sub2);line-height:1.55;margin-top:3px}

/* ===== 全局自绘复选框(原生勾选在部分浏览器/主题下不可见) ===== */
input[type=checkbox]{-webkit-appearance:none;appearance:none;width:16px;height:16px;margin:0;flex-shrink:0;border:1.5px solid var(--line2);border-radius:4px;background:var(--panel);cursor:pointer;transition:background .1s,border-color .1s;position:relative}
input[type=checkbox]:hover{border-color:var(--accent);background:var(--accent-soft)}
input[type=checkbox]:checked{background:var(--accent);border-color:var(--accent)}
input[type=checkbox]:checked:hover{background:var(--accent)}
input[type=checkbox]:checked::before{content:'';position:absolute;left:4.5px;top:1.5px;width:4px;height:8px;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(45deg)}
input[type=checkbox]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
input[type=checkbox]:disabled{opacity:.45;cursor:not-allowed}

/* ===== 个人主页（第45轮改版：封面 + 资料卡 + 数据行，参考主流社区主页版式） ===== */
.home-body{overflow:auto;background:var(--bg)}
.home-wrap{max-width:1000px;margin:0 auto;padding:20px 22px 90px}
.home-closed{text-align:center;padding:90px 0;color:var(--sub2)}
.home-closed svg{margin-bottom:14px;color:var(--sub2)}
.home-closed p{font-size:16px;color:var(--text);margin-bottom:6px}

/* 封面：纯 CSS 渐变 + 三块柔光，不用图片，换主题自动变色 */
.pf-banner{position:relative;height:168px;border-radius:var(--radius);overflow:hidden;
  background:linear-gradient(115deg,var(--accent) 0%,var(--purple) 58%,var(--accent2) 100%)}
.pf-banner i{position:absolute;border-radius:50%;background:rgba(255,255,255,.16);filter:blur(2px)}
.pf-banner i:nth-child(1){width:240px;height:240px;left:-60px;top:-90px}
.pf-banner i:nth-child(2){width:150px;height:150px;right:12%;top:-40px;opacity:.7}
.pf-banner i:nth-child(3){width:300px;height:300px;right:-90px;bottom:-190px;opacity:.5}

/* 资料卡：负 margin 上叠，头像骑在卡片左上角 */
.pf-card{position:relative;display:flex;gap:18px;align-items:flex-start;
  background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px 22px 18px;margin-top:-46px;box-shadow:0 10px 30px rgba(0,0,0,.10)}
.pf-avatar{width:104px;height:104px;flex-shrink:0;border-radius:50%;overflow:hidden;position:relative;
  border:4px solid var(--panel);background:linear-gradient(135deg,var(--accent),var(--purple));
  display:flex;align-items:center;justify-content:center;font-size:40px;color:#fff;
  cursor:default;user-select:none;box-shadow:0 6px 18px rgba(0,0,0,.18)}
.pf-avatar img{width:100%;height:100%;object-fit:cover}
.pf-avatar .cam{position:absolute;left:0;bottom:0;width:100%;background:rgba(0,0,0,.5);color:#fff;
  font-size:11px;text-align:center;padding:3px 0;font-style:normal;opacity:0;transition:.15s}
.pf-avatar:hover .cam{opacity:1}
.pf-meta{flex:1;min-width:0;padding-top:8px}
.pf-name{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.pf-name h1{font-size:22px;line-height:1.3}
.pf-id{font-size:11px;color:var(--sub2);background:var(--panel2);border:1px solid var(--line);
  border-radius:20px;padding:2px 9px}
.pf-sub{display:flex;align-items:center;gap:8px;flex-wrap:wrap;color:var(--sub);font-size:12.5px;margin-top:8px}
.pf-sub .grp-tag{background:var(--accent-soft);color:var(--accent-text);border-radius:20px;padding:1px 8px;font-size:11.5px}
.pf-bio{color:var(--sub);font-size:13px;margin-top:10px;line-height:1.7;white-space:pre-wrap;max-width:640px}
.pf-acts{display:flex;flex-direction:column;gap:8px;align-items:flex-end;flex-shrink:0;padding-top:8px}
.home-state{font-size:11.5px;color:var(--sub2)}
.home-state.on{color:var(--ok)}

/* 数据行：作品 / 粉丝 / 关注 / 收藏 / 播放 / 空间 */
.pf-stats{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin:14px 0 4px;
  background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:14px 8px}
.pf-stats .ps{text-align:center;border-radius:8px;padding:6px 4px;transition:.15s}
.pf-stats .ps b{display:block;font-size:19px;color:var(--text);margin-bottom:3px;font-weight:700}
.pf-stats .ps span{font-size:12px;color:var(--sub2)}
.pf-stats .ps.link{cursor:pointer}
.pf-stats .ps.link:hover{background:var(--accent-soft)}
.pf-stats .ps.link:hover b{color:var(--accent-text)}

.home-tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);margin:20px 0 18px}
.home-tabs a{padding:9px 16px;font-size:13.5px;color:var(--sub);cursor:pointer;border-bottom:2px solid transparent;user-select:none}
.home-tabs a:hover{color:var(--text)}
.home-tabs a.on{color:var(--accent-text);border-bottom-color:var(--accent)}
.home-grid{margin-bottom:20px}

/* ===== 筛选区单位与区间 ===== */
.filter-line .unit{font-size:11px;color:var(--sub2);margin-left:2px}
.filter-line label:empty{width:var(--flabel-w,42px)}
.mini-in.wide{width:62px}

/* ===== 树形：+ / − 折叠图标(方块按钮,让用户知道可展开) ===== */
.tree .caret{width:16px;height:16px;text-align:center;color:var(--sub);font-size:12px;line-height:14px;user-select:none;flex-shrink:0;border:1px solid var(--line2);border-radius:4px;background:var(--panel2);transition:.12s;box-sizing:border-box}
.tree .caret:hover{color:var(--accent-text);border-color:var(--accent);background:var(--accent-soft)}
.tree .caret.open{color:var(--accent-text);border-color:var(--accent);background:var(--accent-soft)}

/* ===== 后台：日期范围条 ===== */
.range-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:10px 0 14px;padding:10px 12px;background:var(--panel2);border:1px solid var(--line);border-radius:8px}
.range-bar label{font-size:12.5px;color:var(--sub);margin:0}
.inp.tiny-date{padding:4px 8px;font-size:12.5px;width:140px}
.range-bar .dash{color:var(--sub2)}

/* ===== 后台：排行榜 ===== */
.rank-2col{display:grid;grid-template-columns:1fr 1fr;gap:16px}
@media(max-width:1100px){.rank-2col{grid-template-columns:1fr}}
.rank-h{font-size:13px;color:var(--accent-text);margin:0 0 8px;font-weight:600}
.bar-mini{height:3px;background:var(--line);border-radius:2px;margin-top:4px;overflow:hidden;max-width:260px}
.bar-mini i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--purple));border-radius:2px}
td .neg{color:var(--danger)}
td .pos{color:var(--ok)}

/* ===== 后台：地区热力图 ===== */
.geo-legend{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--sub);margin-bottom:12px}
.geo-legend i{width:22px;height:12px;border-radius:3px;background:var(--accent);display:inline-block}
.geo-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(78px,1fr));gap:6px;margin-bottom:20px}
.geo-cell{position:relative;border:1px solid var(--line);border-radius:7px;padding:8px 6px;text-align:center;background:var(--panel2);overflow:hidden}
.geo-cell i{position:absolute;inset:0;background:var(--accent);opacity:.08;pointer-events:none}
.geo-cell.has{border-color:var(--line2)}
.gc-name{position:relative;display:block;font-size:12px;color:var(--sub)}
.geo-cell.has .gc-name{color:var(--text)}
.gc-val{position:relative;display:block;font-size:14px;font-weight:600;color:var(--text);margin-top:2px}

/* ===== 顶栏导航 ===== */
.top-nav{display:flex;gap:2px;margin:0 10px}
.top-nav .tn-item{padding:6px 14px;border-radius:8px;font-size:13.5px;color:var(--sub);cursor:pointer;user-select:none;white-space:nowrap}
.top-nav .tn-item:hover{color:var(--text);background:var(--panel2)}
.top-nav .tn-item.on{color:var(--accent-text);background:var(--accent-soft);font-weight:600}
.side-toggle{display:none}

/* ===== 列表头: 素材 (N) + 排序 ===== */
.list-head{display:flex;align-items:center;gap:10px;margin:2px 0 12px;flex-wrap:wrap}
.lh-left{display:flex;align-items:baseline;gap:8px;min-width:0}
.lh-title{font-size:16px;font-weight:700;color:var(--text)}
.lh-count{font-size:13.5px;color:var(--sub)}
.lh-right{margin-left:auto;display:flex;align-items:center;gap:8px}
.lh-right .seg{display:flex;align-items:center;padding:0 8px;border:1px solid var(--line);border-radius:8px;background:var(--panel)}
.lh-right .seg input[type=range]{width:90px}

/* ===== 顶部筛选 chips + 工具(排序/缩放/视图) 同一行 ===== */
.filter-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:2px 0 12px;padding:8px 12px;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius)}
.fb-chips{display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0}
.fb-item{position:relative}
.fb-chip{display:inline-flex;align-items:center;gap:5px;padding:5px 12px;border:1px solid var(--line);border-radius:999px;background:var(--panel2);color:var(--sub);font-size:12.5px;cursor:pointer;user-select:none;transition:.12s;position:relative;box-shadow:0 1px 2px rgba(0,0,0,.04)}
.fb-chip:hover{color:var(--text);border-color:var(--line2);transform:translateY(-1px);box-shadow:0 2px 6px rgba(0,0,0,.08)}
.fb-chip em{font-style:normal;color:var(--accent-text);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fb-chip .arr{display:block;flex-shrink:0;opacity:.55;transition:transform .18s,opacity .12s}
.fb-chip:hover .arr{opacity:.9}
.fb-chip.on{border-color:var(--accent);color:var(--accent-text);background:var(--accent-soft)}
.fb-chip.on .arr{opacity:1;transform:rotate(180deg)}
.fb-chip.pending::after{content:'';position:absolute;top:-3px;right:-3px;width:8px;height:8px;border-radius:50%;background:var(--warn,#f2a33c);border:2px solid var(--panel)}
.fb-reset{margin-left:4px;padding:5px 12px;border:1px dashed var(--line2);border-radius:999px;background:none;color:var(--sub2);font-size:12.5px;cursor:pointer;transition:.12s;white-space:nowrap}
.fb-reset:hover{color:var(--text);border-color:var(--sub2);background:var(--panel2)}
.fb-reset.off{opacity:.4;cursor:default;pointer-events:none}
.fb-tools{margin-left:auto;display:flex;align-items:center;gap:8px;flex-shrink:0}
.fb-tools .seg{display:flex;align-items:center;padding:0 8px;border:1px solid var(--line);border-radius:8px;background:var(--panel2)}
.fb-tools .seg input[type=range]{width:90px}
/* 列表/缩略图双图标切换: 激活高亮 */
.view-seg{display:flex;align-items:center;gap:2px;padding:2px;border:1px solid var(--line);border-radius:9px;background:var(--panel2)}
.view-seg .icon-btn{width:28px;height:28px;border:none;border-radius:7px;background:transparent;color:var(--sub2)}
.view-seg .icon-btn:hover{background:var(--track);color:var(--text)}
.view-seg .icon-btn.on{background:var(--accent-soft);color:var(--accent-text);box-shadow:inset 0 0 0 1px var(--accent)}
.view-seg .icon-btn svg{display:block}

/* ===== 下拉面板 ===== */
.fb-panel{position:absolute;top:calc(100% + 6px);left:0;z-index:60;min-width:230px;max-width:290px;background:var(--panel);border:1px solid var(--line2);border-radius:10px;box-shadow:0 10px 32px rgba(0,0,0,.28);animation:fbIn .13s ease}
@keyframes fbIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}

/* ---------- 后台文件管理: 标题跳前台 ---------- */
.ftitle{cursor:pointer}
.ftitle:hover{color:var(--accent-text);text-decoration:underline}
.fb-body{max-height:280px;overflow:auto;padding:6px}
.fb-none{padding:14px 8px;font-size:12px;color:var(--sub2);text-align:center}
.fb-search{padding:2px 2px 6px}
.fb-search input{width:100%;box-sizing:border-box;padding:6px 10px;border:1px solid var(--line);border-radius:7px;background:var(--panel2);color:var(--text);font-size:12.5px;outline:none}
.fb-search input:focus{border-color:var(--accent)}
.fb-opt{display:flex;align-items:center;gap:8px;padding:7px 9px;min-height:32px;box-sizing:border-box;border-radius:7px;font-size:12.5px;color:var(--text);cursor:pointer;user-select:none}
.fb-opt:hover{background:var(--panel2)}
.fb-opt.on{background:var(--accent-soft);color:var(--accent-text)}
.fb-opt input[type=checkbox]{flex-shrink:0}
.fb-opt .fb-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fb-opt .fb-count{font-size:11.5px;color:var(--sub2)}
.fb-opt .fb-dot{width:12px;height:12px;border-radius:50%;border:2px solid var(--line2);flex-shrink:0}
.fb-opt.on .fb-dot{border-color:var(--accent);background:var(--accent)}
.fb-opt.color{justify-content:center;padding:6px 4px}
.fb-colors{display:grid;grid-template-columns:repeat(4,1fr);gap:2px}
.fb-presets{display:flex;flex-wrap:wrap;gap:4px;padding:4px 4px 8px}
.fb-minmax{display:flex;align-items:center;gap:6px;padding:2px 4px 4px}
.fb-minmax input{width:76px;padding:5px 8px;border:1px solid var(--line);border-radius:7px;background:var(--panel2);color:var(--text);font-size:12.5px;outline:none}
.fb-minmax input:focus{border-color:var(--accent)}
.fb-minmax .dash{color:var(--sub2)}
.fb-minmax .unit{font-size:11px;color:var(--sub2);white-space:nowrap}
.fb-foot{display:flex;justify-content:flex-end;gap:8px;padding:8px;border-top:1px solid var(--line)}

/* ===== 侧栏抽屉(响应式) ===== */
.side-mask{display:none}

/* ===== 响应式 ===== */
/* 笔记本（1366/1440）+ 125%~150% DPI 缩放 = 实际到手的 CSS 宽度只有 1093/768…，
 * 顶栏是「logo + 搜索 + 导航 + 一堆按钮」一整条 flex，最容易在这种宽度上互相挤爆。
 * 收口原则：先让「文字间距/尺寸」缩，绝不隐藏导航项（隐藏了用户就点不到了）。 */
.topbar{min-width:0}
.topbar>*{min-width:0}
@media(max-width:1280px){
  .topbar-actions .admin-entry{display:none}   /* 管理后台入口收进头像菜单 */
  .top-nav .tn-item{padding:6px 10px}
  .search-box{max-width:440px}
}
@media(max-width:1100px){
  .tn-item{padding:6px 8px;font-size:13px}
  .brand span{display:none}
  .search-box{max-width:360px}
  .top-nav{margin:0 4px}
}
@media(max-width:1024px){
  .side-toggle{display:inline-flex}
  .sidebar{position:fixed;left:0;top:0;bottom:0;width:270px;max-width:82vw;z-index:90;transform:translateX(-102%);transition:.22s;overflow-y:auto;box-shadow:8px 0 30px rgba(0,0,0,.25)}
  body.side-open .sidebar{transform:none}
  body.side-open .side-mask{display:block;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:80}
  .search-box{flex:1;min-width:120px}
  #siteName{display:none}
}
@media(max-width:760px){
  .fb-tools .seg{display:none}
  .fb-chip em{display:none}
  .fb-reset{padding:4px 9px;font-size:12px}
  .topbar{flex-wrap:wrap;gap:8px;padding:8px 12px}
  .search-box{order:10;flex-basis:100%}
  .top-nav{margin:0}
  .topbar-actions .btn:not(.primary){display:none}
  /* 第103轮：原「窄屏保留投稿入口 .earn-btn」的例外规则已删 —— 「上传赚钱」按钮从顶栏
   * 撤到头像菜单宫格里了，这条选择器再也匹配不到任何元素，留着只会误导后来人。 */
  .detail{position:fixed;right:0;top:0;bottom:0;width:420px;width:min(92vw,420px);z-index:95}
}

/* ===== 第17轮: 站内信铃铛 / 搜索历史 / 我的标签快捷条 / 标签管理 / 头像裁剪 ===== */
.msg-bell{position:relative}
.msg-badge{position:absolute;top:2px;right:0;min-width:16px;height:16px;padding:0 4px;border-radius:8px;
  background:var(--danger,#e5484d);color:#fff;font-size:10.5px;line-height:16px;text-align:center;font-weight:600;
  box-shadow:0 0 0 2px var(--panel)}
/* 有未读站内信: 铃铛轻微摇摆,提示更醒目 */
.msg-bell.has-unread{animation:bell-ring 2.4s ease-in-out infinite;transform-origin:top center}
@keyframes bell-ring{
  0%,72%,100%{transform:rotate(0)}
  76%{transform:rotate(11deg)}
  80%{transform:rotate(-9deg)}
  84%{transform:rotate(7deg)}
  88%{transform:rotate(-5deg)}
  92%{transform:rotate(3deg)}
  96%{transform:rotate(0)}
}
.search-hist{position:absolute;top:calc(100% + 6px);left:0;right:0;background:var(--panel);border:1px solid var(--line2);
  border-radius:10px;box-shadow:0 10px 28px rgba(0,0,0,.28);padding:6px;z-index:120;display:none}
.search-hist.on{display:block}
.sh-h{font-size:11px;color:var(--sub2);padding:4px 8px 6px}
.sh-i{display:flex;align-items:center;gap:7px;padding:7px 9px;border-radius:7px;font-size:13px;color:var(--sub);cursor:pointer}
.sh-i svg{color:var(--sub2);flex-shrink:0}
.sh-i:hover{background:var(--panel2);color:var(--text)}

/* 标签管理弹窗行 */
.tm-row{display:flex;align-items:center;gap:8px;padding:7px 0;border-bottom:1px dashed var(--line)}
.tm-row:last-of-type{border-bottom:0}
.tm-row .tm-name{flex:1;min-width:0}
.tm-cnt{font-size:11.5px;color:var(--sub2);white-space:nowrap}
/* 就地编辑状态: dirty=已改待保存(蓝边) / gone=标记待删(划线淡显) / new=待新建(虚线框) */
.tm-row.dirty .tm-name{border-color:var(--accent)}
.tm-row.gone{opacity:.5}
.tm-row.gone .tm-name{text-decoration:line-through}
.tm-row.new .tm-name{border-style:dashed}
/* 头像裁剪 */
.crop-wrap{display:flex;justify-content:center;background:#14171c;border-radius:10px;padding:10px}
.crop-wrap canvas{border-radius:8px;cursor:grab;touch-action:none;display:block}
.crop-wrap canvas:active{cursor:grabbing}

/* ===== 第18轮: 后台紧凑标签选择器 ===== */
.fe-tag-sel{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px;min-height:26px}
.fe-tag-sel .tag-pill b{cursor:pointer;margin-left:2px;font-weight:400;opacity:.65}
.fe-tag-sel .tag-pill b:hover{opacity:1}
.fe-tag-drop{position:absolute;top:calc(100% + 4px);left:0;right:96px;max-height:210px;overflow-y:auto;z-index:20;
  background:var(--panel);border:1px solid var(--line2);border-radius:10px;box-shadow:0 10px 28px rgba(0,0,0,.3);padding:4px}
.fe-tag-drop a{display:block;padding:6px 9px;border-radius:6px;font-size:13px;color:var(--text);cursor:pointer}
.fe-tag-drop a:hover{background:var(--panel2)}
.fe-tag-drop a.on{color:var(--accent-text);font-weight:600}

/* ===== 第20轮: 框选橡皮筋 / 菜单分组标题 ===== */
.rubber{position:fixed;z-index:140;pointer-events:none;border:1px solid var(--accent);
  background:var(--accent-soft);border-radius:2px}
.menu-item.head{color:var(--sub2);font-size:11.5px;cursor:default;background:var(--panel2);
  border-radius:6px;margin:2px 4px;padding:4px 9px}
.menu-item.head:hover{background:var(--panel2)}

/* ===== 第34轮: 投稿审核「编辑」弹窗（投稿信息块） ===== */
.fe-info{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin-bottom:14px}
.fe-info-t{display:flex;align-items:baseline;gap:8px;font-weight:600;font-size:13.5px;margin-bottom:10px}
.fe-info-t span{font-weight:400;font-size:12px;color:var(--sub2)}
.fe-info-g{display:grid;grid-template-columns:1fr 1fr;gap:8px 14px}
.fe-info-g>div{display:flex;align-items:baseline;gap:8px;font-size:12.5px;min-width:0}
.fe-info-g>div>span{flex:0 0 62px;color:var(--sub2)}
.fe-info-g>div>b{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fe-info-note{margin-top:10px;font-size:12.5px;color:var(--danger);background:rgba(229,72,77,.09);
  border:1px solid rgba(229,72,77,.28);border-radius:8px;padding:7px 10px;line-height:1.7}
.fe-info-hint{margin-top:10px;font-size:12px;color:var(--sub2);line-height:1.8}
/* 第71轮：存储位置 / 切换试听线路的说明块。中性信息色 —— 不是警告，别用 fe-info-note(红) */
.fe-info-tip{margin-top:10px;font-size:12.5px;color:var(--sub);background:var(--accent-soft);
  border:1px solid var(--line);border-radius:8px;padding:7px 10px;line-height:1.75}
/* 第71轮：本地文件的「服务器上的完整路径」清单（标签列窄，长标签会折行，所以单独排一块） */
.fe-paths{margin-top:10px;border:1px solid var(--line);border-radius:8px;background:var(--accent-soft);padding:8px 10px}
.fe-paths-t{font-size:12px;color:var(--sub2);margin-bottom:6px}
.fe-paths-row{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap;font-size:12px;line-height:2}
.fe-paths-row>span{flex:0 0 60px;color:var(--sub)}
.fe-paths-row>code{flex:1 1 320px;min-width:0;word-break:break-all;font-size:11.5px;color:var(--text);
  font-family:ui-monospace,Menlo,Consolas,monospace}
/* ===== 第62轮：后台套餐价格表 ===== */
.at-scroll{overflow-x:auto;margin-top:6px;border:1px solid var(--line);border-radius:9px}
.at-table{border-collapse:collapse;width:100%;font-size:12px;min-width:420px}
.at-table th,.at-table td{padding:7px 9px;text-align:center;border-bottom:1px solid var(--line);white-space:nowrap}
.at-table thead th{background:var(--accent-soft);color:var(--accent-text);font-weight:600}
.at-table thead th i{font-style:normal;font-size:10px;color:var(--sub2)}
.at-table tbody tr:last-child td{border-bottom:none}
.at-table .at-name{text-align:left;color:var(--text);font-weight:500}
.at-table .at-name i{font-style:normal;font-size:10.5px;color:var(--sub2);font-weight:400}
.at-table .at-price{color:var(--text);font-weight:600}
.audit-st{font-size:12px;padding:2px 8px;border-radius:20px;font-weight:500}
.audit-st.s0{background:rgba(242,163,60,.16);color:var(--warn)}
.audit-st.s1{background:rgba(34,176,125,.14);color:var(--ok)}
.audit-st.s2{background:rgba(229,72,77,.14);color:var(--danger)}
.btn.ok{background:var(--ok);border-color:var(--ok);color:#fff}
.btn.ok:hover{filter:brightness(1.08)}

/* ===== 第93轮：多维度去重 =====
 * 设计上的一条硬要求：**分数必须看得见「为什么」**。
 * 只显示一个 92% 的审核员没法行动（是转码还是剪辑？），
 * 所以每个维度都要有名字 + 权重 + 进度条 + 分数 + 未参与的原因。 */
.fe-dup-box{margin-top:8px;border:1px solid var(--line);border-radius:9px;background:var(--accent-soft);padding:9px 11px}
.fe-dup-box.hot{border-color:rgba(229,72,77,.45);background:rgba(229,72,77,.07)}
.fe-dup-warn{font-size:12.5px;color:var(--danger);line-height:1.7;font-weight:600}
.fe-dup-ok{font-size:12.5px;color:var(--sub);line-height:1.7}
/* 每个维度一行：名字(含权重) / 进度条 / 分数 / 备注。窄屏下备注另起一行，不挤成一团 */
.fe-dup-dims{margin-top:9px;display:flex;flex-direction:column;gap:6px}
.fe-dup-dim{display:flex;align-items:center;gap:9px;font-size:12px;color:var(--text);line-height:1.5;flex-wrap:wrap}
.fe-dup-dim.off{opacity:.55}
.fe-dup-dim .n{flex:0 0 148px;color:var(--sub)}
.fe-dup-dim .n em{font-style:normal;margin-left:5px;font-size:10.5px;color:var(--sub2)}
.fe-dup-dim .v{flex:0 0 46px;text-align:right;font-weight:600;color:var(--text)}
.fe-dup-dim .t{flex:1 1 100%;font-size:11px;color:var(--sub2);padding-left:157px}
.fe-dup-bar{flex:1 1 90px;min-width:80px;height:7px;border-radius:6px;background:var(--line);overflow:hidden;position:relative}
.fe-dup-bar>b{display:block;height:100%;border-radius:6px;background:linear-gradient(90deg,var(--ok),var(--warn))}
.fe-dup-bar.na{background:transparent;font-style:normal;font-size:10.5px;color:var(--sub2);text-align:left}
.fe-dup-ops{margin-top:9px;display:flex;gap:8px}
.fe-dup-more{margin-top:7px;font-size:11.5px;color:var(--sub2);line-height:1.7}
.fe-dup-head{display:flex;flex-direction:column;gap:6px;font-size:12.5px;margin-bottom:4px}
.fe-dup-head>div{display:flex;gap:9px;align-items:baseline}
.fe-dup-head>div>span{flex:0 0 74px;color:var(--sub2)}
.fe-dup-head>div>b{flex:1;min-width:0;color:var(--text);word-break:break-all}

/* ===== 第95轮: 相似素材「定位」与「并排比对」 =====
 * 定位的关键不是把 id 打出来，而是让管理员**一键跳到那条素材**并能当场比对。
 * 所以审核弹窗里的相似条目、去重清单里的「最相似的素材」都做成可点的胶囊。 */
.fe-dup-pick{display:inline-flex;align-items:center;gap:4px;padding:1px 7px;border-radius:9px;
  border:1px solid var(--line2);background:var(--panel);color:var(--accent-text);
  font-size:11.5px;cursor:pointer;font:inherit}
.fe-dup-pick:hover{border-color:var(--accent);background:var(--accent-soft)}
.fe-dup-more .fe-dup-pick{margin:0 2px}
/* 审核弹窗里的相似素材候选列表（第95轮）：每行「标签 + 可点标题 + 可点分数」 */
.fe-dup-cands{margin-top:9px;border:1px solid var(--line);border-radius:9px;background:var(--panel2);padding:8px 10px}
.fe-dup-cands-t{font-size:11.5px;color:var(--sub2);margin-bottom:6px}
.fe-dup-cand{display:flex;align-items:center;gap:7px;padding:4px 0;font-size:12px}
.fe-dup-cand+.fe-dup-cand{border-top:1px solid var(--line)}
.fe-dup-cand .n{flex:0 0 auto;font-size:11px;color:var(--sub2)}
.fe-dup-cand.top .n b{color:var(--danger);font-weight:600}
/* 并排比对弹窗 */
.cmp-verdict{padding:8px 12px;border-radius:9px;font-size:12.5px;color:var(--sub);
  background:var(--panel2);border:1px solid var(--line);margin-bottom:10px}
.cmp-verdict b{color:var(--text)}
.cmp-verdict.hit{border-color:rgba(229,72,77,.45);background:rgba(229,72,77,.08)}
.cmp-verdict.hit b{color:var(--danger)}
.cmp-sides{display:grid;grid-template-columns:1fr 1fr;gap:10px}
@media (max-width:640px){.cmp-sides{grid-template-columns:1fr}}
.cmp-side{padding:9px 11px;border:1px solid var(--line);border-radius:10px;background:var(--panel2);
  border-left:3px solid var(--accent)}
.cmp-side.b{border-left-color:var(--purple)}
.cmp-side-h{display:flex;align-items:baseline;gap:7px;min-width:0}
.cmp-tag{flex:0 0 auto;padding:1px 6px;border-radius:8px;font-size:11px;
  background:var(--accent-soft);color:var(--accent-text)}
.cmp-side.b .cmp-tag{background:rgba(155,109,255,.16);color:var(--purple)}
.cmp-title{flex:1;min-width:0;font-size:13px;color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cmp-meta{display:flex;flex-wrap:wrap;gap:9px;margin-top:6px;font-size:11.5px;color:var(--sub2)}
.cmp-meta>span{display:inline-flex;align-items:center;gap:4px}
.cmp-ops{display:flex;flex-wrap:wrap;gap:7px;margin-top:8px}
.cmp-wave{margin-top:12px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--panel2)}
.cmp-wave-t{display:flex;align-items:baseline;gap:8px;font-size:13px;font-weight:600;
  color:var(--accent-text);margin-bottom:8px}
.cmp-wave-t>span{font-size:11.5px;font-weight:400;color:var(--sub2)}
.cmp-wave-legend{margin-top:7px;font-size:11.5px;color:var(--sub2);display:flex;align-items:center;gap:5px}
.cmp-wave-legend i{display:inline-block;width:9px;height:9px;border-radius:2px;margin-left:8px}
.cmp-wave-legend i:first-child{margin-left:0}
.cmp-wave-legend i.a{background:var(--accent)}
.cmp-wave-legend i.b{background:var(--purple)}
.cmp-wave-legend em{font-style:normal;color:var(--warn)}
/* 列表里的相似度数字：达到阈值才变红 —— 颜色只用来标「需要重点看」，不做装饰 */
.dd-sc{font-weight:600}
.dd-sc.hot,tr.dd-hot .dd-sc{color:var(--danger)}
tr.dd-hot{background:rgba(229,72,77,.06)}
/* 第94轮：相似度条。只用长度表达分数，数字仍跟在右边 —— 纯数字一列看不出轻重。
 * ★ 必须写 width：**不能只靠 flex:0 0 62px**。这里不是 flex 容器，
 *   宽度会退回「由内容决定」，而里面是 width:% 的块级 <i> → 父宽由子决定、子宽由父决定，
 *   整条塌成 0（截图里表现为「相似度列只有数字没有条」）。 */
.dd-bar{display:inline-block;width:62px;height:6px;border-radius:4px;background:var(--line);overflow:hidden;vertical-align:middle;margin-right:7px}
.dd-bar>i{display:block;height:100%;border-radius:4px;background:var(--sub2);transition:width .2s}
tr.dd-hot .dd-bar>i{background:var(--danger)}
table.adm.dd-list td:nth-child(3){white-space:nowrap}

/* ---- 第94轮：多维度去重页（重排版） ----
 * 原来这页是「3 个 admin-panel 竖排 + 一个 11 行行式表单」，观感差的根因是结构不是配色。
 * 现在：一条口径横条 + 一排紧凑统计 + 两个子页签 + 维度卡片网格。
 * 所有色值都走变量，深浅色自动跟随；不给 .dd-* 再单独定义颜色。 */
.dd-hero{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:11px 16px;margin-bottom:12px}
.dd-hero-t{font-size:12px;font-weight:600;color:var(--sub2);letter-spacing:.04em;flex-shrink:0}
.dd-chips{display:flex;align-items:center;gap:6px;flex-wrap:wrap;flex:1;min-width:0}
.dd-chip{display:inline-flex;align-items:center;height:23px;padding:0 10px;border-radius:12px;
  font-size:11.5px;color:var(--sub);background:var(--panel2);border:1px solid var(--line);white-space:nowrap}
.dd-chip.dim{color:var(--accent-text);background:var(--accent-soft);border-color:var(--accent-ring)}
.dd-chip.ok{color:var(--ok);border-color:var(--ok);background:rgba(34,176,125,.10)}
.dd-chip.off{color:var(--sub2)}
.dd-chip.warn{color:var(--warn);border-color:var(--warn);background:rgba(242,163,60,.12)}
.dd-hero-ops{display:flex;gap:8px;flex-shrink:0}
.dd-hero-ops .btn:disabled{opacity:.5;cursor:progress}

/* 紧凑统计条：一行四个，不再四张 16px 内边距的大卡占掉两行屏幕 */
.dd-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:10px;margin-bottom:14px}
.dd-stat{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:11px 14px;
  display:flex;flex-direction:column;gap:2px}
.dd-stat b{font-size:20px;font-weight:600;line-height:1.2;color:var(--text)}
.dd-stat span{font-size:11.5px;color:var(--sub2)}
.dd-stat.hot{border-color:var(--danger);background:rgba(229,72,77,.06)}
.dd-stat.hot b{color:var(--danger)}
.dd-stat.warn b{color:var(--warn)}

.dd-tabs,.dd-sub2{margin-bottom:12px}
.dd-sub2{border-bottom:0;padding-bottom:0;margin:-2px 0 10px}
.dd-pane{padding:14px 16px}
.dd-pane h3{margin-bottom:12px}

/* 全局判定区：自适应多列，比「label + 控件」纵向堆一列省一半高度 */
.dd-gi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(258px,1fr));gap:11px}
.dd-gi{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:11px 13px;
  display:flex;flex-direction:column;gap:7px;min-width:0}
.dd-gi-t{font-size:13px;font-weight:600;color:var(--text);display:flex;align-items:baseline;gap:7px}
.dd-gi-t i{font-style:normal;font-family:Consolas,monospace;font-size:10.5px;color:var(--sub2);letter-spacing:0}
.dd-gi-c select,.dd-gi-c input[type=number]{max-width:200px}
.dd-gi-c select{width:200px}
.dd-gi-c input[type=number]{width:120px}
.dd-gi-d{font-size:11.5px;color:var(--sub2);line-height:1.75}

/* 维度卡片：一维一卡，开关 + 权重 + 「抗什么/怕什么」都在这一张里。
 * .on 才亮（左边一道强调色）；.now=无权重维（md5 命中即满分，不参与加权）。 */
.dd-dim-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(272px,1fr));gap:11px}
.dd-dim{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:11px 13px;
  border-left:3px solid transparent;display:flex;flex-direction:column;gap:6px;min-width:0;transition:border-color .15s,background .15s}
.dd-dim.on{border-left-color:var(--accent);background:var(--accent-soft)}
.dd-dim.on.now{border-left-color:var(--ok)}
/* 开着但权重=0：后端按停用处理，卡片必须自己说清楚，否则灯亮着却在骗人 */
.dd-dim.zerow{border-left-color:var(--warn);background:rgba(242,163,60,.10)}
.dd-dim-h{display:flex;align-items:center;gap:9px;min-width:0}
.dd-dim-n{font-size:13px;font-weight:600;color:var(--text);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dd-dim-w{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--sub2);flex-shrink:0}
.dd-dim-w input[type=number]{width:52px;text-align:center;padding:3px 4px;
  background:var(--panel);border:1px solid var(--line);border-radius:6px;color:var(--text);font-size:12px;font-family:inherit}
.dd-dim-w input[type=number]:focus{border-color:var(--accent);outline:none}
.dd-dim-w.none{color:var(--sub2);opacity:.8}
.dd-rg{width:76px;cursor:pointer}
.dd-dim-d{font-size:11.5px;color:var(--sub);line-height:1.7}
.dd-dim-p{font-size:11px;color:var(--sub2);line-height:1.7;padding-top:5px;border-top:1px dashed var(--line)}

/* 开关：整块 label 可点，比只点 16px 的小方框好按 */
.dd-sw{position:relative;display:inline-flex;align-items:center;cursor:pointer;flex-shrink:0}
.dd-sw input{position:absolute;opacity:0;width:100%;height:100%;margin:0;cursor:pointer}
.dd-sw>i{display:block;width:32px;height:18px;border-radius:9px;background:var(--line2);
  position:relative;transition:background .16s}
.dd-sw>i::after{content:'';position:absolute;left:2px;top:2px;width:14px;height:14px;border-radius:50%;
  background:var(--panel);transition:transform .16s}
.dd-sw input:checked+i{background:var(--accent)}
.dd-sw input:checked+i::after{transform:translateX(14px)}
.dd-sw input:focus-visible+i{outline:2px solid var(--accent);outline-offset:2px}

.dd-save{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:14px}
.dd-save .muted{font-size:11.5px;color:var(--sub2);line-height:1.7}
.dd-save .muted strong{color:var(--warn);font-weight:600}

/* ---- 第94轮：后台文件管理的「当前分类」列 ----
 * 祖先链名字（"短视频 / 综艺"）在 132px 列里必然放不下，所以固定单行 + 省略号，
 * 全名留在 title 上。图标用 currentColor，跟文字一起变灰。 */
.fcat{display:inline-flex;align-items:center;gap:5px;max-width:100%;min-width:0;
  font-size:12px;color:var(--sub);vertical-align:middle;cursor:pointer}
.fcat>i{font-style:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fcat:hover{color:var(--accent-text)}
.fcat:hover .ai{opacity:1}
.fcat.none{color:var(--sub2);cursor:default;opacity:.8}
.fcat.none:hover{color:var(--sub2)}
/* 没有分类时可点（点了等于没筛选）→ 不给手型光标 */
.fcat:not(.none)[data-ffold]{cursor:pointer}

/* ===== 第95轮: 列表里的「试听」与「存储位置」两列 =====
 * 两者都是「一眼要看懂」的信息，所以不写长句，只写词 + 图标 + 颜色：
 *   本地=中性灰、COS=蓝、双端=绿（且必须标出此刻走哪边）。
 * 颜色只用来区分**线路**，不用来表达好坏 —— 否则管理员会以为云端=有问题。 */
.pvl,.sto{display:inline-flex;align-items:center;gap:4px;max-width:100%;min-width:0;
  font-size:12px;vertical-align:middle;white-space:nowrap}
.pvl .ai,.sto .ai{flex:0 0 auto}
.pvl.local,.sto.local{color:var(--sub)}
.pvl.oss,.sto.oss{color:var(--accent-text)}
.pvl.both{color:var(--ok,#22b07d)}
.pvl.none,.sto.none{color:var(--sub2);opacity:.85}
/* 「双端」右侧的小徽标：当前实际走哪一侧。
   双端不是「两个都在用」，而是负载在挑 —— 不标出来管理员无从判断此刻在烧谁的流量。 */
.pvl-now{display:inline-block;margin-left:2px;padding:0 5px;border-radius:8px;
  font-size:11px;line-height:16px;font-weight:500;color:#fff;background:var(--ok,#22b07d)}
/* 迁移前的存量脏数据：preview_path 里塞的是 oss://，需要跑数据库升级 */
.pvl-legacy{display:inline-block;margin-left:4px;padding:0 5px;border-radius:8px;
  font-size:11px;line-height:16px;color:#fff;background:var(--warn,#f2a33c)}

/* ===== 第95轮: 编辑弹窗里的「试听线路」三选一 =====
 * 为什么不用 select / radio：
 *   三项各带一句代价说明（本地省钱、烧带宽；云端反之；双端要占两份空间）。
 *   select 一收起来说明就没了，radio 又放不下这么长的说明文字。
 *   所以做成三枚「带说明的按钮卡」，选中态用左边一道色条 + 浅底，与 .gd-opt.on 同一套路。 */
.sk-line{margin-top:12px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--panel2)}
.sk-line-t{display:flex;align-items:baseline;gap:8px;font-size:13px;font-weight:600;color:var(--accent-text);margin-bottom:8px}
.sk-line-t>span{font-size:11.5px;font-weight:400;color:var(--sub2)}
.sk-line-opts{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px}
.sk-lo{display:flex;flex-direction:column;align-items:flex-start;gap:3px;text-align:left;
  padding:8px 10px;border:1px solid var(--line);border-radius:9px;background:var(--panel);
  color:var(--sub);cursor:pointer;font:inherit;transition:border-color .12s,background .12s}
.sk-lo>b{font-size:12.5px;font-weight:600;color:var(--text)}
.sk-lo>i{font-style:normal;font-size:11.5px;line-height:1.5;color:var(--sub2)}
.sk-lo .ai{flex:0 0 auto;margin-bottom:1px}
.sk-lo:hover:not(:disabled){border-color:var(--accent)}
.sk-lo:disabled{opacity:.5;cursor:not-allowed}
/* 选中态：左边一道色条 + 浅底。不用 CSS :has()（360se 不支持），由后端按实际状态打 class。 */
.sk-lo.on{border-color:var(--accent);background:var(--accent-soft);
  box-shadow:inset 3px 0 0 var(--accent)}
.sk-lo.on>b{color:var(--accent-text)}
.sk-line-now{margin-top:8px;font-size:12px;color:var(--sub)}
.sk-line-now.warn{color:var(--warn)}

/* ===== 第95轮: 试听线路面板的读数条 =====
 * 三个格子等宽并排，阈值以「进度条打满」为界 —— 一眼能看出离切云端还有多远。
 * 超阈值的格子整块变 danger 色（不用只改数字颜色：色块在余光里也能看见）。 */
.pv-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:10px;margin-top:4px}
.pv-g{padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--panel2)}
.pv-g-t{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--sub)}
.pv-g-v{margin-top:4px;font-size:22px;font-weight:600;line-height:1.15;color:var(--text)}
.pv-g-v em{font-style:normal;font-size:11.5px;font-weight:400;color:var(--sub2);margin-left:2px}
.pv-g-v em.na{color:var(--sub2)}
.pv-g-bar{margin-top:7px;height:6px;border-radius:4px;background:var(--line);overflow:hidden}
/* 同第94轮的坑：inline-block/flex 里的条必须写死 width，否则父子互相依赖塌成 0 */
.pv-g-bar>i{display:block;height:6px;width:0;border-radius:4px;background:var(--accent)}
.pv-g-s{margin-top:5px;font-size:11.5px;color:var(--sub2)}
.pv-g.over{border-color:var(--danger);background:rgba(224,69,74,.08)}
.pv-g.over .pv-g-bar>i{background:var(--danger)}
.pv-g.over .pv-g-s{color:var(--danger)}
.pv-verdict{margin-top:10px;padding:8px 11px;border-radius:9px;font-size:12.5px;
  background:var(--panel2);border:1px solid var(--line);color:var(--sub)}
.pv-verdict b{color:var(--text)}
.pv-verdict.busy{border-color:var(--warn);background:rgba(242,163,60,.08)}
.pv-verdict.busy b{color:var(--warn)}
.pv-verdict em{font-style:normal;color:var(--sub2)}
.pv-cov{margin-top:8px;font-size:12px;color:var(--sub)}
.pv-cov b{color:var(--text)}

/* ===== 第34轮: 个人中心配置表单 ===== */
.form-sec{margin:18px 0 8px;padding:7px 0 7px 11px;font-size:13px;font-weight:600;color:var(--accent-text);
  border-left:3px solid var(--accent);background:linear-gradient(90deg,var(--accent-soft),transparent 70%)}
.form-sec:first-of-type{margin-top:6px}
.uc-def{display:flex;align-items:baseline;gap:10px;margin-top:5px;font-size:11.5px;color:var(--sub2)}
.uc-def>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:70%}
.uc-def>a{color:var(--accent-text);cursor:pointer;white-space:nowrap;border-bottom:1px dashed var(--accent-ring)}
.uc-def>a:hover{color:var(--accent)}

/* ===== 第34轮: 源码编辑器（高级） ===== */
.src-warn{background:rgba(242,163,60,.10);border:1px solid rgba(242,163,60,.34);border-radius:10px;
  padding:12px 14px;margin-bottom:16px}
.src-warn>b{display:block;font-size:13.5px;color:var(--warn);margin-bottom:7px}
.src-warn ul{margin:0;padding-left:18px}
.src-warn li{font-size:12.5px;line-height:1.95;color:var(--sub)}
.src-warn li b{color:var(--text)}
.src-wrap{display:grid;grid-template-columns:270px minmax(0,1fr);gap:14px;align-items:stretch}
.src-files{display:flex;flex-direction:column;gap:6px;align-content:start}
.src-files>a{display:block;padding:9px 11px;border:1px solid var(--line);border-radius:9px;background:var(--panel2);
  cursor:pointer;transition:.15s}
.src-files>a:hover{border-color:var(--line2);background:var(--panel3)}
.src-files>a.on{border-color:var(--accent);background:var(--accent-soft);box-shadow:0 0 0 3px var(--accent-ring)}
.src-files>a.dis{opacity:.45;cursor:not-allowed}
.src-files>a>b{display:block;font-size:12.5px;font-weight:600;margin-bottom:3px;line-height:1.45}
.src-files>a>em{display:block;font-size:11px;color:var(--sub2);font-style:normal}
.src-editor{border:1px solid var(--line);border-radius:10px;background:var(--panel2);overflow:hidden;
  display:flex;flex-direction:column;min-width:0}
.src-bar{display:flex;align-items:center;gap:9px;padding:8px 10px;border-bottom:1px solid var(--line);flex-wrap:wrap}
.src-bar .src-name{font-size:12.5px;display:flex;align-items:baseline;gap:8px;min-width:0}
.src-bar .src-name em{font-size:11px;color:var(--sub2);font-style:normal}
.src-bar .src-stat{font-size:11.5px;color:var(--sub2);white-space:nowrap}
.src-bar .src-stat .dirty{color:var(--warn)}
.src-area{flex:1;width:100%;min-height:430px;border:0;outline:none;resize:vertical;
  background:var(--panel);color:var(--text);font:12.5px/1.65 "Cascadia Mono",Consolas,"Courier New",monospace;
  padding:12px 14px;tab-size:2;white-space:pre;overflow:auto}
.src-area[readonly]{color:var(--sub2)}
.src-tip{padding:7px 12px;font-size:11.5px;color:var(--sub2);border-top:1px solid var(--line);min-height:30px;line-height:1.6}
.src-tip.ok{color:var(--ok);background:rgba(34,176,125,.08)}
.src-tip.bad{color:var(--danger);background:rgba(229,72,77,.08)}
/* 源码预览弹窗 */
.src-pv-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:12.5px;color:var(--sub);margin-bottom:8px}
.src-pv-bar em{font-style:normal;font-size:12px;color:var(--sub2)}
.src-pv-note{font-size:12px;line-height:1.75;color:var(--sub2);background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:7px 10px;margin-bottom:10px}
.src-pv-note b{color:var(--accent-text)}
.src-pv{height:62vh;min-height:360px;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:#fff}
.src-pv iframe{width:100%;height:100%;border:0;display:block;background:#fff}
@media(max-width:900px){.src-wrap{grid-template-columns:1fr}.fe-info-g{grid-template-columns:1fr}.src-pv{height:56vh;min-height:300px}}

/* ===== 第37轮: 帮助工单（后台「会员管理 → 帮助工单」） ===== */
.help-bar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px}
.help-q{margin-left:auto;display:flex;gap:6px}
.help-q input{height:32px;padding:0 10px;border:1px solid var(--line2);border-radius:8px;
  background:var(--panel2);color:var(--text);font-size:12.5px;outline:none;width:210px}
.help-q input:focus{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.tk-meta{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:12.5px;color:var(--sub);margin-bottom:14px}
.tk-sec{font-size:12.5px;font-weight:600;color:var(--text);margin:14px 0 7px;
  padding-left:9px;border-left:3px solid var(--accent)}
.tk-sec:first-of-type{margin-top:0}
.tk-body{font-size:13px;line-height:1.85;color:var(--text);word-break:break-word}
.tk-reply{font-size:13px;line-height:1.85;color:var(--text);background:var(--panel2);
  border-radius:9px;padding:10px 12px;word-break:break-word}
.tk-atts{display:flex;flex-wrap:wrap;gap:8px}
.tk-thumb img{width:76px;height:76px;object-fit:cover;border-radius:8px;
  border:1px solid var(--line2);display:block}
.tk-doc{display:inline-flex;align-items:center;gap:6px;font-size:12px;padding:6px 11px;
  border-radius:8px;background:var(--panel2);border:1px solid var(--line);color:var(--sub);
  text-decoration:none;max-width:240px}
.tk-doc span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tk-doc em{font-style:normal;color:var(--sub2);font-size:11px;flex-shrink:0}
.tk-doc:hover{border-color:var(--accent);color:var(--accent-text)}

/* ===== 第40轮: 工单「在线对话」（后台弹窗 + 个人中心弹窗共用） =====
 * 改成会话流的原因：原来是一条「问题描述 + 一个窄 textarea」，
 * 宽屏下整个右半边全是空白（textarea 默认 cols≈20 就 170px 宽），
 * 看着像没做完。现在气泡占满宽度、输入区整宽、时间线可滚动。
 * 结构: .chat > .modal-body > (.chat-top / .chat-stream) + .chat-foot */
.modal.chat{width:860px;width:min(860px,94vw);max-height:88vh;overflow:hidden;
  display:flex;flex-direction:column}
.modal.chat .modal-body{padding:0;flex:1;min-height:0;display:flex;flex-direction:column}
.modal.chat .modal-foot{position:static}
.chat-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap;flex-shrink:0;
  padding:11px 20px;border-bottom:1px solid var(--line);background:var(--panel);font-size:12.5px;color:var(--sub)}
.chat-top .grow{flex:1}
.chat-stream{flex:1;min-height:180px;max-height:48vh;overflow-y:auto;padding:16px 20px;
  display:flex;flex-direction:column;gap:14px;background:var(--panel2)}
.chat-stream .chat-empty{color:var(--sub2);font-size:12.5px;text-align:center;padding:24px 0}
.chat-row{display:flex;flex-direction:column;gap:5px;max-width:78%}
.chat-row.them{align-self:flex-start;align-items:flex-start}
.chat-row.me{align-self:flex-end;align-items:flex-end}
.chat-who{font-size:11.5px;color:var(--sub2);padding:0 3px;display:flex;align-items:center;gap:6px}
.chat-bubble{padding:10px 13px;border-radius:12px;font-size:13px;line-height:1.8;
  word-break:break-word;white-space:pre-wrap;border:1px solid var(--line);background:var(--panel);color:var(--text)}
.chat-row.them .chat-bubble{border-top-left-radius:4px}
.chat-row.me .chat-bubble{background:var(--accent-soft);border-color:transparent;border-top-right-radius:4px}
.chat-atts{display:flex;flex-wrap:wrap;gap:8px}
/* 客服离线自动回复(role=2)：系统代答的话术，不是人发的 —— 虚线气泡 + 「自动回复」角标，
 * 与真实管理员回复区分开（它并不代表问题已被人工处理，后台未读角标仍会亮） */
.chat-row.sys .chat-bubble{border-style:dashed;background:var(--panel2)}
.chat-row.sys .chat-who{color:var(--sub2)}
.chat-auto{font-style:normal;font-size:10.5px;line-height:1;padding:2px 6px;border-radius:99px;
  background:var(--accent-soft);color:var(--accent)}
.chat-foot{padding:12px 20px 14px;border-top:1px solid var(--line);background:var(--panel);flex-shrink:0}
.chat-foot textarea{display:block;width:100%;box-sizing:border-box;min-height:46px;max-height:140px;
  padding:10px 12px;line-height:1.7;border:1px solid var(--line2);border-radius:9px;
  background:var(--panel2);color:var(--text);font-size:13px;outline:none;resize:vertical;
  font-family:inherit;transition:border-color .15s, box-shadow .15s}
.chat-foot textarea:focus{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.chat-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px}
.chat-tools .grow{flex:1}
.chat-tools .hint{margin:0}
.chat-files{display:flex;flex-wrap:wrap;gap:8px;margin-top:9px}
.chat-files:empty{margin-top:0}
.chat-file{display:inline-flex;align-items:center;gap:6px;font-size:12px;padding:5px 8px 5px 10px;
  border-radius:8px;background:var(--panel2);border:1px solid var(--line2);color:var(--sub);max-width:230px}
.chat-file img{width:30px;height:30px;object-fit:cover;border-radius:5px;display:block;flex-shrink:0}
.chat-file span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chat-file em{font-style:normal;color:var(--sub2);font-size:11px;flex-shrink:0}
.chat-file b{cursor:pointer;color:var(--sub2);font-weight:400;font-size:15px;line-height:1;padding:0 2px}
.chat-file b:hover{color:var(--danger,#e35)}
.chat-flag{margin-top:8px;font-size:12px;color:var(--sub2)}
/* 第41轮: 对话即时刷新 —— 对方发来新消息且自己正往上翻历史时，
 * 不硬把视口拽到底，先在输入框上方浮一个提示，点了才跳（否则看记录会被打断） */
.chat-foot{position:relative}
.chat-new{position:absolute;left:50%;bottom:100%;transform:translateX(-50%);margin-bottom:8px;
  padding:5px 13px;border-radius:99px;border:0;cursor:pointer;font-size:12px;line-height:1.6;
  background:var(--accent);color:#fff;box-shadow:0 4px 14px rgba(0,0,0,.22);animation:chatNewIn .18s ease}
.chat-new:hover{filter:brightness(1.06)}
@keyframes chatNewIn{from{opacity:0;transform:translate(-50%,6px)}to{opacity:1;transform:translate(-50%,0)}}
/* 窄屏：气泡占满、弹窗贴边，避免左右挤压 */
@media (max-width:760px){
  .modal.chat{width:min(96vw,860px);max-height:92vh}
  .chat-row{max-width:92%}
  .chat-stream{max-height:44vh;padding:13px 14px}
  .chat-foot{padding:10px 14px 12px}
  .chat-top{padding:10px 14px}
}

/* ===== 第38轮: 后台站内信收件箱（顶栏铃铛 + 用户求助提醒） ===== */
.inbox-list{display:flex;flex-direction:column;gap:8px}
.inbox-item{border:1px solid var(--line);border-radius:10px;padding:10px 12px;background:var(--panel2)}
.inbox-item.unread{border-color:var(--accent);background:var(--accent-soft)}
.ib-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ib-h b{font-size:13.5px}
.ib-h em{margin-left:auto;font-style:normal;font-size:11.5px;color:var(--sub2)}
/* 类型徽章: 与个人中心站内信同色系(求助=橙, 通知=主题色, 资产=蓝) */
.ib-type{display:inline-block;padding:1px 8px;border-radius:9px;font-size:11.5px;
  background:var(--panel3);color:var(--sub);flex-shrink:0}
.ib-type.help{background:rgba(242,163,60,.16);color:#c9821f}
.ib-type.notice{background:var(--accent-soft);color:var(--accent-text)}
.ib-type.pay{background:rgba(77,139,255,.14);color:#4d8bff}
.ib-c{font-size:12.5px;color:var(--sub);margin-top:6px;line-height:1.7;word-break:break-word}
.ib-op{display:flex;align-items:center;gap:10px;margin-top:9px}
.ib-op .btn{margin-left:auto}
/* 第41轮: 同一会话的提醒已合并 → 卡片上标「共 N 条」，避免以为漏看了几条 */
.ib-cnt{font-size:11.5px;color:var(--sub2);background:var(--panel3);border-radius:9px;padding:1px 8px;flex-shrink:0}
.ib-item{display:flex;align-items:center;gap:8px}
.ib-who{font-size:11.5px;color:var(--sub2);background:var(--panel3);border-radius:9px;padding:1px 8px;flex-shrink:0}

/* ==================== 第39轮: 后台重规划 ==================== */
/* 合并页签的副标题(说明这页把哪些功能收在一起了) */
.page-hint{font-size:12.5px;color:var(--sub2);line-height:1.6;margin:-8px 0 14px}
/* 收件箱工具条 + 未读高亮 */
.ib-toolbar{display:flex;align-items:center;gap:8px;margin-bottom:12px}
.ib-unread-n{color:var(--danger);font-weight:600}
/* 需要处理的面板(数据库待升级等): 左侧一道警示色 */
.panel-alert{border-left:3px solid var(--warn)}
/* 数据库升级面板 */
.mig-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px}
.mig-num{font-size:13px;color:var(--sub)}
.mig-num b{font-size:18px;color:var(--accent-text)}
.mig-ops{margin-left:auto;display:flex;gap:8px;align-items:center}
.mig-list{border:1px solid var(--line);border-radius:9px;overflow:hidden;margin-bottom:12px}
.mig-item{display:flex;align-items:center;gap:10px;padding:8px 12px;font-size:12.5px;border-bottom:1px solid var(--line)}
.mig-item:last-child{border-bottom:0}
.mig-item code{font-size:12px;color:var(--text);background:var(--panel2);padding:1px 6px;border-radius:5px}
.mig-item span{margin-left:auto;font-size:11.5px}
.migtip-ok{font-size:12.5px;color:var(--ok);background:rgba(34,176,125,.1);border-radius:9px;padding:10px 12px;margin-bottom:12px}
.mig-tip{font-size:12px;color:var(--sub2);line-height:1.85}
.mig-tip code{background:var(--panel2);padding:1px 5px;border-radius:5px;font-size:11.5px}
.mig-out{margin-top:12px;border-top:1px dashed var(--line);padding-top:10px;font-size:12.5px;line-height:1.8}
.mig-res code{background:var(--panel2);padding:1px 5px;border-radius:5px;font-size:11.5px;margin:0 2px}
.mig-fail{color:var(--danger);font-size:12.5px;line-height:1.8}
/* 窄屏: 侧栏先收窄, 再收成图标条(保持可用而不是塞不下) */
@media (max-width:820px){
  .admin-nav{width:160px;padding:10px 8px 20px}
  .anav-t{padding:9px 9px 4px}
}
@media (max-width:640px){
  .admin-nav{width:58px;padding:10px 8px 20px}
  .admin-nav a{justify-content:center;padding:10px 0;gap:0}
  .admin-nav a>span{display:none}
  .anav-t{font-size:0;padding:0;margin:7px 9px;border-top:1px solid var(--line)}
  .anav-sec:first-child .anav-t{display:none}
  .admin-nav a .nav-badge{position:absolute;top:1px;right:5px;margin:0;min-width:15px;height:15px;
    line-height:15px;font-size:10px;padding:0 3px}
  .admin-main{padding:14px 12px}
}

/* ---------- 协议管理(后台「系统设置 → 协议管理」) ---------- */
/* 小标签: 与个人中心 .tag 同一套配色口径,但后台只加载 app.css,所以自带一份 */
.p-tag{display:inline-block;padding:1px 8px;border-radius:9px;font-size:11.5px;
  background:var(--panel3);color:var(--sub);white-space:nowrap}
.p-tag.ok{background:rgba(34,176,125,.14);color:#22b07d}
.p-tag.bad{background:rgba(229,72,77,.14);color:#e5484d}
/* 编辑弹窗里的复选行(注册必勾 / 启用) */
.chk{display:inline-flex;align-items:center;gap:7px;font-size:13px;color:var(--text);
  cursor:pointer;user-select:none}
/* 协议正文编辑器: 给足高度,长条款不用在窄框里滚 */
#modalBox textarea#pBody{min-height:340px;line-height:1.85;font-size:13px}

/* ============================================================
   第45轮：头像下拉菜单图标化 + 好友关注/私信
   ============================================================ */

/* ---------- 头像下拉菜单（.menu.umenu：带图标与资料头的版本） ----------
   旧的 .menu / .menu-item 是素材卡右键菜单在用的（纯文字、hover 整行变蓝），
   这里用 .umenu 前缀单独覆盖，互不影响：
     · 图标是圆角浅底色块 + 彩色线性图标（参考主流社区，比纯文字好认）
     · 悬停只做浅色底，不再把整行涂成主色 —— 否则彩色图标会整块糊掉 */
/* 240 = 资料头(40 头像 + 间距 + 等级徽标) 与 3 列宫格(每列 ~69px，放得下 4 个字) 两者的较大值。
 * 第87轮这里曾是 288px：那时候宫格有 9 项、最长标签是 5 字「创作者中心」，288 才不折行。
 * 第88轮撤掉三个入口后最长只剩 4 字（「我的主页」「创作中心」「关闭预览」），
 * 288 就显得空荡荡 —— 每列 96px 装一个 28px 图标，两侧各空 30 多px，视觉上散。
 * 收到 240：每列 ~69px，4 字标签(48px)仍有余量，图标与文字不再被拉开。
 * 真放不下时靠 .um-tile b 的 ellipsis 兜底，不会折行撑破布局。 */
.menu.umenu{min-width:240px;padding:6px;border-radius:13px}
.menu.umenu .menu-item{padding:5px 8px;gap:8px;border-radius:9px;font-size:13.5px}
.menu.umenu .menu-item:hover{background:var(--panel2);color:var(--text)}
.menu.umenu .menu-item.danger{color:var(--danger)}
.menu.umenu .menu-item.danger:hover{background:rgba(229,72,77,.12)}
.menu.umenu .menu-item .mt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.menu.umenu .m-tail{font-size:11px;color:var(--sub2)}
.menu.umenu .menu-sep{margin:5px 3px}
/* 资料头：头像 + 昵称 + 粉丝/关注。头像 44→40 是跟着菜单一起收窄的（见上方 min-width 处的说明） */
.um-head{display:flex;align-items:center;gap:9px;padding:4px 6px 8px}
.um-ava{flex-shrink:0;display:block}
.um-av{width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-size:16px;font-weight:700;color:#fff;
  background:linear-gradient(135deg,var(--accent),var(--purple));overflow:hidden}
img.um-av{display:block;object-fit:cover}
.um-hi{flex:1;min-width:0}
.um-name{display:block;font-size:14px;font-weight:600;color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.um-name:hover{color:var(--accent-text)}
.um-sub{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--sub);margin-top:3px}
.um-sub a{cursor:pointer}
.um-sub a:hover{color:var(--accent-text)}
.um-sub b{color:var(--text);font-weight:600}
.um-sub i{font-style:normal;opacity:.45}
.um-grp{flex-shrink:0;font-size:11px;color:var(--sub2);background:var(--panel2);
  border:1px solid var(--line);border-radius:20px;padding:2px 8px}
/* 第87轮：图标宫格（资料头下面 3 列入口，替代原来一整条纯文字竖列）。
 * 色块沿用 .mi-*；宫格只定布局。三列是**固定**的（菜单是定宽浮层，不跟视口走），
 * 所以这里不挂媒体查询 —— 窄屏时是菜单自身宽度被 .um-tile b 的 ellipsis 兜住（「创作中心」不折行）。
 * 第88轮：菜单从 288 收到 240，宫格内边距/行距跟着一起收，否则会出现
 * 「框窄了但格子里还是原来那么松」的割裂感。 */
.um-tiles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:2px;padding:4px 3px 6px}
.um-tile{display:flex;flex-direction:column;align-items:center;gap:5px;padding:7px 2px;
  border-radius:10px;cursor:pointer;text-align:center;transition:background .14s}
.um-tile:hover{background:var(--panel2)}
.um-tile b{font-size:12px;font-weight:500;color:var(--sub);max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.um-tile:hover b{color:var(--text)}
/* 图标色块：浅底 + 同色系图标，深浅主题下都能看清 */
.mi{width:28px;height:28px;flex-shrink:0;border-radius:9px;
  display:flex;align-items:center;justify-content:center}
.mi-blue  {background:rgba(77,139,255,.16); color:#4d8bff}
.mi-purple{background:rgba(155,109,255,.16);color:#9b6dff}
.mi-pink  {background:rgba(255,105,150,.16);color:#ef5f8c}
.mi-teal  {background:rgba(34,176,125,.16); color:#1fa877}
.mi-orange{background:rgba(242,140,60,.18); color:#e5811f}
.mi-amber {background:rgba(240,176,32,.20); color:#d79a10}
.mi-gray  {background:rgba(140,150,165,.18);color:#8a94a4}
.mi-indigo{background:rgba(110,120,240,.16);color:#6572ee}
.mi-cyan  {background:rgba(40,180,200,.16); color:#1a9aae}
.mi-red   {background:rgba(255,91,91,.16);  color:#ef5350}
body.theme-light .mi-blue  {color:#2f6fe4}
body.theme-light .mi-teal  {color:#12a06a}
body.theme-light .mi-amber {color:#c07f06}
body.theme-light .mi-orange{color:#c96c10}
body.theme-light .mi-pink  {color:#d94a78}
body.theme-light .mi-purple{color:#7c53e8}
body.theme-light .mi-red   {color:#d93b40}

/* ---------- 关注按钮：三态（+ 关注 / 已关注 / 互相关注） ---------- */
.btn-follow{min-width:98px;justify-content:center}
.btn-follow.on,.btn-follow.mutual{background:var(--panel2);border-color:var(--line2);color:var(--sub)}
.btn-follow.on:hover,.btn-follow.mutual:hover{background:transparent;border-color:var(--danger);color:var(--danger)}
.btn-follow.busy{opacity:.6;pointer-events:none}
.btn.tiny.btn-follow{min-width:74px}
.pp-act .btn-follow,.pp-act .btn{white-space:nowrap}

/* ---------- 私信会话窗（个人中心「私信」面板与弹窗共用） ---------- */
.dm{display:flex;flex-direction:column;height:100%;min-height:0}
.dm-host{height:min(58vh,470px)}
.dm-list{flex:1;overflow-y:auto;padding:2px 2px 10px;min-height:0}
.dm-row{display:flex;margin-bottom:10px}
.dm-row.me{justify-content:flex-end}
.dm-bubble{max-width:78%;background:var(--panel2);border:1px solid var(--line);border-radius:12px;
  padding:8px 11px 5px;font-size:13.5px;line-height:1.7;word-break:break-word;white-space:pre-wrap}
.dm-row.me .dm-bubble{background:var(--accent-soft);border-color:transparent}
.dm-time{display:block;font-size:10.5px;color:var(--sub2);margin-top:5px;text-align:right}
.dm-foot{flex-shrink:0;border-top:1px solid var(--line);padding-top:10px}
.dm-inp{width:100%;background:var(--panel2);border:1px solid var(--line);color:var(--text);
  border-radius:9px;padding:9px 11px;font-size:13.5px;line-height:1.6;font-family:inherit;
  outline:none;resize:vertical;transition:.15s}
.dm-inp:focus{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.dm-inp.bad{border-color:var(--danger);box-shadow:0 0 0 3px rgba(255,91,91,.18)}
.dm-inp:disabled{opacity:.6;cursor:not-allowed}
.dm-foot-r{display:flex;align-items:center;justify-content:flex-end;gap:10px;margin-top:8px}
.dm-count{font-size:11.5px;color:var(--sub2)}
.dm-block{margin-top:8px;font-size:12.5px;line-height:1.6;color:var(--warn);
  background:rgba(242,163,60,.10);border:1px solid rgba(242,163,60,.28);border-radius:8px;padding:7px 10px}
.dm-empty{color:var(--sub2);font-size:13px;text-align:center;padding:26px 10px}

/* ---- 第47轮：气泡旁的头像 ----
   每人一列 32px 头像，自己的在右、对方在左（.me 用 row-reverse 把 DOM 顺序翻过来，
   这样不用改变渲染顺序，消息流仍是「头像 + 气泡」）。 */
.dm-row{gap:9px;align-items:flex-start}
.dm-row.me{justify-content:flex-start;flex-direction:row-reverse}
.dm-bubble{max-width:74%}
.dm-av{flex-shrink:0;width:32px;height:32px;margin-top:2px}
.dm-av .avatar{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;font-size:13px;font-weight:700;color:#fff;
  background:linear-gradient(135deg,var(--accent),var(--purple));overflow:hidden}
.dm-av img.avatar{display:block;object-fit:cover}
/* 第50轮：点对方头像 → 去 TA 的个人主页。整块可点，悬停给一点反馈让人知道能点 */
.dm-av-link{display:inline-flex;flex-shrink:0;border-radius:50%;transition:.15s}
.dm-av-link:hover{transform:translateY(-1px);box-shadow:0 0 0 2px var(--accent-ring)}
/* 被管理员中断 / 私信被禁用：和「等对方回复」区分开，用醒目的红色告警样式 */
.dm-block.sys{color:var(--danger);background:rgba(229,72,77,.09);
  border-color:rgba(229,72,77,.30)}
/* 消息流顶部的横幅：进入一个已被中断的会话时先看到原因，而不是等到打字才发现发不出 */
.dm-notice{font-size:12.5px;line-height:1.65;color:var(--danger);background:rgba(229,72,77,.09);
  border:1px solid rgba(229,72,77,.28);border-radius:8px;padding:8px 10px;margin-bottom:10px}

/* ---------- 粉丝 / 关注列表 ---------- */
.pf-people{max-height:min(62vh,460px);overflow-y:auto;margin:-4px 0}
.pp-row{display:flex;align-items:center;gap:11px;padding:9px 2px;border-bottom:1px solid var(--line)}
.pp-row:last-child{border-bottom:none}
.pp-av{flex-shrink:0;display:block}
.pp-av .avatar{width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-size:15px;font-weight:700;color:#fff;
  background:linear-gradient(135deg,var(--accent),var(--purple));overflow:hidden}
.pp-av img.avatar{display:block;object-fit:cover}
.pp-info{flex:1;min-width:0}
.pp-name{display:block;font-size:13.5px;font-weight:600;color:var(--text)}
.pp-name:hover{color:var(--accent-text)}
.pp-bio{display:block;font-size:12px;color:var(--sub2);margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pp-act{display:flex;gap:6px;flex-shrink:0;align-items:center}
.pp-tag{font-size:11.5px;color:var(--sub2);background:var(--panel2);
  border:1px solid var(--line);border-radius:20px;padding:3px 9px}

/* ---------- 个人主页：窄屏适配 ---------- */
@media (max-width:760px){
  .home-wrap{padding:14px 14px 80px}
  .pf-banner{height:132px}
  .pf-card{flex-direction:column;align-items:center;text-align:center;margin-top:-40px;padding:14px 16px 16px}
  .pf-avatar{width:88px;height:88px;font-size:34px}
  .pf-meta{padding-top:0;width:100%}
  .pf-name,.pf-sub{justify-content:center}
  .pf-bio{max-width:none;text-align:left}
  .pf-acts{flex-direction:row;flex-wrap:wrap;justify-content:center;width:100%;align-items:center;padding-top:0}
  .pf-stats{grid-template-columns:repeat(3,1fr);row-gap:14px}
  .pf-stats .ps b{font-size:17px}
}
@media (max-width:420px){
  .menu.umenu{min-width:0;width:calc(100vw - 20px)}
  .pf-stats{grid-template-columns:repeat(3,1fr)}
}

/* ---------- 后台「聊天监控」（第47轮） ----------
   配色沿用后台既有变量。关键词高亮统一用 <mark>，命中行用红框标出，
   这样一屏里「哪个词踩线了、是哪一句」不用再看文字描述。 */
.dm-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:10px;margin-bottom:14px}
.dm-stats .dsc{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:10px 13px}
.dm-stats .dsc b{display:block;font-size:20px;font-weight:700;line-height:1.4;color:var(--text)}
.dm-stats .dsc span{font-size:11.5px;color:var(--sub2)}
.dm-stats .dsc.hot b{color:var(--danger)}
.dm-stats .dsc.ok b{color:#22b07d}
.dm-flt{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:12px}
.dm-flt>label{font-size:12.5px;color:var(--sub2)}
.dm-flt select,.dm-flt input{background:var(--panel2);border:1px solid var(--line);color:var(--text);
  border-radius:7px;padding:5px 8px;font-size:12.5px;font-family:inherit;outline:none;max-width:220px}
.dm-flt input{width:160px}
.dm-flt select:focus,.dm-flt input:focus{border-color:var(--accent)}
.dm-avc{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.dm-avc .avatar{width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;
  font-size:11px;font-weight:700;color:#fff;flex-shrink:0;overflow:hidden;
  background:linear-gradient(135deg,var(--accent),var(--purple))}
.dm-avc img.avatar{display:block;object-fit:cover}
.dm-word{display:inline-block;padding:1px 8px;border-radius:9px;font-size:11.5px;font-weight:600;
  background:rgba(229,72,77,.14);color:#e5484d;white-space:nowrap}
.dm-word.on{background:var(--accent-soft);color:var(--accent-text)}
.dm-snippet{max-width:360px;font-size:12.5px;line-height:1.65;color:var(--sub);word-break:break-word}
.dm-snippet mark,.dm-ctx-b mark{background:rgba(229,72,77,.22);color:inherit;border-radius:3px;padding:0 2px}
.dm-arrow{color:var(--sub2);font-size:12px}
/* 上下文弹窗里的对话流 */
.dm-ctx-who{display:flex;flex-wrap:wrap;align-items:center;gap:10px;font-size:12.5px;color:var(--sub2);margin-bottom:10px}
.dm-ctx{max-height:min(52vh,440px);overflow-y:auto;background:var(--panel2);border:1px solid var(--line);
  border-radius:10px;padding:12px}
.dm-ctx-row{display:flex;gap:9px;align-items:flex-start;margin-bottom:10px}
.dm-ctx-row.me{flex-direction:row-reverse}
.dm-ctx-row .avatar{width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:700;color:#fff;flex-shrink:0;overflow:hidden;
  background:linear-gradient(135deg,var(--accent),var(--purple))}
.dm-ctx-row img.avatar{display:block;object-fit:cover}
.dm-ctx-b{max-width:76%;background:var(--panel);border:1px solid var(--line);border-radius:10px;
  padding:7px 10px;font-size:13px;line-height:1.65;word-break:break-word}
.dm-ctx-row.me .dm-ctx-b{background:var(--accent-soft);border-color:transparent}
/* 命中的那一条：红框 + 光环，滚到它时一眼能找到 */
.dm-ctx-row.flag .dm-ctx-b{border-color:rgba(229,72,77,.6);box-shadow:0 0 0 2px rgba(229,72,77,.15)}

/* ---------- 会员等级（第101轮）：卡片沿用 .gx-card，下面这些只服务这一页 ---------- */
.vx-top{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:12px}
.gx-card.vx-off{opacity:.6}
.vx-badge{display:inline-flex;align-items:center;height:19px;padding:0 8px;border-radius:999px;
  font-size:11.5px;font-weight:600;color:#fff;border:1px solid transparent}
.vx-badge.bg-gray{background:#9aa3ad}
.vx-badge.bg-blue{background:#3b82f6}
.vx-badge.bg-amber{background:#e0a028}
.vx-badge.bg-purple{background:#7c56d6}
.vx-badge.bg-green{background:#22b07d}
.vx-badge.bg-red{background:#e0533d}
.vx-line{display:inline-flex;align-items:center;gap:7px;cursor:pointer}
.vx-tip{font-size:12.5px;color:var(--sub2);line-height:1.65;margin-bottom:12px}
.vx-tip b{color:var(--text)}
.vx-grp{margin-bottom:14px}
.vx-grp>h5{font-size:13px;margin:0 0 8px;padding-bottom:6px;border-bottom:1px solid var(--line)}
.vx-it{display:grid;grid-template-columns:150px 1fr;gap:3px 12px;padding:8px 0;
  border-bottom:1px dashed var(--line);align-items:center}
.vx-it:last-child{border-bottom:none}
.vx-lb{font-size:13px;font-weight:600}
.vx-ctl{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.vx-num{width:132px}
.vx-des{grid-column:1/3;font-size:11.5px;color:var(--sub2);line-height:1.55}
.vx-sw{display:inline-flex;align-items:center;position:relative;cursor:pointer}
.vx-sw input{position:absolute;opacity:0;width:0;height:0}
.vx-sw i{display:block;width:36px;height:19px;border-radius:999px;background:var(--line);position:relative;transition:background .15s}
.vx-sw i::after{content:'';position:absolute;top:2px;left:2px;width:15px;height:15px;border-radius:50%;
  background:#fff;transition:transform .15s}
.vx-sw input:checked+i{background:var(--accent)}
.vx-sw input:checked+i::after{transform:translateX(17px)}
.vx-filter{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:12px}
.vx-gap{flex:1;min-width:10px}
.vx-pg{display:flex;align-items:center;gap:8px;margin-top:12px}
.vx-rule{display:flex;flex-direction:column;gap:14px}
.vx-rw{display:flex;gap:9px;align-items:flex-start;padding:9px 0;
  border-bottom:1px dashed var(--line);cursor:pointer}
.vx-rw:last-child{border-bottom:none}
.vx-chk{width:16px;height:16px;margin-top:2px;flex:none;cursor:pointer}
.vx-rw b{font-size:13px;display:block}
.vx-rw em{display:block;font-style:normal;font-size:12px;color:var(--sub2);line-height:1.55;margin-top:3px}
.vx-foot{padding-top:4px}
.dm-ctx-t{display:block;font-size:10.5px;color:var(--sub2);margin-top:5px}
.dm-ctx-bar{display:flex;gap:8px;justify-content:center;margin-top:10px}

/* ===== 后台：站点访问记录（第104轮） =====
 * 弹窗里「日期范围 + 身份 + 排序 + 关键字」一行排开；下面概况条复用 .ol-sum（与在线卡片同一套视觉）。
 * ★ 焦点样式沿用第100轮规范：一律 inset 单框，不再外扩 3~4px 光晕（那会与边框叠成双框）。 */
.ac-filter{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:10px}
.ac-filter .range-bar{margin:0;flex:1 1 100%}
.ac-q{width:210px;flex:0 0 auto}
.ac-tb th,.ac-tb td{white-space:nowrap}
.ac-days{display:flex;align-items:flex-end;gap:4px;height:64px;padding:8px 12px 0;
  margin-bottom:12px;border:1px solid var(--line);border-radius:8px;background:var(--panel2)}
.ac-day{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;
  justify-content:flex-end;height:100%}
.ac-day i{display:block;width:100%;max-width:30px;background:var(--accent);opacity:.72;
  border-radius:3px 3px 0 0}
.ac-day em{font-style:normal;font-size:10px;color:var(--sub2);margin-top:4px;white-space:nowrap}
.ac-pager{display:flex;align-items:center;gap:8px;margin-top:12px}
.ac-iphead{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:14px;
  padding:9px 12px;border:1px solid var(--line);border-radius:8px;background:var(--panel2);font-size:13px}
.ac-sec{margin-bottom:16px}
.ac-sec h4{margin:0 0 7px;font-size:13px;font-weight:600;color:var(--sub)}
.ac-sec .adm{margin:0}
/* 第105轮：列变多了（多了「停留时长」），窄屏一行放不下时**让表格自己横滚**，别去挤列宽、
 * 更别把弹窗撑破 —— 撑破的时候是整块布局一起歪，比滚动条难看得多。 */
.ac-wrap{overflow-x:auto;margin:0 -2px}
.ac-wrap .ac-tb{margin:0}
/* 第106轮：后台 IP 后面跟的地区标签。
 *   · 用 muted 小字跟在 IP 后面，不抢 IP 的视觉；
 *   · 局域网 / 未识别 这类没信息的 Geo.fill 已过滤不显示；
 *   · 城市与省同名（如「北京」）后端已折叠，这里只负责呈现。 */
.ip-cell{display:inline-flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.ip-region{font-size:11px;color:var(--sub2);white-space:nowrap}
/* 第105轮：明细弹窗底部的「清除访问记录」区。
 * 用 danger 色描边做**静态**提示：这个入口要显眼，但不做动画、不再叠外扩光晕
 * （第100轮的坑：border + 外扩 box-shadow 会叠成双圆角框）。 */
.ac-del{margin-top:4px;padding:10px 12px;border:1px solid #5a3038;border-radius:8px;
  background:rgba(229,72,77,.06)}
.ac-del h4{color:#ff7b7b}
.ac-del .muted{font-size:12px;line-height:1.7}
.ac-del-btns{display:flex;gap:8px;margin-top:10px}

/* ============================================================
   第116轮：素材详情页 · 评论区 + 相似推荐
   ============================================================ */
.cm-post { margin-bottom: 10px; }
.cm-post textarea.inp { width: 100%; resize: vertical; font-size: 13px; line-height: 1.5; }
.cm-post-b { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 6px; }
.cm-post-b .hint { margin-right: auto; }
.cm-list { display: flex; flex-direction: column; gap: 10px; }
.cm-i {
  border-top: 1px solid var(--line, #eceef2);
  padding-top: 9px;
}
.cm-i:first-child { border-top: 0; padding-top: 0; }
.cm-h { display: flex; align-items: baseline; gap: 8px; font-size: 13px; }
.cm-h b { font-weight: 600; }
.cm-h em { font-style: normal; font-size: 11px; color: var(--sub2, #8a8f99); }
.cm-flag {
  font-size: 11px; padding: 0 5px; border-radius: 20px;
  background: rgba(240, 176, 32, .14); color: #a2760d;
}
.cm-c { font-size: 13px; line-height: 1.6; margin: 4px 0 6px; word-break: break-word; }
.cm-rs {
  border-left: 2px solid var(--line, #eceef2);
  padding-left: 9px; margin: 6px 0; display: flex; flex-direction: column; gap: 4px;
}
.cm-r { font-size: 12px; line-height: 1.5; color: var(--sub, #5a6070); }
.cm-r b { color: var(--txt, #222); margin-right: 5px; font-weight: 600; }
.cm-ops { display: flex; gap: 6px; flex-wrap: wrap; }

/* 相似推荐 */
.sim-list { display: flex; flex-direction: column; gap: 4px; }
.sim-i {
  display: block; padding: 7px 9px; border-radius: 8px; text-decoration: none;
  color: inherit; transition: background .15s;
}
.sim-i:hover { background: var(--hover, #f4f6fa); }
.sim-i b {
  display: block; font-size: 13px; font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sim-i em { font-style: normal; font-size: 11px; color: var(--sub2, #8a8f99); }

/* 第116轮：搜索框下拉（我的历史 + 热词） */
.sp-panel {
  position: absolute; left: 0; right: 0; top: 100%; z-index: 60;
  margin-top: 6px; padding: 10px 12px;
  background: var(--card, #fff); border: 1px solid var(--line, #e6e8ec);
  border-radius: 10px; box-shadow: 0 8px 24px rgba(0, 0, 0, .1);
  max-height: 320px; overflow-y: auto;
}
.sp-g + .sp-g { margin-top: 10px; }
.sp-gt {
  display: flex; align-items: center; font-size: 12px; color: var(--sub2, #8a8f99);
  margin-bottom: 6px;
}
.sp-clr { margin-left: auto; cursor: pointer; }
.sp-clr:hover { color: var(--accent, #3b6df6); }
.sp-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.sp-tag {
  font-size: 12px; padding: 4px 10px; border-radius: 20px; cursor: pointer;
  background: var(--hover, #f2f4f8); color: var(--txt, #222);
  display: inline-flex; align-items: center; gap: 4px;
}
.sp-tag:hover { background: var(--accent, #3b6df6); color: #fff; }
.sp-tag.hot { background: rgba(240, 176, 32, .14); }
.sp-tag i { font-style: normal; font-size: 10px; opacity: .7; }
.sp-load, .sp-empty { font-size: 12px; color: var(--sub2, #8a8f99); padding: 4px 0; }

/* 第116轮：加入歌单弹窗 */
.pl-pick { display: flex; flex-direction: column; gap: 2px; max-height: 300px; overflow-y: auto; }
.pl-pick-i {
  display: flex; align-items: center; gap: 8px; padding: 7px 8px;
  border-radius: 8px; cursor: pointer; font-size: 13px;
}
.pl-pick-i:hover { background: var(--hover, #f4f6fa); }
.pl-pick-i span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-pick-i em { font-style: normal; font-size: 11px; color: var(--sub2, #8a8f99); }
.pl-new {
  display: flex; gap: 8px; margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--line, #eceef2);
}
.pl-new .inp { flex: 1; }
