@charset "utf-8";
/* ==========================================================================
   快播影视 · 芒果TV 风格模板(暗色版 v3)
   template/mango_pc/css/style.css
   主色沿用芒果TV线上令牌；配色为暗色：页面纯黑 + 深灰面板 + 橙色主色
   沿用官方默认结构的页面(用户中心/文章等)由 base.css 提供样式，文件末尾做暗色兜底
   ========================================================================== */

:root {
    /* —— 主色(芒果TV 线上令牌) —— */
    /* ⚠️ 这三个值只是**兜底**：正常情况下后台会内联一段 <style> 覆盖它们
       （见 template/default/html/public/include.html + model/system/ThemeColor.go）。
       这里改成和 Go 侧 defaultThemeColor 一致，是为了「内联样式没加载出来」时
       观感也不会跑偏。改主色请改后台设置，不要只改这里。 */
    --m-primary: #ff5f00;
    --m-primary-d: #ea5d19;
    --m-primary-l: #ff8a00;
    --m-grad: linear-gradient(90deg, #ff8a00 0%, #ff5f00 100%);
    /* 主色底上的文字色：默认白色。
       后台把主色设成浅色（比如亮黄 #ffe100）时，Go 那边会算出 #000 覆盖它，
       免得按钮上的白字看不清（见 model/system/ThemeColor.go 的 ContrastInk）。 */
    --m-primary-ink: #ffffff;
    /* 主色的半透明版（兜底值，正常由后台内联样式用 color-mix 覆盖）。
       用于「主色 + 透明度」的地方：选中底、hover 底、边框、阴影、卡片播放按钮……
       ⚠️ 这几个必须带兜底值 —— color-mix 在 2023 年前的浏览器不支持，
          直接写 var(--m-primary-16) 会解析失败导致**整条属性失效**。 */
    --m-primary-08: rgba(255,95,0,.08);
    --m-primary-12: rgba(255,95,0,.12);
    --m-primary-16: rgba(255,95,0,.16);
    --m-primary-32: rgba(255,95,0,.32);
    --m-primary-45: rgba(255,95,0,.45);
    --m-primary-95: rgba(255,95,0,.95);
    /* 深/浅两档也补上兜底（和上面 --m-primary 保持一致） */
    --m-gold: #ffa516;
    --m-grad-gold: linear-gradient(90deg, #ffcf7a 0%, #ffa516 55%, #ff7a00 100%);
    --m-playing: linear-gradient(0deg, #fd43bf, #ff4500);

    /* —— 暗色表面 —— */
    --m-bg: #000000;
    --m-surface: #131316;
    --m-surface-2: #1c1c21;
    --m-surface-3: #26262c;
    --m-pic-bg: #2e2e36;
    --m-line: #2a2a30;
    --m-line-2: #35353c;

    /* —— 文字 —— */
    --m-ink: #f3f3f6;
    --m-text: #d3d3da;
    --m-sub: #9a9aa3;
    --m-muted: #6f6f79;

    --m-radius: 8px;
    --m-radius-lg: 12px;
    --m-card-gap: 12px;
    /* 首图上的文字亮度：标题纯白，副信息逐级变淡（见 .m-hero-info 那几条规则） */
    --m-hero-ink-2: rgba(255,255,255,.80);
    --m-hero-ink-3: rgba(255,255,255,.72);
    --m-shadow: 0 2px 12px rgba(0, 0, 0, .6);
    --m-shadow-h: 0 10px 30px rgba(0, 0, 0, .8);
    /* 内容区宽度上限。以前是 1500px，1920 的屏上正文两边各空 226px、2560 上各空 546px，
       而首页轮播是通栏的 —— 上下对不齐、看着就是"内容区左右留白莫名其妙地大"。
       现在放到 2200px：1920（及以下）直接铺满，比 1920 更宽时才开始居中留白。 */
    --m-wrap: 2200px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
body {
    font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
    font-size: 14px; line-height: 1.6; color: var(--m-text);
    background: var(--m-bg) !important;
    -webkit-font-smoothing: antialiased;
    color-scheme: dark;
}
a { color: inherit; text-decoration: none; }
a:hover { color: var(--m-primary); }
img { border: 0; display: block; max-width: 100%; }
ul, ol, li { list-style: none; }
input, button, select, textarea { font-family: inherit; font-size: inherit; outline: none; }
em, i { font-style: normal; }
h1, h2, h3, h4 { color: var(--m-ink); }
.m-wrap { width: 100%; max-width: var(--m-wrap); margin: 0 auto; padding: 0 16px; }
.m-clear::after { content: ""; display: block; clear: both; }

/* ================================================================ 顶部 */
.m-header { position: sticky; top: 0; z-index: 90; background: rgba(8, 8, 10, .96); backdrop-filter: blur(12px); border-bottom: 1px solid var(--m-line); }
.m-header-inner { display: flex; align-items: center; justify-content: space-between; height: 62px; gap: 20px; }
.m-hd-left { display: flex; align-items: center; gap: 26px; min-width: 0; flex: 1 1 0; }
/* 中间区块 = 搜索框 + 热搜词。左边(logo)和右边(VIP入口)都是 flex:1 1 0 等宽，
   所以中间这一块永远落在页面水平正中的位置 */
.m-hd-center { display: flex; align-items: center; gap: 18px; flex: 0 1 auto; min-width: 0; }
.m-hd-right { display: flex; align-items: center; gap: 16px; flex: 1 1 0; justify-content: flex-end; }

/* 首页:整条页头透明悬浮在轮播之上(轮播从页面最顶端开始，穿过搜索栏下方) */
.m-home .m-header { position: fixed; left: 0; right: 0; background: linear-gradient(180deg, rgba(0, 0, 0, .82) 0%, rgba(0, 0, 0, .45) 62%, rgba(0, 0, 0, 0) 100%); backdrop-filter: none; border-bottom: 0; transition: background .25s ease, border-color .25s ease; }
.m-home .m-header.is-solid { background: rgba(8, 8, 10, .96); backdrop-filter: blur(12px); border-bottom: 1px solid var(--m-line); }

.m-logo { flex: 0 0 auto; display: flex; align-items: center; }
.m-logo img { height: 34px; width: auto; }
.m-logo-txt { font-size: 22px; font-weight: 800; letter-spacing: .5px; line-height: 1.05; color: var(--m-primary); white-space: nowrap; }
.m-logo-txt small { display: block; font-size: 9px; font-weight: 600; letter-spacing: 3.5px; color: var(--m-muted); }
/* logo 有桌面/手机两张图（后台基本设置里分别配）：默认只显示桌面那张，
   手机上换成手机那张；只配了手机 logo 时用 m-logo-mb-solo 在桌面也显示它 */
.m-logo-pc, .m-logo-mb-solo { display: flex; }
.m-logo-mb { display: none; }

.m-nav { display: flex; align-items: center; gap: 2px; overflow: hidden; min-width: 0; }
.m-nav a { position: relative; padding: 0 11px; height: 62px; line-height: 62px; font-size: 15px; color: var(--m-text); white-space: nowrap; transition: color .18s; }
.m-nav a:hover { color: var(--m-primary); }
.m-nav a.on { color: #fff; font-weight: 700; }
.m-nav a.on::after { content: ""; position: absolute; left: 11px; right: 11px; bottom: 12px; height: 3px; border-radius: 2px; background: var(--m-grad); }

/* 页头里那排横排频道（logo 右边）—— **只有播放页用**（见下面 .m-playpage）。
   其它页面还是左边那排竖排导航（.m-side-nav），两者共用 public/nav-items.html 那一份链接。
   图标在这版里藏起来：10 个频道，每个 21px 的图标要多占 200 多像素，
   页头本来就挤（logo + 搜索框 + 右侧几个入口），只留文字反而清爽。
   桌面窄一点的时候这排可以让出宽度横向滑动（滚动条藏起来），不会把页头挤爆。 */
.m-hd-nav {
    display: none; align-items: center; gap: 0; min-width: 0;
    overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
}
.m-hd-nav::-webkit-scrollbar { display: none; }
.m-hd-nav a {
    position: relative; display: inline-flex; align-items: center; height: 62px;
    padding: 0 9px; color: var(--m-text); font-size: 14px; white-space: nowrap;
    transition: color .18s;
}
.m-hd-nav a svg { display: none; }
.m-hd-nav a:hover { color: var(--m-primary); }
/* 选中的频道：**只**用纯白 + 加粗，底下那条橙色横杠已按站长要求去掉
   （整排频道 62px 高，再挂一条 3px 渐变横杠在页头里显得很闹）。
   左边那排竖排导航的选中态也是"纯白 + 加粗"（外加一颗星光），两边观感一致。 */
.m-hd-nav a.on { color: #fff; font-weight: 700; }

/* ---------------- 左侧竖向频道导航(桌面端悬浮在网页左边) ---------------- */
.m-side-nav {
    position: fixed; left: 12px; top: 50%; transform: translateY(-50%); z-index: 85;
    display: flex; flex-direction: column; gap: 8px;
    /* 宽度跟着内容走：容器宽度 = 最宽的那个频道（例如"最近更新"），
       这样文字不会被省略号截断；每个 a 是 flex item，默认 stretch 会自动撑满同宽 */
    width: max-content; min-width: 118px; padding: 12px 9px;
    background: rgba(18, 18, 22, .74); backdrop-filter: blur(14px);
    border: 1px solid rgba(255, 255, 255, .09); border-radius: 20px;
    box-shadow: 0 10px 34px rgba(0, 0, 0, .55);
    max-height: min(82vh, calc(100vh - 150px)); overflow-y: auto; scrollbar-width: none;
}
.m-side-nav::-webkit-scrollbar { display: none; }
/* 右上角汉堡按钮：只在窄屏（≤1024px）显示，点了滑出右侧分类抽屉。
   桌面上左侧那排分类是常驻的，不需要它。 */
.m-menu-btn {
    display: none; align-items: center; justify-content: center;
    width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%;
    background: transparent; color: #fff; cursor: pointer;
    transition: background .18s, color .18s;
}
.m-menu-btn svg { width: 20px; height: 20px; display: block; }
.m-menu-btn:hover { background: rgba(255, 255, 255, .12); }
.m-menu-btn[aria-expanded="true"] { background: rgba(255, 255, 255, .16); }
/* 每个频道：左边一个白色图标 + 右边文字。
   选中态不要整块橙色背景（那样太重），改成：
     · 未选中 → 文字和图标微微透明（.72）
     · 选中   → 纯白 + 右侧一颗星光（.m-side-nav a.on::after） */
.m-side-nav a {
    position: relative;
    /* 右边留出 28px 给选中时那颗星光：所有项都留，这样选中时文字不会左右跳 */
    display: flex; align-items: center; gap: 10px; padding: 11px 28px 11px 11px;
    color: rgba(255, 255, 255, .72); font-size: 15px; line-height: 1.3; border-radius: 12px;
    white-space: nowrap; transition: background .18s, color .18s;
}
.m-side-nav a svg { flex: 0 0 auto; width: 21px; height: 21px; color: inherit; opacity: 1; }
.m-side-nav a span { flex: 0 0 auto; }
.m-side-nav a:hover { background: var(--m-surface-3); color: #fff; }
.m-side-nav a:hover svg { color: #fff; }
.m-side-nav a.on { background: transparent; color: #fff; font-weight: 700; }
.m-side-nav a.on svg { color: #fff; }
.m-side-nav a.on:hover { background: var(--m-surface-2); }
/* 选中项右侧那颗星光：四角星（内联 SVG 当背景图，不引图标库也不依赖字体）
   + 一点点"闪烁"呼吸动画（尊重系统的"减少动态效果"设置） */
.m-side-nav a.on::after {
    content: ""; position: absolute; right: 9px; top: 50%; width: 14px; height: 14px;
    margin-top: -7px; pointer-events: none;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.6l2.5 7.9 7.9 2.5-7.9 2.5L12 22.4l-2.5-7.9L1.6 12l7.9-2.5z' fill='%23ffffff'/%3E%3C/svg%3E") center/contain no-repeat;
    filter: drop-shadow(0 0 5px rgba(255, 255, 255, .75)) drop-shadow(0 0 10px rgba(255, 138, 0, .55));
    animation: m-star-twinkle 1.9s ease-in-out infinite;
}
@keyframes m-star-twinkle {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: .55; transform: scale(.86); }
}
@media (prefers-reduced-motion: reduce) {
    .m-side-nav a.on::after { animation: none; }
}
/* 桌面端给左侧导航预留空间(页头/热搜行不缩进，logo 保持贴左)。
   侧栏固定在 left:12，宽度跟着内容走（字号/图标放大过之后实测约 150）→ 右边缘约 162，
   正文需要的左侧自由空间 = 162 + 16 间隙 ≈ 180。
   正文容器是居中的 .m-wrap(max-width: var(--m-wrap))：窗口越宽两侧留白越多，
   需要让出的就越少，最少回到 16px。用 max() 算，保证任何宽度下都刚好不压住正文。 */
@media (min-width: 1025px) {
    .m-wrap { padding-left: max(16px, 180px - max(0px, (100vw - var(--m-wrap)) / 2)); }
    /* 页头：logo 这一侧固定留 50px（用户要求"左边加 50px"）。
       页头整条铺满屏幕，所以这 50px 是**到屏幕左边缘**的距离，任何窗口宽度下都一样
       （以前页头跟着正文那个居中的 1500px 容器走，1920 宽的屏幕上 logo 会被推到 226px 外）。
       右侧图标仍然贴右边 16px；正文容器不受影响，还是居中的 .m-wrap。 */
    .m-header .m-wrap { max-width: none; padding-left: 50px; padding-right: 16px; }
    .m-hotline .m-wrap { padding-left: 16px; }

    /* ---------------- 播放页：不要左边那排竖排导航（站长要求） ----------------
       播放页（<body class="m-playpage">）：
         · 左侧竖排收起来；
         · 频道改到页头里 logo 右边横排（.m-hd-nav，见上面那段）；
         · 页头那行热搜词让位（搜索框里点一下就有"热门搜索"，功能不缺）；
         · 正文不再为左侧竖排留 180px，播放器/选集跟着变宽。 */
    .m-playpage .m-side-nav { display: none; }
    .m-playpage .m-hotline { display: none; }
    .m-playpage .m-hd-nav { display: flex; }
    .m-playpage .m-play-wrap { padding-left: 16px; }
    /* 页头这块要重新分配宽度：默认 logo 和右边图标各占一半（所以搜索框永远居中），
       但一半放不下"logo + 10 个频道"。播放页改成：左边有多少占多少、右边只占自己那点，
       搜索框跟着往右挪一点（不再严格居中）—— 这是"频道放 logo 右边"必然的代价。
       搜索框同时收窄到 300px，再给频道腾一点。实测：1600/1440 十项全在，1366 九项。 */
    .m-playpage .m-hd-left { flex: 1 1 auto; }
    .m-playpage .m-hd-right { flex: 0 0 auto; }
    .m-playpage .m-search form { width: 300px; }
}

.m-search { flex: 0 0 auto; position: relative; }
/* 搜索框聚焦时弹出的面板：搜索历史（本地存） + 热门搜索（后台热搜词）。
   窄屏热搜词那一行是隐藏的，所以窄屏看热搜词就靠这个面板。 */
.m-suggest {
    position: absolute; top: calc(100% + 10px); left: 0; right: 0; z-index: 140;
    background: var(--m-surface); border: 1px solid var(--m-line);
    border-radius: var(--m-radius-lg); padding: 12px 14px 14px;
    box-shadow: 0 18px 40px rgba(0, 0, 0, .6);
}
.m-suggest[hidden] { display: none; }
.m-suggest-sec + .m-suggest-sec { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--m-line); }
.m-suggest-hd { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 12px; color: var(--m-muted); margin-bottom: 9px; }
.m-suggest-clear { background: none; border: 0; padding: 0; color: var(--m-muted); font-size: 12px; cursor: pointer; }
.m-suggest-clear:hover { color: var(--m-primary); }
.m-suggest-tags { display: flex; flex-wrap: wrap; gap: 8px; }
.m-suggest-tags a {
    padding: 4px 11px; border-radius: 14px; background: var(--m-surface-2);
    color: var(--m-sub); font-size: 12.5px; max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-suggest-tags a:hover { background: var(--m-grad); color: var(--m-primary-ink); }
/* 窄屏搜索框是"弹在页头下面"的固定条，面板就跟着它往下排 */
@media (max-width: 560px) {
    .m-suggest { position: fixed; top: 112px; left: 12px; right: 12px; }
}
/* 窄屏专用的圆形搜索按钮：桌面端隐藏（桌面搜索框常驻） */
.m-search-toggle {
    display: none; align-items: center; justify-content: center;
    width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%;
    background: rgba(255, 255, 255, .10); color: #fff; cursor: pointer;
    transition: background .18s, color .18s;
}
.m-search-toggle svg { width: 16px; height: 16px; display: block; }
.m-search-toggle:hover { background: rgba(255, 255, 255, .16); }
.m-search-toggle[aria-expanded="true"] { background: var(--m-grad); }
/* 搜索框：半透明的"玻璃"底（比原来的实心面板更透），描边也是低透明度白色，
   所以放在首页那张大图上、以及滚动后的实心页头上都好看。
   文字和放大镜都用纯白，保证任何背景上都清楚。 */
.m-search form { display: flex; align-items: center; width: 360px; height: 34px;
    background: rgba(255, 255, 255, .10);
    border: 1px solid rgba(255, 255, 255, .16);
    border-radius: 17px; padding: 0 4px 0 14px;
    backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
    transition: border-color .2s, background .2s; }
.m-search form:hover { background: rgba(255, 255, 255, .14); }
.m-search form:focus-within { border-color: var(--m-primary); background: rgba(255, 255, 255, .18); }
.m-search input[type=text] { flex: 1 1 auto; min-width: 0; border: 0; background: transparent; color: #fff; font-size: 13px; }
.m-search input[type=text]::placeholder { color: rgba(255, 255, 255, .58); }
/* 放大镜用内联 SVG（原来是 emoji 🔍，彩色 emoji 没法变成纯白） */
.m-search form button { flex: 0 0 auto; width: 26px; height: 26px; border: 0; border-radius: 50%;
    background: transparent; cursor: pointer; color: #fff; padding: 0;
    display: flex; align-items: center; justify-content: center;
    transition: color .2s, background .2s; }
.m-search form button svg { width: 16px; height: 16px; display: block; }
.m-search form button:hover { color: var(--m-primary); background: rgba(255, 255, 255, .10); }
/* 输入框本身要"透到底"（露出上面那层玻璃底），文字纯白。
   注意：下面那条全局暗色兜底规则
     input[type=text]{ background-color: var(--m-surface-2) !important; color: var(--m-ink) !important }
   带 !important，所以这里必须同样用 !important 才盖得住（实测不加的话输入框还是不透明、
   文字是 #f3f3f6 而不是纯白）。搜索页那个大搜索框同理。 */
.m-search input[type=text], .m-search input.mac_wd,
.m-searchbox input[type=text], .m-searchbox input.mac_wd {
    background-color: transparent !important;
    border: 0 !important;
    color: #fff !important;
}
.m-search input[type=text]::placeholder, .m-search input.mac_wd::placeholder {
    color: rgba(255, 255, 255, .58) !important;
}
.m-searchbox input[type=text]::placeholder, .m-searchbox input.mac_wd::placeholder {
    color: rgba(255, 255, 255, .5) !important;
}
/* 浏览器自动填充会强行刷一层底色（蓝/黄），这两行把它按住 */
.m-search input:-webkit-autofill, .m-searchbox input:-webkit-autofill {
    -webkit-text-fill-color: #fff;
    -webkit-box-shadow: 0 0 0 1000px rgba(18, 18, 22, .92) inset;
}

.m-hd-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 14px; font-size: 13px; color: var(--m-sub); }
.m-hd-actions a:hover { color: var(--m-primary); }
.m-vip-btn { display: inline-flex; align-items: center; height: 30px; padding: 0 14px; border-radius: 15px; background: var(--m-grad-gold); color: #4a2c00 !important; font-weight: 700; font-size: 13px; box-shadow: 0 2px 10px rgba(255, 165, 22, .3); }
.m-vip-btn:hover { filter: brightness(1.06); color: #4a2c00 !important; }

/* 页头右上角的 消息/历史 图标、头像、下载客户端 */
.m-hd-ic { display: inline-flex; align-items: center; gap: 5px; height: 32px; color: var(--m-sub); font-size: 13px; white-space: nowrap; transition: color .18s; }
.m-hd-ic svg { width: 18px; height: 18px; flex: 0 0 auto; }
.m-hd-ic:hover { color: var(--m-primary); }
/* 「下载客户端」这几个字右边留 20px（站长要求）：它是页头最右边那一项，
   文字贴着窗口右边会显得挤。注意只给这一个加 —— .m-hd-txt 是「消息 / 历史 / 下载客户端」
   共用的类，直接写 .m-hd-txt 会把那三个一起推走。
   窄屏（文字被 display:none 藏起来的断点）这条不起作用，正好不影响图标排布。 */
.m-hd-app .m-hd-txt { margin-right: 20px; }
.m-hd-avatar { display: block; flex: 0 0 auto; width: 32px; height: 32px; border-radius: 50%; overflow: hidden; background: var(--m-surface-3); border: 1px solid rgba(255, 255, 255, .22); transition: border-color .18s; }
.m-hd-avatar img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* 游客时头像位置放的是人形图标（登录后会被换成会员头像），让"还没登录"一眼看得出来 */
.m-hd-avatar svg { display: block; width: 100%; height: 100%; padding: 5px; color: var(--m-sub); }
.m-hd-avatar:hover { border-color: var(--m-primary); }
/* 首页页头是悬浮在轮播图上的，浅色 + 阴影才看得清 */
.m-home .m-hd-ic { color: rgba(255, 255, 255, .78); text-shadow: 0 1px 8px rgba(0, 0, 0, .7); }
.m-home .m-hd-ic:hover { color: var(--m-primary); }
.m-home .m-hd-avatar { border-color: rgba(255, 255, 255, .34); }

/* ================================================================ 页头悬浮小框（消息 / 历史 / 头像） */
/* 纯 CSS 弹出：.m-hd-drop 包住图标 + 面板，鼠标悬停或键盘聚焦时展开（不需要 JS）。
   .m-hd-drop::after 是一条透明的"桥"——图标和面板之间那 10px 空隙如果点不到，
   鼠标从图标移到面板的过程中会闪断。 */
.m-hd-drop { position: relative; display: inline-flex; align-items: center; }
.m-hd-drop::after { content: ""; position: absolute; left: -10px; right: -10px; top: 100%; height: 14px; }
.m-hd-pop {
    position: absolute; right: 0; top: calc(100% + 12px); width: 320px; z-index: 150;
    padding: 12px 14px 14px; text-align: left; white-space: normal;
    background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg);
    box-shadow: 0 18px 40px rgba(0, 0, 0, .62);
    opacity: 0; visibility: hidden; transform: translateY(-6px); pointer-events: none;
    transition: opacity .18s ease, transform .18s ease, visibility .18s;
}
.m-hd-drop:hover .m-hd-pop, .m-hd-drop:focus-within .m-hd-pop { opacity: 1; visibility: visible; transform: none; pointer-events: auto; }
.m-hd-pop-hd { display: flex; align-items: center; justify-content: space-between; gap: 10px;
    font-size: 13px; font-weight: 700; color: var(--m-ink); padding-bottom: 9px; margin-bottom: 8px;
    border-bottom: 1px solid var(--m-line); }
.m-hd-pop-hd a { font-size: 12px; font-weight: 400; color: var(--m-muted); }
.m-hd-pop-hd a:hover { color: var(--m-primary); }
.m-hd-pop-list {
    max-height: 320px; overflow-y: auto;
    overscroll-behavior: contain;      /* 滚到头不要带着整个页面一起滚 */
}
/* 滚动条细一点：默认那条 15~17px 宽，压在列表右边很抢眼。
   ⚠️ Chromium 只要看到 scrollbar-width / scrollbar-color，就会**忽略 ::-webkit-scrollbar**
   （结果就是"写了细滚动条但一点没变"）。所以分两条路：
   Chromium/Safari 走 ::-webkit-*，Firefox 走标准属性（用 @supports 隔开）。 */
.m-hd-pop-list::-webkit-scrollbar { width: 6px; height: 6px; }
.m-hd-pop-list::-webkit-scrollbar-track { background: transparent; }
.m-hd-pop-list::-webkit-scrollbar-thumb { background: var(--m-line-2); border-radius: 3px; }
.m-hd-pop-list::-webkit-scrollbar-thumb:hover { background: var(--m-muted); }
@supports not selector(::-webkit-scrollbar) {
    .m-hd-pop-list { scrollbar-width: thin; scrollbar-color: var(--m-line-2) transparent; }
}
.m-hd-pop-empty { font-size: 12.5px; line-height: 1.7; color: var(--m-muted); padding: 4px 0 2px; }
.m-hd-pop-acts { display: flex; gap: 8px; margin-top: 10px; }
.m-hd-pop-acts .m-btn { flex: 1 1 0; height: 32px; font-size: 13px; padding: 0; }
/* 消息：一行一条（标题 + 说明 + 时间） */
.m-hd-note { display: block; padding: 8px 10px; border-radius: 8px; }
.m-hd-note:hover { background: var(--m-surface-2); }
.m-hd-note b { display: block; font-size: 13px; font-weight: 600; color: var(--m-ink); }
.m-hd-note span { display: block; margin-top: 2px; font-size: 12px; color: var(--m-muted); }
.m-hd-note em { display: block; margin-top: 3px; font-size: 11px; font-style: normal; color: var(--m-primary); }
/* 历史：小横条（封面 + 片名 + 集数 + 时间） */
.m-hd-play { display: flex; align-items: center; gap: 9px; padding: 7px 8px; border-radius: 8px; }
.m-hd-play:hover { background: var(--m-surface-2); }
.m-hd-play img { flex: 0 0 auto; width: 54px; height: 32px; border-radius: 5px; object-fit: cover; background: var(--m-pic-bg); }
.m-hd-play-body { flex: 1 1 auto; min-width: 0; }
.m-hd-play-body b { display: block; font-size: 13px; font-weight: 600; color: var(--m-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-hd-play:hover .m-hd-play-body b { color: var(--m-primary); }
.m-hd-play-body em { display: block; margin-top: 2px; font-size: 11.5px; font-style: normal; color: var(--m-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-hd-play-time { flex: 0 0 auto; font-size: 11px; font-style: normal; color: var(--m-muted); }
/* 头像面板：用户信息 + 快捷入口 */
.m-hd-pop-user { width: 260px; }
.m-hd-user { display: flex; align-items: center; gap: 10px; padding-bottom: 10px; margin-bottom: 8px; border-bottom: 1px solid var(--m-line); }
.m-hd-user > img { flex: 0 0 auto; width: 42px; height: 42px; border-radius: 50%; object-fit: cover; background: var(--m-surface-3); }
.m-hd-user-info { min-width: 0; }
.m-hd-user-info b { display: block; font-size: 14px; color: var(--m-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-hd-user-info span { display: block; margin-top: 2px; font-size: 12px; color: var(--m-muted); }
.m-hd-user-info em { display: block; margin-top: 2px; font-size: 11.5px; font-style: normal; color: var(--m-gold); }
.m-hd-vip { display: inline-block; margin-right: 5px; padding: 0 5px; border-radius: 4px; font-size: 11px; font-style: normal;
    background: var(--m-grad-gold); color: #3a2a00; font-weight: 700; }
.m-hd-user-links { display: flex; flex-direction: column; }
.m-hd-user-links a { padding: 8px 10px; border-radius: 8px; font-size: 13px; color: var(--m-text); }
.m-hd-user-links a:hover { background: var(--m-surface-2); color: var(--m-primary); }
.m-hd-user-links .m-hd-logout { color: var(--m-muted); border-top: 1px solid var(--m-line); border-radius: 0 0 8px 8px; margin-top: 4px; }
/* 管理组账号的「网站后台」入口：给一点颜色，和普通菜单项区分开 */
.m-hd-user-links .m-hd-admin { color: var(--m-primary); font-weight: 700; }
/* 有消息时图标右上角一个小红点 */
.m-hd-msg { position: relative; }
.m-hd-dot { position: absolute; right: -2px; top: 2px; width: 7px; height: 7px; border-radius: 50%;
    background: var(--m-primary); box-shadow: 0 0 0 2px rgba(8, 8, 10, .8); }
/* 触摸设备没有 hover：这三个框直接不弹（图标本身仍然是可点的链接） */
@media (hover: none) {
    .m-hd-pop { display: none; }
}
/* 窄屏（手机/平板）：页头图标本来就少了，弹出框也要收窄、靠右不出屏 */
@media (max-width: 1024px) {
    .m-hd-pop { width: min(88vw, 320px); }
}

/* 热搜词:紧跟在搜索框右边，同一行显示（原来它自己占一整行） */
.m-hotline { display: flex; align-items: center; gap: 10px; font-size: 12px; color: var(--m-muted); white-space: nowrap; overflow: hidden; }
.m-hotline a { color: var(--m-sub); }
.m-hotline a:first-of-type { color: var(--m-primary); }
/* 首页悬浮页头里的热搜:透在图上，靠阴影保证可读 */
.m-home .m-hotline { color: rgba(255, 255, 255, .55); }
.m-home .m-hotline a { color: rgba(255, 255, 255, .62); text-shadow: 0 1px 8px rgba(0, 0, 0, .7); }
.m-home .m-hotline a:first-of-type { color: var(--m-primary); }
/* 搜索页那一处热搜词是"单独一行、居中"的用法，和页头跟在搜索框后面的那行不一样 */
.m-hotline-block { display: block; text-align: center; white-space: normal; overflow: visible; margin-top: 12px; color: var(--m-sub); }
.m-hotline-block a { margin: 0 7px; }

/* ================================================================ 主视觉(整屏出血，首页从页面最顶端开始) */
/* 轮播高度跟着**视口宽度**走（clamp 一行代替原来 600/480/380 三档跳变）：
   以前手机上固定 380px，420 宽的屏幕几乎是正方形，很占地方；
   现在 1600 宽 600px、1024 宽 450px、640 宽 282px、≤520 宽回到下限 230px。 */
.m-hero { position: relative; height: clamp(230px, 44vw, 600px); overflow: hidden; background: #101014;
    /* 手机上手指左右滑：横向手势归我们自己处理（见 kuaibo.js 的 initHero），
       竖向留给页面滚动 —— 不写这条的话浏览器会把手势判成滚动并把手势"抢走"（touchcancel）。 */
    touch-action: pan-y; }
.m-home .m-hero { margin-top: 0; }
.m-hero-bg { position: absolute; top: 0; left: 50%; width: 100vw; height: 100%; transform: translateX(-50%); }
.m-hero-slide { position: absolute; top: 0; left: 0; right: 0; bottom: 0; opacity: 0; visibility: hidden;
    /* transform 的过渡是给"松手后滑到终点/弹回原位"用的（时长要和 kuaibo.js 里的 DRAG_MS 对齐）；
       手指还在屏幕上的时候由 .m-hero.is-dragging 把过渡关掉，画面才能真正跟手。 */
    transition: opacity .5s ease, visibility .5s ease, transform .3s ease; will-change: transform; }
.m-hero-slide.is-active { opacity: 1; visibility: visible; }
/* 拖动中：不要过渡，图片直接跟着手指走 */
.m-hero.is-dragging .m-hero-slide { transition: none; }
/* 正在从侧面滑进来的那一张：先露出来（它还不是 is-active，否则看不到跟手效果） */
.m-hero-slide.is-peek { opacity: 1; visibility: visible; }
.m-hero-slide img { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; }
/* 层级：图片(0) < 压暗遮罩(1) < 文字信息(2)。
   ::after 是 .m-hero-slide 的最后一个"子元素"，默认会盖在 .m-hero-slidebody 上面，
   于是那层黑色渐变糊在白字上，字就发灰看不清 —— 所以这里必须显式分层。 */
.m-hero-slide::after {
    content: ""; position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: 1;
    background:
        /* 顶部压暗，保证透明页头上的导航/搜索看得清 */
        linear-gradient(180deg, rgba(0,0,0,.72) 0%, rgba(0,0,0,.34) 12%, rgba(0,0,0,0) 30%),
        linear-gradient(90deg, rgba(0,0,0,.9) 0%, rgba(0,0,0,.55) 36%, rgba(0,0,0,.05) 64%),
        linear-gradient(0deg, var(--m-bg) 2%, rgba(0,0,0,.45) 26%, rgba(0,0,0,0) 55%);
}
.m-hero-slidebody { position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: 2; display: flex; align-items: flex-end; }
/* 首图信息块：整体往右挪一点，别贴着左边的侧栏导航（1600 宽时刚好只剩 16px 间隙，太挤）。
   底部留白 = **给下面那排缩略图让位**：那排的高度是固定的（缩略图 74px + 外边距 ≈ 88px），
   而这里以前写的是 clamp(26px, 7vw, 108px)（跟着视口缩），于是窄到 1100 以下留白比缩略图还矮，
   「立即观看」那排按钮就压在缩略图上了（实测 1200 重叠 4px、1068 重叠 13px、641 重叠 43px）。
   改成固定 100px（= 缩略图高度 + 12px 间距），任何宽度下都是同一个 12px 间隙。
   窄到整块内容装不下缩略图时（≤768）缩略图隐藏，留白再收回去 —— 见下面的媒体查询。
   container-type 是为了让里面的按钮/字号按这块的宽度缩放（见 .m-hero-btns）。 */
.m-hero-info { max-width: 620px; padding: 0 0 100px; margin-left: 26px; color: #fff; container-type: inline-size; }
/* 缩略图那一排（.m-hero-thumbs）：高度固定 88px，压在轮播底部。
   窄屏（≤768）整排隐藏 + 信息块底部留白收回去（见文件末尾的媒体查询）。 */
/* 轮播上的「热播推荐」标签已按用户要求去掉（CSS 一并删掉，免得以后有人以为还在用）。
   标题现在是这一块的第一个元素，所以上边距清零。 */
.m-hero-title { font-size: 36px; font-weight: 800; line-height: 1.2; margin: 0 0 10px; color: #fff; text-shadow: 0 2px 16px rgba(0,0,0,.6); }
.m-hero-title a { color: #fff; }
.m-hero-meta { font-size: 13px; color: var(--m-hero-ink-2); margin-bottom: 10px; text-shadow: 0 1px 6px rgba(0,0,0,.7); }
.m-hero-meta span { margin-right: 14px; }
.m-hero-desc { font-size: 13px; line-height: 1.8; color: var(--m-hero-ink-3); text-shadow: 0 1px 8px rgba(0,0,0,.75); max-height: 66px; overflow: hidden; margin-bottom: 20px; }
.m-hero-desc p { margin: 0; color: inherit; }
/* 主视觉信息区：里面的文字一律浅白。
   base.css 里有 body{color:#666} 和 a:link{color:#666}，只要有一个元素没被 .m-hero-info
   的颜色继承到（例如简介里自带的 <p>、或浏览器把非法嵌套的 <p> 顶到外面），就会变成深灰看不清，
   所以这里显式兜一层，不做任何依赖继承的假设。 */
.m-hero-info,
.m-hero-info p, .m-hero-info span, .m-hero-info em, .m-hero-info strong, .m-hero-info small,
.m-hero-info div, .m-hero-info h1, .m-hero-info h2, .m-hero-info h3 {
    color: #fff;
}
.m-hero-info a, .m-hero-info a:link, .m-hero-info a:visited, .m-hero-info a:active, .m-hero-info a:hover {
    color: #fff;
}
.m-hero-info .m-hero-title, .m-hero-info .m-hero-title a { color: #fff; }
/* 标题保持纯白，副信息稍微透一点（纯白一片看着太"硬"）：
   分类/年份那行 .80，简介 .72 —— 层级从亮到暗，压在大图上更透气 */
.m-hero-info .m-hero-meta, .m-hero-info .m-hero-meta span { color: var(--m-hero-ink-2); }
.m-hero-info .m-hero-desc, .m-hero-info .m-hero-desc p { color: var(--m-hero-ink-3); }
/* 角标原本是金色底+深棕字，改成芒果TV 那种橙色渐变底+白字，白字才看得清 */
.m-hero-btns { display: flex; gap: 12px; }
/* 首图上的两个按钮跟着**信息块宽度**缩放（容器查询 cqi）：
   以前高度 40px、字号 15px 是写死的，拖窗口时背景图小了、按钮和文字还是那么大，比例就散了。
   实测：信息块 620px → 按钮 40px / 字 15px；388px（手机）→ 26px / 12px。 */
@supports (container-type: inline-size) {
    .m-hero-btns { gap: clamp(8px, calc(1.9cqi + 0px), 12px); }
    .m-hero-btns .m-btn {
        height: clamp(26px, calc(4.3cqi + 13.3px), 40px);
        padding: 0 clamp(14px, calc(2.6cqi + 7.9px), 24px);
        border-radius: 999px;
        font-size: clamp(12px, calc(0.86cqi + 9.66px), 15px);
    }
}
.m-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 40px; padding: 0 24px; border-radius: 20px; font-size: 15px; font-weight: 700; border: 0; cursor: pointer; }
.m-btn-main { background: var(--m-grad); color: var(--m-primary-ink); box-shadow: 0 6px 18px var(--m-primary-32, rgba(255,95,0,.32)); }
.m-btn-main:hover { color: #fff; filter: brightness(1.06); }
.m-btn-ghost { background: rgba(255,255,255,.12); color: #fff; border: 1px solid rgba(255,255,255,.42); backdrop-filter: blur(2px); }
.m-btn-ghost:hover { color: #fff; background: rgba(255,255,255,.2); }
.m-btn-line { background: var(--m-surface-2); color: var(--m-ink); border: 1px solid var(--m-line-2); }
.m-btn-line:hover { background: var(--m-surface-3); color: var(--m-primary); border-color: var(--m-primary); }
.m-btn-sm { height: 32px; padding: 0 16px; font-size: 13px; border-radius: 16px; }

.m-hero-rank { position: absolute; right: 16px; bottom: 108px; width: 290px; border-radius: var(--m-radius-lg); background: rgba(18,18,22,.72); backdrop-filter: blur(12px); padding: 12px 6px 8px; color: #fff; border: 1px solid rgba(255,255,255,.08); }
.m-hero-rank h2 { font-size: 15px; padding: 0 12px 8px; display: flex; align-items: center; color: #fff; }
.m-hero-rank h2::before { content: ""; width: 3px; height: 14px; border-radius: 2px; background: var(--m-grad-gold); margin-right: 8px; }
.m-hero-rank h2 a { margin-left: auto; font-size: 12px; color: rgba(255,255,255,.55); }
.m-hero-rank li { display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 12px; border-radius: 6px; font-size: 13px; }
.m-hero-rank li:hover { background: rgba(255,255,255,.08); }
.m-hero-rank .no { flex: 0 0 16px; text-align: center; font-weight: 700; color: rgba(255,255,255,.4); font-size: 12px; }
.m-hero-rank li:nth-child(1) .no, .m-hero-rank li:nth-child(2) .no, .m-hero-rank li:nth-child(3) .no { color: var(--m-gold); }
.m-hero-rank .nm { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: rgba(255,255,255,.92); }
.m-hero-rank .sc { flex: 0 0 auto; font-size: 12px; color: rgba(255,255,255,.45); }

.m-hero-thumbs { position: absolute; left: 0; right: 0; bottom: 0; padding: 0 0 14px; }
.m-hero-thumbs-inner { display: flex; gap: 8px; }
.m-hero-thumb { flex: 0 0 132px; height: 74px; border-radius: 6px; overflow: hidden; position: relative; cursor: pointer; opacity: .45; transition: opacity .25s; background: #1c1c20; border: 1px solid transparent; }
.m-hero-thumb img { width: 100%; height: 100%; object-fit: cover; }
.m-hero-thumb span { position: absolute; left: 0; right: 0; bottom: 0; padding: 12px 8px 4px; font-size: 12px; color: #fff; background: linear-gradient(0deg, rgba(0,0,0,.88), transparent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-hero-thumb:hover { opacity: .8; }
.m-hero-thumb.is-active { opacity: 1; border-color: var(--m-primary); box-shadow: 0 0 0 1px var(--m-primary); }
/* 手机/平板（≤768）缩略图条隐藏后，用底部的这排小圆点当指示器：
   宽屏不显示（缩略图条本身就是指示器，两套同时出现反而乱）。
   圆点 7px，选中那个拉成 18px 的胶囊并换成橙色 —— 和缩略图的选中态用同一个主色。 */
.m-hero-dots { display: none; }
@media (max-width: 768px) {
    .m-hero-dots {
        display: flex; justify-content: center; align-items: center; gap: 2px;
        position: absolute; left: 0; right: 0; bottom: 12px; z-index: 6;
    }
}
.m-hero-dot {
    width: 22px; height: 22px; padding: 0; border: 0; background: none; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    -webkit-tap-highlight-color: transparent;
}
.m-hero-dot::before {
    content: ""; display: block; width: 7px; height: 7px; border-radius: 50%;
    background: rgba(255,255,255,.42); box-shadow: 0 1px 4px rgba(0,0,0,.5);
    transition: width .2s ease, background .2s ease;
}
.m-hero-dot:hover::before { background: rgba(255,255,255,.7); }
.m-hero-dot.is-active::before { width: 18px; border-radius: 4px; background: var(--m-primary); }
.m-hero-dot:focus-visible { outline: 2px solid var(--m-primary); outline-offset: -2px; border-radius: 50%; }

/* ================================================================ 板块 + 横向行 */
.m-sec { padding: 30px 0 2px; }
.m-sec-hd { display: flex; align-items: center; gap: 16px; margin-bottom: 14px; }
.m-sec-hd h2 { font-size: 22px; font-weight: 800; color: var(--m-ink); letter-spacing: .3px; }
.m-sec-hd h2 em { color: var(--m-primary); font-weight: 800; }
.m-sec-cats { display: flex; gap: 14px; overflow: hidden; }
.m-sec-cats a { font-size: 14px; color: var(--m-sub); white-space: nowrap; }
.m-sec-cats a:hover { color: var(--m-primary); }
.m-sec-more { margin-left: auto; font-size: 13px; color: var(--m-muted); white-space: nowrap; display: inline-flex; align-items: center; gap: 2px; }
.m-sec-more:hover { color: var(--m-primary); }

/* 首页「即将上映」面板右边那句说明（共 N 部 / 后台配的提示语） */
.m-sec-note { margin-left: auto; font-size: 13px; color: var(--m-muted); white-space: nowrap; }
/* 面板里的频道小夹子（全部 / 电影 / 电视剧 …） */
.m-subtabs { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: -6px 0 12px; }
.m-subtab { padding: 4px 12px; border-radius: 14px; font-size: 13px; color: var(--m-sub); background: var(--m-surface-2); border: 1px solid transparent; }
.m-subtab:hover { color: var(--m-ink); }
.m-subtab.on { color: var(--m-primary-ink); background: var(--m-grad); }

/* ================================================================ 即将上映 · 横向时间轴 */
/* 每一个上映日期是一列，整行可以左右滚动（箭头 / 触摸都行），
   所以不管有多少个档期，占的高度都只有"最忙的那一天"那么高。 */
/* 频道面板：每个频道的整条时间轴都在 DOM 里，JS 只切显示（hidden 属性） */
.m-tl-panel[hidden] { display: none; }
/* （原来这里有一条 .m-tl-note 的样式：时间轴卡片上「播出平台」那一行。
   该行已按用户要求从模板里去掉，样式一并删掉。） */
/* 手指左右滑动：这两条横向滚动带都是 overflow-x:auto，移动端/平板本来就支持触摸拖动
   （已用真实 touch 事件在 390/414/768/1024 四个宽度上验证：左滑右滑都能滚）。
   -webkit-overflow-scrolling:touch 是给老 iOS(<13) 的惯性滚动用的，新系统不需要但无害。 */
.m-timeline-x { display: flex; overflow-x: auto; -webkit-overflow-scrolling: touch; scroll-behavior: smooth; scrollbar-width: none; -ms-overflow-style: none; padding-bottom: 4px; }
.m-timeline-x::-webkit-scrollbar { display: none; }
/* 一列 = 一个档期；列宽由这一档有几部片决定（左右并排，所以宽度随片子数量长） */
.m-tl-col { flex: 0 0 auto; padding-right: 22px; }
/* 日期 + 星期 */
.m-tl-date { display: flex; align-items: baseline; gap: 8px; }
.m-tl-date b { font-size: 16px; font-weight: 800; color: var(--m-ink); letter-spacing: .3px; white-space: nowrap; }
.m-tl-date em { font-size: 12px; font-style: normal; color: var(--m-muted); white-space: nowrap; }
/* 每个日期下面一小段轴线，横跨整列接到下一列；圆点标在这一档的位置上 */
.m-tl-axis { position: relative; height: 24px; margin-top: 6px; }
.m-tl-axis::before { content: ""; position: absolute; left: 4px; right: -22px; top: 11px; height: 1px; background: var(--m-line); }
.m-tl-col:last-child .m-tl-axis::before { right: 4px; }
.m-tl-axis i { position: absolute; left: 0; top: 7px; width: 9px; height: 9px; border-radius: 50%; background: var(--m-primary); box-shadow: 0 0 0 4px var(--m-primary-16, rgba(255,95,0,.14)); }
/* 同一档期的片子：竖版小卡，左右并排（高度只等于一张卡，和一天上几部无关） */
.m-tl-items { display: flex; align-items: flex-start; gap: 10px; }
.m-tl-item { display: block; flex: 0 0 auto; width: 108px; min-width: 0; }
.m-tl-pic { display: block; width: 108px; height: 162px; border-radius: var(--m-radius); overflow: hidden; background: var(--m-pic-bg); position: relative; transition: transform .18s; }
.m-tl-item:hover .m-tl-pic { transform: translateY(-2px); }
.m-tl-pic img { width: 100%; height: 100%; object-fit: cover; display: block; }
.m-tl-item > b { display: block; margin-top: 7px; font-size: 13px; font-weight: 600; color: var(--m-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-tl-item:hover > b { color: var(--m-primary); }
.m-tl-item > em { display: block; margin-top: 2px; font-size: 11.5px; font-style: normal; color: var(--m-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 已经在库里的片（点进去有播放）：海报右上角点一个绿点，和纯预告区分开 */
.m-tl-item.is-local .m-tl-pic::after { content: ""; position: absolute; right: 6px; top: 6px; width: 7px; height: 7px; border-radius: 50%; background: var(--m-playing); box-shadow: 0 0 0 2px rgba(0,0,0,.45); }
@media (max-width: 640px) {
    .m-tl-col { padding-right: 16px; }
    .m-tl-date b { font-size: 15px; }
    .m-tl-item, .m-tl-pic { width: 92px; }
    .m-tl-pic { height: 138px; }
}

.m-scroller { position: relative; }
/* 横向卡片行：手机/平板可以直接用手指左右拖（真实 touch 事件验证过）；
   -webkit-overflow-scrolling:touch 是给老 iOS 的惯性滚动用的。 */
.m-track { display: flex; gap: var(--m-card-gap); overflow-x: auto; -webkit-overflow-scrolling: touch; scroll-behavior: smooth; scrollbar-width: none; -ms-overflow-style: none; }
.m-track::-webkit-scrollbar { display: none; }
.m-track > * { flex: 0 0 calc((100% - var(--m-card-gap) * 5) / 6); min-width: 0; }
.m-track.col5 > * { flex: 0 0 calc((100% - var(--m-card-gap) * 4) / 5); min-width: 0; }
.m-track.col4 > * { flex: 0 0 calc((100% - var(--m-card-gap) * 3) / 4); min-width: 0; }
.m-arrow {
    position: absolute; top: 34%; width: 40px; height: 40px; margin-top: -20px; border-radius: 50%;
    border: 1px solid rgba(255,255,255,.14); background: rgba(28,28,33,.92); box-shadow: var(--m-shadow);
    color: #fff; font-size: 18px; line-height: 1; cursor: pointer; z-index: 5;
    display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity .2s, background .2s;
    backdrop-filter: blur(6px);
}
.m-arrow:hover { background: var(--m-primary); border-color: var(--m-primary); color: var(--m-primary-ink); }
.m-arrow.prev { left: -14px; }
.m-arrow.next { right: -14px; }
.m-scroller:hover .m-arrow { opacity: 1; }
/* 键盘 Tab 到箭头时也要显示出来（它平时 opacity:0，只有鼠标悬停才现形） */
.m-arrow:focus-visible { opacity: 1; outline: 2px solid var(--m-primary); outline-offset: 2px; }
.m-arrow[disabled] { opacity: 0 !important; pointer-events: none; }

/* ================================================================ 卡片(16:9 横向) */
/* 卡片标题/副标题的字号跟着**卡片自己的宽度**走（容器查询 cqi）：
   拖动窗口时卡片会变窄，标题也跟着变小 —— 以前字号是死的，缩小窗口会出现
   "海报小了、标题还是 14px"，比例就散了。
   实测：卡片 204px → 14px（上限）；150px → 11px（下限）；187px → 12.9px。
   不支持容器查询的老浏览器会忽略 cqi，回落到下面那行固定字号。 */
.m-card { display: block; min-width: 0; container-type: inline-size; }
.m-card-pic { position: relative; display: block; padding-top: 56.25%; border-radius: var(--m-radius); overflow: hidden; background: var(--m-pic-bg); }
.m-card-pic img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .2s ease; z-index: 1; }
.m-card:hover .m-card-pic img { transform: scale(1.03); }
/* 网格卡片(.m-grid：频道列表页 / 搜索结果 / 详情页猜你喜欢)用竖向海报框 2:3。
   我们采集到的海报本身就是竖图（实测宽高比 0.68~0.75，即高≈宽的 1.33~1.47 倍），
   套在 16:9 横框里会被裁掉一大半（只剩中间一条），竖框才看得全。
   首页各栏目的横排缩略图带(.m-track)现在也用同一套竖框 —— 见下面 .m-track 那组规则。 */
.m-grid .m-card-pic, .m-list-page .m-card-pic { padding-top: 150%; }
/* 首页横排缩略图带(.m-track)默认还是 **16:9 横图**（电视剧/综艺/动漫…保持原样）。
   只有带 .is-poster 的两条 —— **电影 / 短剧**（模板里按 type_en 加类）—— 用 2:3 竖海报，
   并按用户要求去掉左上角那个「HD国语 / HD中字」角标，只留右下角的集数渐变带。
   分数角标 .m-card-badge 保留。 */
.m-track.is-poster .m-card-pic { padding-top: 150%; }
.m-track.is-poster .m-card-corner { display: none; }
/* 竖版这两条的列数**单独一套**：桌面一行 8 张（用户要求），窄屏逐档递减，
   保证卡片宽度落在 130~260px 之间（16:9 横图行仍然是 5~6 张，不受影响）。
   ⚠️ .m-track.is-poster 比通用的 .m-track 更具体，会盖掉下面的通用档位，
   所以手机/平板档必须在这里也写一遍，不然竖版行会跟着桌面档走。 */
.m-track.is-poster > * { flex-basis: calc((100% - var(--m-card-gap) * 4) / 5); }          /* 兜底 */
@media (min-width: 1025px) { .m-track.is-poster > * { flex-basis: calc((100% - var(--m-card-gap) * 5) / 6); } }
@media (min-width: 1300px) { .m-track.is-poster > * { flex-basis: calc((100% - var(--m-card-gap) * 6) / 7); } }
@media (min-width: 1500px) { .m-track.is-poster > * { flex-basis: calc((100% - var(--m-card-gap) * 7) / 8); } }
@media (max-width: 1024px) { .m-track.is-poster > * { flex-basis: calc((100% - var(--m-card-gap) * 3) / 4); } }
@media (max-width: 640px) { .m-track.is-poster > * { flex-basis: calc((100% - var(--m-card-gap) * 2) / 3); } }
.m-card-badge { position: absolute; right: 6px; top: 6px; z-index: 3; padding: 1px 6px; border-radius: 4px; background: rgba(0,0,0,.62); color: var(--m-gold); font-size: 12px; font-weight: 700; }
.m-card-corner { position: absolute; left: 6px; top: 6px; z-index: 3; padding: 1px 6px; border-radius: 4px; background: var(--m-grad); color: var(--m-primary-ink); font-size: 11px; max-width: 76%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 右下角的集数角标：更新至01集 / 全32集 */
/* 集数/状态角标：整条「从下往上的黑色透明渐变」铺满海报宽度，文字贴右下角。
   对标芒果TV/爱奇艺的角标做法 —— 比一个小黑药丸更耐看，长集数（更新至181集）也不会显得突兀。
   注意：这条渐变带和左下角的 .m-card-live 声波条是叠在同一条带子上的
   （文字靠右、声波靠左），所以文字给了 max-width 留出声波的位置，两者不会互相压字。 */
.m-card-eps { position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
    padding: 26px 8px 6px; text-align: right;
    background: linear-gradient(to top, rgba(0,0,0,.86) 0%, rgba(0,0,0,.55) 42%, rgba(0,0,0,0) 100%);
    color: #fff; font-size: 11px; line-height: 16px; letter-spacing: .2px;
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 渐变带上不再要那个小红点（连载中本来就有左下角的声波条在表示"在更新"） */
.m-card-eps::before { content: none; }
/* 有「连载中」声波条时，给文字留出左边的位置 */
.m-card-live ~ .m-card-eps { padding-left: 30px; }
/* 16:9 的横图卡片（电视剧/综艺/动漫…）图只有 125px 高，
   26px 的渐变带会盖掉三分之一，所以这些行把渐变收窄一档；
   竖海报那两条（.is-poster：电影/短剧）图有 ~300px 高，用标准高度即可。 */
.m-track:not(.is-poster) .m-card-eps { padding-top: 16px; }
.m-card-play { position: absolute; left: 50%; top: 50%; z-index: 3; width: 42px; height: 42px; margin: -21px 0 0 -21px; border-radius: 50%; background: var(--m-primary-95, rgba(255,95,0,.95)); opacity: 0; transform: scale(.82); transition: opacity .2s, transform .2s; display: flex; align-items: center; justify-content: center; }
/* 给播放按钮加一层「容器投影」——只有阴影，没有描边/边框。
   用 filter: drop-shadow 而不是 box-shadow：
     · box-shadow 是给**矩形盒子**投的，虽然按钮是圆角，阴影轮廓仍按盒子算，
       圆外的四个角会带出一圈淡淡的方形痕迹；
     · drop-shadow 是按**实际不透明像素的轮廓**投的，圆就是圆的，干净。
   两层由近到远（4px/16px 较实、12px/32px 更散更淡），叠出「渐变」的过渡感。
   这里**不放 0 0 0 2px 那种 0 模糊的层** —— 那是描边，不是阴影。
   ⚠️ filter 会触发合成层，但这个元素本身就有 transition + transform，
      本来就在合成层上，所以不额外增加开销。 */
.m-card-play {
    filter: drop-shadow(0 3px 10px rgba(0,0,0,.55))
            drop-shadow(0 8px 26px rgba(0,0,0,.34));
}
/* hover 时阴影加重一点，配合 scale 放大，浮起来的层次更明显 */
.m-card:hover .m-card-play {
    filter: drop-shadow(0 4px 13px rgba(0,0,0,.62))
            drop-shadow(0 10px 32px rgba(0,0,0,.40));
}
.m-card-play::before { content: ""; border-style: solid; border-width: 6px 0 6px 11px; border-color: transparent transparent transparent #fff; margin-left: 3px; }
.m-card:hover .m-card-play { opacity: 1; transform: scale(1); }
.m-card-live { position: absolute; left: 8px; bottom: 8px; z-index: 3; display: flex; align-items: flex-end; height: 12px; }
.m-card-live i { display: block; width: 3px; margin-right: 3px; border-radius: 3px; background: var(--m-playing); }
.m-card-live i:nth-child(1) { height: 6px; animation: mg-wave .6s ease-in-out infinite; }
.m-card-live i:nth-child(2) { height: 8px; animation: mg-wave .6s ease-in-out .1s infinite; }
.m-card-live i:nth-child(3) { height: 11px; animation: mg-wave .6s ease-in-out .2s infinite; }
@keyframes mg-wave { 0%, 100% { transform: scaleY(.5); } 50% { transform: scaleY(1); } }
.m-card .m-card-title { display: block; margin-top: 10px; font-size: 14px; font-weight: 600; color: var(--m-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-card:hover .m-card-title { color: var(--m-primary); }
.m-card-desc { font-size: 12px; color: var(--m-muted); margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 注意选择器写成 .m-card .m-card-title（加了 .m-card 提高特异性）：base.css 里有一条
   a:link,a:visited{font-size:14px}，特异性比单个 .m-card-title 高，不改写就盖不住，
   标题会一直卡在 14px（实测踩过）。
   上面两行是"老浏览器兜底"的固定字号；支持容器查询时按卡片宽度缩放 */
@supports (container-type: inline-size) {
    .m-card .m-card-title { font-size: clamp(11px, 6.9cqi, 14px); }
    .m-card .m-card-desc { font-size: clamp(10px, 5.9cqi, 12px); }
}

/* 小横条 */
.m-mini { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--m-line); }
.m-mini:last-child { border-bottom: 0; }
.m-mini-pic { flex: 0 0 108px; height: 62px; border-radius: 6px; overflow: hidden; background: var(--m-pic-bg); position: relative; }
.m-mini-pic img { width: 100%; height: 100%; object-fit: cover; }
.m-mini-body { flex: 1 1 auto; min-width: 0; }
.m-mini-body h4 { font-size: 14px; font-weight: 600; color: var(--m-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-mini-body p { font-size: 12px; color: var(--m-muted); margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-mini-tag { display: inline-block; margin-top: 4px; font-size: 11px; color: var(--m-primary); border: 1px solid var(--m-primary-45, rgba(255,95,0,.45)); border-radius: 3px; padding: 0 5px; }

/* VIP 金卡 */
.m-vip-banner { margin-top: 30px; border-radius: var(--m-radius-lg); background: linear-gradient(120deg, #241a0b 0%, #4d340c 45%, #7d5312 100%); border: 1px solid rgba(255,165,22,.28); padding: 22px 26px; display: flex; align-items: center; gap: 26px; color: #ffe6b8; overflow: hidden; position: relative; }
.m-vip-banner::after { content: ""; position: absolute; right: -40px; top: -60px; width: 260px; height: 260px; border-radius: 50%; background: radial-gradient(circle, rgba(255,186,60,.28), transparent 70%); }
.m-vip-left { flex: 0 0 auto; }
.m-vip-left h3 { font-size: 24px; color: #ffd98a; font-weight: 800; letter-spacing: .5px; }
.m-vip-left p { font-size: 13px; color: rgba(255,230,184,.7); margin-top: 4px; }
.m-vip-points { flex: 1 1 auto; display: flex; gap: 26px; }
.m-vip-points div { font-size: 13px; color: rgba(255,230,184,.85); }
.m-vip-points strong { display: block; font-size: 15px; color: #ffd98a; margin-bottom: 2px; }
.m-vip-btn2 { flex: 0 0 auto; height: 40px; padding: 0 30px; border: 0; border-radius: 20px; background: var(--m-grad-gold); color: #4a2c00; font-size: 15px; font-weight: 800; cursor: pointer; position: relative; z-index: 1; }
.m-vip-btn2:hover { filter: brightness(1.06); }

/* 榜单 */
.m-rank-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
/* 排行榜的选择夹：只在窄屏（≤1024，三个榜单竖着堆的时候）显示，宽屏三列并排时隐藏。
   按钮复用 .m-subtab 的圆角胶囊样式，但它是 button 不是 a，得把浏览器默认样式清掉。 */
.m-ranktabs { display: none; }
.m-ranktabs .m-subtab { font: inherit; font-size: 13px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.m-rank { background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); padding: 16px; }
.m-rank-hd { font-size: 16px; font-weight: 800; color: var(--m-ink); margin-bottom: 6px; display: flex; align-items: center; }
.m-rank-hd::before { content: ""; width: 3px; height: 14px; border-radius: 2px; background: var(--m-grad); margin-right: 8px; }
.m-rank li { display: flex; align-items: center; gap: 10px; padding: 8px 0; font-size: 13px; border-bottom: 1px solid var(--m-line); }
.m-rank li:last-child { border-bottom: 0; }
.m-rank .no { flex: 0 0 18px; font-weight: 800; color: var(--m-muted); }
.m-rank li:nth-child(1) .no, .m-rank li:nth-child(2) .no, .m-rank li:nth-child(3) .no { color: var(--m-primary); }
.m-rank .nm { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--m-text); }
.m-rank .sc { flex: 0 0 auto; font-size: 12px; color: var(--m-muted); }
/* 侧栏榜单条目的鼠标悬停高亮。
   之前只有首页那个悬浮热播榜(.m-hero-rank li:hover)有，侧栏这个 .m-rank 忘了写，
   所以鼠标移上去没有任何反馈。这里和首页那套手感保持一致（底色变亮 + 片名变主题橙）。
   左右负 margin 是为了让高亮块比文字宽一点，看起来像一整行而不是贴着字。 */
.m-rank li { margin: 0 -8px; padding: 8px; border-radius: 6px; transition: background .18s; }
.m-rank li:hover { background: var(--m-surface-3); }
.m-rank li:hover .nm { color: var(--m-primary); }

/* ================================================================ 面包屑 / 筛选 */
.m-crumb { padding: 16px 0 4px; font-size: 13px; color: var(--m-muted); }
.m-crumb a { color: var(--m-sub); }
.m-crumb i { margin: 0 6px; color: var(--m-line-2); }

/* 筛选条（分类页 + 搜索页共用）。
   **上下间距跟着窗口宽度连续缩放**：宽屏一行留 10px 看着舒展，窄屏（手机）还是 10px 就
   5 行筛选占掉大半屏 —— 用 clamp 让它随宽度变小，不用堆一堆媒体查询断点。
   算一下每行的竖直占用：宽屏 = 3+3(选项内边距) + 20(行高) + 10×2(行内边距) = 46px；
   手机 ≈ 2+2 + 20 + 4×2 = 32px，整条筛选条能省下三分之一的高度。 */
.m-filter { background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); padding: clamp(2px, .35vw, 4px) 16px; margin-top: 12px; }
.m-filter-row { display: flex; gap: 12px; padding: clamp(4px, .8vw, 10px) 0; border-top: 1px dashed var(--m-line); }
.m-filter-row:first-child { border-top: 0; }
.m-filter-label { flex: 0 0 60px; color: var(--m-muted); font-size: 13px; line-height: clamp(20px, 1.8vw, 26px); }
.m-filter-list { flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: clamp(4px, .45vw, 6px); min-width: 0; }
.m-filter-item { padding: clamp(2px, .25vw, 3px) clamp(10px, 1vw, 14px); border-radius: 15px; font-size: 13px; line-height: 20px; color: var(--m-text); white-space: nowrap; }
.m-filter-item:hover { color: var(--m-primary); background: var(--m-surface-3); }
.m-filter-item.on { background: var(--m-grad); color: var(--m-primary-ink); }
.m-filter-item.on:hover { color: #fff; }
/* 手机（≤560）再压紧一档：clamp 只把行内边距从 10px 收到 4px，但手机上真正撑高筛选条的是
   **折行**（标签列 60px 占掉一行的宽度，24 个类型要多折一行）。所以这里把标签列收窄、
   行内边距再减 1px；选项本身保持 24px 高（手指点得着，不为了省高度牺牲可点区域）。 */
@media (max-width: 560px) {
    .m-filter { padding: 2px 10px; }
    .m-filter-row { padding: 3px 0; gap: 8px; }
    .m-filter-label { flex: 0 0 40px; font-size: 12px; line-height: 22px; }
    .m-filter-list { gap: 4px; }
    .m-filter-item { padding: 3px 10px; line-height: 18px; }
}

/* ================================================================ 列表页布局 */
/* 正文 + 侧栏：**用 flex-wrap 自动换行**，不再靠 1024px 断点硬切。
   规则：正文的 flex-basis 是 640px、侧栏 292px，两者 basis 之和（954px）放不下时
   侧栏自己换到下一行 —— 换行后正文独占一行、flex-grow 撑满，所以
   **侧栏一掉到下面，列表立刻就是整行满宽**（以前 1024~1500px 之间列表被压到 541px，
   到 1024 又突然跳到满宽，看着像"没铺满/跳一下"）。
   注意：flex-shrink 只在同一行内生效，换行与否只看 basis，所以这里的宽度是可预期的。 */
.m-listwrap { display: flex; flex-wrap: wrap; gap: 22px; margin-top: 18px; align-items: flex-start; }
.m-main { flex: 1 1 640px; min-width: 0; }
.m-side { flex: 0 1 292px; }
/* 侧栏里上下堆叠的块（热播榜 / 好评榜 / 最近更新）之间留出间距，别贴在一起 */
.m-side > * + * { margin-top: 16px; }
.m-side .m-rank + .m-rank, .m-side .m-rank + .m-rowbox, .m-side .m-rowbox + .m-rank { margin-top: 16px; }

/* 平板这一段（侧栏已经换行到列表**下面**、又还没到手机档 ≤640）：侧栏内部改成**并排**，
   别一路堆到底 —— 「热播榜」和「最近更新」左右各占一列，整块高度立刻减半。
   用 auto-fit + 260px 下限：
     · 只有一个块时（播放页只有榜单）自动占满整行；
     · 窄到一列都放不下时（或者侧栏还在右边只有 292px 宽时）自动退回单列堆叠，
       所以这段只在"确实换行到下面"的宽度区间里生效，右侧栏那种窄侧栏不受影响。
   「最近更新」里的小横条再套一层多列网格 —— 一行 2~3 条横向排开（用户要求"表项横向排列"）。 */
@media (min-width: 641px) and (max-width: 1128px) {
    /* 换行到下面之后**占满整行**（换行本身由 .m-listwrap 的 flex-wrap 决定，
       正文 flex-basis 是 640px；1128px 是两者 basis 之和 954 + 左侧 175 让位的分界）。
       以前这条写在 ≤1024 里，于是 1025~1128 这一段侧栏虽然也换行了、却仍是 292px 窄条，
       里面只能一路堆到底 —— 现在整段一致：整行宽 + 内部网格。 */
    .m-side {
        flex-basis: 100%;
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
        gap: 16px 22px;
        align-items: start;
    }
    /* 有三个块时（分类页：热播榜 + 好评榜 + 最近更新）auto-fit 会挤成三列、每列才 316px，
       小横条只能一条一行。这种版面改成"前两个并排、最近更新整行铺开"，
       最近更新就能一行放 3~4 条小横条（= 用户要的"表项横向排列"）。 */
    .m-side:has(> .m-rank + .m-rank) { grid-template-columns: repeat(2, minmax(260px, 1fr)); }
    .m-side:has(> .m-rank + .m-rank) > .m-rowbox { grid-column: 1 / -1; }
    /* 网格的 gap 已经在管间距了，把堆叠时的 margin-top 清掉（否则第一行会被顶下去） */
    .m-side > * + *,
    .m-side .m-rank + .m-rank,
    .m-side .m-rank + .m-rowbox,
    .m-side .m-rowbox + .m-rank { margin-top: 0; }
    /* 小横条也瘦一点：缩略图 108→84、内边距收 1px。
       不缩的话一条最起码要 208px 宽，半栏（约 380~480px）里塞两条会顶出去。 */
    .m-mini { gap: 8px; padding: 8px 0; }
    .m-mini-pic { flex-basis: 84px; height: 52px; }
    .m-rowbox { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 10px 12px; align-content: start; }
    /* 与榜单并排、只有半栏宽时（搜索页：热播榜 + 最近更新）门槛再放到 180，
       否则 380~430px 的栏宽里只能一条一行，等于没横向排列。 */
    .m-side:not(:has(> .m-rank + .m-rank)) .m-rowbox { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
    .m-rowbox > .m-rowbox-hd { grid-column: 1 / -1; }
    .m-rank { align-self: start; }
}
.m-empty { padding: 56px 0; text-align: center; color: var(--m-muted); }
.m-empty strong { display: block; font-size: 16px; color: var(--m-sub); margin-bottom: 6px; }

/* ================================================================ 专题（/topic 列表 + /topic/<别名> 详情） */
/* 专题卡片：封面 2:3？不 —— 专题封面是横图（采集时取第一部片子的海报也是竖的，
   所以这里用 16:9 会裁掉一截，直接用 3:2 偏横的比例最耐看）+ 名称 + 一句话简介 + 片数角标。
   首页「专题精选」那一行（.m-track.m-track-topic）和 /topic 列表页（.m-topic-grid）共用。 */
.m-topic-card { display: block; min-width: 0; }
.m-topic-pic { position: relative; display: block; padding-top: 62%; border-radius: var(--m-radius); overflow: hidden; background: var(--m-pic-bg); }
.m-topic-pic img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .2s ease; }
.m-topic-card:hover .m-topic-pic img { transform: scale(1.04); }
/* 专题封面「拼图」：把专题里前 2~4 部片子的海报用元素拼成一张图（不是生成图片文件）。
   2 张并排 / 3 张一行 / 4 张 2×2，缝隙用底色露出来当分割线，整体还是一块封面。
   ⚠️ 行高必须写 minmax(0, 1fr)：网格项（img）的自动最小尺寸是 min-content，
      竖版海报在 121px 宽下 min-content 高就是 181px，会把 1fr 行顶出封面框
      （图会溢出到卡片外面）。img 上再补 min-height/min-width: 0 双保险。 */
.m-topic-mosaic { position: absolute; inset: 0; display: grid; gap: 2px; background: var(--m-line); }
.m-topic-mosaic.is-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: minmax(0, 1fr); }
.m-topic-mosaic.is-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: minmax(0, 1fr); }
.m-topic-mosaic.is-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(2, minmax(0, 1fr)); }
.m-topic-mosaic img { position: static; width: 100%; height: 100%; min-width: 0; min-height: 0; object-fit: cover; display: block; }
.m-topic-ph { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding: 12px; text-align: center;
    background: linear-gradient(135deg, #2b2b33 0%, #1c1c21 60%, #33241a 100%); }
.m-topic-ph em { font-size: 15px; font-weight: 700; color: rgba(255,255,255,.86); overflow: hidden; }
.m-topic-count { position: absolute; right: 8px; bottom: 8px; padding: 1px 8px; border-radius: 10px;
    background: rgba(0,0,0,.62); color: var(--m-gold); font-size: 11.5px; font-weight: 700; }
.m-topic-name { display: block; margin-top: 8px; font-size: 15px; font-weight: 700; color: var(--m-ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-topic-card:hover .m-topic-name { color: var(--m-primary); }
.m-topic-blurb { display: block; margin-top: 3px; font-size: 12px; font-style: normal; color: var(--m-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 首页那一行：一行 5~8 张（跟着 .m-track 的通用档位），卡片比例同上 */
.m-track-topic > * { flex: 0 0 calc((100% - var(--m-card-gap) * 4) / 5); }
@media (min-width: 1800px) { .m-track-topic > * { flex-basis: calc((100% - var(--m-card-gap) * 5) / 6); } }
@media (max-width: 1024px) { .m-track-topic > * { flex-basis: calc((100% - var(--m-card-gap) * 2) / 3); } }
/* /topic 列表页：自适应卡片墙（和 .m-grid 一个手感） */
.m-topic-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 18px var(--m-card-gap); }
@media (max-width: 640px) { .m-topic-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 14px 10px; } }
/* 专题详情顶部那块介绍：纯文字（用户要求去掉封面图），窄屏下字号收一档 */
.m-topic-hero { display: flex; gap: 22px; align-items: flex-start; margin-top: 16px; padding: 18px 20px;
    background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); }
.m-topic-hero-info { flex: 1 1 auto; min-width: 0; }
.m-topic-hero-info h1 { font-size: 24px; font-weight: 800; color: var(--m-ink); display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.m-topic-hero-info h1 small { font-size: 12.5px; font-weight: 400; color: var(--m-muted); }
.m-topic-hero-blurb { margin-top: 8px; font-size: 14px; color: var(--m-text); }
.m-topic-hero-content { margin-top: 10px; font-size: 13px; line-height: 1.9; color: var(--m-sub); max-width: 1100px; }
@media (max-width: 768px) {
    .m-topic-hero { padding: 14px; }
    .m-topic-hero-info h1 { font-size: 19px; }
}

/* ================================================================ 留言板（/gbook） */
/* 左边留言列表 + 右边提交表单；≤1024 变成上下排。
   提交是真的表单 POST（/gbook），入库 status=0 等后台审核。 */
.m-flash { margin-top: 14px; padding: 10px 16px; border-radius: var(--m-radius); font-size: 13.5px;
    border: 1px solid var(--m-line); background: var(--m-surface); color: var(--m-text); }
.m-flash.ok { border-color: rgba(52,199,123,.45); color: #7ee2a8; background: rgba(52,199,123,.08); }
.m-flash.err { border-color: var(--m-primary-45, rgba(255,95,0,.45)); color: var(--m-primary); background: var(--m-primary-08, rgba(255,95,0,.08)); }
.m-gbook { display: flex; gap: 24px; align-items: flex-start; margin-top: 18px; }
.m-gbook-list { flex: 1 1 auto; min-width: 0; }
/* 留言表单这一列：最小 440，桌面按容器 40% 走，2K 屏最多 880。
   原来是写死的 380px —— 2K 屏上留言列表 1400 多像素、表单才 380，输入框窄得写不下话。
   clamp 放在 flex-basis 里 = 跟着容器宽度连续变化，不用按断点写三四个媒体查询。
   实测（视口 → 表单列 / 留言列表列）：1280→442/639、1440→506/735、1920→698/1023、2560→868/1276。 */
.m-gbook-form { flex: 0 1 clamp(440px, 40%, 880px); position: sticky; top: 84px; }
.m-gbook-items { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
.m-gbook-item { display: flex; gap: 12px; padding: 14px 16px; background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); }
.m-gbook-body { flex: 1 1 auto; min-width: 0; }
/* 留言头像：会员头像 / 游客填的 QQ 号公开头像；没有头像时是个中性人形图标。
   用 background-image 而不是 <img>：拿不到就什么都不用改，占位图标一直在 DOM 里。 */
.m-gbook-face {
    flex: 0 0 auto; width: 40px; height: 40px; border-radius: 50%; overflow: hidden;
    background-color: var(--m-surface-2, #f2f4f7); background-size: cover; background-position: center;
    border: 1px solid var(--m-line); color: var(--m-muted);
    display: flex; align-items: center; justify-content: center;
}
.m-gbook-face svg { width: 22px; height: 22px; }
.m-gbook-hd { display: flex; align-items: center; gap: 8px; }
.m-gbook-hd b { font-size: 13.5px; color: var(--m-ink); }
.m-gbook-tag { padding: 0 6px; border-radius: 4px; font-size: 11px; font-style: normal;
    background: var(--m-primary-16, rgba(255,95,0,.16)); color: var(--m-primary); }
.m-gbook-time { margin-left: auto; font-size: 12px; color: var(--m-muted); }
.m-gbook-text { margin-top: 7px; font-size: 13.5px; line-height: 1.75; color: var(--m-text); word-break: break-word; }
.m-gbook-reply { margin-top: 10px; padding: 10px 12px; border-radius: var(--m-radius);
    background: var(--m-surface-2); border-left: 3px solid var(--m-primary); }
.m-gbook-reply b { font-size: 12.5px; color: var(--m-primary); }
.m-gbook-reply p { margin-top: 4px; font-size: 13px; line-height: 1.7; color: var(--m-sub); word-break: break-word; }
/* 留言卡片右下角的「IP属地：湖南」（只显示属地，不显示完整 IP） */
.m-gbook-loc { margin-top: 8px; font-size: 11.5px; color: var(--m-muted); text-align: right; }
/* 「我的留言」那一块：和「大家的留言」并排时的样式（公开列表关掉时它是唯一的内容块） */
.m-gbook-mine { margin-bottom: 18px; }
.m-gbook-mine .m-gbook-item { border-color: var(--m-primary); }
/* 左列什么都没有时（公开列表关掉 + 我自己还没留言）：表单独占一行居中，
   别缩在左边留一大片空白。站长明确要求这时候不要显示"留言列表暂不公开"那种空提示。 */
.m-gbook-solo { justify-content: center; }
.m-gbook-solo .m-gbook-form { flex: 0 1 min(760px, 100%); }
/* 待审核的角标：和「会员」标签区分开（橙色） */
.m-gbook-tag-wait { background: rgba(255, 149, 0, .16); color: #b25e09; }
/* 「站长还没回复」那句提示 */
.m-gbook-wait { margin-top: 8px; font-size: 12.5px; color: var(--m-muted); }
.m-gbook-form-body { margin-top: 14px; padding: 16px; background: var(--m-surface);
    border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); }
.m-gbook-field { display: block; margin-bottom: 12px; }
.m-gbook-field > span { display: block; margin-bottom: 5px; font-size: 12.5px; color: var(--m-muted); }
.m-gbook-field input[type=text], .m-gbook-field textarea {
    width: 100% !important; padding: 9px 12px; border-radius: 8px;
    border: 1px solid var(--m-line-2); background: var(--m-surface-2) !important;
    color: var(--m-ink) !important; font-size: 13.5px; font-family: inherit; resize: vertical; }
.m-gbook-field input[type=text]:focus, .m-gbook-field textarea:focus { border-color: var(--m-primary); }
.m-gbook-field-code { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: end; }
.m-gbook-field-code > span { grid-column: 1 / -1; }
.m-gbook-field-code img { width: 108px; height: 40px; border-radius: 8px; border: 1px solid var(--m-line); cursor: pointer; }
.m-gbook-count { display: block; margin-top: 4px; font-size: 11.5px; font-style: normal; color: var(--m-muted); text-align: right; }
.m-gbook-acts { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.m-gbook-acts .muted { font-size: 12px; }
@media (max-width: 1024px) {
    /* 列方向后必须 align-items:stretch + 给子项 width:100%：
       .m-gbook 是 align-items:flex-start 的 flex 容器，子项在交叉轴上会收缩成 max-content，
       于是平板上留言列表只剩 485px、右边空一大片（和列表页 .m-main 踩的是同一个坑）。 */
    .m-gbook { flex-direction: column; gap: 18px; align-items: stretch; }
    .m-gbook-list { width: 100%; }
    .m-gbook-form { position: static; flex-basis: auto; width: 100%; }
}

/* ================================================================ 分页 */
.m-paging { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 28px 0 8px; flex-wrap: wrap; }
.m-paging .tip { color: var(--m-muted); font-size: 13px; margin-right: 8px; }
.m-paging a, .m-paging span.cur { min-width: 34px; height: 34px; line-height: 32px; text-align: center; padding: 0 10px; border: 1px solid var(--m-line); border-radius: 6px; background: var(--m-surface); color: var(--m-text); font-size: 13px; }
.m-paging a:hover { border-color: var(--m-primary); color: var(--m-primary); }
.m-paging span.cur { background: var(--m-grad); border-color: transparent; color: var(--m-primary-ink); font-weight: 700; }
.m-paging input.pg { width: 46px; height: 34px; border: 1px solid var(--m-line); border-radius: 6px; text-align: center; background: var(--m-surface-2); color: var(--m-ink); }
.m-paging button { height: 34px; padding: 0 14px; border: 1px solid var(--m-line); background: var(--m-surface); color: var(--m-text); border-radius: 6px; cursor: pointer; }
.m-paging button:hover { border-color: var(--m-primary); color: var(--m-primary); }
/* 手机/平板列表页：分页条换成"滚到底自动加载"（见 kuaibo.js 的 initInfiniteList）。
   JS 在手机档给分页条加 .is-auto-hidden，同时把 .m-loadmore 显示出来；
   没有 JS 时这两个类都不存在 —— 分页条照旧可用（渐进增强）。 */
.m-loadmore { display: none; text-align: center; padding: 18px 0 8px; color: var(--m-muted); font-size: 13px; }
.m-loadmore.is-on { display: block; }
.m-loadmore a { color: var(--m-primary); }
@media (max-width: 1024px) {
    .m-paging.is-auto-hidden { display: none; }
}

/* ================================================================ 详情页 */
.m-detail { background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); padding: 24px; margin-top: 12px; }
/* base.css 的 #pinglun{width:1000px} 是老模板遗留的**固定宽度**（ID 选择器，优先级比类高）：
   窄屏时它比视口还宽，会把整页撑出横向滚动条、评论区右边被切掉（实测 414px 宽时页面宽 1016px）。
   评论内容本身是空的（GoFilm 没实现苹果CMS 那套 MAC.Comment），所以直接让它跟着正文走。 */
#pinglun, .m-block#pinglun { width: auto; max-width: 100%; }
/* 同一批老固定宽度还留在两个页面上：「最近更新 /map」的 .bread-crumb-nav(998)/.ui-qire(1000)/
   #qire-lasted .ui-cnt(960)，「会员中心 /user」的 .layout(1000)。
   390px 宽的手机上它们比视口宽一倍多，整页会左右滚。这些本来就是 m-wrap 里的正文，跟着容器走。 */
.layout, .bread-crumb-nav, .ui-qire, #qire-lasted, #qire-lasted .ui-cnt { width: auto; max-width: 100%; }
.m-detail-cols { display: flex; gap: 26px; }
.m-detail-pic { flex: 0 0 244px; border-radius: var(--m-radius); overflow: hidden; background: var(--m-pic-bg); position: relative; }
.m-detail-pic::before { content: ""; display: block; padding-top: 140%; }
.m-detail-pic img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; }
.m-detail-info { flex: 1 1 auto; min-width: 0; }
.m-detail-title { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.m-detail-title h1 { font-size: 26px; font-weight: 800; color: var(--m-ink); line-height: 1.3; }
.m-detail-title .sub { color: var(--m-muted); font-size: 14px; }
.m-score { display: flex; align-items: baseline; gap: 8px; margin: 12px 0 4px; }
.m-score strong { font-size: 32px; color: var(--m-primary); line-height: 1; font-family: Georgia, "Times New Roman", serif; }
.m-score span { color: var(--m-muted); font-size: 12px; }
.m-meta { display: flex; flex-wrap: wrap; gap: 6px 8px; margin: 10px 0 2px; }
.m-chip { display: inline-block; padding: 2px 10px; border-radius: 12px; background: var(--m-surface-2); color: var(--m-sub); font-size: 12px; border: 1px solid var(--m-line); }
.m-chip:hover { background: var(--m-surface-3); color: var(--m-primary); border-color: var(--m-primary); }
.m-info-lines { margin-top: 8px; }
.m-info-lines dl { display: flex; gap: 8px; padding: 3px 0; font-size: 13px; }
.m-info-lines dt { flex: 0 0 54px; color: var(--m-muted); }
.m-info-lines dd { flex: 1 1 auto; min-width: 0; color: var(--m-text); }
/* 简介是整段正文：正文容器放宽到 2200 之后，不封顶的话一行能有 100 多个字，读起来很累。
   1200px 大约一行 90 个汉字（13px 字号），是三栏之外最舒服的上限。 */
.m-blurb { margin-top: 12px; font-size: 13px; line-height: 1.9; color: var(--m-sub); max-width: 1200px; }
.m-blurb a { color: var(--m-primary); }
.m-btns { display: flex; gap: 12px; margin-top: 18px; flex-wrap: wrap; }

.m-block { background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); padding: 18px 20px; margin-top: 18px; }
.m-block-hd { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.m-block-hd h2 { font-size: 18px; font-weight: 800; color: var(--m-ink); }
.m-block-hd h2::before { content: ""; display: inline-block; width: 3px; height: 15px; border-radius: 2px; background: var(--m-grad); margin-right: 9px; vertical-align: -2px; }
.m-block-hd .tip { font-size: 12px; color: var(--m-muted); }
.m-block-hd .more { margin-left: auto; font-size: 13px; color: var(--m-muted); }

.m-eps { display: flex; flex-wrap: wrap; gap: 8px; }
.m-eps a { min-width: 52px; padding: 7px 12px; text-align: center; border-radius: 6px; background: var(--m-surface-2); color: var(--m-text); font-size: 13px; border: 1px solid transparent; }
.m-eps a:hover { background: var(--m-surface-3); color: var(--m-primary); border-color: var(--m-primary); }
.m-eps a.on { background: var(--m-grad); color: var(--m-primary-ink); font-weight: 700; border-color: transparent; }
.m-playfrom { display: flex; gap: 10px; margin-bottom: 12px; border-bottom: 1px solid var(--m-line); flex-wrap: wrap; }
.m-playfrom span { padding: 6px 4px; font-size: 14px; color: var(--m-sub); cursor: pointer; border-bottom: 2px solid transparent; }
.m-playfrom span.on { color: var(--m-primary); font-weight: 700; border-bottom-color: var(--m-primary); }

/* 留言板：没登录时挡在表单前面的登录引导（后台开着「开启用户登录注册」时才出现） */
.m-gbook-gate {
    padding: 18px; border-radius: var(--m-radius-lg);
    background: var(--m-surface); border: 1px solid var(--m-line);
}
.m-gbook-gate strong { display: block; font-size: 15px; color: var(--m-ink); }
.m-gbook-gate p { margin-top: 8px; font-size: 13px; line-height: 1.8; color: var(--m-sub); }
.m-gbook-gate-acts { display: flex; gap: 10px; flex-wrap: wrap; }
/* 留言板：填了 QQ 号自动带出来的小头像 + 说明文字 */
.m-gbook-id { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.m-gbook-id > img {
    width: 34px; height: 34px; border-radius: 50%; object-fit: cover; flex: 0 0 auto;
    background: var(--m-surface-3); border: 1px solid var(--m-line-2);
}
/* 还没拿到地址时不显示破图占位（JS 填上 src 后这条就不再命中） */
.m-gbook-id > img:not([src]) { display: none; }
.m-gbook-id > i { font-style: normal; font-size: 12px; color: var(--m-muted); }
.m-gbook-id-hint { display: block; margin-top: 6px; font-style: normal; font-size: 12px; color: var(--m-muted); }

/* 留言板：登录用户那行「将以会员身份留言」 */
.m-gbook-as {
    padding: 10px 14px; border-radius: 10px; font-size: 13px; color: var(--m-sub);
    background: var(--m-surface-2); border: 1px solid var(--m-line);
}
.m-gbook-as b { color: var(--m-ink); }

/* 播放页 */
/* ---------------- 播放页整体布局（对齐芒果TV 的 vod-page：左正文 + 右窄栏） ----------------
   .vod-page  两栏网格：左栏自适应，右栏固定 380（和芒果TV 一样）
   .vod-main  播放器 / 看了还会看 / 剧情介绍 / 评论
   .vod-aside 剧集信息 → 操作条 → VIP 卡 → 选集 → 精彩推荐（窄屏整块落到下面）
   ⚠️ 右栏**不要 sticky、也不给自己加滚动条**：站长反馈"播放器和右边的详情面板
   不一起上下滚"—— 之前做成 sticky + max-height，右栏就钉在那儿、还多出一条自己的
   滚动条。现在两栏跟着页面一起滚（右栏内容长了就整页变长，选集默认收着 24 集，不会太长）。 */
.vod-page { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 22px; align-items: start; margin-top: 12px; }
.vod-main { min-width: 0; }
.vod-aside { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
/* 左栏（播放器这块面板）整体往右留 40px（站长要求），看起来不再紧贴页面左边。
   和下面右栏那条 margin-right 一个思路、一样只在桌面宽度下生效：窄屏（≤1180px）
   右栏会落到下面、整页变一列，那里再缩 40px 就太挤了。
   注意：栅格那一列宽度不变，所以是"左栏内容往右收 40px"（播放器/卡片跟着窄 40px）。 */
@media (min-width: 1181px) {
    .vod-main { margin-left: 40px; }
}
/* 右栏和容器右边再留 20px（站长要求）。栅格那一列还是 380，所以是右栏**内容**往里收
   （380 → 360），右边多出一条 20px 的空隙 —— 看起来右栏不再贴着页面右边。
   窄屏右栏会落到下面变成满宽，那里不加（加了会左边对齐、右边缩进，很别扭）。 */
@media (min-width: 1181px) {
    .vod-aside { margin-right: 20px; }
}
/* 右栏的每块卡片 */
.m-aside-card { background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); padding: 14px 16px; }
.m-aside-hd { display: flex; align-items: baseline; gap: 8px; margin-bottom: 10px; }
.m-aside-hd h3 { font-size: 15px; color: var(--m-ink); }
.m-aside-hd .muted { font-size: 12px; }
/* 「更多 >」原来是橙色（--m-primary），站长要求改成灰色（--m-sub，悬停时再亮一点） */
.m-aside-hd .more { margin-left: auto; font-size: 12.5px; color: var(--m-sub); transition: color .18s; }
.m-aside-hd .more:hover { color: var(--m-text); }
/* 剧集信息：标题 + 详情入口 + 标签 */
.m-aside-title { display: flex; align-items: center; gap: 10px; }
.m-aside-title h2 {
    flex: 1 1 auto; min-width: 0; font-size: 18px; color: var(--m-ink); line-height: 1.35;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-aside-detail { flex: 0 0 auto; font-size: 12.5px; color: var(--m-sub); }
/* ---------- 影片介绍（点「详情 ›」原地盖一层） ----------
   定位祖先是 .m-aside-info 那张卡：inset:0 盖住卡片内部（含原来的内边距区），
   自己再补一份同样的内边距，圆角继承卡片，所以看起来就是"面板换了内容"。
   面板内 .m-aside-intro-body 自己滚动（右栏很长，内容长了不撑破页面）。 */
.m-aside-info { position: relative; }
.m-aside-intro {
    position: absolute; inset: 0; z-index: 3;
    display: flex; flex-direction: column;
    padding: 14px 16px;
    background: var(--m-surface); border-radius: inherit;
}
.m-aside-intro[hidden] { display: none; }
.m-aside-intro-hd { display: flex; align-items: flex-start; gap: 10px; flex: 0 0 auto; }
.m-aside-intro-hd h3 {
    flex: 1 1 auto; min-width: 0; font-size: 16px; line-height: 1.4; color: var(--m-ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 右上角那个 ✕（站长要求：用它关掉当前的介绍） */
.m-aside-intro-x {
    flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; padding: 0; margin-top: -2px;
    border: 1px solid var(--m-line-2); border-radius: 50%;
    background: var(--m-surface-2); color: var(--m-sub);
    cursor: pointer; transition: color .18s, border-color .18s;
}
.m-aside-intro-x svg { width: 14px; height: 14px; }
.m-aside-intro-x:hover { color: var(--m-primary); border-color: var(--m-primary); }
.m-aside-intro-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; margin-top: 12px; padding-right: 2px; }
/* 和讨论列表一样的细滚动条（5px，不用 scrollbar-width: thin 那个坑） */
.m-aside-intro-body::-webkit-scrollbar { width: 5px; height: 5px; }
.m-aside-intro-body::-webkit-scrollbar-track { background: transparent; }
.m-aside-intro-body::-webkit-scrollbar-thumb { background: var(--m-line-2); border-radius: 3px; }
.m-aside-intro-body::-webkit-scrollbar-thumb:hover { background: var(--m-muted); }
@supports not selector(::-webkit-scrollbar) {
    .m-aside-intro-body { scrollbar-width: thin; scrollbar-color: var(--m-line-2) transparent; }
}
.m-aside-intro-meta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3px 14px; }
.m-aside-intro-meta > div { display: flex; gap: 6px; min-width: 0; font-size: 12px; line-height: 1.7; }
.m-aside-intro-meta dt { flex: 0 0 auto; color: var(--m-muted); }
.m-aside-intro-meta dd {
    flex: 1 1 auto; min-width: 0; color: var(--m-sub);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-aside-intro-t {
    margin: 14px 0 6px; padding-top: 10px; border-top: 1px solid var(--m-line);
    font-size: 12.5px; color: var(--m-ink);
}
.m-aside-intro-text { font-size: 12.5px; line-height: 1.85; color: var(--m-sub); white-space: pre-line; }
.m-aside-tabs { display: flex; align-items: center; gap: 18px; margin-top: 12px; border-bottom: 1px solid var(--m-line); }
/* 选项卡条现在贴在右栏**最上面**（原来在「剧集信息」卡里面）：它自己就是一张卡片，
   下边那条线（border-bottom）正好是卡片底边。 */
.m-aside-tabsbar { padding: 12px 16px 0; margin-top: 0; }
/* ---------- 「详细信息 / 讨论」选项卡（剧集信息卡片里） ----------
   站长要求：剧集信息卡里再加一个讨论面板，用选择夹（选项卡）切换。
   选中态：**不要橙色（黄色）横杠**，改成"星光"（站长否掉了"单独一颗星星"那版，
   还是用这个星光）：文字带一层暖色光晕 + 周围几颗一闪一闪的小星星。纯 CSS：
   · 两颗伪元素各画一层径向渐变的亮点（不用图片、不加 DOM）
   · 按钮加 isolation:isolate 隔出层叠上下文，星星 z-index:-1 →
     画在文字**下面**、卡片背景**上面**（不然 -1 会钻到卡片背景底下，什么都看不见）
   · 原来那条橙色横杠就是 ::after 的 background，已经删掉了 */
.m-aside-tabs button {
    position: relative; isolation: isolate;
    padding: 0 0 9px; border: 0; background: none; cursor: pointer;
    font: inherit; font-size: 13.5px; color: var(--m-sub); transition: color .18s;
}
.m-aside-tabs button:hover { color: var(--m-text); }
.m-aside-tabs button.is-on {
    color: #fff; font-weight: 700;
    text-shadow: 0 0 7px rgba(255, 229, 180, .9), 0 0 18px rgba(255, 187, 106, .5);
}
.m-aside-tabs button.is-on::before,
.m-aside-tabs button.is-on::after {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    inset: -9px -8px -7px -8px; border-radius: 10px;
    background-repeat: no-repeat; background-size: 100% 100%;
    animation: m-tab-twinkle 2.8s ease-in-out infinite;
}
.m-aside-tabs button.is-on::before {
    background-image:
        radial-gradient(circle at 10% 24%, rgba(255, 255, 255, .95) 0 .9px, transparent 1.8px),
        radial-gradient(circle at 86% 16%, rgba(255, 236, 198, .9) 0 1.1px, transparent 2px),
        radial-gradient(circle at 64% 86%, rgba(255, 255, 255, .75) 0 .8px, transparent 1.6px);
}
.m-aside-tabs button.is-on::after {
    /* 第二层星星（错开时间闪）+ 一点从底部透上来的暖光 */
    background-image:
        radial-gradient(circle at 26% 88%, rgba(255, 226, 176, .85) 0 1px, transparent 1.9px),
        radial-gradient(circle at 94% 70%, rgba(255, 255, 255, .7) 0 .8px, transparent 1.5px),
        radial-gradient(130% 100% at 50% 132%, rgba(255, 190, 110, .20), transparent 72%);
    animation-delay: .9s;
}
@keyframes m-tab-twinkle {
    0%, 100% { opacity: .5; transform: scale(1); }
    50% { opacity: 1; transform: scale(1.06); }
}
/* 系统开了"减少动态效果"就不闪，只留星星和光晕 */
@media (prefers-reduced-motion: reduce) {
    .m-aside-tabs button.is-on::before,
    .m-aside-tabs button.is-on::after { animation: none; opacity: 1; }
}
/* 讨论条数：跟在「讨论」两个字后面（没有讨论时不渲染这个 i） */
.m-aside-tabs button i {
    display: inline-block; margin-left: 5px; padding: 0 6px; border-radius: 9px;
    background: var(--m-surface-3); color: var(--m-sub); font-size: 11px; font-style: normal; line-height: 17px;
    vertical-align: 1px;
}
.m-aside-tabs button.is-on i { background: var(--m-surface-3); color: var(--m-text); }
.m-aside-tabpanel { padding-top: 12px; }
.m-aside-tabpanel[hidden] { display: none; }
/* 切到「讨论」子夹时（站长要求）：
   · 「操作条」和「选集」收起来
   · 「精彩推荐」也整块隐藏 —— 讨论面板一个人占满右栏
   · 剧集信息卡给一个**固定的高个子高度**，讨论消息在面板内部滚动，页面高度不再跟着变
   （高度想调就改这里的 min(80vh, 760px)，一行的事） */
.vod-aside.is-discuss .m-aside-acts,
.vod-aside.is-discuss .m-aside-eps,
.vod-aside.is-discuss .m-aside-rel { display: none; }
/* 讨论模式下连上面那行「片名 + 详情」也收起来（站长要求）：整栏都留给讨论 */
.vod-aside.is-discuss .m-aside-title { display: none; }
.vod-aside.is-discuss .m-aside-info {
    /* 高度由 kuaibo.js 的 syncAsideHeight 量出来（= 左栏「看了还会看」网格
       最后一张卡片的底部 − 这个面板的顶部），写在 --m-dis-h 上；
       没量到（没 JS / 量不出来）时才退回 min(80vh,760px)。 */
    height: var(--m-dis-h, min(80vh, 760px));
    display: flex; flex-direction: column;
}
/* 「详情 ›」打开的影片介绍：把整个「详细信息」面板盖住（= 播放器右边这一整块），
   所以这里和讨论模式一样，把操作条 / 选集 / 精彩推荐 / 片名行都收起来，
   面板高度也用同一个 --m-dis-h（底部对齐左栏网格最后一张卡）。 */
.vod-aside.is-intro .m-aside-acts,
.vod-aside.is-intro .m-aside-eps,
.vod-aside.is-intro .m-aside-rel,
.vod-aside.is-intro .m-aside-vip,
.vod-aside.is-intro .m-aside-title { display: none; }
.vod-aside.is-intro .m-aside-info {
    position: relative;
    height: var(--m-dis-h, min(80vh, 760px));
    display: flex; flex-direction: column;
}
/* 介绍面板没开着的时候也要给 [data-tab-panel] 留活路 → 只在这两个"接管右栏"的状态下藏 */
.vod-aside.is-intro [data-tab-panel] { display: none; }
.vod-aside.is-discuss [data-tab-panel="discuss"] { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.vod-aside.is-discuss .m-dis-post { flex: 0 0 auto; }
.vod-aside.is-discuss .m-dis-sec { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.vod-aside.is-discuss .m-dis-list { flex: 1 1 auto; min-height: 0; max-height: none; overflow-y: auto; padding-right: 2px; }

/* ---------- 讨论面板 ---------- */
/* 发言区：平时只有一个"单行输入框"（其实是按钮，长得像输入框），点开才展开完整表单 */
.m-dis-post { margin-bottom: 14px; }
.m-dis-quick {
    display: block; width: 100%; padding: 9px 12px; text-align: left;
    border: 1px solid var(--m-line-2); border-radius: 9px; background: var(--m-surface-2);
    color: var(--m-muted); font: inherit; font-size: 12.5px; cursor: text;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    transition: border-color .18s, color .18s;
}
.m-dis-quick:hover { border-color: var(--m-primary); color: var(--m-sub); }
.m-dis-quick[hidden] { display: none; }
.m-dis-sec { border-top: 1px solid var(--m-line); padding-top: 12px; }
/* 讨论消息列表：高度由外面的固定高度面板决定，这里只管内部滚动。
   滚动条要**细**（站长要求）：Chrome/Edge 用 ::-webkit-scrollbar 定 5px；
   ⚠️ 不要写 scrollbar-width: thin —— Chrome 121+ 一旦看到它就用浏览器自己的
   "细"（Windows 上约 10px），会把 ::-webkit-scrollbar 的宽度整个顶掉，反而更粗。 */
.m-dis-list { display: flex; flex-direction: column; gap: 12px; }
.m-dis-list::-webkit-scrollbar { width: 5px; height: 5px; }
.m-dis-list::-webkit-scrollbar-track { background: transparent; }
.m-dis-list::-webkit-scrollbar-thumb { background: var(--m-line-2); border-radius: 3px; }
.m-dis-list::-webkit-scrollbar-thumb:hover { background: var(--m-muted); }
/* 只有"不支持 webkit 滚动条样式"的浏览器（Firefox）才退回浏览器的细滚动条 */
@supports not selector(::-webkit-scrollbar) {
    .m-dis-list { scrollbar-width: thin; scrollbar-color: var(--m-line-2) transparent; }
}
.m-dis-item { display: flex; gap: 9px; }
/* 一个主楼下面的**所有回复**共用一个圆角背景容器（站长要求：不要每条回复
   各套一个圆角面板）。容器往右缩进一点，回复之间只用一条细分隔线分开。
   margin-top 用小负值把列表的 12px 行间距抵消掉一点，让这块紧贴在主楼下面
   （"这是主楼的一条回复"，而不是又一个独立条目）。 */
.m-dis-replies {
    margin: -4px 0 0 14px; padding: 2px 10px;
    border-radius: 10px; background: var(--m-surface-2); border: 1px solid var(--m-line);
}
.m-dis-replies > .m-dis-item.is-reply { padding: 8px 0; margin: 0; }
.m-dis-replies > .m-dis-item.is-reply + .m-dis-item.is-reply { border-top: 1px solid var(--m-line); }
/* 回复的头像、昵称、正文都比主楼再小一号（站长要求）：
   主楼头像 28px / 昵称 12.5px / 正文 13px → 回复 20px / 11.5px / 11.5px */
.m-dis-item.is-reply .m-dis-face { width: 20px; height: 20px; }
.m-dis-item.is-reply .m-dis-face svg { width: 14px; height: 14px; }
.m-dis-item.is-reply .m-dis-hd b { font-size: 11.5px; }
.m-dis-item.is-reply .m-dis-text { font-size: 11.5px; }
.m-dis-repflag { font-size: 11.5px; color: var(--m-muted); }
.m-dis-repflag b { color: var(--m-primary); font-weight: 600; }
/* 发言框顶部那个「回复 @某某 ✕」小标签 */
.m-dis-repto {
    display: flex; align-items: center; gap: 6px; margin-bottom: 8px; padding: 5px 8px;
    border-radius: 8px; background: var(--m-surface-2); border: 1px solid var(--m-line-2);
    font-size: 12px; color: var(--m-sub);
}
.m-dis-repto b { color: var(--m-primary); font-weight: 600; }
.m-dis-repto button {
    margin-left: auto; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 50%;
    background: none; color: var(--m-muted); font-size: 12px; line-height: 1; cursor: pointer;
}
.m-dis-repto button:hover { background: var(--m-surface-3); color: var(--m-ink); }
.m-dis-repto[hidden] { display: none; }
.m-dis-face {
    flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%; overflow: hidden;
    background: var(--m-surface-2) center/cover no-repeat; color: var(--m-muted);
    display: flex; align-items: center; justify-content: center;
}
.m-dis-face svg { width: 20px; height: 20px; }
.m-dis-body { flex: 1 1 auto; min-width: 0; }
.m-dis-hd { display: flex; align-items: baseline; gap: 8px; }
.m-dis-hd b { font-size: 12.5px; color: var(--m-text); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 45%; }
.m-dis-time { margin-left: auto; font-size: 11.5px; color: var(--m-muted); white-space: nowrap; }
/* 卡片底部这一行：点赞 / 回复 /（自己的）删除 + 时间 + 右边「⋮」更多（举报）。
   站长要求这一行的**文字和图标都再小一点**（原来文字 11.5px / 图标 14px）。
   图标 + 文字，和留言板/操作条一个风格；时间用相对时间（刚刚 / 3 分钟前），
   鼠标停上去用 title 显示精确时间。 */
.m-dis-foot { display: flex; align-items: center; gap: 14px; margin-top: 8px; position: relative; }
.m-dis-act {
    display: inline-flex; align-items: center; gap: 3px; padding: 0;
    border: 0; background: none; color: var(--m-muted); font: inherit; font-size: 10.5px; cursor: pointer;
    transition: color .18s;
}
.m-dis-act svg { width: 12px; height: 12px; }
.m-dis-act:hover { color: var(--m-primary); }
.m-dis-act.is-on { color: var(--m-primary); font-weight: 700; }
.m-dis-act.is-on svg { fill: var(--m-primary); }
.m-dis-act i { font-style: normal; }
.m-dis-act i[hidden] { display: none; }
/* 点赞 / 回复：数字 > 0 时把"点赞 / 回复"文字收起来，只留图标 + 数字；是 0 就显示文字
   （站长要求，两个按钮同一个规则） */
.m-dis-act.has-count [data-dis-act-label] { display: none; }
.m-dis-act-del:hover { color: #ff6a6a; }
.m-dis-time { margin-left: auto; font-size: 10.5px; color: var(--m-muted); white-space: nowrap; }
/* 「⋮」更多：鼠标移上去（或键盘聚焦）弹出菜单，现在里面只有「举报」。
   站长要求：竖向三个点，而且和左边那串「相对时间 · IP属地」贴紧一点 ——
   整行 gap 是 14px，这里用负外边距把间距压到 2px（视觉上约 5px）。 */
.m-dis-moremenu { position: relative; margin-left: -12px; }
.m-dis-dots {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; padding: 0; border: 0; border-radius: 50%;
    background: none; color: var(--m-muted); cursor: pointer; transition: color .18s, background .18s;
}
.m-dis-dots svg { width: 13px; height: 13px; }
.m-dis-dots:hover { color: var(--m-ink); background: var(--m-surface-3); }
/* ⚠️ 弹出菜单和按钮之间原来留了 4px 空隙 —— 鼠标从「⋮」往下走会经过这条缝，
   缝里既不是按钮也不是菜单，:hover 立刻断掉，菜单就"点不住"（站长反馈过）。
   现在：① 间距改由 padding 撑，中间那层 .m-dis-pop::before 是一条透明"桥"（盖住缝）；
   ② 靠近列表底部时 JS 会给 .is-up，菜单朝上弹（不然会被列表的 overflow 裁掉）。 */
.m-dis-pop {
    position: absolute; right: 0; top: calc(100% + 6px); z-index: 6; min-width: 84px;
    padding: 4px; border-radius: 9px; background: var(--m-surface); border: 1px solid var(--m-line-2);
    box-shadow: 0 10px 24px rgba(0, 0, 0, .55);
    opacity: 0; visibility: hidden; transform: translateY(-4px); transition: opacity .16s, transform .16s;
}
.m-dis-pop::before { content: ""; position: absolute; left: 0; right: 0; top: -8px; height: 8px; }
.m-dis-moremenu.is-up .m-dis-pop { top: auto; bottom: calc(100% + 6px); transform: translateY(4px); }
.m-dis-moremenu.is-up .m-dis-pop::before { top: auto; bottom: -8px; }
.m-dis-moremenu:hover .m-dis-pop, .m-dis-moremenu:focus-within .m-dis-pop { opacity: 1; visibility: visible; transform: translateY(0); }
.m-dis-pop button {
    display: block; width: 100%; padding: 6px 10px; border: 0; border-radius: 7px;
    background: none; color: var(--m-sub); font: inherit; font-size: 12px; text-align: left; cursor: pointer;
}
.m-dis-pop button:hover { background: var(--m-surface-2); color: var(--m-primary); }
/* 「普通用户」小标记（会员才有） */
.m-dis-tag { padding: 0 5px; border-radius: 4px; background: var(--m-surface-3); color: var(--m-muted); font-size: 10.5px; font-style: normal; }
/* 「待审核」：自己刚发的、还没过审的那条（只有本人看得到） */
.m-dis-tag-wait { background: rgba(255, 149, 0, .16); color: var(--m-primary); }
.m-dis-text { margin-top: 3px; font-size: 13px; line-height: 1.65; color: var(--m-sub); word-break: break-word; white-space: pre-wrap; }
.m-dis-reply { margin-top: 7px; padding: 8px 10px; border-radius: 8px; background: var(--m-surface-2); border-left: 2px solid var(--m-primary); }
.m-dis-reply b { font-size: 12px; color: var(--m-primary); }
.m-dis-reply span { margin-left: 6px; font-size: 11.5px; color: var(--m-muted); }
.m-dis-reply p { margin-top: 3px; font-size: 12.5px; line-height: 1.6; color: var(--m-sub); word-break: break-word; }
.m-dis-empty { padding: 14px 0; text-align: center; font-size: 12.5px; color: var(--m-muted); }
.m-dis-more { margin-top: 10px; text-align: center; font-size: 11.5px; color: var(--m-muted); }
.m-dis-gate { margin-top: 12px; padding: 12px; border-radius: 10px; background: var(--m-surface-2); text-align: center; }
.m-dis-gate strong { display: block; font-size: 13px; color: var(--m-ink); margin-bottom: 8px; }
/* 发言表单：内容 + 称呼/QQ + 验证码 + 发表 */
.m-dis-form { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; }
.m-dis-form textarea {
    width: 100%; min-height: 62px; resize: vertical; padding: 9px 11px;
    border: 1px solid var(--m-line-2); border-radius: 9px; background: var(--m-surface-2);
    color: var(--m-text); font-size: 13px; line-height: 1.6;
}
.m-dis-form textarea:focus { border-color: var(--m-primary); }
.m-dis-fields { display: flex; gap: 8px; }
.m-dis-fields input {
    flex: 1 1 0; min-width: 0; height: 32px; padding: 0 10px;
    border: 1px solid var(--m-line-2); border-radius: 9px; background: var(--m-surface-2);
    color: var(--m-text); font-size: 12.5px;
}
.m-dis-fields input:focus { border-color: var(--m-primary); }
.m-dis-code { display: flex; align-items: center; gap: 8px; }
.m-dis-code[hidden] { display: none; }
/* 自动审核规则说明（正常评论不用验证码、直接发布） */
/* （讨论表单下面那段「正常评论直接发布；含网址/联系方式…要验证码」的说明文字
   已按站长要求删掉，.m-dis-rule 这个样式也一并去掉；规则本身照旧生效。） */
.m-dis-code input {
    flex: 1 1 auto; min-width: 0; height: 32px; padding: 0 10px;
    border: 1px solid var(--m-line-2); border-radius: 9px; background: var(--m-surface-2);
    color: var(--m-text); font-size: 12.5px;
}
.m-dis-code input:focus { border-color: var(--m-primary); }
.m-dis-code img { flex: 0 0 auto; width: 84px; height: 30px; border-radius: 6px; cursor: pointer; }
.m-dis-acts { display: flex; align-items: center; gap: 10px; }
.m-dis-acts .m-btn { padding: 7px 20px; font-size: 13px; }
.m-dis-cancel {
    padding: 7px 14px; border: 0; border-radius: 8px; background: none;
    color: var(--m-muted); font: inherit; font-size: 12.5px; cursor: pointer;
}
.m-dis-cancel:hover { color: var(--m-sub); background: var(--m-surface-2); }
.m-dis-count { margin-left: auto; font-size: 11.5px; color: var(--m-muted); font-style: normal; }
.m-dis-tip { margin-top: 8px; font-size: 12px; line-height: 1.6; }
.m-dis-form { margin-top: 10px; }
.m-dis-form[hidden] { display: none; }
.m-dis-tip.is-ok { color: var(--m-primary); }
.m-dis-tip.is-err { color: #ff6a6a; }
.m-dis-tip[hidden] { display: none; }
.m-aside-detail i { font-style: normal; }
.m-aside-detail:hover { color: var(--m-primary); }
/* 标签行：默认只露一行（26px），溢出由 overflow 裁掉。
   padding-right: 32px 是给「展开标签」按钮**留位置**（26px 按钮 + 6px 间距）——
   这样第一行最后一个标签不会顶到按钮底下，按钮看起来就紧跟在它右边。 */
.m-aside-chips { position: relative; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; padding-right: 32px; max-height: 26px; overflow: hidden; }
.m-aside-chips.is-open { max-height: none; }
.m-aside-chips .m-chip { font-size: 12px; padding: 2px 9px; }
/* 「展开标签」按钮：站长要求**不要文字**，就一个圆圈 + 展开/收起箭头。
   箭头靠 .is-open 旋转 180°，不换图标也不换文字。
   站长后来又要求它挪到"最后一个标签的右边"（原来是另起一行居中在下面）→
   现在它是标签行里的最后一个元素 + absolute 定位：不参与 flex 换行、不会被裁掉，
   收起时永远贴在第一行右端。 */
.m-aside-chips-more {
    position: absolute; top: 0; right: 0;
    display: flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; margin: 0; padding: 0;
    border: 1px solid var(--m-line-2); border-radius: 50%;
    background: var(--m-surface-2); color: var(--m-sub);
    cursor: pointer; transition: color .18s, border-color .18s, transform .18s;
}
.m-aside-chips-more[hidden] { display: none; }
.m-aside-chips-more svg { width: 15px; height: 15px; }
.m-aside-chips-more:hover { color: var(--m-primary); border-color: var(--m-primary); }
.m-aside-chips-more.is-open svg { transform: rotate(180deg); }
/* 操作条：收藏 / 分享 / 留言 / 报错 */
.m-aside-acts { display: flex; align-items: center; justify-content: space-around; padding: 12px 8px; }
.m-aside-acts a {
    display: flex; flex-direction: column; align-items: center; gap: 5px;
    font-size: 12px; color: var(--m-sub); min-width: 56px;
}
.m-aside-acts a svg { width: 20px; height: 20px; }
.m-aside-acts a:hover { color: var(--m-primary); }
/* 收藏 / 报错点过之后的状态（站长要求：四个按钮都得有反馈，不能点完不知道成没成） */
.m-aside-acts a.is-on { color: var(--m-primary); }
.m-aside-acts a.is-on svg { fill: currentColor; fill-opacity: .18; }
/* VIP 卡 */
.m-aside-vip {
    display: flex; align-items: center; gap: 12px; padding: 14px 16px;
    border-radius: var(--m-radius-lg); color: #3b2a10;
    background: linear-gradient(120deg, #ffdfae, #f6c98a 60%, #e9b877);
    border: 1px solid #e6b877;
}
.m-aside-vip-txt { display: flex; flex-direction: column; gap: 3px; }
.m-aside-vip-txt b { font-size: 15px; }
.m-aside-vip-txt em { font-style: normal; font-size: 12px; opacity: .78; }
.m-aside-vip-btn {
    margin-left: auto; background: #3b2a10; color: #ffe6bd; font-size: 12.5px;
    padding: 6px 14px; border-radius: 16px; font-weight: 700; white-space: nowrap;
}
/* 选集：集数按钮（当前集高亮）+ 线路切换。
   站长要求：① 按钮里只显示数字（「第01集」→「01」，模板那边走 mac_ep_num 这个过滤器）；
             ② 普通剧集做成正方形；
             ③ **综艺这种"集名是长标题"的**（「第20260904期首映篇」）别硬做成正方形 ——
                改成"宽度跟着文字走"的长方块。
   ⚠️ 所以这里用 **flex 换行 + 宽度 auto**，不是 grid：
      grid 里同一行的轨道宽度是统一的（auto-fill/minmax 那一套），长标题和短数字混在一行时
      要么长标题被压窄、要么把数字小块一起撑成大方块 —— 怎么调都不对。
      flex 里每个按钮 flex:0 0 auto，宽度就是"文字 + 内边距"：
        · 纯数字的（01 / 100）：min-width 46 + 高度 46 → 看着还是正方形小方块
        · 长标题的：自然变成长方块，一行放不下就换行
      （踩过的另一个坑：老规则 .m-eps a 有个 min-width:52px + padding，会把方块撑出轨道、
        把 6px 间距吃掉，站长反馈过"集数之间的间距没有了"。现在宽度跟着内容走，间距就是 gap 的 6px。） */
.m-aside-eps .m-playfrom { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; }
.m-eps-grid { display: flex; flex-wrap: wrap; gap: 6px; }
.m-eps-grid a {
    flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    min-width: 46px; height: 46px; padding: 0 10px;
    font-size: 13px; line-height: 1.15; text-align: center;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
    border-radius: 8px; background: var(--m-surface-2); color: var(--m-sub);
}
.m-eps-grid a:hover { color: var(--m-primary); }
.m-eps-grid a.on { background: var(--m-grad); color: var(--m-primary-ink); font-weight: 700; }
/* 长标题的（综艺那种「第20260904期首映篇」，class 由 mac_ep_cls 给）：高度比正方形小块
   再矮一点（站长要求），宽度照旧跟着文字走 —— 一行能多放下一两块。 */
.m-eps-grid a.is-text { height: 40px; padding: 0 9px; font-size: 12.5px; }
/* 综艺/日更（集名是日期）的选集：**竖着一行一条、最新的在最上面**（站长要求）。
   倒序是在服务端把选集列表整体倒过来的（page.go 的 urls_list），所以这里只要竖排就行；
   DOM 顺序 = 视觉顺序 = 最新→最旧，下面的"分段"自然也是"第 1 段 = 最新那 30 集"。 */
.m-eps-grid.is-vlist { flex-direction: column; }
.m-eps-grid.is-vlist a { width: 100%; height: 38px; padding: 0 12px; font-size: 12.5px; }
/* 集数多的时候**分段显示**（站长要求：300 多集一下子全摊开太多了）：
   kuaibo.js 给网格加 .is-paged，一次只显示一段（每段 30 集）里的格子，
   下面那排「1-30 / 31-60 / …」是选择夹，点哪段显示哪段。
   当前正在播的那一集所在的那一段默认打开，所以高亮永远看得见。 */
.m-eps-grid.is-paged a { display: none; }
.m-eps-grid.is-paged a.is-in-seg { display: flex; }
.m-eps-segs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.m-eps-segs[hidden] { display: none; }
.m-eps-seg {
    padding: 5px 10px; border: 1px solid var(--m-line-2); border-radius: 7px;
    background: var(--m-surface-2); color: var(--m-sub); font: inherit; font-size: 12px;
    line-height: 1.2; cursor: pointer; transition: color .18s, background .18s, border-color .18s;
}
.m-eps-seg:hover { color: var(--m-primary); border-color: var(--m-primary); }
.m-eps-seg.is-on { background: var(--m-grad); color: var(--m-primary-ink); border-color: transparent; font-weight: 700; }
/* 精彩推荐：横向图卡片（站长要求：图片横向显示、标题和副标题放在图片**下面**、2 列）。
   列数用 auto-fill 而不是写死 2：右栏（内容 328px）算出来正好 2 列（每格约 159px），
   窄屏右栏落到下面变满宽时会自动排成 6~7 列，卡片大小基本不变（不会变成一排巨卡）。
   条数：模板里渲染 18 个，默认只露前 6 个（is-collapsed），点底部「更多影视」往下展开。 */
.m-aside-rellist { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px 10px; margin-top: 10px; }
/* 默认只露前 10 个（站长要求；原来是 6 个），点下面「更多影视」展开全部 18 个。
   ⚠️ 这个数字要和 kuaibo.js 的 initRelMore 里那个 10 对上（那边决定按钮显不显示）。 */
.m-aside-rellist.is-collapsed > a:nth-child(n+11) { display: none; }
/* 列表底部那个「更多影视 / 收起」（站长要求：点它向下展开更多） */
.m-rel-more {
    display: block; width: 100%; margin-top: 12px; padding: 7px 0;
    border: 1px solid var(--m-line-2); border-radius: 8px; background: var(--m-surface-2);
    color: var(--m-sub); font: inherit; font-size: 12.5px; cursor: pointer;
    transition: color .18s, border-color .18s;
}
.m-rel-more:hover { color: var(--m-primary); border-color: var(--m-primary); }
.m-rel-more[hidden] { display: none; }
.m-aside-relitem { display: flex; flex-direction: column; gap: 6px; min-width: 0; overflow: hidden; }
/* 图片横向：铺满格子宽度、按 16:9 裁切（竖版海报裁中间那条，观感就是"横图卡片"）。
   object-fit: cover 保证任何比例的图都不会变形/留白。 */
.m-aside-relitem img {
    width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
    border-radius: 8px; background: var(--m-surface-2);
}
.m-aside-relitem span { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.m-aside-relitem b { font-size: 12.5px; color: var(--m-text); font-weight: 600; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.m-aside-relitem em { font-style: normal; font-size: 11.5px; color: var(--m-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-aside-relitem:hover b { color: var(--m-primary); }
/* 左栏里的小节（看了还会看 / 剧情介绍 / 评论） */
.m-play-sec { margin-top: 20px; }
.m-play-sec-hd { display: flex; align-items: baseline; gap: 10px; }
/* 站长要求：小节标题再大一点（原来 16px） */
.m-play-sec-hd h2 { font-size: 19px; color: var(--m-ink); }
.m-play-sec-hd .more { margin-left: auto; font-size: 12.5px; color: var(--m-primary); }
.m-grid-loose { margin-top: 12px; }
/* 播放页左栏的「看了还会看」：站长要求 **7 列 × 5 行**（模板里 num="35"，同频道周热播）。
   7 列是固定列数：宽屏不跟着变多（以前按宽度加到 4/5 列，卡片大小会飘），
   卡片宽度跟着容器走；窄屏按列数往下减，别把卡片挤成一条缝。 */
.m-play-sec .m-grid { grid-template-columns: repeat(7, minmax(0, 1fr)); }
@media (max-width: 900px) { .m-play-sec .m-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (max-width: 700px) { .m-play-sec .m-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 460px) { .m-play-sec .m-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 360px) { .m-play-sec .m-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* 窄屏：右栏整块落到**播放器下面**（站长要求：不是在「看了还会看」下面，
   那样得先划过 35 张卡片才看得到选集/讨论）。
   右栏本身已经是普通文档流（不 sticky、不自己滚），所以只需要：
     1) 压成一列；
     2) 用 display:contents 把左栏这层"壳"（.vod-main）拆掉 ——
        它的两个子元素（播放器 / 看了还会看）就成了栅格子项；
     3) 用 order 排序：播放器(1) → 右栏(2) → 看了还会看(3)。
   ⚠️ display:contents 的元素自己不生成盒子，所以那一层的 margin 都不生效
      （桌面那 40px 左外边距本来也只在 ≥1181px 下加）。
   ⚠️ 排 order 的选择器要按 **DOM** 写：display:contents 只改盒子树，
      `.vod-page > .m-player` 这种是匹配不上的（播放器的 DOM 父亲还是 .vod-main），
      得写 `.vod-main > .m-player`。踩过：写成直接子代选择器 → 只有右栏拿到 order，
      于是它反而被排到最后去了。
   选集的方块列数不用管 —— .m-eps-grid 的 auto-fill 会自己加列，方块边长基本不变。 */
@media (max-width: 1180px) {
    .vod-page { grid-template-columns: minmax(0, 1fr); }
    .vod-main { display: contents; }
    .vod-main > .m-player { order: 1; }
    .vod-page > .vod-aside { order: 2; }
    .vod-main > .m-play-sec { order: 3; }
}
@media (max-width: 560px) {
    /* 手机宽度：选集改成**一整行横向滚动**（站长要求）——
       一格格排成一行，手指左右滑；不再换行成一大片、也不会挤掉间距。
       每格宽度还是跟着内容走（数字 46px、长标题跟着文字变宽），所以间距稳定是 8px；
       「分段显示」（.is-paged，>30 集时只有当前段的格子显示）照旧，这一行只放当前那段。
       滚动条在手机上不显示（本来也是浮层），滑到右端自然有"还有"的感觉。 */
    .m-eps.m-eps-grid:not(.is-vlist) {
        flex-wrap: nowrap;
        gap: 8px;
        overflow-x: auto;
        overflow-y: hidden;
        padding: 2px 2px 6px;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .m-eps.m-eps-grid::-webkit-scrollbar { height: 0; }
    .m-aside-acts a { min-width: 0; }
}

/* ---------- 横向滚动条：鼠标也能按住左右拖 ----------
   kuaibo.js 的 initDragScroll 会给"真的能横向滚动"的那些容器加 .is-draggable
   （首页卡片行 / 时间轴 / 手机版小横条面板 / 手机版选集 / 页头频道），
   这里只管手势光标和拖动时的状态：抓着的样子 + 拖动时别选中文字。
   触摸设备上这些是浏览器原生滑动，指针样式看不出来也无所谓。 */
.is-draggable { cursor: grab; }
.is-draggable.is-dragging { cursor: grabbing; user-select: none; -webkit-user-select: none; }

.m-player { background: #000; border-radius: var(--m-radius-lg); overflow: hidden; margin-top: 0; border: 1px solid var(--m-line); }
/* 「已从上次看到的位置继续播放（12:34）」提示条：盖在画面底部，6 秒后自己消失，
   带一个「从头播放」按钮（点错了/就想从头看的时候用）。见 player.go 的 showResumeTip。 */
.m-player-resume {
    position: absolute; left: 50%; bottom: 54px; transform: translateX(-50%);
    z-index: 6; display: flex; align-items: center; gap: 10px;
    max-width: 92%; padding: 7px 12px; border-radius: 18px;
    background: rgba(0, 0, 0, .78); color: #fff; font-size: 12.5px; line-height: 1.4;
}
.m-player-resume span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.m-player-resume button {
    flex: 0 0 auto; padding: 3px 10px; border: 1px solid rgba(255, 255, 255, .45);
    border-radius: 12px; background: transparent; color: #fff; font: inherit;
    font-size: 12px; cursor: pointer;
}
.m-player-resume button:hover { border-color: #fff; background: rgba(255, 255, 255, .14); }
.m-player-box { position: relative; width: 100%; padding-top: 56.25%; }
/* ---------- 起播前先藏住**控件**（不是整个播放器画布）----------
   打开播放页时能看见"控件乱乱地还没摆好"，根因在 ArtPlayer 自己：
   它的 .art-bottom（控制条所在的那一层）按 CSS 是 inset:0 + height:100%，
   也就是**铺满整个播放器**、靠 justify-content:flex-end 把控制条压在底部；
   而 .art-controls 默认 transform:translateY(var(--art-bottom-offset))（20px），
   只有 .art-control-show / .art-hover 时才 translateY(0)。
   没在播时还挂着 .art-control-hide，会再往下推一个 --art-bottom-offset。

   正常情况下这一套没问题，但**起播那几百毫秒**里：
     · 自动播放被浏览器拦着、还在等 hls 清单 → 一直停在 .art-control-hide
       → 控制条正被推到画面外，却在**半路上**（transition .2s）被看到；
     · 淡入 / 上下位移的过渡叠在一起，于是"控件在画面里乱摆、还没到位"。
   另外 <video> 这时候 videoWidth 还是 0，ArtPlayer 量不到画面比例，
   方形的居中层（大播放按钮 / 加载圈 / 弹幕输入框）也只能按容器算，位置会偏。

   所以：**只把控件那一套藏起来**，播放器画布本身照常显示（黑底 + 封面照旧，
   作为"正在加载"的视觉背景），等摆好了（见 player.go 的 markReady）再淡入。
   ⚠️ 只动 ArtPlayer 自己生成的那些层（.art-bottom / .art-center / .art-state /
      .art-danmuku / .art-loading），**不碰** .art-video-player 本体，也不碰
      <video> —— 画布和视频照常参与布局、照常加载，只是看不见控件而已。
   ⚠️ 用 visibility 而不是 display:none：这些层里有 ArtPlayer 需要量尺寸的，
      display:none 会让它们量到 0 并在显示时重新错位一次（反而更乱）。
   ⚠️ 我们自己的占位（.m-player-off / .m-player-cover / .m-player-lock /
      .m-player-resume / .m-player-stall / .m-player-captcha）不在这个选择器里，
      它们该显示就显示，不受影响。 */
.m-player-box:not(.is-ready) .art-video-player > .art-bottom,
.m-player-box:not(.is-ready) .art-video-player > .art-center,
.m-player-box:not(.is-ready) .art-video-player > .art-danmuku,
.m-player-box:not(.is-ready) .art-video-player > .art-loading,
.m-player-box:not(.is-ready) .art-video-player .art-state,
.m-player-box:not(.is-ready) .art-video-player .art-controls,
.m-player-box:not(.is-ready) .art-video-player .art-progress,
.m-player-box:not(.is-ready) .art-video-player .art-settings,
.m-player-box:not(.is-ready) .art-video-player .art-contextmenus,
.m-player-box:not(.is-ready) .art-video-player .art-notice,
.m-player-box:not(.is-ready) .art-video-player .art-info,
.m-player-box:not(.is-ready) .art-video-player .art-subtitle,
.m-player-box:not(.is-ready) .art-video-player .art-layers {
    visibility: hidden !important;
}
/* 摆好了 → 控件淡入（画布本来就在，不用管） */
.m-player-box.is-ready .art-video-player > .art-bottom,
.m-player-box.is-ready .art-video-player > .art-center,
.m-player-box.is-ready .art-video-player > .art-danmuku,
.m-player-box.is-ready .art-video-player .art-controls,
.m-player-box.is-ready .art-video-player .art-progress {
    animation: m-player-fade-in .24s ease both;
}
@keyframes m-player-fade-in { from { opacity: 0; } to { opacity: 1; } }
/* 兜底：进页面就挂上 .is-booting，万一 JS 出错没走到 markReady，
   3.2 秒后也强制把控件放出来（宁可看到控件，也不能一直是黑画面没入口）。 */
.m-player-box.is-booting .art-video-player > .art-bottom,
.m-player-box.is-booting .art-video-player > .art-center,
.m-player-box.is-booting .art-video-player > .art-danmuku {
    animation: m-player-reveal .24s ease 3.2s both;
}
@keyframes m-player-reveal { to { visibility: visible; } }
/* ---------- 起播空档期：留住封面 + 叠一个转圈 ----------
   为什么需要这个：ArtPlayer 的 .art-poster（封面）一旦开始"播"就自己设成
   display:none（这是它内部行为），而 HLS 从"开始拉流"到"真出第一帧"通常还要
   好几秒（实测：327ms 封面被隐藏、2.5s 才出画面；线路慢的时候更久）。
   这中间露出来的是 <video> 自己的黑底 —— 就是"刚看到封面、马上又黑屏"的现象。

   做法：把封面**按住**（.is-holding-poster），让它一直盖在黑画面上面；
   等"画面真的出来了"再由 JS 摘掉这个类（见 player.go 的 releasePoster），
   ArtPlayer 自己会把封面隐藏掉 —— 两边无缝接上，中间不出现黑屏。
   ⚠️ 挂在**独立**的类上，不是 .is-booting：控件那侧有 5 秒超时（超时也要给操作入口），
      封面不该跟着它一起放 —— 否则流慢的时候又变成"5 秒后黑屏"。
   ⚠️ 必须 !important：ArtPlayer 是通过**内联 style** 设 display:none 的，
      内联优先级高于普通类选择器（实测确认，不是随手加的保险）。
   ⚠️ 只在起播阶段覆盖 —— 放开后立刻失效，不影响 ArtPlayer 换集/切线路时的正常
      poster 行为（那时候它由 ArtPlayer 自己按状态显示）。 */
.m-player-box.is-holding-poster .art-video-player .art-poster { display: block !important; }

/* 转圈：盖在封面之上，告诉用户"在加载"而不是"卡住了/坏了"。
   由 JS 注入（见 player.go），起播期间在、markReady 之后被移除。 */
.m-player-bootspinner {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    z-index: 21; width: 46px; height: 46px; pointer-events: none;
    border: 3px solid rgba(255, 255, 255, .30);
    border-top-color: var(--m-primary);
    border-radius: 50%;
    /* 深色描边 + 阴影：封面图有深有浅，纯白圈在浅色封面上会糊掉 */
    box-shadow: 0 2px 12px rgba(0, 0, 0, .55);
    animation: m-player-spin .8s linear infinite;
}
@keyframes m-player-spin { to { transform: translate(-50%, -50%) rotate(360deg); } }
.m-player-bootspinner[hidden] { display: none; }
/* 正文容器放宽到 2200 之后，16:9 的播放器在 2K 屏上会变成 2168×1220 —— 比屏幕还高，
   要滚半天才能看到选集。这里用 aspect-ratio + max-height 兜住：宽度照样铺满，
   高度最多 72vh（视频自己在框里留黑边，和各大站点的做法一致）。
   ⚠️ 必须把 #bofang_box 一起写上：base.css 里有 `#bofang_box{height:620px}`（老模板遗留的
   写死高度，ID 选择器优先级比 .m-player-box 高），不给 height:auto 的话 aspect-ratio 根本不起作用。
   包在 @supports 里：万一浏览器不支持 aspect-ratio，还退回上面 padding-top 的老写法。 */
@supports (aspect-ratio: 16 / 9) {
    .m-player-box, #bofang_box { padding-top: 0; height: auto; aspect-ratio: 16 / 9; max-height: 72vh; }
}
/* ⚠️ 只让**直接子元素**那个 video 铺满：ArtPlayer 内部有自己的 <video>（嵌在
   .art-video-player 里），它自己会铺满，被这条规则按 absolute 拉出来反而会错位。 */
.m-player-box > iframe, .m-player-box > video, .m-player-box > .embed-responsive-item { position: absolute; top: 0; left: 0; width: 100% !important; height: 100% !important; border: 0; }
/* 播放器本体（ArtPlayer，见 plugin/front/player.go）：铺满播放框、黑底。
   ArtPlayer 自己的控件样式是运行时注入的，这里的主题色通过实例的 theme 选项给。 */
.m-artplayer, .m-artplayer > .art-video-player { position: absolute; inset: 0; width: 100%; height: 100%; }
.m-artplayer .art-video-player { background: #000; }
.m-artplayer .art-video { background: #000; }
.m-player-video { display: block; background: #000; outline: none; }
/* 控制条上那个「后台继续播放」耳机按钮**已按站长要求去掉**（只留齿轮设置里那一项）。
   下面两条样式先留着：哪天想把它挂回控制条（player.go 里那段注释解开的代码），
   样式不用再写一遍。 */
.m-player-bgbtn svg { width: 18px; height: 18px; display: block; }
/* 全屏按钮（控制条最右边那颗）右外边距 20px。
   它贴着播放器右边缘时，鼠标移到右下角容易擦到、也可能被系统任务栏挡住，
   留 20px 视觉上也没那么顶。只给 fullscreen 加，不影响它左边那颗网页全屏。 */
.m-player-box .art-control-fullscreen { margin-right: 20px; }
/* ---------- 修正 ArtPlayer 设置面板里的「开关」颜色 ----------
   ⚠️⚠️ 这是站长反馈「主色改了、播放器设置里的开关还是蓝色」的根因：
      ArtPlayer 的开关是**图标**（.art-icon-switchOn / switchOff），它的 SVG 里
      写死了 fill="#648FFC"（蓝色）—— 属于 SVG 表现属性，**theme 选项对它完全无效**，
      所以怎么改主色它都不动。
   解法：用 CSS 覆盖 fill。CSS 规则优先级高于 SVG 表现属性，所以能盖住；
      但为了压过 ArtPlayer 运行时可能写的行内样式，这里加 !important。
   注意要连 path 一起选中：fill 是画在 <path> 上的，只写 .art-icon 不生效。 */
.m-player-box .art-icon-switchOn .icon path,
.m-player-box .art-icon-switchOn .icon,
.m-player-box .art-icon-switchOn svg,
.m-player-box .art-icon-switchOn svg path { fill: var(--m-primary) !important; }
/* 关闭状态的图标：保持低调的灰（跟控制条其他图标一致），不要也跟着变主色 ——
   否则开/关两态长得一样，看不出当前是开还是关。 */
.m-player-box .art-icon-switchOff .icon path,
.m-player-box .art-icon-switchOff .icon,
.m-player-box .art-icon-switchOff svg,
.m-player-box .art-icon-switchOff svg path { fill: currentColor !important; opacity: .55; }
/* 手机窄屏控制条本来就挤，20px 太奢侈，收成 8px（仍然留出安全距离）。 */
@media (max-width: 560px) {
    .m-player-box .art-control-fullscreen { margin-right: 8px; }
}
/* ---------- 倍速按钮（控制条上、设置齿轮左边）----------
   站长要求：倍速不要埋在齿轮里，直接摆在控制条上。
   这里只管样式；按钮本身由 player.go 的 rateControl 注册（index=25 → 落在 setting 左边）。
   按钮里显示的是"倍速"或"1.5x"（1 倍时显示"倍速"，避免让人以为被改过）。 */
.m-player-box .art-control-rate { min-width: 52px; }
/* 倍速按钮的悬停气泡（「播放速度」）。
   ArtPlayer 的 tooltip 是**纯 CSS :hover 驱动**的：它只给按钮设 aria-label
   并加成 hint--rounded / hint--top 两个类，气泡本体是按钮的 ::after（小三角是 ::before），
   靠 .hint--top:hover:after 显示 —— 没有 JS 开关可以控制。
   所以「点开菜单后气泡要消失」只能靠下面这条 .is-notip 压住
   （类由 player.go 的 suppressRateTip 在 click 时加、mouseleave 时摘）。 */
/* ⚠️ 必须用 :hover:after / :hover:before 的完整形式覆盖，只写 .is-notip:after 没用 ——
   ArtPlayer 那条规则带 :hover，选择器权重更高，压不住。 */
.m-player-box .art-control-rate.is-notip:hover::after,
.m-player-box .art-control-rate.is-notip:hover::before {
    opacity: 0 !important;
    visibility: hidden !important;
}
.m-player-box .art-control-rate > span {
    font-size: 13px; line-height: 1; letter-spacing: .2px;
    padding: 0 4px; white-space: nowrap;
}
/* 非 1 倍时高亮（跟主题色走），一眼能看出"速度被调过了" */
.m-player-box .art-control-rate.is-changed > span { color: var(--m-primary); font-weight: 700; }
/* 倍速菜单：贴在**倍速按钮正上方**。
   ⚠️ 这里原来写死了 right:10px，结果菜单永远贴在播放器右边，
      和倍速按钮的实际位置对不上（站长反馈"为啥不在倍数元素上面"）。
      现在改成由 JS 量按钮位置后写 left/bottom（见 player.go 的 openRateMenu），
      所以这里**不要**再给 left/right/bottom，只保留 appearance。
   z-index 要高过 .art-bottom(60) 与 .art-loading(70)，避免被盖住。 */
.m-player-box .m-player-ratemenu {
    position: absolute; z-index: 95;
    display: flex; flex-direction: column; gap: 2px;
    padding: 6px; min-width: 104px;
    border-radius: 8px; border: 1px solid rgba(255, 255, 255, .14);
    /* ⚠️ 透明度 .78：之前 .96 几乎不透明，跟播放器画面完全脱开、显得很"实"。
       调低后能看到底下的画面，更像播放器自带的面板。
       模糊 blur(6px) 也加大了一点 —— 背景越透明，越需要模糊来保证文字可读。 */
    background: rgba(20, 20, 24, .78); backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .5);
}
.m-player-box .m-player-rateitem {
    display: block; width: 100%; padding: 7px 12px;
    border: 0; border-radius: 6px; background: transparent;
    color: #fff; font: inherit; font-size: 13px; line-height: 1.2;
    text-align: left; cursor: pointer; white-space: nowrap;
}
.m-player-box .m-player-rateitem:hover { background: rgba(255, 255, 255, .12); }
/* 当前生效的那一档 */
.m-player-box .m-player-rateitem.is-on {
    color: var(--m-primary); font-weight: 700;
    background: rgba(255, 255, 255, .08);
}
/* 手机窄屏：控制条本来就挤，倍速按钮收窄一点，别把全屏挤掉。
   注意菜单的左/下位置由 JS 算，这里只调宽度。 */
@media (max-width: 560px) {
    .m-player-box .art-control-rate { min-width: 42px; }
    .m-player-box .art-control-rate > span { font-size: 12px; }
    .m-player-box .m-player-ratemenu { min-width: 96px; }
}
/* ---------- 设置面板（齿轮那颗按钮弹出的面板）对齐倍速菜单的观感 ----------
   站长要求：设置弹窗的 UI 和倍速弹窗长一样。
   两边的取值**必须保持一致**，改一边记得改另一边（倍速菜单见上面 .m-player-ratemenu）：
     背景 rgba(20,20,24,.96) / 边框 1px rgba(255,255,255,.14) / 圆角 8px
     阴影 0 8px 24px rgba(0,0,0,.5) / 模糊 blur(4px) / 内边距 6px

   ⚠️⚠️ 为什么这里要写 !important（其他地方尽量不写）——
      ArtPlayer 在**暂停时**会给播放器加 .art-backdrop 类，并有一条规则：
        .art-video-player.art-backdrop .art-settings {
            background-color:#000000bf!important;
            backdrop-filter:saturate(180%) blur(20px);
        }
      它**自带 !important**，且选择器多了 .art-backdrop 一段（权重更高）。
      不写 !important 就压不住 —— 实测现象就是「暂停时面板是纯黑毛玻璃、
      播放时才是我们要的颜色」，站长会觉得"改了没生效"。
      所以下面把 !important 和 .art-backdrop 两种情况都覆盖掉。

   ⚠️ 只覆盖**外观**，不动 .art-settings 的 position/right/bottom ——
      那几个是 ArtPlayer 算好的「控制条上方」定位，改了面板会跑偏。 */
.m-player-box .art-video-player .art-settings,
.m-player-box .art-video-player.art-backdrop .art-settings {
    background-color: rgba(20, 20, 24, .78) !important;
    border: 1px solid rgba(255, 255, 255, .14);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .5);
    -webkit-backdrop-filter: blur(6px) !important;
    backdrop-filter: blur(6px) !important;
    padding: 6px;
}
/* 面板里的每一项：跟倍速菜单的条目一样是 6px 圆角。
   原来 ArtPlayer 给的是 padding:0 5px（贴着面板边），有了外层 6px 内边距后
   再留 5px 会显得空，所以这里给 0 6px，文字左边缘和内边距对齐。 */
/* ---------- 设置面板不要上下滚动条：高度 = 内容高度 ----------
   ⚠️⚠️ 根因：ArtPlayer 给 .art-settings 写死了一条
       max-height: var(--art-settings-max-height)（默认 300px）
       overflow-y: auto
   于是表项一多，面板就被卡在 300px 并冒出滚动条（站长反馈的"为啥还有上下滚动条"）。

   解法：把 max-height 放开成「内容多高就多高」。
   ⚠️ 但**不能**直接写 max-height:none —— 这两条是配套的：
      手机上横屏、或者以后表项加得很多时，面板会高过播放器、顶出画面外，
      反而看不到下面的项。所以上限改成「播放器高度 - 控制条高度 - 一点余量」：
        · 正常项目数（10 项左右 ≈ 340px）时这个上限够用 → 不出滚动条，高度=内容高度；
        · 极端情况（项特别多/手机横屏）才会兜底出滚动条，总比溢出屏幕强。
   calc 里的 --art-control-height / --art-padding 都是 ArtPlayer 自己的变量。
   overflow-y 保持 auto：配上新的上限，平时不会触发，只在兜底时才出现。 */
.m-player-box .art-video-player .art-settings,
.m-player-box .art-video-player.art-backdrop .art-settings {
    /* ⚠️⚠️ 关键：height:auto !important ——
       ArtPlayer 用 **JS 行内样式**把面板高度写死了：
           style="height: 140px; width: 250px; left: ...; right: auto"
       行内样式优先级高于任何 CSS 选择器，所以之前光改 max-height 完全没用 ——
       实测面板一直是 140px，而里面内容需要 150~162px，底部就被切掉了
       （站长看到的「最后一项下边距加了但被裁掉」就是这个）。
       这里必须用 height:auto!important 盖掉行内 height，面板才会按内容撑开。
       width 不用管（它是 250px 固定宽，和内容高度无关）。 */
    height: auto !important;
    /* 高度 = 内容高度（不出现上下滚动条）。
       上限放到「播放器高 - 控制条高 - 一点余量」，正常项目数（十几项以内）都远够用，
       所以平时撑不到这个上限 → 不会出滚动条。
       ⚠️ 保留这个上限（而不是 none）是为了手机横屏、或以后表项暴增时兜底，
          否则面板会高过播放器、顶出画面。 */
    max-height: calc(100% - var(--art-control-height) - var(--art-padding) - 6px) !important;
    /* ⚠️ 关键：把纵向滚动关掉。ArtPlayer 原来给的是 overflow-y:auto，
       哪怕只差 1px 也会冒出一条滚动条（站长反馈的就是这个）。
       改成 hidden：内容比上限矮时（绝大多数情况）完全看不出区别，
       真超高时直接裁掉而不是滚动 —— 宁可少看一项，也不要那条碍眼的滚动条。 */
    overflow-y: hidden !important;
    /* 顺带把「有没有内容溢出」判断也理顺：padding 算进高度里，
       免得内容高度正好等于上限时又被 padding 顶出滚动条。 */
    box-sizing: border-box;
    /* font-size 12px (was 14px).
       Icons: --art-settings-icon-size 18px (was 24px).
       NOTE: must change the VARIABLE, not .art-icon width/height --
       ArtPlayer uses it to size the icon SLOT. Changing only the svg leaves
       an empty gap where the icon used to be. */
    font-size: 12px;
}
/* 面板里的滚动条本身也美化一下（万一真触发了兜底）：细一点、半透明，
   别用系统默认那条粗灰条破坏观感。 */
.m-player-box .art-video-player .art-settings::-webkit-scrollbar { width: 4px; }
.m-player-box .art-video-player .art-settings::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, .25); border-radius: 2px;
}
.m-player-box .art-video-player .art-settings .art-setting-item {
    border-radius: 6px;
    padding: 0 6px;
    /* explicit font-size: some values are input/button which do NOT inherit. */
    font-size: 12px;
    line-height: 1.35;
}
/* Last item gets 2px bottom margin.
   Why: .art-settings has padding: 6px and overflow hidden. The last row sits
   right on the padding edge, so the panel bottom looks tighter than the top.
   2px restores the visual balance asked for.
   NOTE: :last-child applies per PANEL, so it also covers sub-panels
   (ArtPlayer can render nested panels, each is its own .art-setting-panel). */
.m-player-box .art-video-player .art-settings .art-setting-panel .art-setting-item:last-child {
    margin-bottom: 2px;
}
/* 单选列表（播放速度/清晰度那种展开项）的容器也跟着用同款圆角，
   免得它和面板圆角不一致、露出直角。 */
.m-player-box .art-video-player .art-settings .art-selector-list {
    border-radius: 6px;
}
/* ---------- icons: force 18px ----------
   Directly size .art-icon (both sides).
   We do NOT rely on --art-settings-icon-size: that variable is declared by
   ArtPlayer on a wider scope, and a declaration on .art-settings did not win
   (measured: still 24px). Writing width/height here is deterministic.
   .art-icon is a flex box containing the <svg>, so sizing the box is enough --
   the svg scales to fit. */
.m-player-box .art-video-player .art-settings .art-setting-item-left-icon,
.m-player-box .art-video-player .art-settings .art-setting-item-right-icon {
    font-size: 18px;
}
.m-player-box .art-video-player .art-settings .art-setting-item-left-icon .art-icon,
.m-player-box .art-video-player .art-settings .art-setting-item-right-icon .art-icon {
    width: 18px !important;
    height: 18px !important;
    max-width: 18px !important;
    max-height: 18px !important;
}
/* the svg inside must fill the 18px box, otherwise it keeps its own 26/32px */
.m-player-box .art-video-player .art-settings .art-setting-item-left-icon .art-icon svg,
.m-player-box .art-video-player .art-settings .art-setting-item-right-icon .art-icon svg {
    width: 100% !important;
    height: 100% !important;
}
.m-player-bgbtn.is-on { color: var(--m-primary); }
/* 「已静音播放，点一下开启声音」：浏览器严格策略下我们只能静音起播，
   这时候给一句能点的提示（点画面任意处也会开声音）。见 player.go 的 showMutedTip。 */
/* 「浏览器不让自动出声」的提示：站长反馈过"一刷新就静音了、不知道怎么弄回来"，
   所以做成画面正中间一个显眼的喇叭按钮（跟别的视频站一样），点它/点画面/按任意键都能开声音。
   见 player.go 的 showMutedTip：真开上声音（或用户点了页面）之后它会自己收掉。 */
.m-player-mutedtip {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 33;
    display: flex; align-items: center; gap: 9px;
    padding: 11px 18px; border-radius: 28px; border: 1px solid rgba(255, 255, 255, .26);
    background: rgba(0, 0, 0, .78); color: #fff; font: inherit; font-size: 13.5px;
    cursor: pointer; backdrop-filter: blur(2px);
}
.m-player-mutedtip:hover { background: rgba(0, 0, 0, .9); }
.m-player-mutedtip-ic { display: block; }
.m-player-mutedtip-ic svg { width: 21px; height: 21px; display: block; color: var(--m-primary); }
.m-player-mutedtip em { font-style: normal; }
/* 自动播放被拒时我们自己盖的那层「点击播放」在最上面：ArtPlayer 自己也有一套
   大播放按钮（.art-state），两层叠一起很丑，所以盖着的时候把它的藏起来。 */
.m-player-box.has-cover .art-video-player .art-state { display: none !important; }
/* 播不了时的就地提示（换线路 / 刷新），别让人对着黑框猜 */
.m-player-off {
    position: absolute; inset: 0; z-index: 34; display: flex; align-items: center; justify-content: center;
    padding: 20px; text-align: center; font-size: 13.5px; line-height: 1.7;
    color: var(--m-sub); background: rgba(0, 0, 0, .72);
}
/* 自动换线路时的一句提示（贴在播放器底部中间，几秒后自己消失，不挡控制条）。
   见 plugin/front/player.go 的 pgTip：线路卡了/播不了自动切到别的线路时出现。 */
.m-player-pgtip {
    position: absolute; left: 50%; bottom: 54px; transform: translateX(-50%); z-index: 32;
    max-width: 88%; padding: 7px 14px; border-radius: 16px;
    background: rgba(0, 0, 0, .78); color: #fff; font-size: 12.5px; line-height: 1.5;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    border: 1px solid rgba(255, 255, 255, .14); pointer-events: none;
}
/* 「声音还在放、画面卡住」时的自救提示（见 plugin/front/player.go 的 stall 检测：
   requestVideoFrameCallback 一连 2.5 秒数不到新画面就推一下播放位置，推不动才亮这个）。
   pointer-events 只留给按钮 —— 别把播放器自带的控制条一起盖住。 */
.m-player-stall {
    position: absolute; inset: 0; z-index: 31; display: flex; flex-direction: column; gap: 12px;
    align-items: center; justify-content: center; padding: 20px; text-align: center;
    background: rgba(0, 0, 0, .55); pointer-events: none;
}
.m-player-stall p { font-size: 13.5px; color: #fff; }
.m-player-stall .m-btn { pointer-events: auto; }
/* 发弹幕命中风险内容时，就在播放器里问一次验证码（和留言/评论同一套自动审核规则，
   见 plugin/front/player.go 的 askCaptcha / plugin/front/danmaku.go）。 */
.m-player-captcha {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 35;
    display: flex; flex-direction: column; gap: 8px; align-items: center;
    padding: 14px 16px; border-radius: 12px; text-align: center;
    background: rgba(0, 0, 0, .86); border: 1px solid rgba(255, 255, 255, .18);
}
.m-player-captcha p { font-size: 12.5px; color: #fff; line-height: 1.6; max-width: 260px; }
.m-player-captcha img {
    width: 108px; height: 36px; border-radius: 6px; cursor: pointer; background: #fff;
}
.m-player-captcha input {
    width: 160px; padding: 6px 10px; border-radius: 8px; text-align: center;
    border: 1px solid rgba(255, 255, 255, .28); background: rgba(255, 255, 255, .08);
    color: #fff; font: inherit; font-size: 13px;
}
.m-player-captcha-act { display: flex; gap: 8px; }
/* 弹幕输入框（artplayer-plugin-danmuku 自带的那一行）：跟着站里的橙色走，
   顺便把它的字号调小一点，免得在窄屏上把播放器挤满。 */
.m-player-box .apd-input { font-size: 13px; }
.m-player-box .apd-send { background: var(--m-primary) !important; }

/* ---------- 弹幕设置面板（点弹幕齿轮弹出）对齐倍速菜单的观感 ----------
   站长要求：弹幕设置的弹窗背景 UI 和倍速弹窗长一样。
   插件（artplayer-plugin-danmuku v5.3.0）自带的原始样式写在 min.js 里：
       .apd-config-panel { bottom:24px; left:0; width:320px; padding:10px }
       .apd-config-panel-inner { border-radius:3px; background-color:#000000d9; padding:10px }
   → 纯黑 85% 不透明 + 3px 小圆角，和我们面板/倍速菜单完全脱节。
   这里覆盖成与 .m-player-ratemenu 一致的取值：
     背景 rgba(20,20,24,.78) / 边框 1px rgba(255,255,255,.14) / 圆角 8px
     阴影 0 8px 24px rgba(0,0,0,.5) / 模糊 blur(6px) / 内边距 6px
   ⚠️ 面板本体是 .apd-config-panel（只有 padding:10px 做定位留白），
      **真正的背景块是里面的 .apd-config-panel-inner**，所以两处都要覆盖：
      外层去掉 10px 留白、只留我们的 6px；内层给背景/边框/圆角/阴影。
   ⚠️ 不动它的 position/bottom/left/width —— 那是插件算好的弹出定位，改了会跑偏。 */
.m-player-box .artplayer-plugin-danmuku .apd-config .apd-config-panel {
    /* 站长要求「整个内边距再加 2px」：6px → 8px。
       注意这一层是 .apd-config-panel 的**定位留白**（它自己不画背景），
       真正画背景的是里面的 .apd-config-panel-inner，
       所以下面 inner 的内边距也一并 +2px（10px → 12px），
       两层一起加，视觉上才是"整个弹窗内容离边框更松"。 */
    padding: 8px;
}
.m-player-box .artplayer-plugin-danmuku .apd-config .apd-config-panel .apd-config-panel-inner {
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, .14);
    background: rgba(20, 20, 24, .78);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .5);
    /* 10px → 12px（整个内边距 +2px） */
    padding: 12px;
    /* 背景变透明后，面板里所有文字统一白色，保证可读性 */
    color: #fff;
}
/* 面板里的「按类型屏蔽 / 防止弹幕重叠 / 同步视频速度」等小节：和倍速条目一样 6px 圆角 */
.m-player-box .artplayer-plugin-danmuku .apd-modes .apd-mode {
    border-radius: 6px;
}
/* ---------- 弹幕设置弹窗整体宽度收窄 ----------
   站长要求：「弹幕设置弹窗整体宽度再小一点」。

   ⚠️ 插件把宽度写死在 .apd-config-panel 上（min.js 里 width:320px），
      而且**面板本身是 position:absolute**，宽度不受内容撑开影响，
      必须显式给新值才有效。

   为什么是 280px（从 320px 收）：
     · 里面最宽的一行是「按类型屏蔽」的 3 个图标（每个 20px）+ .apd-modes 的
       gap:20px，加上刚调大的 12px 内边距，实测 280px 刚好不挤；
     · 再窄（比如 240px）会让滑杆变短、刻度文字换行，反而难用。
   ⚠️ 这里的 width 覆盖是安全的：插件只在 .apd-config-panel 上设过这一个宽度，
      不涉及 JS 计算（对比 .ant-settings 那种由 JS 量出来的定位就不敢动）。 */
.m-player-box .artplayer-plugin-danmuku .apd-config .apd-config-panel {
    width: 280px;
}
/* 手机窄屏：在收窄后的 280px 基础上再收一档，保证小屏不顶到边缘
   （倍速菜单同样是窄屏收窄） */
@media (max-width: 560px) {
    .m-player-box .artplayer-plugin-danmuku .apd-config .apd-config-panel { width: 232px; }
}

/* ---------- 弹幕面板改成「点击」展开（原来鼠标一碰就弹） ----------
   ⚠️⚠️ 站长反馈：「为啥弹幕弹窗设置不要点击，只要把鼠标放上去他就弹出来了」
   根因：**插件把展开做成了纯 CSS :hover**（min.js 插件样式表里）：
       .apd-config:hover .apd-config-panel { opacity:100; pointer-events:all }
   所以只要鼠标扫过那个齿轮图标，面板立刻弹出来 —— 想点别的很容易误触。
   （JS 里另有 onMouseEnter 只负责**水平**摆位，见 player.go 不用动。）

   解法：不改插件 JS，纯 CSS 反转开关 ——
     1) 未点开时：把 hover 那条的展开效果**盖回去**，即
        强制 opacity:0 / pointer-events:none，并补 visibility:hidden
        （隐藏后不参与命中测试，鼠标划过齿轮不会再弹出）；
     2) 点开后：JS 给 .apd-config 加上 .is-open 类，这时才允许显示。
   ⚠️ 为什么必须带 !important：
      插件那条是 `.apd-config:hover .apd-config-panel`，多了个伪类，
      权重比我们下面第一条（只用 .apd-config）高一档，不标 !important 压不住。
   ⚠️ 顺序有讲究：**先写关闭态，再写 .is-open 打开态** ——
      两条都带 !important、权重也相同（.is-open 那条多一段类，其实更高），
      所以打开态一定赢。这个顺序保证"点开能显示"。
   ⚠️ 加了 visibility 之后，插件原有的 opacity 过渡仍然生效（visibility 不算过渡属性
      但会跟随 transition 一起延迟切换），弹出手感还在。 */
.m-player-box .artplayer-plugin-danmuku .apd-config .apd-config-panel,
.m-player-box .artplayer-plugin-danmuku .apd-style .apd-style-panel {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
}
/* ⚠️⚠️ 这条是**开启态**，必须放在上面关闭态之后（同权重靠后生效），
   而且选择器要多带 `.is-open` 一段提高权重，双保险。 */
.m-player-box .artplayer-plugin-danmuku .apd-config.is-open .apd-config-panel,
.m-player-box .artplayer-plugin-danmuku .apd-style.is-open .apd-style-panel {
    opacity: 100 !important;
    visibility: visible !important;
    pointer-events: all !important;
}
/* ⚠️⚠️ 兜底：面板**没开**时，把插件那条 `:hover` 展开彻底废掉。
   为什么要单独一条：`.apd-config:hover` 的权重其实比上面第一条
   （`.apd-config .apd-config-panel`，没有伪类）**高**（伪类算一个类），
   刚好又都能命中 —— 所以第一条的 !important 是压得住它的（!important 层级更高），
   但为了"以后插件版本变了/别处又加了 hover 规则"不再翻车，
   这里再加一条显式把 hover 态也关掉，语义更直白。 */
.m-player-box .artplayer-plugin-danmuku .apd-config:not(.is-open):hover .apd-config-panel,
.m-player-box .artplayer-plugin-danmuku .apd-style:not(.is-open):hover .apd-style-panel {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
}
/* ---------- 弹窗底部到控制条按钮的距离，对齐倍速菜单 ----------
   ⚠️⚠️ 站长反馈：「弹窗下面到控制条弹幕按钮的距离 和 倍数弹窗到下面倍数的距离不一样」

   ⚠️ 调这个值的两个坑（都用 CDP 实测过，别再凭感觉改）：
     坑 1：bottom 是相对**定位祖先 .apd-config** 算的，而它不是只有图标那么高 ——
           它是 display:flex，除了 24px 的 svg 图标还有插件留下的行高/内边距，
           实测容器比图标高出约 24px。直接写 bottom:6px 会让面板**压在图标上**。
     坑 2：用户眼睛看到的"弹窗下边缘"是**有背景色的那个方块**
           (.apd-config-panel-inner) 的底边，不是 .apd-config-panel 的底边 ——
           外层那圈 padding 是**透明的**、却算在高度里，属于视觉误差。

   实测标定（量的是「.apd-config-panel-inner 底边」到「齿轮图标顶边」，
   正数=有间隙，负数=面板压住图标）：
       bottom:24px  →  -18px
       bottom:16px  →    0px
       bottom:10px  →   -6px
   → 三个点连起来是完美直线：**bottom 每 +6px，间隙就 +6px**（斜率 1:1）。
   所以要间隙 +6px（和倍速菜单一致），取 bottom = 16 + 6 = **22px**。
   ⚠️ 别再凭感觉猜这个值，它 = 16（基准点）+ 6（想要的间隙），
   斜率是 1:1 所以可以直接加减；换插件版本后要重新量三个点标定。 */
.m-player-box .artplayer-plugin-danmuku .apd-config .apd-config-panel,
.m-player-box .artplayer-plugin-danmuku .apd-style .apd-style-panel {
    bottom: 22px;
}

/* ---------- 弹幕插件的「强调色」全部换成站里的主色调 ----------
   ⚠️⚠️ 站长反馈：「弹幕设置弹窗里面的主色调为啥不是我们设置的那个」
                          「控制条弹幕开关图标里面的色调也不是我们那个」
   根因：artplayer-plugin-danmuku v5.3.0 把 B 站蓝 **硬编码** 在样式表里，
         完全不读任何 CSS 变量 —— 一共有 **12 处** 写死的 #00a1d6：
           · .apd-slider-progress（滑杆已填充部分）background
           · .apd-slider-dot（滑杆圆点）background
           · .apd-send（发送按钮）background
           · .apd-modes .apd-mode:hover（屏蔽类型悬停文字）
           · .apd-config-other .apd-other:hover（防止重叠/同步速度悬停文字）
           · .apd-config-panel 里 3 个滑块（透明度/显示区域/字号…）各一处 ——
             这就是站长看到的「弹窗里的主色调不对」
           · [data-danmuku-mode="0|1|2"] .apd-style-mode [data-mode] 的 color 与
             其内部 path 的 fill（发弹幕的调色板里，当前类型高亮）—— 共 6 处
   所以这里**必须逐条覆盖**，别指望改一个变量就能全变。

   ⚠️ 写法要点：
     1) 选择器前缀用 .m-player-box，权重比插件那条（.artplayer-plugin-* 开头）高一段，
        够压住；只有 .apd-send / .apd-slider-progress 带了 !important（上一版留下的），
        其它都是普通声明。
     2) color 用的是 --m-primary-ink 派生色吗？—— 不是。文字/线条这种「小面积图形」
        直接用主色最还原站长想要的效果，所以统一 var(--m-primary)。
     3) 3 个滑块的规则写在一起，免得以后改主色漏掉某一个。

   改完效果：弹幕面板的滑杆、发送按钮、悬停高亮、调色板当前类型高亮，
   **以及控制条上弹幕开关/齿轮图标**（见下面 [data-danmuku-theme] 那条）全部跟随主色。 */
.m-player-box .artplayer-plugin-danmuku .apd-slider .apd-slider-progress {
    background-color: var(--m-primary) !important;
}
.m-player-box .artplayer-plugin-danmuku .apd-slider .apd-slider-dot {
    background-color: var(--m-primary);
}
/* 三个滑块（透明度 / 显示区域高度 / 字号）都属于 .apd-config-slider，这里一次覆盖 */
.m-player-box .artplayer-plugin-danmuku .apd-config-slider .apd-slider .apd-slider-progress,
.m-player-box .artplayer-plugin-danmuku .apd-config-slider .apd-slider .apd-slider-dot {
    background-color: var(--m-primary) !important;
}
.m-player-box .artplayer-plugin-danmuku .apd-modes .apd-mode:hover,
.m-player-box .artplayer-plugin-danmuku .apd-config-other .apd-other:hover {
    color: var(--m-primary);
}
/* 发弹幕的调色板：当前选中的弹幕类型（滚动/顶部/底部）跟着主色走。
   插件用 [data-danmuku-mode] 这个**属性选择器**做高亮，所以这里要连同
   它内部 svg 的 path fill 一起覆盖（插件给 svg 的是表现属性级别，
   CSS 的 fill 能盖住，但必须写成同权重或更高）。 */
[data-danmuku-mode] .apd-style-mode [data-mode] {
    color: var(--m-primary);
}
[data-danmuku-mode] .apd-style-mode [data-mode] path {
    fill: var(--m-primary);
}
/* ⚠️ 主题色（控制条那一排小图标：弹幕开关、齿轮）
   插件写的是 **fill:#fff**（.apd-icon），也就是纯白、不带任何色调。
   站长要「图标里的色调也是我们的主色」，所以把「已开启」状态
   （data-danmuku-visible=true 时显示的 .apd-toggle-on）涂成主色，
   关闭态 .apd-toggle-off 保持白色作区分。齿轮同理不起眼，保持白。
   注意：.apd-icon 里是 <svg fill=...>，要连 path 一起覆盖，
   且这个选择器必须带上 .m-player-box 才压得住插件那条同权重的规则。 */
.m-player-box .artplayer-plugin-danmuku .apd-toggle-on {
    fill: var(--m-primary) !important;
}
.m-player-box .artplayer-plugin-danmuku .apd-toggle-on path {
    fill: var(--m-primary) !important;
}
/* 悬停时提亮（插件默认只改 opacity，这里保持不冲突，只是补一条更明显的） */
.m-player-box .artplayer-plugin-danmuku .apd-toggle-on:hover {
    filter: brightness(1.15);
}
/* 已锁定（发送按钮不可用）时也不要用插件那个灰底，跟主色协调一点 */
.m-player-box .artplayer-plugin-danmuku .apd-send.apd-lock {
    background-color: rgba(255, 255, 255, .18) !important;
}

/* ---------- 复选框 / 屏蔽类型图标：又一处写死的蓝色 ----------
   ⚠️⚠️ 站长反馈「防止弹幕重叠 前面那个复选框颜色还是没有改」——
      上一轮只改了 CSS 里的 #00a1d6，但这批图标的颜色**不在 CSS 里**，
      而是写死在 svg 标签内部的 **fill 表现属性**上（min.js 的图标字符串）：
        .apd-check-on   → fill="#00AEEC"   ← 另一个色号！(#00AEEC 不是 #00a1d6)
        .apd-check-off  → fill="#FFFFFF"
        .apd-mode-0-off → fill="#00AEEC"（两段 path）
        .apd-mode-1-off → fill="#00AEEC"（两段 path）
        .apd-mode-2-off → fill="#00AEEC"
        .apd-mode-*-on  → fill="#FFFFFF"
     这解释了为什么上一轮漏掉 —— 我按 #00a1d6 搜的，而复选框用的是 #00AEEC。

   ⚠️ 覆盖原理：svg 上的 fill="..." 属于**表现属性**，优先级低于任何 CSS 声明
      （表现属性的权重相当于最低一档的作者样式）。
      所以只要写 CSS fill 就能盖住，**不需要 !important**；但为了保险
      （以及防止以后插件改成内联 style）这里仍然给 !important。

   ⚠️ 注意要同时命中 **svg 本身** 和它内部的 **path**：
      fill 是可继承属性，本可直接继承下来，但插件给部分 path 也单独写了 fill，
      那些 path 上的值是"自己声明的"，会盖过从 svg 继承来的颜色，
      所以 path 必须单独再写一条。 */

/* 「开启/已勾选」态：涂成主色（防止弹幕重叠、同步视频速度这两个开关） */
.m-player-box .artplayer-plugin-danmuku .apd-check-on,
.m-player-box .artplayer-plugin-danmuku .apd-check-on path {
    fill: var(--m-primary) !important;
}
/* 「关闭/未勾选」态：保持白色空心，和开启态形成对比（插件原本就是 #FFFFFF，写明是为了防止被继承污染） */
.m-player-box .artplayer-plugin-danmuku .apd-check-off,
.m-player-box .artplayer-plugin-danmuku .apd-check-off path {
    fill: #fff !important;
}

/* 「按类型屏蔽」那三个大图标同理：
   -off 系列是带斜杠的"已屏蔽"图（原本 #00AEEC 蓝）→ 涂成主色
   -on 系列是"未屏蔽"的实心白图 → 保持白色
   这三组每个都有 1~2 段 path，都要带上，否则会留下蓝色的半截。 */
.m-player-box .artplayer-plugin-danmuku .apd-mode-0-off,
.m-player-box .artplayer-plugin-danmuku .apd-mode-0-off path,
.m-player-box .artplayer-plugin-danmuku .apd-mode-1-off,
.m-player-box .artplayer-plugin-danmuku .apd-mode-1-off path,
.m-player-box .artplayer-plugin-danmuku .apd-mode-2-off,
.m-player-box .artplayer-plugin-danmuku .apd-mode-2-off path {
    fill: var(--m-primary) !important;
}
.m-player-box .artplayer-plugin-danmuku .apd-mode-0-on,
.m-player-box .artplayer-plugin-danmuku .apd-mode-0-on path,
.m-player-box .artplayer-plugin-danmuku .apd-mode-1-on,
.m-player-box .artplayer-plugin-danmuku .apd-mode-1-on path,
.m-player-box .artplayer-plugin-danmuku .apd-mode-2-on,
.m-player-box .artplayer-plugin-danmuku .apd-mode-2-on path {
    fill: #fff !important;
}

/* ---------- 弹幕设置弹窗：文字和图标整体缩小 ----------
   站长要求：「弹窗里面的文字大小再小一点，里面的图标也小一点」。

   ⚠️ 先看插件原本的尺寸（都写死在 min.js 的样式表里）：
     · 根容器 .artplayer-plugin-danmuku  font-size:12px
       → 但注意：**panel 是根容器的子元素，只有能继承 font-size 的元素才会跟着变**，
         滑杆刻度 .apd-slider-step / 数值 .apd-value 这类 div 会继承，
         所以只要在根容器上改字号，这些文字就一起变小了（省事且不易漏）。
     · .apd-modes .apd-mode 图标：svg 自带 width/height="28"（viewBox 0 0 28 28）
     · .apd-config-other .apd-check-on/.apd-check-off：插件只在 .artplayer-plugin-danmuku
       下的 .apd-config-other 里给了 width:16px;height:16px（svg 属性是 32×32，
       被这条 CSS 压到了 16px）
     · .apd-colors .apd-color（发弹幕调色板色块）：16×16
     · .apd-slider（滑杆行）height:20px，.apd-slider-dot 12×12

   ⚠️⚠️ 为什么这里选择器前缀可以用 `.artplayer-plugin-danmuku`，
      而上面 fill 那些却要拼 `.m-player-box`？
      —— 因为 **panel 是运行时动态 append 进 .m-player-box 里的**，
         但它在 DOM 里就是 .artplayer-plugin-danmuku 的后代；
         给 fill 用的那些选择器要压过插件同权重规则，所以带了 .m-player-box
         多一段提高权重；而这里改的 width/height/font-size 都是**插件没写过的属性**
         （除了下面的 check 尺寸），不存在权重争夺，所以从简。
      ⚠️ 但 .apd-check-on/.apd-check-off 的 16px 插件**写过**，必须提高权重压住它，
         所以那两条单独拼上 .m-player-box（权重更高）。 */

/* 1) 字号：根容器 12px → 11px。
      滑杆刻度、数值、面板里所有可继承文字一起变小。 */
.m-player-box .artplayer-plugin-danmuku {
    font-size: 11px;
}
/* 2) 「按类型屏蔽」的三个大图标 28×28 → 20×20。
      这三个 svg 的尺寸来自标签属性（width="28" height="28"），
      但 .artplayer-plugin-danmuku .apd-icon 这条规则只设了 fill，
      没设宽高 —— 说明属性生效中。CSS 宽度是可以覆盖 svg 属性宽度的
      （CSS 属性 > 表现属性），所以直接写 width/height 即可。
      ⚠️ 三个类名都要列上：apd-mode-0/1/2-off 和 -on。 */
.m-player-box .artplayer-plugin-danmuku .apd-modes .apd-mode .apd-icon {
    width: 20px !important;
    height: 20px !important;
}
/* 3) 复选框 16×16 → 13×13。这条插件写过 16px，所以必须 .m-player-box 提权重。 */
.m-player-box .artplayer-plugin-danmuku .apd-config-other .apd-check-on,
.m-player-box .artplayer-plugin-danmuku .apd-config-other .apd-check-off {
    width: 13px !important;
    height: 13px !important;
}
/* 4) 发弹幕调色板的色块 16×16 → 13×13，间距也跟着收紧，免得显得松散。 */
.m-player-box .artplayer-plugin-danmuku .apd-colors {
    gap: 7px;
}
.m-player-box .artplayer-plugin-danmuku .apd-colors .apd-color {
    width: 13px;
    height: 13px;
}
/* 5) 滑杆：行高 20px → 16px，圆点 12px → 10px。
      行高不缩的话，文字变小了但每行还是老高，面板会显空。 */
.m-player-box .artplayer-plugin-danmuku .apd-slider {
    height: 16px;
}
.m-player-box .artplayer-plugin-danmuku .apd-slider .apd-slider-dot {
    width: 10px;
    height: 10px;
    /* 圆点原来是 transform:translate(-6px)（按 12px 半径偏移），
       缩成 10px 后偏移量要改成 -5px，否则圆点会偏左半格。 */
    transform: translate(-5px);
}
/* 6) 滑杆下方的刻度文字也要跟着缩小一点（它继承根字号，这里再降一档更紧凑）。 */
.m-player-box .artplayer-plugin-danmuku .apd-slider .apd-slider-steps {
    font-size: 10px;
    /* 原本 bottom:-12px 是按大字号留的，字号变小后上移 1px 更贴合 */
    bottom: -11px;
}
/* 7) 各小节之间的垂直间距：15px → 11px。
      文字图标都缩小了，间距不变会显得很散，整体高度也降不下来。 */
.m-player-box .artplayer-plugin-danmuku .apd-config-mode,
.m-player-box .artplayer-plugin-danmuku .apd-config-slider,
.m-player-box .artplayer-plugin-danmuku .apd-config-other,
.m-player-box .artplayer-plugin-danmuku .apd-style-mode {
    margin-bottom: 11px;
}
/* 8) 数值列（如"100%"）原来固定 width:32px，字号变小后收窄一点，
      给滑杆留出更多可拖动长度。 */
.m-player-box .artplayer-plugin-danmuku .apd-config-slider .apd-value {
    width: 28px;
}
/* 自动播放被浏览器策略拦下时盖在画面上的「点击播放」按钮（见 plugin/front/player.go）。
   带上声音的自动播放要求"用户跟本站交互过"，所以第一次被拒时给一个明显的播放入口；
   用户在本页第一次点/触摸/按键后 JS 还会自动再试一次，通常不用真去点它。 */
.m-player-cover {
    position: absolute; inset: 0; z-index: 33; width: 100%; cursor: pointer;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
    border: 0; padding: 0; font: inherit; text-align: center; color: #fff;
    background: radial-gradient(60% 60% at 50% 50%, rgba(0, 0, 0, .18), rgba(0, 0, 0, .5));
}
.m-player-cover b {
    width: 62px; height: 62px; border-radius: 50%; padding-left: 5px;
    display: flex; align-items: center; justify-content: center;
    font-size: 22px; line-height: 1; background: var(--m-grad);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .5);
}
.m-player-cover span { font-size: 14.5px; font-weight: 700; letter-spacing: .5px; }
.m-player-cover em { font-style: normal; font-size: 12.5px; color: rgba(255, 255, 255, .8); }
.m-player-cover:hover b { transform: scale(1.06); }
.m-player-cover:focus-visible { outline: 2px solid var(--m-primary); outline-offset: -4px; }
/* VIP / 积分影片还没解锁时替换播放器的那块（地址不会输出到页面里） */
.m-player-lock {
    position: absolute; inset: 0; display: flex; flex-direction: column; gap: 14px;
    align-items: center; justify-content: center; padding: 24px; text-align: center;
    background: linear-gradient(180deg, rgba(20, 20, 26, .96), rgba(8, 8, 12, .96));
}
.m-player-lock strong { font-size: 15.5px; color: var(--m-ink); line-height: 1.7; }
.m-player-lock-acts { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
/* 「即将播放下一集」的倒计时卡片：贴在播放器右下角（和 B 站/YouTube 一个位置） */
.m-player-next {
    position: absolute; right: 14px; bottom: 14px; z-index: 30;
    display: flex; flex-direction: column; gap: 8px; align-items: flex-start;
    padding: 12px 14px; border-radius: var(--m-radius-lg);
    background: rgba(0, 0, 0, .78); color: #fff; box-shadow: 0 8px 24px rgba(0, 0, 0, .45);
}
.m-player-next-txt { font-size: 13px; line-height: 1.5; }
.m-player-next-acts { display: flex; gap: 8px; }
.m-player-next .m-btn { padding: 4px 12px; font-size: 12.5px; }
/* 换集时播放框上盖一层淡提示，避免"点了没反应"的错觉 */
.m-player-box.is-loading::after {
    content: "正在切换…"; position: absolute; inset: 0; z-index: 30;
    display: flex; align-items: center; justify-content: center;
    font-size: 13px; color: #fff; background: rgba(0, 0, 0, .45);
}
/* 「已从上次看到的位置继续播放（12:34）」提示条：盖在画面底部，6 秒后自己消失 */
.m-player-resume { z-index: 31; }

/* 搜索页 */
.m-searchbox { background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); padding: 22px; margin-top: 14px; }
.m-searchbox form { display: flex; max-width: 620px; margin: 0 auto; height: 44px; border: 2px solid var(--m-primary); border-radius: 22px; overflow: hidden; background: var(--m-surface-2); }
.m-searchbox input[type=text] { flex: 1 1 auto; border: 0; padding: 0 20px; background: transparent; color: var(--m-ink); }
.m-searchbox button { border: 0; padding: 0 30px; background: var(--m-grad); color: var(--m-primary-ink); font-weight: 700; font-size: 15px; cursor: pointer; }

/* ================================================================ 页脚(暗色) */
.m-foot { background: #08080a; border-top: 1px solid var(--m-line); margin-top: 44px; padding: 30px 0 26px; font-size: 13px; color: var(--m-sub); }
.m-foot-nav { display: flex; flex-wrap: wrap; gap: 8px 16px; padding-bottom: 16px; border-bottom: 1px solid var(--m-line); margin-bottom: 16px; }
.m-foot-nav a { color: var(--m-sub); }
.m-foot-nav a:hover { color: var(--m-primary); }
.m-foot-copy { line-height: 2; color: var(--m-muted); }
.m-foot-copy a { color: var(--m-muted); }

.m-gotop { position: fixed; right: 26px; bottom: 40px; width: 42px; height: 42px; border-radius: 50%; background: var(--m-surface-2); border: 1px solid var(--m-line-2); box-shadow: var(--m-shadow-h); color: var(--m-primary); font-size: 17px; font-weight: 700; display: none; align-items: center; justify-content: center; z-index: 80; cursor: pointer; }
.m-gotop:hover { background: var(--m-primary); color: var(--m-primary-ink); border-color: var(--m-primary); }

/* 空数据兜底 */
.m-hero-empty { position: absolute; top: 0; left: 0; right: 0; bottom: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--m-muted); text-align: center; z-index: 0; }
.m-hero-empty .lg { font-size: 38px; font-weight: 800; letter-spacing: 5px; color: var(--m-sub); margin-bottom: 8px; }
.m-hero-bg:has(.m-hero-slide) .m-hero-empty { display: none; }
.m-sec:has(.m-track:empty) { display: none; }
.m-links { display: flex; flex-wrap: wrap; gap: 8px 18px; background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); padding: 16px; color: var(--m-sub); }
.m-links:empty { display: none; }
.m-sec:has(.m-links:empty) { display: none; }

/* 列表页网格 */
/* 网格列必须写 minmax(0, 1fr) 而不是 1fr：
   1fr 等价于 minmax(auto, 1fr)，而 auto 的下限是"最小内容宽度"。
   卡片标题是 nowrap 的，长片名（比如「拯救替身千金的是冷酷无情冰之王子的爱」）
   会把那一列撑宽 → 该列卡片比别的宽 → 16:9 的图片框也就比别的高一截。
   用 minmax(0, 1fr) 让列可以压缩到 0，标题再自己省略号截断。 */
/* 卡片网格：列数由**容器宽度**自动决定（auto-fill + minmax），拖窗口时列数和卡片尺寸
   一起变、永远填满整行。以前是写死的 5/4/3/2 档，实测 1200 宽时 5 列每张只有 131px、
   缩到 1024 反而变成 4 列 238px —— 中间那一段既挤又跳。 */
.m-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 24px 14px; }
.m-grid.col4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* 双列小横条面板 */
/* 小横条多列面板（首页「最近更新」、/map「最近更新」页共用）：列数按屏幕分三档 ——
   电脑 ≥1025 三列、平板 769~1024 两列、手机 ≤768 一行横滑（下面两段媒体查询）。
   以前这个类叫 .m-panel-2col（只有两列），现在通用化了。 */
.m-panel-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 30px; background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); padding: 6px 18px; }
/* 即将上映里"我们还没有片源"的那些条目：不是链接，鼠标不要变成手型，
   整块稍微暗一点，暗示"只是预告信息" */
.m-mini-soon { cursor: default; }
.m-mini-soon:hover h4 { color: var(--m-ink); }
.m-mini-soon .m-mini-tag { background: var(--m-primary-16, rgba(255,95,0,.16)); color: var(--m-primary); }

/* 缺图兜底 */
.m-card-ph { position: absolute; top: 0; left: 0; right: 0; bottom: 0; display: flex; align-items: center; justify-content: center; padding: 10px; text-align: center; background: linear-gradient(135deg, #2b2b33 0%, #1c1c21 60%, #33241a 100%); }
.m-card-ph em { font-size: 13px; line-height: 1.5; color: rgba(255,255,255,.8); font-weight: 600; max-height: 100%; overflow: hidden; }
.m-card-ph.sm { position: absolute; top: 0; left: 0; right: 0; bottom: 0; padding: 4px; }
.m-card-ph.sm em { font-size: 11px; font-weight: 500; }

/* ================================================================ 暗色兜底:沿用官方默认结构的页面(用户中心/文章/专题/留言等) */
.mac_msg_jump, .ui-box, .box_con, .user-box, .member-box, .mac_pages, .mac_comment,
.mac_login, .mac_reg, .mac_user_box, .ui-bar {
    background-color: var(--m-surface) !important;
    border-color: var(--m-line) !important;
    color: var(--m-text) !important;
}
.ui-title h2, .ui-title h3, .mac_msg_jump .title, .mac_msg_jump .msg_jump_tit, .mac_pages .page_tip {
    color: var(--m-ink) !important;
}
.mac_msg_jump .text, .mac_pages .page_info { color: var(--m-text) !important; }
.mac_pages a { background: var(--m-surface-2) !important; border-color: var(--m-line) !important; color: var(--m-text) !important; }
.mac_pages a.page_current { background: var(--m-grad) !important; color: var(--m-primary-ink) !important; border-color: transparent !important; }
table, table td, table th { border-color: var(--m-line) !important; color: var(--m-text); }
table th { background-color: var(--m-surface-2) !important; color: var(--m-sub) !important; }
input[type=text], input[type=password], input[type=email], input[type=number], select, textarea {
    background-color: var(--m-surface-2) !important; border-color: var(--m-line) !important; color: var(--m-ink) !important;
}
input::placeholder, textarea::placeholder { color: var(--m-muted) !important; }
hr { border-color: var(--m-line) !important; }

/* ================================================================ 响应式 */
/* 超宽屏（≥1800）：一行多塞几张，卡片尺寸保持在 200~260px。
   正文上限放到 2200 之后，如果还固定 6 张一行，1920 上每张变 275px、2560 上 330px，
   看着就像"一行 6 张大海报"，所以按窗口宽度加档。
   （阈值对着正文宽度算：正文 ≈ 窗口 - 175，见上面 .m-wrap 的 padding-left 公式）
   ⚠️ 顺序必须**从小到大**：min-width 查询是"后面的赢"，如果 2500 写在 1800 前面，
   2560 的屏会命中后面那条 1800 的规则，变成一行 7 张（踩过）。 */
@media (min-width: 1800px) {
    .m-track > *, .m-track.col5 > *, .m-track.col4 > * { flex-basis: calc((100% - var(--m-card-gap) * 6) / 7); }
}
@media (min-width: 2100px) {
    .m-track > *, .m-track.col5 > *, .m-track.col4 > * { flex-basis: calc((100% - var(--m-card-gap) * 7) / 8); }
}
@media (min-width: 2500px) {
    .m-track > *, .m-track.col5 > *, .m-track.col4 > * { flex-basis: calc((100% - var(--m-card-gap) * 8) / 9); }
}
@media (max-width: 1500px) {
    .m-track > * { flex-basis: calc((100% - var(--m-card-gap) * 4) / 5); }
}
@media (max-width: 1240px) {
    .m-track > * { flex-basis: calc((100% - var(--m-card-gap) * 3) / 4); }
    .m-hero-rank { width: 260px; }
    /* 窄屏放不下"搜索框+热搜词"一整排，搜索框收窄，热搜词只留一行可滚动 */
    .m-search form { width: 240px; }
    .m-hotline { -webkit-mask-image: linear-gradient(90deg, #000 82%, transparent); mask-image: linear-gradient(90deg, #000 82%, transparent); }
    /* 窄屏只留图标，去掉"消息/历史/下载客户端"的文字 */
    .m-hd-ic .m-hd-txt { display: none; }
}
@media (max-width: 1024px) {
    .m-nav { display: none; }
    /* 手机/平板:搜索框占满中间，热搜词藏起来(底部导航已经有分类入口了) */
    .m-hd-left, .m-hd-right { flex: 0 0 auto; }
    /* 手机/平板：logo 换成「手机端 logo」那张 */
    .m-logo-pc, .m-logo-mb-solo { display: none; }
    .m-logo-mb { display: flex; }
    .m-hd-center { flex: 1 1 auto; }
    .m-hotline { display: none; }
    /* 手机上只留 VIP 按钮 + 头像，图标太挤 */
    .m-hd-msg, .m-hd-hist, .m-hd-app { display: none; }
    .m-search { flex: 1 1 auto; min-width: 0; }
    /* 手机/平板（≤1024）：搜索框**照常显示**，宽度跟着空间伸缩（见下面的 width:100%）；
       真正收成圆形图标是在 ≤560 那个断点（页头实在挤不下时才收） */
    .m-search form { width: 100%; min-width: 96px; }
    /* 手机/平板：左侧分类不再是"底部横条"，改成**右上角汉堡按钮 + 右侧抽屉**。
       抽屉复用的还是同一个 .m-side-nav（.is-open 时滑进来），所以分类链接只写一份。 */
    .m-menu-btn { display: inline-flex; }
    .m-side-nav {
        top: 0; left: auto; right: 0; bottom: 0;
        width: min(280px, 78vw); height: 100%;
        transform: translateX(102%);
        flex-direction: column; gap: 6px; padding: 16px 14px 26px;
        border-radius: 0; border: 0; border-left: 1px solid var(--m-line);
        max-height: none; overflow-y: auto; overflow-x: hidden;
        background: rgba(14, 14, 18, .98); backdrop-filter: blur(14px);
        box-shadow: -14px 0 34px rgba(0, 0, 0, .5);
        z-index: 120; transition: transform .26s ease;
    }
    .m-side-nav.is-open { transform: translateX(0); }
    /* 手机端抽屉：字号/图标跟桌面那排保持同一档（15px / 21px），别一边大一边小 */
    .m-side-nav a { padding: 12px 12px; gap: 11px; background: transparent; border-radius: 10px; font-size: 15px; }
    .m-side-nav a svg { width: 21px; height: 21px; }
    .m-side-nav a:hover, .m-side-nav a.on { background: rgba(255, 255, 255, .10); color: #fff; }
    .m-side-nav a.on::after { width: 13px; height: 13px; margin-top: -6.5px; right: 12px; }
    /* 抽屉打开时把页面锁住，并压一层遮罩 */
    body.nav-open { overflow: hidden; }
    .m-nav-mask {
        position: fixed; inset: 0; z-index: 119; background: rgba(0, 0, 0, .58);
        opacity: 0; visibility: hidden; transition: opacity .26s ease;
    }
    .m-nav-mask.is-open { opacity: 1; visibility: visible; }
    /* 轮播高度这里不再写死（用上面 base 里的 clamp，跟着视口宽度连续变化） */
    .m-hero-rank { display: none; }
    /* 这一档一行 3 张是给 16:9 横图行算的（电视剧/综艺/动漫…保持原样）；
       竖版海报那两条（电影/短剧）的列数在卡片那一段单独定义（桌面 8 张往下递减）。 */
    .m-track > *, .m-track.col5 > * { flex-basis: calc((100% - var(--m-card-gap) * 2) / 3); }
    /* 侧栏换行后的排版（占满整行 + 内部网格：榜单并排、最近更新横向铺开）
       统一由上面 (min-width: 641px) and (max-width: 1128px) 那段负责，这里不再重复写 .m-side。
       正文也不用写 width:100% —— 换行后它独占一行，flex-grow 自然撑满。 */
    .m-detail-cols { flex-direction: column; }
    .m-detail-pic { flex-basis: auto; width: 200px; }
    /* 排行榜：三个榜单在这里从"三列并排"变成"竖着堆"，会拉得很长，
       所以这一档开始用选择夹切换（只显示选中的那个，JS 切 hidden）。 */
    .m-rank-cols { grid-template-columns: 1fr; }
    .m-ranktabs { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 2px 0 12px; }
    .m-rank-cols .m-rank[hidden] { display: none; }
    .m-vip-banner { flex-wrap: wrap; }
    /* 最近更新：平板这一段保持两列（小横条只有 ~70px 高，两列正好；
       压成一列会变成 800+px 的长条）。手机（≤768）再改成一行横滑，见下面那段。 */
    .m-panel-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* 列数交给上面的 auto-fill，这里不再写死 */
}
/* 窄屏（≤768）轮播里放不下那排缩略图了：标题 + 简介 + 按钮本身要 ~210px，
   768px 以下轮播总共才 ~330px 高，再塞 88px 的缩略图必然和按钮重叠 —— 整排隐藏，
   底部留白改成只给「小圆点指示器」让位（圆点占底部 12+22px，留 42px 就是 8px 间隙）。
   不缩小到 20px 那种值，否则圆点会压到「立即观看」按钮上（实测 390px 宽时压 5px）。 */
@media (max-width: 768px) {
    .m-hero-thumbs { display: none; }
    .m-hero-info { padding-bottom: clamp(42px, 6vw, 64px); }

    /* 小横条面板（首页「最近更新」、/map「最近更新」页共用）：手机上竖着排要 700 多 px，
       改成**一行横滑** —— 一条占 78% 宽，露出下一条的一角暗示可以滑，
       手势和首页那些卡片行完全一样（手指左右拖动，见 .m-track 那段注释）。
       容器本身那层"卡片壳"去掉，改成每条自己带边框，滑动时不会有被裁一半的外框。 */
    .m-panel-cols {
        display: flex; flex-wrap: nowrap; gap: 10px;
        overflow-x: auto; -webkit-overflow-scrolling: touch;
        scrollbar-width: none; -ms-overflow-style: none;
        background: none; border: 0; border-radius: 0; padding: 2px 0 8px;
    }
    .m-panel-cols::-webkit-scrollbar { display: none; }
    .m-panel-cols .m-mini {
        flex: 0 0 78%; min-width: 0;
        padding: 10px 12px; border: 1px solid var(--m-line);
        border-radius: var(--m-radius-lg); background: var(--m-surface);
    }
    /* is-long = 「上百条」的列表（/map 最近更新）：横滑会变成几万 px 长的一条，
       这种页面手机档保持网格（两列，超窄屏一列），把"卡片壳"加回来。 */
    .m-panel-cols.is-long {
        display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0 14px; overflow: visible;
        background: var(--m-surface); border: 1px solid var(--m-line);
        border-radius: var(--m-radius-lg); padding: 4px 12px;
    }
    .m-panel-cols.is-long .m-mini { flex-basis: auto; padding: 9px 0; border: 0; border-bottom: 1px solid var(--m-line); border-radius: 0; background: none; }
    .m-panel-cols.is-long .m-mini-pic { flex-basis: 84px; height: 52px; }
}

@media (max-width: 400px) {
    .m-panel-cols.is-long { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
    .m-header-inner { height: 54px; gap: 10px; }
    .m-hd-left { gap: 12px; }
    /* 手机上 logo 别太大，把中间搜索框挤没了
       （写成 .m-logo img.xxx 是为了盖过上面 .m-logo img{height:34px} 的特异性） */
    .m-logo img.m-logo-mb, .m-logo img.m-logo-mb-solo { height: 28px; }
    /* 窄屏只留图标，去掉「消息 / 历史 / 下载客户端」这些文字。
       ⚠️ 必须写成 .m-hd-txt（图标那个 span 的类），不能写 `.m-hd-actions span` ——
       页头三个悬浮框（.m-hd-pop）里全是 span，那样会把框里的文字一起藏掉。 */
    .m-nav, .m-hd-actions .m-hd-txt { display: none; }
    /* 手机（≤640）：**侧栏整块不显示**（各页的 热播榜 / 好评榜 / 最近更新）。
       窄到手机宽度时，正文后面再跟 10 条榜单 + 6 条最近更新，要往下滚很久才到底，
       而这些属于"顺手看看"的内容 —— 用户要求这一档直接隐藏。
       （平板 ≥641 仍然显示在列表下方；桌面显示在右侧，见 .m-listwrap 那段注释。） */
    .m-side { display: none; }
    /* 手机页头更矮（54px），弹出的搜索框跟着往上提一点 */
    .m-search.is-open form { top: 60px; }
    /* 手机上轮播高度交给 base 里的 clamp（跟着宽度连续变，不再固定 380px） */
    .m-hero-title { font-size: 22px; }
    .m-hero-desc { display: none; }
    .m-hero-thumbs { display: none; }
    /* 手机上宽度本来就紧，左外边距收掉（下内边距同样交给 clamp） */
    .m-hero-info { margin-left: 0; }
    .m-track > *, .m-track.col5 > *, .m-track.col4 > * { flex-basis: calc((100% - var(--m-card-gap) * 2) / 3); }
    .m-sec-hd h2 { font-size: 18px; }
    .m-sec-cats { display: none; }
    .m-detail { padding: 16px; }
    .m-vip-points { display: none; }
    /* 手机上卡片最小宽度收一点，保证一行仍有 2 列（360 宽时 328 / 140 = 2.3 列 → 2 列） */
    .m-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
}

/* 页头**实在放不下**搜索框时才把它收成一个圆形图标（560px 上下：文案 logo + 搜索框 +
   VIP 按钮 + 头像 + 汉堡 已经挤到互相压了），点了才在页头下面弹出搜索框。
   1025~561px 之间搜索框照常显示，只是宽度跟着空间伸缩 —— 不提前收。 */
@media (max-width: 560px) {
    .m-search { flex: 0 0 auto; }
    .m-search-toggle { display: inline-flex; }
    .m-search form { display: none; }
    .m-search.is-open form {
        display: flex;
        position: fixed; left: 12px; right: 12px; top: 60px;
        width: auto; height: 44px; padding: 0 6px 0 16px;
        border-radius: 22px;
        background: var(--m-surface-2); border-color: var(--m-line);
        box-shadow: 0 14px 34px rgba(0, 0, 0, .55);
        z-index: 130;
    }
    .m-search.is-open form:focus-within { border-color: var(--m-primary); }

    /* 搜索层（弹出的搜索框 + 搜索历史/热搜面板）背后的**透明遮罩**。
       作用不是变暗，而是"接住"手指：点它只关掉搜索，不会穿透点到下面的卡片。
       层级：页头 90 < 遮罩 125 < 搜索框 130 < 面板 140。 */
    .m-search-mask {
        display: none; position: fixed; inset: 0; z-index: 125; background: transparent;
    }
    .m-search-mask.is-open { display: block; }
}

/* 更窄的手机（≤480）：VIP 按钮和文字 logo 都收一点，给"头像 + 汉堡"让位，
   不然后者会把页头撑出屏幕（实测 360 宽时右边会溢出 10px）。 */
@media (max-width: 480px) {
    .m-vip-btn { height: 28px; padding: 0 10px; font-size: 12px; }
    .m-logo-txt { font-size: 19px; }
    .m-logo-txt small { font-size: 8px; letter-spacing: 2.5px; }
}
/* 小屏手机（≤400）：再把间距/文案收紧一档，避免"头像+汉堡"和搜索图标压在一起 */
@media (max-width: 400px) {
    .m-header-inner { gap: 6px; }
    .m-hd-actions { gap: 8px; }
    .m-vip-btn { padding: 0 8px; }
    .m-logo-txt { font-size: 17px; }
}

/* ================================================================
   排行榜页 (/rank ← 模板 label/rank.html)
   版式是榜单该有的样子：「名次 + 竖版小海报 + 片名/信息 + 右侧数值」两列排开，
   但圆角、色调、间距、阴影全部复用站内已有的 token 和数值，所以
   跟首页、列表页是同一套观感：
     圆角  → var(--m-radius-lg)（和 .m-rank / .m-block / .m-searchbox 面板一致）
     色调  → var(--m-surface)/--m-line/--m-ink/--m-muted/--m-primary
     间距  → var(--m-card-gap)（和首页卡片轨道同一个间距）
     阴影  → 静止不投影（和站内所有面板一致），悬停时用 var(--m-shadow) 抬起来
   ================================================================ */
.m-rankbar { display: flex; flex-wrap: wrap; gap: 10px; margin: 6px 0 2px; }
.m-rankbar a {
    display: inline-flex; align-items: center; height: 34px; padding: 0 18px;
    border-radius: 17px; background: var(--m-surface-2); border: 1px solid var(--m-line);
    color: var(--m-text); font-size: 14px;
    transition: background .18s, color .18s, border-color .18s, box-shadow .18s;
}
.m-rankbar a:hover { color: var(--m-primary); border-color: var(--m-primary); }
.m-rankbar a.on {
    background: var(--m-grad); border-color: transparent; color: var(--m-primary-ink); font-weight: 700;
    /* 和「立即观看」主按钮用同一道橙色投影 */
    box-shadow: 0 6px 18px var(--m-primary-32, rgba(255,95,0,.32));
}

/* 榜单行 */
/* 榜单行：电脑 3 列 / 平板 2 列 / 手机 1 列（用户要求）。
   一行三列时每条 400px 左右，片名 + 一句话简介 + 风格类型（都单行省略）刚好放得下。 */
.m-ranklist { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--m-card-gap) 14px; }
.m-rankitem {
    display: flex; align-items: center; gap: 12px;
    padding: 9px 14px 9px 10px;
    background: var(--m-surface); border: 1px solid var(--m-line);
    border-radius: var(--m-radius-lg);
    transition: background .18s, border-color .18s, box-shadow .18s;
}
.m-rankitem:hover { background: var(--m-surface-2); border-color: var(--m-primary); box-shadow: var(--m-shadow); }
.m-rankitem .no { flex: 0 0 26px; text-align: center; font-style: normal; font-size: 16px; font-weight: 800; color: var(--m-muted); }
.m-rankitem .no.top1 { color: #ffcf7a; }
.m-rankitem .no.top2 { color: #cfd3da; }
.m-rankitem .no.top3 { color: #e0965a; }
.m-rankitem .pic { flex: 0 0 44px; height: 60px; border-radius: var(--m-radius); overflow: hidden; background: var(--m-pic-bg); }
.m-rankitem .pic img { display: block; width: 100%; height: 100%; object-fit: cover; }
.m-rankitem .body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.m-rankitem .nm { font-size: 14px; font-weight: 600; color: var(--m-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-rankitem:hover .nm { color: var(--m-primary); }
.m-rankitem .mt { font-size: 12px; color: var(--m-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-rankitem .rm { font-size: 12px; color: var(--m-sub); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-rankitem .sc { flex: 0 0 auto; font-size: 15px; font-weight: 800; color: var(--m-primary); }

.m-rank-page .m-sec { padding-top: 26px; }
.m-rank-page .m-sec:first-of-type { padding-top: 14px; }

@media (max-width: 1024px) {
    /* 平板：两列。
       ⚠️ 必须写 minmax(0, 1fr)：光写 1fr 的话轨道最小值是 auto（= 内容的 min-content），
       而榜单行的片名是 nowrap，整行会把轨道撑得比屏幕还宽（实测 360px 时溢出 21px）。 */
    .m-ranklist { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
    /* 手机：一列 */
    .m-ranklist { grid-template-columns: minmax(0, 1fr); }
    .m-rankitem { padding: 8px 12px 8px 8px; gap: 10px; }
    .m-rankitem .pic { flex-basis: 38px; height: 52px; }
    .m-rankitem .no { flex-basis: 22px; font-size: 14px; }
}

/* ================================================================ 登录弹窗 */
/* 游客点页头「登录」/点会员专属地址时弹在屏幕中间，不再跳 /login 页面。
   结构见 html/public/head.html 末尾，逻辑见 js/kuaibo.js 的 initLoginModal。
   默认 display:none（配合模板上的 hidden，禁 JS 时不会露出来），JS 加 .is-open 才显示。 */
.m-login {
    position: fixed; inset: 0; z-index: 200;
    display: none; align-items: center; justify-content: center;
    padding: 20px; overflow-y: auto;
}
.m-login.is-open { display: flex; }
.m-login-mask { position: absolute; inset: 0; background: rgba(0, 0, 0, .72); backdrop-filter: blur(3px); }
.m-login-card {
    position: relative; z-index: 1; width: 100%; max-width: 380px;
    padding: 26px 24px 20px;
    background: var(--m-surface); border: 1px solid var(--m-line-2);
    border-radius: var(--m-radius-lg); box-shadow: var(--m-shadow-h);
    animation: m-login-pop .18s ease-out;
}
@keyframes m-login-pop {
    from { opacity: 0; transform: translateY(14px) scale(.98); }
    to { opacity: 1; transform: none; }
}
.m-login-x {
    position: absolute; top: 8px; right: 10px; width: 32px; height: 32px;
    display: flex; align-items: center; justify-content: center;
    border: 0; border-radius: 50%; background: transparent;
    color: var(--m-sub); font-size: 22px; line-height: 1; cursor: pointer;
}
.m-login-x:hover { color: #fff; background: rgba(255, 255, 255, .1); }
/* 登录 / 注册 两个面板的切换标签 */
.m-login-tabs {
    display: flex; gap: 4px; width: max-content; margin: 0 auto 16px; padding: 4px;
    background: var(--m-surface-2); border: 1px solid var(--m-line); border-radius: 999px;
}
.m-login-tab {
    padding: 6px 22px; border: 0; border-radius: 999px; background: transparent;
    color: var(--m-sub); font-size: 14px; font-weight: 700; cursor: pointer;
}
.m-login-tab:hover { color: var(--m-ink); }
.m-login-tab.is-on { background: var(--m-grad); color: var(--m-primary-ink); box-shadow: 0 4px 14px var(--m-primary-32, rgba(255,95,0,.30)); }
.m-login-form[hidden] { display: none; }
.m-login-title { font-size: 20px; font-weight: 800; text-align: center; }
.m-login-sub { margin-top: 6px; font-size: 12.5px; color: var(--m-muted); text-align: center; }
.m-login-form { margin-top: 18px; display: flex; flex-direction: column; gap: 12px; }
.m-login-field { display: block; }
.m-login-field > span { display: block; margin-bottom: 6px; font-size: 12.5px; color: var(--m-sub); }
.m-login-field input {
    width: 100%; height: 42px; padding: 0 14px;
    background: var(--m-surface-2); border: 1px solid var(--m-line);
    border-radius: 21px; color: var(--m-ink); font-size: 14px;
    transition: border-color .15s, background .15s;
}
.m-login-field input::placeholder { color: var(--m-muted); }
.m-login-field input:focus { border-color: var(--m-primary); background: var(--m-surface-3); }
/* 验证码：左边输入框，右边那张现画的 PNG（点一下换一张） */
.m-login-cap { display: flex; gap: 10px; align-items: center; }
.m-login-cap input { flex: 1 1 auto; min-width: 0; letter-spacing: 2px; text-transform: uppercase; }
.m-login-cap img {
    flex: 0 0 auto; width: 104px; height: 42px; border-radius: 10px;
    background: var(--m-surface-3); border: 1px solid var(--m-line); cursor: pointer;
}
.m-login-cap img:hover { border-color: var(--m-primary); }
.m-login-err { font-size: 12.5px; line-height: 1.5; color: #ff6b6b; }
.m-login-err[hidden] { display: none; }
.m-login-submit { width: 100%; margin-top: 2px; }
.m-login-submit[disabled] { opacity: .68; cursor: default; }
.m-login-foot { margin-top: 14px; font-size: 12.5px; color: var(--m-muted); text-align: center; }
.m-login-foot a { color: var(--m-primary); font-weight: 700; }
/* 弹窗开着时锁住页面滚动（不然手机上背景会跟着手指滑） */
body.login-open { overflow: hidden; }
@media (max-width: 480px) {
    .m-login { padding: 14px; }
    .m-login-card { padding: 22px 18px 16px; }
    .m-login-title { font-size: 18px; }
}

/* ================================================================ 会员中心 */
/* 和首页同一套主题：页头/页脚复用 public/head、public/foot，这里只管中间那块。
   结构见 html/user/uc_*.html，数据见 plugin/front/usercenter.go。 */
.m-uc-page { padding-bottom: 30px; }
.m-uc {
    display: grid; grid-template-columns: 268px minmax(0, 1fr);
    gap: 20px; align-items: start; padding-top: 22px;
}

/* ---- 左侧：会员卡 + 菜单 ---- */
.m-uc-side { position: sticky; top: 78px; display: flex; flex-direction: column; gap: 14px; }
.m-uc-card {
    background: var(--m-surface); border: 1px solid var(--m-line);
    border-radius: var(--m-radius-lg); padding: 20px 18px 16px; text-align: center;
}
.m-uc-face { width: 68px; height: 68px; margin: 0 auto 10px; border-radius: 50%; object-fit: cover; background: var(--m-surface-3); border: 2px solid rgba(255, 255, 255, .16); }
.m-uc-name { display: block; font-size: 15px; color: var(--m-ink); }
.m-uc-group { display: inline-flex; align-items: center; gap: 5px; margin-top: 4px; font-size: 12px; color: var(--m-sub); }
.m-uc-vip { display: inline-block; padding: 1px 6px; border-radius: 4px; background: var(--m-grad-gold); color: #3a2400; font-size: 11px; font-weight: 800; }
.m-uc-vip-time { margin-top: 6px; font-size: 12px; color: var(--m-muted); }
.m-uc-stat { display: flex; margin-top: 14px; border-top: 1px solid var(--m-line); padding-top: 12px; }
.m-uc-stat > div { flex: 1 1 0; }
.m-uc-stat em { display: block; font-size: 17px; font-weight: 800; color: var(--m-primary); font-style: normal; }
.m-uc-stat span { font-size: 12px; color: var(--m-muted); }
.m-uc-vipbtn { margin-top: 14px; width: 100%; height: 36px; font-size: 14px; }
.m-uc-menu { display: flex; flex-direction: column; background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); padding: 8px; }
.m-uc-menu a { padding: 10px 14px; border-radius: 8px; font-size: 14px; color: var(--m-text); }
.m-uc-menu a:hover { background: var(--m-surface-2); color: var(--m-primary); }
.m-uc-menu a.on { background: var(--m-grad); color: var(--m-primary-ink); font-weight: 700; }
/* 管理组账号：会员中心侧栏的「网站后台」入口 */
.m-uc-menu a.m-uc-admin { color: var(--m-primary); font-weight: 700; }
.m-uc-menu a.m-uc-admin::after { content: "↗"; margin-left: 6px; font-size: 12px; }
.m-uc-menu .m-uc-out { margin-top: 6px; border-top: 1px solid var(--m-line); border-radius: 0 0 8px 8px; color: var(--m-muted); }

/* ---- 右侧：内容区 ---- */
.m-uc-main { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.m-uc-flash {
    padding: 12px 16px; border-radius: 10px; font-size: 14px;
    background: var(--m-primary-12, rgba(255,95,0,.12)); border: 1px solid var(--m-primary-45, rgba(255,95,0,.45)); color: #ffd9c2;
}
.m-uc-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.m-uc-statcard {
    background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg);
    padding: 16px; transition: border-color .18s, transform .18s;
}
.m-uc-statcard:hover { border-color: var(--m-primary); transform: translateY(-2px); }
.m-uc-statcard em { display: block; font-size: 22px; font-weight: 800; color: var(--m-ink); font-style: normal; }
.m-uc-statcard span { font-size: 12.5px; color: var(--m-muted); }
.m-uc-panel { background: var(--m-surface); border: 1px solid var(--m-line); border-radius: var(--m-radius-lg); padding: 18px; }
.m-uc-hd { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.m-uc-hd h3 { font-size: 16px; font-weight: 800; }
.m-uc-hd-sub { margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--m-line); }
.m-uc-hd-sub em, .m-uc-more, .m-uc-count { font-size: 12.5px; color: var(--m-muted); font-style: normal; }
.m-uc-more { margin-left: auto; }
.m-uc-more:hover, .m-uc-tip a { color: var(--m-primary); }
.m-uc-count { margin-left: auto; }
.m-uc-tip { font-size: 12.5px; color: var(--m-muted); line-height: 1.7; }

/* 影片小卡（观看记录 / 片单 / 已购） */
.m-uc-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 14px; }
.m-uc-item { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.m-uc-item-pic { position: relative; display: block; aspect-ratio: 3 / 4.2; border-radius: 8px; overflow: hidden; background: var(--m-pic-bg); }
.m-uc-item-pic img { width: 100%; height: 100%; object-fit: cover; }
.m-uc-play {
    position: absolute; left: 0; right: 0; bottom: 0; padding: 5px 8px; font-style: normal;
    font-size: 12px; color: #fff; background: linear-gradient(0deg, rgba(0,0,0,.78), rgba(0,0,0,0));
    opacity: 0; transition: opacity .18s;
}
.m-uc-item:hover .m-uc-play { opacity: 1; }
.m-uc-item b { font-size: 13.5px; font-weight: 600; color: var(--m-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-uc-item b a:hover { color: var(--m-primary); }
.m-uc-item em, .m-uc-time { font-size: 12px; color: var(--m-muted); font-style: normal; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-uc-item-acts { display: flex; gap: 6px; margin-top: 2px; }
.m-uc-empty { padding: 26px 10px; text-align: center; font-size: 13.5px; color: var(--m-muted); }
.m-uc-empty a { color: var(--m-primary); }

/* 表格（消费记录 / 会员组） */
.m-uc-table { display: flex; flex-direction: column; }
.m-uc-tr { display: grid; grid-template-columns: 150px 110px minmax(0, 1fr) 90px; gap: 10px; padding: 10px 6px; font-size: 13.5px; color: var(--m-text); border-bottom: 1px solid var(--m-line); }
.m-uc-tr:last-child { border-bottom: 0; }
.m-uc-tr span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-uc-th { color: var(--m-muted); font-size: 12.5px; }
.m-uc-table-group .m-uc-tr { grid-template-columns: 160px minmax(0, 1fr) 80px; }

/* 表单（资料修改 / 卡密充值） */
.m-uc-form { display: flex; flex-direction: column; gap: 14px; max-width: 560px; }
.m-uc-field { display: block; }
.m-uc-field > span { display: block; margin-bottom: 6px; font-size: 12.5px; color: var(--m-sub); }
.m-uc-field input[type=text], .m-uc-field input[type=password] {
    width: 100%; height: 40px; padding: 0 14px; border-radius: 20px;
    background: var(--m-surface-2); border: 1px solid var(--m-line); color: var(--m-ink); font-size: 14px;
}
.m-uc-field input::placeholder { color: var(--m-muted); }
.m-uc-field input:focus { border-color: var(--m-primary); background: var(--m-surface-3); }
.m-uc-field input:disabled { color: var(--m-muted); background: var(--m-surface); }
.m-uc-field em { display: block; margin-top: 4px; font-size: 12px; color: var(--m-muted); font-style: normal; }
.m-uc-radio { display: flex; gap: 18px; font-size: 13.5px; color: var(--m-text); }
.m-uc-radio label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.m-uc-acts { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }

/* 头像上传 */
.m-uc-face-row { display: flex; gap: 20px; align-items: center; flex-wrap: wrap; }
.m-uc-face-lg { width: 96px; height: 96px; border-radius: 50%; object-fit: cover; background: var(--m-surface-3); border: 2px solid var(--m-line-2); }
.m-uc-face-form { display: flex; flex-direction: column; gap: 10px; }
.m-uc-face-form input[type=file] { font-size: 13px; color: var(--m-sub); }

/* 卡密充值 */
.m-uc-redeem { display: grid; grid-template-columns: minmax(0, 380px) minmax(0, 1fr); gap: 24px; }
.m-uc-note { font-size: 13px; color: var(--m-sub); line-height: 1.8; }
.m-uc-note b { display: block; margin-bottom: 6px; color: var(--m-ink); }
.m-uc-note em { font-style: normal; color: var(--m-primary); }
.m-uc-note a { color: var(--m-primary); }

/* 开通会员 */
.m-uc-vipbox { display: flex; gap: 20px; align-items: center; justify-content: space-between; flex-wrap: wrap; }
.m-uc-vipbox-l b { font-size: 17px; color: var(--m-ink); }
.m-uc-vipbox-l p { margin-top: 6px; font-size: 13px; color: var(--m-sub); }
.m-uc-vipbox-r { display: flex; flex-direction: column; gap: 8px; align-items: flex-end; }
.m-uc-benefits { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.m-uc-benefits > div { padding: 14px; border-radius: 10px; background: var(--m-surface-2); border: 1px solid var(--m-line); }
.m-uc-benefits b { display: block; font-size: 14px; color: var(--m-ink); margin-bottom: 4px; }
.m-uc-benefits span { font-size: 12.5px; color: var(--m-muted); }
.m-uc-steps { display: flex; flex-direction: column; gap: 12px; }
.m-uc-steps > div { display: flex; gap: 12px; align-items: center; }
.m-uc-steps em {
    flex: 0 0 auto; width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    background: var(--m-grad); color: var(--m-primary-ink); font-size: 12px; font-weight: 800; font-style: normal;
}
.m-uc-steps p { font-size: 13.5px; color: var(--m-text); }

/* 窄屏：侧栏变成上方横排/换行 */
@media (max-width: 1024px) {
    .m-uc { grid-template-columns: minmax(0, 1fr); }
    .m-uc-side { position: static; }
    .m-uc-menu { flex-direction: row; flex-wrap: wrap; }
    .m-uc-menu a { flex: 1 1 auto; text-align: center; padding: 9px 10px; font-size: 13px; }
    .m-uc-menu .m-uc-out { border-top: 0; margin-top: 0; }
    .m-uc-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .m-uc-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .m-uc-redeem { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
    .m-uc-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
    .m-uc-tr { grid-template-columns: 96px 76px minmax(0, 1fr) 60px; font-size: 12.5px; }
    .m-uc-table-group .m-uc-tr { grid-template-columns: 110px minmax(0, 1fr) 56px; }
    .m-uc-benefits { grid-template-columns: minmax(0, 1fr); }
    .m-uc-panel { padding: 14px; }
}

/* ================================================================ 消息中心 */
/* 站内公告 + 会员自己的通知。页头「消息」悬浮框里点某条会跳到 /notice#<id>，
   下面 .m-msg:target 负责把落点那条"点亮"，让人一眼看到看的是哪条。 */
.m-msg-page { padding-bottom: 40px; }
.m-msg-wrap { max-width: 860px; padding-top: 22px; }
.m-msg-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 14px; }
.m-msg-head h1 { font-size: 20px; font-weight: 800; }
.m-msg-head span { font-size: 12.5px; color: var(--m-muted); }
.m-msg-tip {
    margin-bottom: 14px; padding: 12px 16px; border-radius: 10px; font-size: 13px;
    background: var(--m-surface); border: 1px solid var(--m-line); color: var(--m-sub);
}
.m-msg-tip a { color: var(--m-primary); font-weight: 700; }
.m-msg {
    background: var(--m-surface); border: 1px solid var(--m-line);
    border-radius: var(--m-radius-lg); padding: 16px 18px; scroll-margin-top: 84px;
}
.m-msg + .m-msg { margin-top: 12px; }
.m-msg:target { border-color: var(--m-primary); box-shadow: 0 0 0 1px var(--m-primary-45, rgba(255,95,0,.45)); }
.m-msg-hd { display: flex; align-items: center; gap: 10px; }
.m-msg-title { font-size: 15.5px; font-weight: 700; min-width: 0; }
.m-msg-time { margin-left: auto; flex: 0 0 auto; font-size: 12px; color: var(--m-muted); font-style: normal; }
.m-msg-kind {
    flex: 0 0 auto; padding: 1px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 700;
    background: var(--m-surface-3); color: var(--m-sub);
}
.m-msg-kind-notice { background: var(--m-primary-16, rgba(255,95,0,.16)); color: var(--m-primary); }
.m-msg-kind-vip { background: rgba(255, 165, 22, .18); color: var(--m-gold); }
.m-msg-kind-order { background: rgba(120, 200, 255, .16); color: #8fd0ff; }
.m-msg-body { margin-top: 10px; font-size: 13.5px; line-height: 1.85; color: var(--m-text); }
.m-msg-act { margin-top: 12px; }
.m-msg-empty { padding: 40px 10px; text-align: center; color: var(--m-muted); font-size: 13.5px; }
@media (max-width: 640px) {
    .m-msg { padding: 14px; }
    .m-msg-hd { flex-wrap: wrap; }
    .m-msg-time { margin-left: 0; }
}

