@charset "UTF-8";
/* ============================================================
   torrent 影视/游戏/软件资源门户 —— 前台样式(单文件, 自包含)

   【设计来源】设计 token(颜色/圆角/阴影/字体栈)逐字提炼自
   shared_admin/css/ui-kit.css:11-18, 组件观感(卡片/按钮/表格/pill/输入框)
   按 ui-kit 同一套配方复刻 —— 目标是"和 erp 后台看起来是同一个产品"。

   【为什么不直接 <link> ui-kit.css】(ui-kit.css 其实已经躺在本 webapp 的
   dist/css/ 里, build.xml copy-admin-www 把整个 shared_admin 平铺过来了, 所以
   这是"能引但不引")：
     1. ui-kit.css:25 有 `@media(min-width:769px){html{zoom:.9}}` —— 桌面端整站
        压到 90%。门户是要进搜索索引的, 14px 正文渲染成 ~12.6px 会踩 Lighthouse
        "字号过小/点击目标过小"审计; 且 zoom 非标准, 会污染所有 vh/vw 计算
        (后台已为它打了两个补丁: ui-kit.css:35、:116)。见本文件"吸底 footer"注释。
     2. ui-kit.css 294 行里大半是 .uk-* 后台外壳 + Bootstrap 类覆盖, 而前台不引
        Bootstrap —— 那些 !important 空转, 但 Bootstrap 提供的 padding 也一并
        消失(.btn/.form-control 在 ui-kit 里只有 radius/字重/字号/边框色, 没有
        padding), 反而要在这里补回来。所以不如只搬 token。
     3. 解耦: ui-kit.css 是三个后台的唯一真源, 后台改视觉不该静默改动 SEO 前台。
   【改主色】改下面 :root 的 --primary / --primary-hover / --primary-weak 三个值,
   全站(按钮/链接/激活导航/焦点光圈/选区)一起变; 其它地方不要写死颜色。
   【无 JS 依赖】SEO 范式 A: 内容服务端渲染, 样式不靠 JS 才成型。本文件不含任何
   需要 JS 打标(data-theme / x-cloak / .is-xxx)才生效的规则。

   【注释里引用行号的口径】(2026-07-30 定, 起因见下)
     - **ui-kit.css 写行号**: 它是本站视觉的唯一基准, 且不随本项目的迭代变动, 行号可信、可核。
       下面每一处"和 erp 对齐"的值都带 `ui-kit.css:行号`, 复核时逐条 diff 得动。
     - **本目录的 JSP 只按结构指路, 不写行号**: 门户 5 个页面 + header/footer 片段本轮被大量重构
       (同一批改动里 detail.jsp 的行号漂了三次), 写死行号的注释半天就全指错地方 —— 比没有注释更坏,
       因为读的人会照着错行号下结论。所以一律写成"detail.jsp 的 <ul class=\"attrs\">"这种结构描述,
       类名契约本身是稳定的, 照描述 grep 一次就能定位。
   ============================================================ */

/* ---------- 设计 token(ui-kit.css:11-18 逐字, 剔除后台壳专用的 --sidebar) ---------- */
:root {
    /* 面 / 线 —— ui-kit.css:11 */
    --bg: #f6f7f9;
    --surface: #fff;
    --surface-2: #fafbfc;
    --hover: #f4f5f8;
    --border: #e7e9ee;
    --border-2: #eef0f4;
    /* ui-kit 里没 token 化的两个硬编码值, 这里提升成变量(值不变):
       #d3d7e0 = 输入框 hover 边框(:221) + 滚动条 thumb(:30); #b9bfcc = thumb hover(:222) */
    --border-strong: #d3d7e0;
    --border-strong-2: #b9bfcc;

    /* 文字 —— ui-kit.css:12 */
    --text: #1a1f2b;
    --muted: #6b7385;
    --faint: #9aa1b1;

    /* 主色 —— ui-kit.css:13(改主色只改这三行) */
    --primary: #4263eb;
    --primary-weak: #eef1fe;
    --primary-hover: #3651c9;

    /* 语义色 + weak 底 —— ui-kit.css:14。整组照抄不裁剪: 本文件目前只用到 warn
       (卡片更新状态 / 电驴风险提示), --ok/--danger 和 --sh-lg 先留着 —— 将来加
       成功提示、失效资源标记、弹层时直接取, 免得有人现场发明新颜色。 */
    --ok: #12b76a;
    --ok-weak: #e7f7ee;
    --warn: #f79009;
    --warn-weak: #fef3e2;
    --danger: #f04438;
    --danger-weak: #fdeceb;

    /* 圆角三档 —— ui-kit.css:15 */
    --r-lg: 12px;
    --r: 9px;
    --r-sm: 6px;

    /* 阴影三档 —— ui-kit.css:16 */
    --sh-sm: 0 1px 2px rgba(16, 24, 40, .06);
    --sh: 0 4px 16px rgba(16, 24, 40, .07);
    --sh-lg: 0 12px 32px rgba(16, 24, 40, .12);

    /* 字体栈 —— ui-kit.css:18 */
    --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", sans-serif;
}

/* ---------- 暗色主题(2026-08-04, 跟随系统) ----------
   看片人群的主场景是晚上关灯选片, 纯白页面刺眼 —— 这是全站感知最强的一处升级。
   实现按本文件早前预留的方案: @media(prefers-color-scheme:dark) 里整体换 :root 变量,
   变量体逐字取自 ui-kit.css:230-237 的 [data-theme=dark](后台暗色块, 虽然后台切换钮被砍了,
   但那套值是设计系统的一部分), 再补门户自有的三个 token(--border-strong/-2 与 --primary-weak
   在后台块里有的照抄, 没有的按同一梯度推)。
   ‼️ **不做手动开关**: 跟随系统零 JS 零闪屏零存储(后台那套 localStorage + 阻塞前置脚本
      在 SSR 门户上会拖 FCP), 系统切了网页自动跟。
   ‼️ 有意保持不变的: --ok/--warn/--danger 本色(实测在 #101218 上对比度 4.5:1 以上);
      .card .score/.rank 的深色半透明底(压在海报上, 明暗两态都成立); .brand 渐变(品牌色);
      .player-wrap 纯黑。
   ‼️ color-scheme: dark 让 UA 自绘件(滚动条/video 控件/输入框)一起变深, 别漏。 */
@media (prefers-color-scheme: dark) {
    :root {
        color-scheme: dark;
        /* 面 / 线 —— ui-kit.css [data-theme=dark] 逐字 */
        --bg: #101218;
        --surface: #181b23;
        --surface-2: #1e222c;
        --hover: #242a37;
        --border: #2a3040;
        --border-2: #232837;
        /* 门户自有的两档强边框(后台块没有): 按暗色梯度顺推, 保持"比 --border 更亮一档"的关系 */
        --border-strong: #3a4150;
        --border-strong-2: #4a5266;

        /* 文字 —— ui-kit 暗色块逐字 */
        --text: #e7eaf2;
        --muted: #9aa3b7;
        --faint: #697184;

        /* 主色 —— ui-kit 暗色块逐字(暗底上主色提亮一档才保得住对比度) */
        --primary: #5b78f0;
        --primary-weak: #20294a;
        --primary-hover: #6f88f3;

        /* 语义 weak 底 —— ui-kit 暗色块逐字; 本色三个不换(见上) */
        --ok-weak: #143223;
        --warn-weak: #33290f;
        --danger-weak: #3a1d1a;

        /* 阴影 —— ui-kit 暗色块逐字(暗底上灰阴影没意义, 换纯黑系) */
        --sh-sm: 0 1px 2px rgba(0, 0, 0, .4);
        --sh: 0 4px 16px rgba(0, 0, 0, .5);
        --sh-lg: 0 12px 32px rgba(0, 0, 0, .6);
    }
}

/* ---------- 基础规则(ui-kit.css:20-30 的前台版) ---------- */
* { box-sizing: border-box; }

/* ‼️ 布局 bug 修复 1 / 共 2 —— "footer 之后一大片空白"
   旧写法: body 没有任何高度约束, .site-footer 只有 margin-top:40px, 内容不足一屏时
   footer 就停在内容末尾, 下面留一大片 body 背景色。
   正确做法(教科书三行 flex 吸底): body 撑满视口高度 + 列向 flex, 中间区 flex:1 0 auto
   吃掉剩余高度, footer flex:none 永远贴在下沿; 内容超屏时 footer 自然跟在文末。
   两个坑都避开了:
     - 不抄 ui-kit.css:21 的 `html,body{margin:0;height:100%}` —— height 是硬高度, body
       被钉死一屏, 内容超出后 flex 链失效; 前台要 min-height。
     - 不用 position:sticky/fixed 冒充吸底(sticky 内容不足时不会下沉, 正是"footer 后
       一片白"的另一种典型成因; fixed 会盖住文末内容)。
   这里 vh/dvh 可以放心用: 本文件没抄 zoom:.9, 所以不需要 ui-kit.css:35 那种
   `calc(100vh / .9)` 反除补偿。 */
html {
    min-height: 100%;
}

body {
    margin: 0;
    min-height: 100vh;      /* 旧内核兜底 */
    min-height: 100dvh;     /* dvh 治移动端地址栏伸缩 */
    display: flex;
    flex-direction: column;
    font-family: var(--font);
    background: var(--bg);
    color: var(--text);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

/* ui-kit.css:27: 链接不蓝不下划线, 靠上下文着色(卡片/导航整块可点, 蓝链会很脏);
   正文里真正需要被认出来的链接在下面单独着 --primary。 */
a { color: inherit; text-decoration: none; }

img { max-width: 100%; }

/* 滚动条 / 选区 —— ui-kit.css:29-30 + :222 + :219 */
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 6px; }
::-webkit-scrollbar-thumb:hover { background: var(--border-strong-2); }
::selection { background: var(--primary-weak); }

/* 键盘焦点环 —— ui-kit.css:196 的配方(a11y: 只在键盘操作时出现, 鼠标点击不出) */
a:focus-visible,
button:focus-visible,
.btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 1px var(--primary), 0 0 0 4px var(--primary-weak);
}

/* 动效偏好 —— ui-kit.css:224 逐字 */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* ---------- 组件: 状态 pill(一套配方 —— ui-kit.css:82-84) ---------- */
/* ‼️ 复核修复(中危)"pill 体系碎成 5 套参数, 且 erp 最有辨识度的圆点全站没有":
   后台只有 .uk-pill 一条配方(ui-kit.css:82) + 一个 ::before 圆点(:83) + 三个语义变体(:84),
   而本文件原来七个挂载点各写一套: padding 3px 10px / 2px 9px / 1px 8px / 1px 7px 四种,
   圆角 20px 与 var(--r-sm) 两种, 字号 12px 与 12.5px 两种, 字重 600 与 500 两种 ——
   并排看就不像同一个产品。这里把四个值收敛到一处, 各挂载点只保留"选哪组语义色"和自己的定位外边距。
   ‼️ 为什么写成"既有类名的选择器列表"而不是新增一个 .pill 基类: 不能改 JSP(类名契约变更要另开一轮),
      所以基类只能以选择器列表的形式存在。将来 JSP 能改时, 把列表换成 .pill 即可, 值不用动。
   ‼️ 位置不能挪到下面去: 列表里每条都是 0-2-0, 和后面各组件自己的规则同特异性, 靠源序决定胜负 ——
      基类必须排在前面, 后面的组件规则才能覆盖它(例如 .user-box .me 要把 display 换回 inline-block)。 */
.user-box .me,
.page-title .total,
.page-title .today,
.links .cnt,
.card .status,
.link-table .grp,
.link-table .pwd,
.link-table .warn,
.link-table .ltag,
.link-table .pack,
.link-table .cam,
.link-table .alive-b,
.attrs .stale {
    display: inline-flex;       /* ui-kit.css:82 */
    align-items: center;        /* ui-kit.css:82 */
    gap: 5px;                   /* ui-kit.css:82 —— 圆点与文字的间距 */
    padding: 3px 10px;          /* ui-kit.css:82 */
    /* !! 2026-08-03 由 20px(整胶囊)收到 --r-sm(6px)。
       **标签**和**按钮**从这里开始分道: 两者原来都是 20px, 看久了分不清哪个能点。
       现在 20px 只留给可点的东西(.type-nav a / .facet-vals a / .btn-fav), 纯展示的标签一律小圆角。
       用 --r-sm 而不是随手写 4px: 圆角在本文件是三档 token(--r-lg 12 / --r 9 / --r-sm 6),
       标签是全站最小的一档控件, 就该吃最小那档。 */
    border-radius: var(--r-sm);
    font-size: 12px;            /* ui-kit.css:82 */
    font-weight: 600;           /* ui-kit.css:82 */
    /* ui-kit 里 pill 只出现在表格单元格中, 不需要这条; 本文件的 .total/.cnt 挂在 h1/h2 里,
       要抵消标题继承来的 -.01em 字距, 否则同一个 pill 在标题里和表格里字距不一样。 */
    letter-spacing: 0;
}

/* currentColor 小圆点 —— ui-kit.css:83 逐字。这是 erp pill 最有辨识度的一笔, 原来全站一个没有。
   只给"状态语义"pill: 卡片的更新状态、电驴链接的风险提示 —— 对应 ui-kit.css:84 那三个变体
   (ok/warn/dng)全是状态语义。纯计数(.total/.cnt)、纯标签(.grp/.pwd)和用户名(.me)不带点:
   后台的计数走的是 ui-kit.css:46 的 .badge, 本来就没有圆点。
   flex:none 是本文件的补充(ui-kit.css:83 没写): 后台的 pill 永不折行, 而 .warn 是一整句会折行的
   文案, 圆点若可收缩就会被压成椭圆。 */
.card .status::before,
.link-table .warn::before,
/* 枪版标记(2026-08-06)也带圆点: 它和 .warn 一样是"状态/风险"语义, 不是纯标签。
   ‼️ 它只在 ?cam=1 这个显式变体里出现, 默认视图里查询层已经把这些行滤掉了。 */
.link-table .cam::before {
    content: "";
    width: 6px;
    height: 6px;
    flex: none;
    border-radius: 50%;
    background: currentColor;
}

/* ---------- 栅格容器 ---------- */
/* width:100% + margin:0 auto 是给 flex 子项居中用的(body 是列向 flex 容器,
   交叉轴上的 auto 外边距会吸收剩余空间 = 水平居中); 只写 max-width 不写 width
   在部分内核里会被 stretch 拉满, 保险起见都写上。 */
.wrap {
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 16px;
}

/* ---------- 顶栏 ---------- */
/* 观感取 erp topbar: 白面 + 1px 下边线, 不是原来那块深色 #1f2430 —— 后台整套是
   浅色 SaaS 风, 深色顶栏会立刻显得是两个产品。sticky 吸顶(没有 zoom, top:0 可信)。 */
.site-header {
    flex: none;
    position: sticky;
    top: 0;
    z-index: 20;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
}

.header-inner {
    display: flex;
    align-items: center;
    gap: 16px;
    min-height: 58px;
    /* 窄屏换行处理见文末 <=640px 断点; 这里不写死 height, 换行时才不会把内容挤出去 */
}

/* 站名 —— 字号/字重/字距同 ui-kit.css:37 的 .uk-brand, 前面那块渐变方块是
   ui-kit.css:38 唯一值得搬到前台的强视觉(纯 CSS 伪元素, 不加标签不加图片)。
   ‼️ 清理(复核点名的死规则之一): 原来这里并挂了一条过渡期兼容选择器 `.header-inner > .logo`
   (含它的 ::before 和移动断点里的两条)。已核实 header.jsp:27 是 `<a class="brand" href="/">`,
   契约类名 .brand 已落地, 全仓 grep 无第二处 class="logo" 会命中本文件(news/tool.jsp 有一个,
   但那是另一个站、不引本文件), 所以整条兼容选择器删掉 —— 留着会让下一个人以为 .logo 还在用。 */
.brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;                  /* ui-kit.css:37 */
    flex: none;
    font-size: 17px;            /* ui-kit.css:37 */
    font-weight: 700;           /* ui-kit.css:37 */
    letter-spacing: -.01em;     /* ui-kit.css:37 */
    color: var(--text);
    white-space: nowrap;
}

/* ‼️ 复核修复(低危)"品牌方块和 erp 不是一个尺寸, 而且是个空块": ui-kit.css:38 的 .uk-brand .logo
   是 30px 方块 + 内部 flex 居中一个 16px 白色字形(同一手法在 erp 线上壳里还有一处:
   shared_admin/js/ui-kit.js:82 的 .uk-user .ava 也是色块里放一个字, 见 ui-kit.css:52) ——
   原来这里只搬了渐变和 8px 圆角, 尺寸 26px 且块内空白, 顶栏第一眼的品牌区就对不上
   (同样 8px 圆角配 26px 与配 30px 的角半径占比也不同, 并排看形状都不一样)。
   现在尺寸对齐 30px, 并补上 ui-kit.css:38 后半段的 flex 居中 + #fff + 16px; 字形受限于不能改 JSP,
   只能由伪元素出一个"影"(站名首字, 和 .ava 取用户名首字同一个思路)。 */
.brand::before {
    /* ‼️ 2026-08-01 由汉字改成矢量标识(用户明确要求"别用中文的"):
       原来是 content:"影" —— 靠**查看端装了中文字体**才画得出来, 非中文系统上是豆腐块;
       而且英文站 /en/ 的顶栏顶着一个汉字本身就不对。
       现在换成一个白色播放三角: 纯路径、零字体依赖、中英文场景通用, 且与 favicon
       (favicon.ico / asset/favicon.svg, 由 scripts/torrent_make_favicon.py 生成)是**同一个图形**。
       伪元素内容留空, 读屏器照旧当纯装饰跳过, 无障碍名仍是站名本身。 */
    content: "";
    width: 30px;                /* ui-kit.css:38 */
    height: 30px;               /* ui-kit.css:38 */
    flex: none;                 /* ui-kit.css:38 */
    border-radius: 8px;         /* ui-kit.css:38 */
    /* 两层背景: 三角(内联 SVG)压在渐变上。第一个列出的在上层, 顺序不能反。
       尺寸/坐标与 asset/favicon.svg 逐字一致(viewBox 0 0 30 30, 三角 11.8/9.2 - 21.2/15 - 11.8/20.8),
       改图案要两处一起改, 否则标签页和顶栏会不是一个标识。 */
    background:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath d='M11.8 9.2 L21.2 15 L11.8 20.8 Z' fill='%23fff'/%3E%3C/svg%3E") center / 30px 30px no-repeat,
        linear-gradient(135deg, var(--primary), #7c8cf7);   /* ui-kit.css:38 逐字 */
    display: inline-flex;
}

/* 搜索框 —— 配方 ui-kit.css:59-60 的 .search, 外壳描边 + 内部 input 无边框。
   ‼️ 布局 bug 修复 2 / 共 2 —— "搜索框硬撑":
   旧写法 `flex:1` 简写带 flex-basis:0% 且没有 min-width:0, input 的默认
   intrinsic 宽度(约 20 字符)会把 flex 项撑破, 窄屏顶栏直接溢出横向滚动。
   这里 flex:1 1 260px 给理想宽度、min-width:0 允许收缩、max-width 限制上限,
   三件套齐了才不会既撑破也不会独占整行。 */
.search-box {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1 1 260px;
    min-width: 0;
    max-width: 520px;
    /* ‼️ 复核修复(中危)"搜索框看不出是输入区": 原来这里写的是 background:var(--surface)(#fff),
       而顶栏(上面 .site-header)也是 var(--surface) —— 白压白, 只剩一条 #e7e9ee 的 1px 边(对白底约 1.15:1)。
       上面注释自称照 ui-kit.css:59 的配方, 但那条是 background:var(--bg) 灰底压在白顶栏上(一眼
       就是个输入槽), 值没搬全。这里把底色和壳上的 color 都补齐, 观感回到和后台一致。
       ‼️ 顺带钉一笔, 免得下一轮再被误判成"深顶栏语境": 本站顶栏是**浅色** —— 上面 .site-header 的
       background 就是 var(--surface), 和 erp 的 .uk-topbar(ui-kit.css:56 也是 var(--surface))同色。
       深色 #1f2430 顶栏是本文件更早的写法, 已经被替换掉了(见 .site-header 上方注释)。所以这里直接
       照 ui-kit.css:59 用 var(--bg) 灰底就得到和后台一模一样的"凹陷输入槽", 不需要为深顶栏另设一套。
       ‼️ 与 ui-kit.css:59 唯一**有意**不一致的一项, 写在这里免得下一轮又被当成"值没搬全": 控件总高。
       erp 的 .uk-search 壳里只有一个无边框 input(≈32px 高), 提交靠 JS; 门户按 SEO 范式 A 必须能在
       无 JS 下提交, 所以壳里多了一个真 <button type=submit>(header.jsp:33), 撑到 ≈40px。
       这 8px 差额是"必须有提交钮"带来的, 不是配方跑偏 —— 而且 40px 正好压住 Lighthouse 的
       "点击目标过小"审计门槛(和文末移动断点里 .pager a 撑 min-height:40px 是同一条门户独有的理由,
       文件头也为此放弃了 ui-kit.css:25 的 zoom:.9)。除高度外, 底色/描边/圆角/内边距/字号全部与
       ui-kit.css:59-60 逐值一致。 */
    background: var(--bg);
    color: var(--muted);
    border: 1px solid var(--border);
    border-radius: var(--r);
    padding: 4px 5px 4px 12px;
    transition: border-color .15s, box-shadow .15s;
}

/* 输入框 hover 边框 = ui-kit.css:221; focus 光圈 = 3px + --primary-weak(ui-kit.css:112)。
   用 :focus-within 把光圈画在外壳上, 视觉上和后台的输入框一模一样。 */
.search-box:hover:not(:focus-within) { border-color: var(--border-strong); }

.search-box:focus-within {
    border-color: var(--primary);
    box-shadow: 0 0 0 3px var(--primary-weak);
}

.search-box input {
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    background: transparent;
    outline: 0;
    font-family: inherit;
    font-size: 13px;   /* 复核修复(中危): 对齐 ui-kit.css:60 的 .uk-search input{font-size:13px}, 原来是 13.5px */
    color: var(--text);
    padding: 5px 0;
}

.search-box input::placeholder { color: var(--faint); opacity: 1; }   /* ui-kit.css:220 */

/* 搜索按钮 = 小号实心主色钮(值同 .btn-primary + .btn-sm) */
.search-box button {
    flex: none;
    border: 1px solid var(--primary);
    border-radius: var(--r-sm);
    background: var(--primary);
    color: #fff;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    padding: 6px 14px;
    cursor: pointer;
    transition: background-color .15s, border-color .15s;
}

.search-box button:hover { background: var(--primary-hover); border-color: var(--primary-hover); }

/* 登录态 —— 灰字, hover 才上主色(顶栏不该有第二块蓝) */
.user-box {
    margin-left: auto;
    flex: none;
    display: flex;
    align-items: center;
    gap: 12px;
    white-space: nowrap;
    font-size: 13.5px;
}

.user-box a { color: var(--muted); }
.user-box a:hover { color: var(--primary); }

/* ---- 顶栏语言下拉(2026-08-06 用户定: "跟admin那边一样, 放到header上, 下拉菜单切换") ----
   ‼️ 用 <details>/<summary> 的原生折叠, **零 JS**: 门户是服务端渲染, 切语言 = 换 URL,
      不能像 admin 那样靠 <select> 的 change 事件(没 JS 就跳不了, 且违反 SEO 范式A)。
   ‼️ 视觉对齐 erp: 收起态是 .uk-icon-btn 那套(--surface 底 + --border 边 + var(--r) 圆角),
      展开的面板用 --sh-lg 阴影 + --r 圆角, 选中项用 --primary-weak 淡底 + --primary 字
      (与 ui-kit.css:44 的 .nav-item.active 同向, 不是实心主色 —— 那是 §60 那轮统一过的口径)。 */
.lang-menu { position: relative; }

.lang-menu > summary {
    list-style: none;                 /* 去掉默认三角(Firefox/旧 Safari) */
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 10px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface);
    color: var(--muted);
    cursor: pointer;
    user-select: none;
    font-size: 13px;
}
/* WebKit 的三角要单独去 */
.lang-menu > summary::-webkit-details-marker { display: none; }
.lang-menu > summary::marker { content: ''; }
.lang-menu > summary:hover { background: var(--hover); color: var(--text); }
.lang-menu > summary:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* 收起/展开的指示箭头: 纯 CSS, 不额外插标签 */
.lang-menu > summary::after {
    content: '';
    width: 0; height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 4px solid currentColor;
    transition: transform .12s;
}
.lang-menu[open] > summary::after { transform: rotate(180deg); }
.lang-menu[open] > summary { background: var(--hover); color: var(--text); }

.lang-menu .lang-ico { font-size: 13px; line-height: 1; }

.lang-list {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;                          /* 顶栏右侧, 向左展开免得溢出视口 */
    z-index: 30;
    min-width: 128px;
    margin: 0;
    padding: 4px;
    list-style: none;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r);
    box-shadow: var(--sh-lg);
}
.lang-list li { margin: 0; }
.lang-list a,
.lang-list .on {
    display: block;
    padding: 7px 10px;
    border-radius: var(--r-sm);
    font-size: 13px;
    line-height: 1.2;
    white-space: nowrap;
}
.lang-list a { color: var(--text); }
.lang-list a:hover { background: var(--hover); color: var(--primary); }
/* 当前语言渲染成 <span> 不是 <a>(点自己没意义), 用 erp 的选中态语言标出来 */
.lang-list .on {
    background: var(--primary-weak);
    color: var(--primary);
    font-weight: 600;
    cursor: default;
}

/* 用户名不是链接, 用 pill 底衬一下和"退出"区分。尺寸/圆角/字号/字重全部走上面那套 pill 基配方
   (ui-kit.css:82), 这里只挑"中性 mute"这组色 + 自己的截断行为。
   ‼️ display 必须在这里改回 inline-block(基类给的是 ui-kit.css:82 的 inline-flex):
   text-overflow 只对块级内容盒生效, flex 容器里的文字是匿名 flex 项, 省略号不会出来。
   这条能压住基类不是靠特异性(两边都是 0-2-0), 是靠源序在后 —— 别把 pill 基配方挪到本行之后。 */
.user-box .me {
    display: inline-block;
    max-width: 10em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    background: var(--hover);
    color: var(--muted);
}

/* ---------- 中间弹性区(吸底 footer 的中段) ---------- */
/* ‼️ 清理(复核点名的死规则之二): 原来这里并挂了过渡期兼容选择器 `body > main`, 用来兜住"JSP 还写着
   <main class="wrap"> 没加 .site-main"的情况。已逐页核实 5 个页面全部同步完毕
   (index / search / detail / play / 404 五页的 <main> 都带 class="site-main"), 兼容选择器已成死代码, 删掉。
   flex:1 0 auto 而不是 flex:1 —— 简写会带 flex-basis:0%, 长内容在某些内核里被压。 */
.site-main {
    flex: 1 0 auto;
    padding-bottom: 32px;
}

/* ---------- 类型导航 ---------- */
/* 胶囊 chip: 白面 + 1px 描边 + 20px 全圆角(同 pill 的圆角语言), 选中态 = 主色弱底 + 主色字。
   ‼️ 复核修复(中危)"选中态的视觉语言和 erp 正好倒过来": 原来这里是实心主色 + 白字, 而 erp 的选中态
   通篇都是"弱底染色 + 主色字 + 600", 三处互相印证:
     - ui-kit.css:44  .uk-nav .nav-item.active{background:var(--primary-weak);color:var(--primary);font-weight:600}
     - ui-kit.css:164 .cs-item.on,.cs-item.active{background:var(--primary-weak)}
     - ui-kit.css:293 select option:checked{background:var(--primary-weak);color:var(--primary);font-weight:600}
   而"实心主色"在 erp 里被留给了另外两种语义: 主动作按钮(ui-kit.css:102 .btn-primary)和
   分页当前页(ui-kit.css:137)。门户把实心用在导航上, 等于把 erp 的两套语义调了个头 ——
   这和 .pager .cur 那处(见下面分页段)是同一个 bug 的两半, 本轮**同时**改, 方向对齐 erp。
   ‼️ 关于 ui-kit.css:45 那条 ::before 左侧 3px 主色条: 本组件**不做**等效处理(不加下边框条)。理由:
     1. 那条 3px 条在 ui-kit 里只出现一次, 且只挂在 .uk-nav(竖排侧栏列表)上 —— 它是"整行贴着侧栏
        左沿"这个形态的边缘标记。上面另外两处选中态(.cs-item.on / option:checked)都没有它,
        说明 erp 的选中态里"弱底 + 主色字"才是承重的信号, 3px 条是 .uk-nav 的局部装饰。
     2. 本组件是 20px 全圆角的横排 chip, 一条 3px 直边落在圆角胶囊底部, 要么被圆角切断、要么得
        额外开 overflow 裁剪, 会造出一个 ui-kit 里不存在的形状 —— 那才是真的偏离 erp。 */
.type-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 18px 0 4px;
}

.type-nav a {
    padding: 6px 15px;
    border-radius: 20px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--muted);
    font-size: 13.5px;
    font-weight: 500;
    transition: background-color .15s, border-color .15s, color .15s;
}

.type-nav a:hover {
    background: var(--hover);
    border-color: var(--border-strong);
    color: var(--text);
}

.type-nav a.on {
    background: var(--primary-weak);    /* ui-kit.css:44 */
    color: var(--primary);              /* ui-kit.css:44 */
    font-weight: 600;                   /* ui-kit.css:44 */
    /* erp 的 .nav-item 没有边框, 整块就是一片弱底; 本组件的 chip 有 1px 描边, 所以把边框色也刷成
       --primary-weak, 轮廓才会和 erp 一样融成一整片弱底(刷成 --primary 会变成"描边胶囊", 不是 erp 的样子)。 */
    border-color: var(--primary-weak);
}

/* ‼️ 原来这里还有一条 .type-nav a.on:hover{background:var(--primary-hover)}, 已删。
   erp 的选中项悬停时**不变色**: ui-kit.css:43 的 :hover 与 :44 的 .active 特异性同为 0-3-0,
   .active 源序在后所以压住了 hover。本文件同构 —— .type-nav a:hover(0-2-1) 与 .type-nav a.on(0-2-1)
   特异性也相等, .on 源序在后, 天然就压住了上面那条 hover, 不需要再写第三条规则。 */

/* ---------- 多层筛选(index.jsp .facets) ----------
   视觉配方直接沿用上面的 .type-nav chip(同一个站里"可点的窄标签"只该有一种长相), 只做三处收敛:
   字号小半档、内边距窄一点、选中态同一套 --primary-weak。整块套在一张 surface 卡片里, 与下面的
   卡片列表拉开层次 —— 不这样的话三行 chip 会和分类导航连成一片, 分不清哪行是"我在哪"哪行是"我筛了什么"。 */
.facets {
    margin: 0 0 18px;
    padding: 4px 14px 10px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
}

/* 摘要行(折叠头)只在窄屏出。桌面端整块恒展开, 不需要它, 也不该让桌面多一个点了会收起来的开关。 */
.facets > summary { display: none; }

/* 一行 = 维度名 + 该维度的候选值。用 grid 而不是 flex: 维度名列宽固定, 各行的候选值才会左对齐成一竖列
   (flex 下"产地/语种/类型"字数不同会让每行起点参差)。 */
.facet-row {
    display: grid;
    /* 三列: 维度名 | 候选值 | "更多"。第三列由脚本填(没 JS 时是空列, 宽度 0, 布局不受影响) */
    grid-template-columns: max-content 1fr max-content;
    align-items: start;
    gap: 10px;
    padding: 8px 0;
    border-bottom: 1px dashed var(--border);
}

/* 最后一行不画分隔线 —— 下面紧跟着的要么是"清空筛选", 要么就是卡片边框, 再画一条是双线 */
.facet-row:last-child { border-bottom: none; }

.facet-key {
    padding: 6px 0;
    color: var(--muted);
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
}

.facet-vals {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.facet-vals a {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 11px;
    border-radius: 20px;
    border: 1px solid transparent;   /* 未选中时不画边框: 一行十几个 chip 全描边太吵 */
    color: var(--muted);
    font-size: 13px;
    line-height: 1.4;
    transition: background-color .15s, color .15s;
}

.facet-vals a:hover {
    background: var(--hover);
    color: var(--text);
}

/* 选中态与 .type-nav a.on 完全同配方(弱底 + 主色字 + 边框同色融成一片) */
.facet-vals a.on {
    background: var(--primary-weak);
    border-color: var(--primary-weak);
    color: var(--primary);
    font-weight: 600;
}

/* 条数: 比值本身再弱一档, 用 tabular-nums 让各 chip 的数字宽度一致(不然一行 chip 会像被随机推挤过) */
.facet-vals a i {
    font-style: normal;
    font-size: 11.5px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    opacity: .75;
}

.facet-vals a.on i { color: var(--primary); }

/* 夹成一行。max-height 用固定值而不是 line-height 算 —— 胶囊的高度由 padding 决定,
   跟着字号走会算错; 34px = 5+18+5+2(border) 的实测值, 与下面的 .facet-vals a 内边距同源, 改一处要改两处。 */
.facet-vals.clamp {
    max-height: 34px;
    overflow: hidden;
}

/* "更多": 视觉上比胶囊再弱一档(无底无框), 免得看着像第 18 个候选值 */
.facet-more {
    align-self: start;
    margin-top: 5px;
    padding: 0 2px;
    border: none;
    background: none;
    color: var(--primary);
    font-size: 12.5px;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
}

.facet-more:hover { text-decoration: underline; }

.facet-clear {
    padding: 8px 0 2px;
    text-align: right;
}

.facet-clear a {
    color: var(--muted);
    font-size: 12.5px;
}

.facet-clear a:hover { color: var(--primary); }

/* 产地/语种/类别的可点值(detail.jsp .attrs 里)。
   ‼️ 不做成胶囊: 它们在属性列表里, 排版语义是"这一行的值", 做成一排带底色的胶囊会把属性表打散。
      只上主色 + 悬停下划线, 与正文密度一致。多值之间用 · 分隔(伪元素画, 最后一个不画)。 */
.attrs .chips a { color: var(--primary); }
.attrs .chips a:hover { text-decoration: underline; }
.attrs .chips a + a::before {
    content: ' · ';
    color: var(--faint);
}

/* 资源表上方的即时过滤框(detail.jsp)。
   ‼️ 尺寸/圆角/配色沿用顶栏搜索框那一套, 站里"输入框"只该有一种长相。
   ‼️ 只在 JS 建好之后才有意义, 但**不靠 JS 显示** —— 关掉 JS 时它只是一个不生效的输入框,
      比"闪一下再消失"体面; 内容本身一条不少。 */
.link-filter {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 12px;
}

.link-filter input {
    flex: 1;
    min-width: 0;
    height: 38px;
    padding: 0 12px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface);
    color: var(--text);
    font-size: 13.5px;
    font-family: inherit;
}

.link-filter input:focus {
    outline: none;
    border-color: var(--primary);
}

.link-filter .hit {
    flex: none;
    color: var(--muted);
    font-size: 12.5px;
    font-variant-numeric: tabular-nums;
}

/* ---------- 收藏按钮(detail.jsp) ----------
   配方沿用 .type-nav 的 chip(同一个站里"窄的可点标签"只该有一种长相), 只是尺寸大一档 ——
   它是详情页上除了下载之外唯一的操作, 太小会被属性列表淹掉。 */
.fav-box {
    margin-top: 14px;
}

.btn-fav {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 40px;              /* 触摸目标下限, 桌面端也不缩 */
    padding: 0 18px;
    border-radius: 20px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--muted);
    font-size: 14px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: background-color .15s, border-color .15s, color .15s;
}

.btn-fav:hover {
    background: var(--hover);
    border-color: var(--border-strong);
    color: var(--text);
}

/* ‼️ 同 .autonext[hidden] / .back-top[hidden]: 上面的 display:inline-flex 会压过 UA 的
   [hidden]{display:none}。2026-08-06 起"标记看过"(#watchBtn)靠 hidden 属性出场 ——
   没有这条, 无 JS / localStorage 被禁用时详情页会挂着一颗点不动的死按钮。 */
.btn-fav[hidden] { display: none; }

/* 已收藏 = 与 .type-nav a.on 同一套弱底 + 主色字 */
.btn-fav.on {
    background: var(--primary-weak);
    border-color: var(--primary-weak);
    color: var(--primary);
    font-weight: 600;
}

/* 星形用 CSS 伪元素画一个实心圆点做前导标记 —— 不引图标字体也不外链 SVG。
   未收藏时是空心(只描边), 收藏后填实, 一眼能分辨状态而不必读字。 */
.btn-fav::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    border: 1.5px solid currentColor;
}

.btn-fav.on::before {
    background: currentColor;
}

/* 收藏成功弹跳(2026-08-05): 成功那一下圆点胀大→回弹→落成实心, 比文字从"收藏"变"已收藏"
   更有确认感。.pop 由 detail.jsp 的成功回调挂上、动画时长后自摘; **只在加收藏时弹**,
   取消收藏不弹(撤销动作不需要庆祝)。动效偏好 reduce 时被文件头全局规则统一关掉。 */
@keyframes favpop {
    0% { transform: scale(1); }
    45% { transform: scale(1.9); }
    70% { transform: scale(.85); }
    100% { transform: scale(1); }
}

.btn-fav.pop::before { animation: favpop .45s ease-out; }

/* ---------- 详情页 2026-08-03 新增件 ---------- */
/* 收藏数 + 订阅更新: fav-box 里按钮之后的两个弱化元素 */
.fav-box { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.fav-box .fav-cnt { color: var(--muted); font-size: 12.5px; }
.fav-box .rss-follow { color: var(--muted); font-size: 12.5px; }
.fav-box .rss-follow:hover { color: var(--primary); }
/* 直达资源锚点: 移动端专用(桌面資源列表就在一屏内, 不需要) */
.fav-box .golinks { display: none; }

/* 零下载说明: warn 语义的整行提示条 */
.nodl-tip {
    margin: 0 0 12px;
    padding: 10px 14px;
    border-radius: var(--r);
    background: var(--warn-weak);
    color: var(--warn);
    font-size: 13px;
}

/* 选集条: 维度名 + 胶囊网格(折行), 长剧几百集时限高滚动 —— 别让选集条比资源表还高 */
.ep-nav {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 10px;
    margin: 0 0 12px;
    align-items: start;
}

.ep-nav .ep-k {
    padding: 5px 0;
    color: var(--muted);
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
}

.ep-nav .ep-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    max-height: 132px;
    overflow-y: auto;
}

.ep-nav .ep-chips a {
    min-width: 34px;
    padding: 4px 6px;
    text-align: center;
    border: 1px solid var(--border-2);
    border-radius: var(--r-sm);
    color: var(--muted);
    font-size: 12.5px;
    font-variant-numeric: tabular-nums;
    transition: background-color .15s, border-color .15s, color .15s;
}

.ep-nav .ep-chips a:hover {
    background: var(--primary-weak);
    border-color: var(--primary-weak);
    color: var(--primary);
}

/* ---------- 追看进度(2026-08-06, js/torrent.js 本机打标) ---------- */
/* 拿过的集: 选集胶囊打勾态 —— 弱底 + 主色与"选中"同族, 勾号尾标让它和纯 hover 态也分得清 */
.ep-nav .ep-chips a.got {
    background: var(--primary-weak);
    border-color: var(--primary-weak);
    color: var(--primary);
}

.ep-nav .ep-chips a.got::after {
    content: "✓";
    margin-left: 3px;
    font-size: 10px;
}

/* 拿过的行: 说明列前一个绿勾。不整行变色 —— 几百行的表里大面积着色比不标还乱 */
.link-table tbody tr.got .label::before {
    content: "✓ ";
    color: var(--ok);
    font-weight: 700;
}

/* "上次拿到 SxEy"(js 注入): 堆在"选集"维度名下方, 主色点亮 —— 回访第一眼要找的就是它 */
.ep-nav .ep-k .ep-last {
    display: block;
    margin-top: 2px;
    color: var(--primary);
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
}

/* 快捷过滤胶囊: 观感同筛选条胶囊(.facet-vals a), 但它是 button 不是 a */
.quick-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0 0 10px;
}

.quick-chip {
    padding: 5px 11px;
    border-radius: 20px;
    border: 1px solid var(--border-2);
    background: var(--surface);
    color: var(--muted);
    font-size: 12.5px;
    font-family: inherit;
    cursor: pointer;
    transition: background-color .15s, color .15s;
}

.quick-chip:hover {
    background: var(--primary-weak);
    border-color: var(--primary-weak);
    color: var(--primary);
}

/* 疑似断更: danger 语义小 pill(pill 基配方已并挂) */
.attrs .stale {
    margin-left: 6px;
    background: var(--danger-weak);
    color: var(--danger);
}

/* 豆瓣/IMDb 外链: 与 .chips 链接同语言(主色 + 悬停下划线) */
.attrs .ext { color: var(--primary); }
.attrs .ext:hover { text-decoration: underline; }

/* ---------- 搜索页 2026-08-03 新增件 ---------- */
/* 年代/排序细筛: 白面小卡(与 .facets 同语言但更矮 —— 只有两行, 不值得配折叠) */
.search-filters {
    margin: 0 0 4px;
    padding: 4px 14px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
}

.search-filters .sf-row {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 10px;
    padding: 6px 0;
    align-items: start;
}

.search-filters .sf-row + .sf-row { border-top: 1px dashed var(--border); }

.search-filters .sf-k {
    padding: 5px 0;
    color: var(--muted);
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
}

.search-filters .sf-vals {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.search-filters .sf-vals a {
    padding: 4px 10px;
    border-radius: 20px;
    border: 1px solid transparent;
    color: var(--muted);
    font-size: 13px;
    transition: background-color .15s, color .15s;
}

.search-filters .sf-vals a:hover { background: var(--hover); color: var(--text); }

.search-filters .sf-vals a.on {
    background: var(--primary-weak);
    border-color: var(--primary-weak);
    color: var(--primary);
    font-weight: 600;
}

/* 热搜词 / 你是不是想找: 一行弱化链接, 词是主色可点 */
.hot-words,
.suggest-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin: -6px 0 14px;
    font-size: 13px;
}

.hot-words .hw-k,
.suggest-row .sg-k {
    color: var(--faint);
    font-weight: 600;
}

.hot-words a,
.suggest-row a { color: var(--primary); }

.hot-words a:hover,
.suggest-row a:hover { text-decoration: underline; }

/* 命中高亮: 不用 UA 默认的黄底(与配色打架), 用主色弱底 —— 与选中态同语言 */
.card .title mark {
    background: var(--primary-weak);
    color: var(--primary);
    padding: 0 1px;
    border-radius: 2px;
}

/* 类型标签里的条数(只有搜索页用: 列表页的 type-nav 不显示条数, 那边条数在 h1 上)。
   比标签文字再弱一档, tabular-nums 让各标签的数字宽度一致。配方与筛选胶囊的 <i> 同源。 */
.type-nav a i {
    font-style: normal;
    font-size: 11.5px;
    margin-left: 5px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    opacity: .75;
}

.type-nav a.on i { color: var(--primary); }

/* ---------- 页面标题 ---------- */
.page-title {
    margin: 16px 0 16px;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -.01em;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

/* play.jsp 的标题里是回详情页的链接 */
.page-title a { color: inherit; }
.page-title a:hover { color: var(--primary); }

/* 计数不参与标题字重, 降级成 mute pill —— 尺寸/圆角/字号/字重/字距全部走上面那套 pill 基配方
   (ui-kit.css:82), 这里只挑"中性 mute"这组色。原来这条自己写了 2px 9px 的 padding, 和另外四处
   pill 各不相同, 已收敛。play.jsp 的 h1 里也用它挂"链接标题"(不只是计数), 所以不带圆点是对的。 */
.page-title .total {
    background: var(--hover);
    color: var(--muted);
}

/* 今日更新 N 部(2026-08-03): ok 语义 pill(有新货 = 正向状态), 与 .total 并排 */
.page-title .today {
    background: var(--ok-weak);
    color: var(--ok);
}

/* 收藏页"共 N 部有更新"(2026-08-06, 订阅更新提醒)。
   ‼️ 与卡片上的 .flag.fresh 用同一组 ok 语义色 —— 标题上的数字和卡片上的绿角说的是同一件事,
      颜色不同会让人以为是两回事。选择器沿用 .page-title 那套 pill 基配方, 只挑颜色。 */
.page-title .fresh-n {
    background: var(--ok-weak);
    color: var(--ok);
}

/* ── 个人订阅源入口(favorites.jsp, 2026-08-06) ───────────────────────────────
   配方照 .related / 快捷键面板那套"页内小面板": 弱边框 + 卡片底色, 不引入新的视觉语言。
   ‼️ 地址那一行必须能在窄屏换行(手机上 43 字符的 token 加域名远超一屏宽),
      所以 .row 是 flex-wrap, input 用 flex: 1 1 260px 而不是固定宽度。 */
.feed-box {
    margin: 0 0 18px;
    padding: 14px 16px;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
}

.feed-box h2 {
    margin: 0 0 6px;
    font-size: 15px;
    font-weight: 700;
}

.feed-box .hint {
    margin: 0 0 10px;
    color: var(--muted);
    font-size: 12.5px;
    line-height: 1.6;
}

.feed-box .warn {
    margin: 10px 0 0;
    color: var(--warn);
    font-size: 12.5px;
    line-height: 1.6;
}

.feed-box .row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

/* 地址框: 等宽字体让 base64url 里的 l/1/I、O/0 分得开(用户要肉眼核对自己复制对了没) */
.feed-box .feed-url {
    flex: 1 1 260px;
    min-width: 0;
    padding: 7px 10px;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--bg);
    color: var(--text);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12.5px;
}

.feed-box .feed-url:focus {
    outline: none;
    border-color: var(--primary);
}

/* 2026-08-06 起这个 pill 是链接(指向追剧日历)。‼️ 必须显式压回绿色:
   全站的 .page-title a:hover(0-2-1) 特异性高于 .page-title .today(0-2-0),
   不写这条的话悬停时绿底上会冒出一个蓝字。 */
.page-title a.today:hover { color: var(--ok); }

/* ---------- 窄屏排序条(2026-08-03, h1 下那排; 桌面隐藏 —— 桌面用筛选块里的排序行) ---------- */
.sort-bar { display: none; }

/* ---------- 首页分行(2026-08-03) ---------- */
.home-row { margin: 0 0 8px; }

.home-row h2 {
    margin: 6px 0 10px;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -.01em;
    display: flex;
    align-items: center;
    gap: 10px;
}

.home-row h2 .more {
    margin-left: auto;
    color: var(--muted);
    font-size: 12.5px;
    font-weight: 500;
}

.home-row h2 .more:hover { color: var(--primary); }

/* 分行 = 单行自适应裁剪(2026-08-05 老板点名改: **不要横向拖动窗口**)。
   做法: 沿用 .card-list 的 auto-fill 网格(列数天然跟随页面宽度, 与主列表同配方),
   只加三件事 —— 首行之外的行高压成 0(grid-auto-rows) + 行距归零 + 容器裁剪。
   效果: 宽屏显示 6-7 张、窄屏 2-3 张, 恰好排满一行, 放不下的**直接不可见**,
   想看更多点行标题右侧的"查看全部"。服务端照常给 12 张, 裁剪由 CSS 决定 ——
   分辨率变了显示数自动跟着变, 不用改代码。
   ‼️ 被裁的卡片带 loading=lazy 且被 overflow:hidden 裁出视口交集, 浏览器不会去加载它们的海报。 */
.card-list.row-scroll {
    /* ‼️ grid-template-rows: auto 不能省(2026-08-05 线上踩过): 不声明显式行的话**所有**行都是
       隐式行, 全部吃 grid-auto-rows: 0 —— 连第一行一起压成 0 高, 整行卡片被裁光, 首页只剩行标题。
       声明一条 auto 高的显式首行后, 自动摆放先填满它, 溢出的才进 0 高隐式行被裁掉。 */
    grid-template-rows: auto;
    grid-auto-rows: 0;
    row-gap: 0;
    overflow: hidden;
}

/* ---------- 今日热播 Top10(2026-08-06, index.jsp .hot-row) ---------- */
/* Netflix 式大数字: 排名是一个与 .card .poster 同比例(3/4)的覆盖层, 数字用 flex 沉到
   海报左下角 —— 与 .meta 的可变高度(状态行可有可无)彻底解耦。纯装饰, 不挡点击。 */
.hot-row .hotrank {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    aspect-ratio: 3 / 4;
    display: flex;
    align-items: flex-end;
    padding: 0 0 4px 8px;
    font-size: 48px;
    font-weight: 800;
    font-style: italic;
    line-height: .9;
    color: #fff;
    /* 双层投影: 大扩散保证亮海报上可读, 细描边保证暗海报上有轮廓 */
    text-shadow: 0 2px 12px rgba(0, 0, 0, .7), 0 0 3px rgba(0, 0, 0, .85);
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}

/* ---------- 频道/榜单导航(2026-08-03, 首页) ---------- */
/* 只给读屏器/搜索引擎的文本: 视觉上不占位, 但**不是** display:none ——
   display:none 的内容读屏器也读不到, 搜索引擎还可能当隐藏文本看待。
   这段是通用实现(clip-path + 1px 裁剪), 目前用在 discover 的 h1 上, 见那边注释。 */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ‼️ 2026-08-08: 这一排胶囊换行之后, 视觉上会和**下面的卡片列表**连成一块 ——
   用户实测反馈"还以为下面这些影片都是高分动漫呢"。最后一个胶囊落在单独一行时尤其明显。
   加一条下边框把它收成独立区块: 边框是最轻的分隔手段(不占高度感、不引入新颜色),
   比单纯加大 margin 可靠 —— 纯留白在长列表里会被当成"行间距"而不是"分界"。 */
.channel-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 0 0 20px;
    padding: 0 0 14px;
    border-bottom: 1px solid var(--border);
}

.channel-nav .ch-k {
    color: var(--muted);
    font-size: 13px;
    font-weight: 600;
}

/* 观感 = .type-nav 的 chip(同一个站"可点的窄标签"只该有一种长相) */
.channel-nav a {
    padding: 5px 13px;
    border-radius: 20px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--muted);
    font-size: 13px;
    transition: background-color .15s, border-color .15s, color .15s;
}

.channel-nav a:hover {
    background: var(--hover);
    border-color: var(--border-strong);
    color: var(--text);
}

/* ---------- 追剧日历(2026-08-06, calendar.jsp) ---------- */
/* 页首说明行: 弱化一档, 紧贴 h1(page-title 自带 16px 下边距, 这里往回收一点) */
.cal-tip {
    margin: -8px 0 18px;
    color: var(--muted);
    font-size: 13px;
}

/* 每天一段: 标题配方与 .home-row h2 同款(同一个站"分行标题"只该有一种长相),
   多出的 .rel(今天/昨天)用主色点亮 —— 扫一眼就能定位到"今天"那一段 */
.cal-day { margin: 0 0 22px; }

.cal-day h2 {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin: 6px 0 10px;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -.01em;
    font-variant-numeric: tabular-nums;
}

.cal-day h2 .rel {
    color: var(--primary);
    font-size: 13px;
    font-weight: 600;
}

.cal-day h2 .cnt {
    color: var(--muted);
    font-size: 12.5px;
    font-weight: 500;
}

/* 当天超过每日配额时的"查看全部" —— 推到行尾, 配方同 .home-row h2 .more */
.cal-day h2 .more {
    margin-left: auto;
    color: var(--muted);
    font-size: 12.5px;
    font-weight: 500;
}

.cal-day h2 .more:hover { color: var(--primary); }

/* ---------- 空态 ---------- */
/* 配方 ui-kit.css:205-206。契约类是 .empty-state(带 .ico/.tit/.sub 三段)。
   ‼️ 清理(复核点名的死规则之三): 原来这里(以及下面 .empty a 和移动断点里)并挂了裸 .empty,
   兜"JSP 还写着 <p class="empty">"的过渡期。已反向 grep 全仓确认 JSP 侧再无 class="empty"
   (index / search / detail 三页只在**注释**里提到"不再用裸 <p class=\"empty\">"), 三处兼容选择器一并删掉。 */
.empty-state {
    padding: 48px 20px;         /* ui-kit.css:205 */
    text-align: center;         /* ui-kit.css:205 */
    color: var(--faint);        /* ui-kit.css:205 */
    font-size: 13.5px;
    margin: 0;
}

.empty-state .ico {
    display: block;             /* ui-kit.css:206 */
    font-size: 28px;            /* ui-kit.css:206 */
    line-height: 1;
    /* 复核修复: 原来是 10px, ui-kit.css:206 的 .uk-empty .ic 是 margin-bottom:8px —— 四个页面的
       空态图标到标题的距离比后台松一档, 收回 8px 对齐。 */
    margin-bottom: 8px;
    opacity: .55;               /* ui-kit.css:206 */
}

/* ‼️ 追加修复(本轮新发现, 起因是 JSP 侧在本文件写完之后又改了空态图标的结构):
   .ico 现在是 <div class="ico" aria-hidden="true"> 里包一个 28×28 的内联 <svg>(index / search / detail / 404
   四页同构, feather 风 24 viewBox + stroke="currentColor", 同 ui-kit.css:64 的 .uk-i 那套画法),
   不再是原来那种"span 里放一个字形"。内联 SVG 默认是 inline-level, 要坐在文字基线上, 基线下方还会
   留一截 descender 空隙(28px 字号下约 5-6px) —— 于是 .ico 的实际盒高 > 28px, 上面那条对齐
   ui-kit.css:206 的 margin-bottom:8px 渲染出来变成 13-14px, 四个页面的空态又比后台松一档
   (和上一轮修 UA 的 <p> 外边距是同一类问题, 只是换了个来源)。
   erp 侧知道这个基线坑: ui-kit.css:64 的 .uk-i 给内联图标补了 `vertical-align:-2px` 去抵消它 ——
   但那是 16px 图标混排在文字行里的场景; 这里是一个独占一行的 28px 装饰图标, 直接 display:block
   让它不参与基线更干净(盒高正好 28px, 不用去猜 -2px 该配几)。
   块级元素不再吃 .empty-state 的 text-align:center(ui-kit.css:205), 所以 margin:0 auto 补回水平居中。
   width/height 有意不在这里写死: <svg> 标签自带 width="28" height="28", 和上面 .ico 的 font-size:28px
   (ui-kit.css:206)是同一个 28, 再写第三遍就是三处真源。 */
/* 空态里的行动按钮(目前只有 404 页用): 与上面的说明文字拉开一档距离。
   ‼️ .empty-state 是 text-align:center 的, .btn 是 inline-flex, 天然就居中, 不用再写。 */
.empty-state .btn { margin-top: 14px; }

.empty-state .ico svg {
    display: block;
    margin: 0 auto;
}

.empty-state .tit {
    display: block;
    color: var(--text);
    font-size: 15px;
    font-weight: 600;
    margin-bottom: 6px;
}

.empty-state .sub { display: block; color: var(--muted); font-size: 13px; }

/* ‼️ 复核修复(低危)"空态间距不是写的那个数": .tit/.sub 在 4 个页面(index / search / detail / 404)里都是 <p>,
   本文件没有通用
   p 复位(文件开头那条 * 只给了 box-sizing), UA 的 1em 上下外边距原样生效: .ico 的 10px 与 .tit 的 15px
   相邻外边距合并成 15px、.tit 的 6px 与 .sub 的 13px 合并成 13px, .sub 底部那 13px 又叠在
   容器 48px padding 上(下 61px / 上 48px, 视觉重心下坠)。清掉 UA 外边距, 间距就回到上面
   声明的 8px / 6px(.ico 的 8px 见上面注释, 对齐 ui-kit.css:206)。
   ‼️ 只复位 .empty-state 内的 p, 不写全局 p{margin:0}: 详情页 .intro 里的简介正文也是 <p>,
   全局复位会连它的段间距一起清掉(它自己在 .intro p 里另有 margin:0 的声明, 但将来简介改成多段
   时就要靠 UA 段间距, 别提前埋雷)。 */
.empty-state p { margin: 0; }

/* ---------- 卡片列表 ---------- */
.card-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 16px;
    grid-template-columns: repeat(auto-fill, minmax(164px, 1fr));
}

/* 卡片观感 = ui-kit.css:99 的 .card: 1px 描边 + 12px 圆角 + 极淡 --sh-sm,
   不是"无边框大阴影"那派。ui-kit 没有卡片 hover 抬升, 前台列表需要可点反馈,
   所以只升一级到已有 token(--sh + --border-strong), 不自创阴影值。 */
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-sm);
    overflow: hidden;
    transition: box-shadow .15s, border-color .15s;
}

.card:hover { box-shadow: var(--sh); border-color: var(--border-strong); }

/* position:relative 是评分角标(.card .score, 2026-08-03)的定位上下文, 对布局无副作用 */
.card a { display: block; color: inherit; position: relative; }

/* ‼️ 复核修复(中危, WCAG 2.4.7)"卡片键盘焦点不可见": 上面 .card 的 overflow:hidden(裁 .poster 圆角,
   不能删)会在 .card 的 padding box 边缘裁剪, 而 .card 无 padding + .card a 是 display:block 的唯一子元素
   -> a 的 border box 恰好等于该裁剪边界, 文件开头那条全站焦点环(a:focus-visible, outline:none + 向外扩散 1px/4px 的
   box-shadow)整圈落在边界之外被吃光, Tab 到卡片时零像素反馈。这里改用 outline 负偏移把环画进内侧
   (outline 不参与布局, 负 offset 后位于 padding box 以内, 不会被祖先裁掉), 并关掉那圈必被裁的阴影。
   ‼️ 本轮复核结论: 这条**确实可见**(2px 环整体位于裁剪边界内侧 3px 处), 上一轮的修法成立, 没有回退。
   只补一处收尾: 加 border-radius —— .card 的裁剪曲线是圆角的(内圆角 = --r-lg 12px 减 1px 边框 = 11px),
   而 <a> 本身没有圆角, 直角环的四个角会伸到那条曲线外侧被切掉四个小缺口。outline 会跟随元素的
   border-radius(负 offset 时半径按 offset 收缩), 给 a 补上同一档圆角后四角就贴着曲线走、环是完整的。
   注意: 只在 :focus-visible 上给圆角, .card a 常态不加 —— 它没有背景也没有边框, 加了没意义。 */
.card a:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -3px;
    border-radius: var(--r-lg);
    box-shadow: none;
}

.card .poster {
    display: block;
    width: 100%;
    aspect-ratio: 3 / 4;
    object-fit: cover;
    background: var(--hover);   /* 图未加载/占位 SVG 时的底色, 别露白 */
}

/* 评分角标(2026-08-03): 豆瓣/IMDb 分, 压在海报右上角(四处卡片同款, JSP 见 index.jsp 该处注释)。
   形状走 pill 基配方那套值(20px 圆角 / 12px / 600); 底色不是新颜色 —— 是 --text(#1a1f2b)的
   72% 透明形态: 角标浮在任意海报上, 只有半透明压暗这一种做法能保证白字恒可读。
   星标用伪元素画在数字前, 取 --warn(评分语义在 erp 的语义色盘里最接近 warn 的琥珀色), 不发明新色。 */
.card .score {
    position: absolute;
    top: 8px;
    right: 8px;
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: var(--r-sm);     /* 与 pill 基配方同档, 理由见那里的注释 */
    background: rgba(26, 31, 43, .72);
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.4;
    font-variant-numeric: tabular-nums;
}

.card .score::before {
    content: "★";
    font-size: 10px;
    margin-right: 3px;
    color: var(--warn);
}

/* 左上角旗标带(2026-08-03): 今日更新(ok) / 仅在线(warn)。与右上角评分同一层, 互不遮挡。
   配色走语义色的 weak 底 + 强色字(与 .card .status 同一套语言), 半透明化以便压在海报上可读。 */
.card .flags {
    position: absolute;
    top: 8px;
    left: 8px;
    display: flex;
    gap: 4px;
}

.card .flag {
    padding: 2px 8px;
    border-radius: var(--r-sm);     /* 同上 */
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
}

.card .flag.fresh { background: var(--ok); color: #fff; }
.card .flag.online { background: var(--warn); color: #fff; }
/* 看过(2026-08-06, js/torrent.js 按本机 localStorage 补): 中性深灰 —— 它是"我处理过了"的备忘,
   不是要抢注意力的状态色; 半透明配方与 .card .rank 的号码牌同一形态 */
.card .flag.seen { background: rgba(26, 31, 43, .62); color: #fff; }

/* 排名徽标(2026-08-03, /top/ 榜单页): 左上角方形号码牌 —— 榜单的价值就在"有序有排名"。
   前三名(podium)用主色实心, 其余深色半透明(与评分角标同一个 --text 透明形态)。 */
.card .rank {
    position: absolute;
    top: 0;
    left: 8px;
    min-width: 26px;
    padding: 4px 6px;
    border-radius: 0 0 8px 8px;
    background: rgba(26, 31, 43, .72);
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.card .rank.podium { background: var(--primary); }

/* 卡片第三行(2026-08-03): 资源数/可在线看 —— 决定点不点的最强信号, 比 .sub 再弱一档 */
.card .stats {
    display: block;
    margin-top: 4px;
    font-size: 11.5px;
    color: var(--muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.card .meta { padding: 10px 12px 12px; }

.card .title {
    display: block;
    font-size: 13.5px;
    font-weight: 600;
    line-height: 1.4;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: color .15s;
}

.card a:hover .title { color: var(--primary); }

/* 更新状态("更新至12集")= warn 语义 pill: weak 底 + 强色字, 配方同 ui-kit.css:84 的 .uk-pill.warn。
   尺寸/圆角/字号/字重和 currentColor 圆点都走上面那套 pill 基配方(ui-kit.css:82-83), 这里只挑色 +
   自己的定位外边距。原来这条自己写了 1px 8px 的 padding 且没有圆点, 是全站 pill 里最矮的一个。
   display 不再声明: 基配方给的 inline-flex 就是要的(ui-kit.css:82), 圆点得靠它当 flex 项。 */
.card .status {
    margin-top: 6px;
    background: var(--warn-weak);   /* ui-kit.css:84 */
    color: var(--warn);             /* ui-kit.css:84 */
}

.card .sub {
    display: block;
    margin-top: 5px;
    font-size: 12px;
    color: var(--faint);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---------- 分页 ---------- */
/* 前后页是真链接(SEO 靠 rel=prev/next 理解序列)。整组的尺寸配方 = 后台翻页器 ui-kit.css:135
   (`--bs-pagination-padding-x:.6rem; --bs-pagination-padding-y:.22rem; --bs-pagination-font-size:12.5px`),
   未选中项配色 = ui-kit.css:136 的 .page-link(muted 字 + --border 边 + --surface 底),
   当前页 = ui-kit.css:137 的实心主色。 */
.pager {
    display: flex;
    justify-content: center;
    align-items: center;
    /* ‼️ 2026-08-01 改成数字页码(照 news_raw.jsp 的滑窗)之后必须允许换行: 项数从 3 个涨到最多
       "上一页 + 1 + … + 7 个页码 + … + 末页 + 下一页 + 去第N页表单" = 14 个。不换行的话窄一点的
       视口就会把它们挤扁甚至溢出横滚。 */
    flex-wrap: wrap;
    gap: 10px;
    padding: 28px 0 8px;
}

/* ‼️ 复核修复(低危)"分页控件比 erp 胖近一倍": 原来是 padding:7px 15px / 13.5px / 600, 三个值一个
   都没对上 ui-kit.css:135 的 .22rem .6rem / 12.5px。注意这不是 zoom .9 的反向补偿 —— 本文件没抄
   zoom(见文件头), 而且 12.5px 按 .9 反除也不是 13.5px。字重取 500: ui-kit.css:135-136 的
   .page-link 压根不声明字重(等于 Bootstrap 的 400), 但门户这几个是纯文字链接、没有 Bootstrap 的
   底衬, 400 会显得比后台虚 —— 500 是 ui-kit 里"未选中控件"的字重(ui-kit.css:41 的 .nav-item),
   取它才不算发明新值。 */
.pager a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: .22rem .6rem;      /* ui-kit.css:135 */
    border: 1px solid var(--border);    /* ui-kit.css:136 */
    border-radius: var(--r);            /* ui-kit.css:101 —— erp 的圆角三档里控件用 --r */
    background: var(--surface);         /* ui-kit.css:136 */
    color: var(--muted);                /* ui-kit.css:136 */
    font-size: 12.5px;          /* ui-kit.css:135 */
    font-weight: 500;           /* ui-kit.css:41 */
    transition: background-color .15s, border-color .15s, color .15s;
}

.pager a:hover { background: var(--hover); border-color: var(--border-strong); color: var(--text); }

/* 方向箭头用伪元素, 不动 JSP 里的文案(改文案要动 5 个页面, 不值得)。
   line-height:1 让 16px 的箭头不把行盒顶高: .pager a 是 align-items:center 的 flex, 行高最高的
   那个子项决定高度, 文字行盒 12.5×1.5=18.75px 已经比箭头的 16px 高, 所以箭头不参与撑高。 */
.pager a.prev::before { content: "\2039"; font-size: 16px; line-height: 1; }
.pager a.next::after { content: "\203A"; font-size: 16px; line-height: 1; }

/* ‼️ 复核修复(中危)"两个当前项一个最重一个最轻": 原来 .cur 只是一行灰字(color:var(--muted);
   font-size:12.5px), 连底色和边框都没有 —— 而 erp 的当前页是实心主色胶囊
   (ui-kit.css:137 `.pagination .page-item.active .page-link{background:var(--primary);
   border-color:var(--primary);color:#fff}`)。这是"选中态倒过来"的另一半, 和上面 .type-nav a.on
   一起改: 导航选中回到弱底(erp 的选中语言), 分页当前页升到实心(erp 的实心语义就是留给它的)。
   尺寸/字重和左右两个 a 完全一致(含那 1px 边框), 三个胶囊才会等高、基线不跳。
   等宽数字保留(ui-kit.css:198 的 font-variant-numeric), 防翻页时页码宽度抖动。 */
.pager .cur {
    display: inline-flex;
    align-items: center;
    padding: .22rem .6rem;              /* ui-kit.css:135, 同 .pager a */
    border: 1px solid var(--primary);   /* ui-kit.css:137 */
    border-radius: var(--r);            /* ui-kit.css:101 */
    background: var(--primary);         /* ui-kit.css:137 */
    color: #fff;                        /* ui-kit.css:137 */
    font-size: 12.5px;                  /* ui-kit.css:135 */
    font-weight: 500;                   /* 同 .pager a, 见上面注释 */
    font-variant-numeric: tabular-nums; /* ui-kit.css:198 */
}

/* 数字页码。样式全部继承 .pager a(同一条规则), 这里只补两件 .pager a 管不到的:
   等宽数字(翻页时页码宽度不抖)和一个最小宽度(个位数页码不能比两位数窄一截, 否则整排不齐)。
   ‼️ 没有再声明底色/描边/字号 —— 它们必须和 .pager a 逐值相同, 复制一遍迟早漂移。 */
.pager a.num {
    justify-content: center;
    min-width: 2.1rem;
    font-variant-numeric: tabular-nums;   /* 同 .pager .cur */
}

/* 省略号: 不是控件, 不给描边也不给底色, 只是个间隔标记。
   与 .pager a / .pager .cur 同字号同行高, 三者基线才对齐。 */
.pager .gap {
    color: var(--faint);
    font-size: 12.5px;
    font-weight: 500;
    padding: .22rem .2rem;
    user-select: none;
}

/* 去第 N 页 —— 一个 GET 表单, 不是 JS。
   ‼️ 它是 .pager 这个 flex 容器的一个子项, 自己也得是 flex, 否则里面的 label/input/button
      会按行内基线排, 和左边那排胶囊对不齐。 */
.pager-jump {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    /* 与页码之间比页码彼此之间再拉开一点, 让"翻页"和"跳页"是两组东西 */
    margin-left: 6px;
    color: var(--muted);
    font-size: 12.5px;
    font-weight: 500;
}

/* 输入框: 和 .search-box input 同一套(--bg 底 + 1px 描边 + --r 圆角), 但宽度按页码收窄。
   ‼️ 去掉 number 类型的上下箭头: 那两个箭头在 12.5px 的框里只有几像素高, 点不中反而挡字。 */
.pager-jump input[type="number"] {
    width: 4.2rem;
    padding: .22rem .5rem;              /* 同 .pager a 的纵向内边距, 三者等高 */
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--bg);
    color: var(--text);
    font-size: 12.5px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    text-align: center;
    transition: border-color .15s, box-shadow .15s;
    -moz-appearance: textfield;
    appearance: textfield;
}

.pager-jump input[type="number"]::-webkit-outer-spin-button,
.pager-jump input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.pager-jump input[type="number"]:hover { border-color: var(--border-strong); }

/* focus 光圈与 .search-box 一致(3px + --primary-weak), 全站输入框是同一种反馈 */
.pager-jump input[type="number"]:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px var(--primary-weak);
}

/* 按钮: 与 .pager a 同尺寸同描边, 只是可点的是 button 不是 a */
.pager-jump button {
    padding: .22rem .6rem;              /* 同 .pager a */
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface);
    color: var(--muted);
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
    transition: background-color .15s, border-color .15s, color .15s;
}

.pager-jump button:hover { background: var(--hover); border-color: var(--border-strong); color: var(--text); }

/* ---------- 详情页 ---------- */
.detail { padding-top: 20px; }

/* 面包屑: 一行小字, 不抢 h1 的视觉。最后一级(当前页)是灰的, 前两级是可点的链接色。
   ‼️ 用 flex + wrap: 片名可能很长(库里最长 51 字), 窄屏必须能折行而不是撑破容器。 */
.crumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    padding-bottom: 12px;
    color: var(--faint);
    font-size: 12.5px;
}

.crumb a { color: var(--muted); }
.crumb a:hover { color: var(--primary); }
.crumb .sep { color: var(--border-strong); }

/* 三块面板(head / intro / links)统一用 ui-kit 的卡片面: 白底 + 1px 描边 + 12px 圆角 + --sh-sm */
.detail .head,
.intro,
.links {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-sm);
    padding: 20px;
}

.detail .head { display: flex; gap: 24px; }

/* 沉浸式海报背景(2026-08-06, detail.jsp .head-bg): 同一张海报放大虚化铺满头部卡片。
   ‼️ inset 负值是必须的: blur 会让边缘发虚透底, 往外扩一圈再由 .head 的 overflow 裁掉。
   ‼️ 不透明度压在 .22 —— 它是氛围不是内容, 文字对比度不能被它吃掉; 底部渐变回收到卡片
   底色(var(--surface)), 属性列表越往下越贴近纯色底, 长简介也读得动。 */
.detail .head { position: relative; overflow: hidden; }

.detail .head .head-bg {
    position: absolute;
    inset: -40px;
    background-size: cover;
    background-position: center 25%;
    filter: blur(32px) saturate(1.25);
    opacity: .22;
    pointer-events: none;
}

.detail .head .head-bg::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, transparent 30%, var(--surface) 96%);
}

/* 正文抬到背景层之上(head-bg 自己不带 z-index, 兄弟里 position+z-index 的画在它上面) */
.detail .head > :not(.head-bg) { position: relative; z-index: 1; }

/* 文字列: 有意用 `> div` 而不是 .info —— detail.jsp 的 .head 里现在确实写着 <div class="info">(JSP 侧后加的),
   但 .info 不在类名契约里, 用结构选择器就不会把它变成第二个事实契约; 将来那个 div 改名也不用回来改样式。
   min-width:0 是关键: 不写它, 长片名/长主演会把 flex 项撑破导致海报被压扁。 */
.detail .head > div { flex: 1 1 auto; min-width: 0; }

.poster-big {
    width: 220px;
    flex: none;
    aspect-ratio: 3 / 4;
    object-fit: cover;
    border-radius: var(--r);
    border: 1px solid var(--border-2);
    background: var(--hover);
}

.detail h1 {
    margin: 0 0 6px;
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -.01em;
    line-height: 1.3;
}

.detail h1 .year { color: var(--muted); font-weight: 500; }

/* h1 底下那行副标题。‼️ 类名叫 .en 是历史包袱: 2026-08-06 英文正文上屏后它装的是
   **对侧语言**的片名 —— 中文页放英文名(照旧), 英文页放中文原名并带 lang="zh-CN"。
   样式两种语言通用, 所以没跟着改名; 但别再假设这里一定是英文。 */
.detail .en { margin: 0 0 14px; color: var(--muted); font-size: 13.5px; }

/* 属性表: em 是固定宽标签列, flex 行比 inline-block 稳(值换行时不会跑到标签下面) */
.attrs { list-style: none; margin: 0; padding: 0; }

.attrs li {
    display: flex;
    gap: 10px;
    padding: 4px 0;
    font-size: 13.5px;
}

.attrs em {
    flex: none;
    width: 56px;
    font-style: normal;
    color: var(--muted);
    font-size: 13px;
}

/* ‼️ 预留规则, 当前不命中任何元素(复核点名的"死规则"之一, 有意保留): detail.jsp 的 <ul class="attrs">
   现在每个 <li> 都是 <em>标签</em> + fn:escapeXml 出来的纯文本, 没有 <a>。留着是为了"将来地区/类别/导演做成聚合页链接"时
   不用回来补样式 —— 但下一个人别以为它在生效。同类预留还有 .intro a / .site-footer a。 */
.attrs a { color: var(--primary); }

.intro,
.links,
.related { margin-top: 16px; }

/* 相关推荐: 与 .intro/.links 同一套面板配方(白底 + 1px 描边 + 12px 圆角 + --sh-sm),
   见上面那条组规则 —— 这里只补它自己的两件事。
   ‼️ 里面的 .card-list / .card 直接复用首页那套, 一个新类名都不加。 */
.related { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--sh-sm); padding: 20px; }
/* 卡片列表在面板里不需要再吃 .wrap 的上边距 */
.related .card-list { margin-top: 12px; }

/* ---------- 最近浏览(2026-08-03, js/torrent.js 从 localStorage 渲染进 #recentBox) ---------- */
/* 面板配方与 .related 同款; 里面的卡片直接复用 .card-list/.card, 不加新卡片类。
   ‼️ 不声明 display: 容器默认带 hidden 属性, UA 的 [hidden]{display:none} 要能生效 ——
      在这里写 display 值会把 hidden 顶掉(作者样式压过 UA 样式), 空容器就会露出一个空面板。 */
.recent {
    margin-top: 24px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-sm);
    padding: 20px;
}

/* 标题行与 .links h2 同一套(15px/700/flex); 选择器单列一条是因为那边的组规则不便再挂新成员
   (它们在 .intro/.links 语境下, 这块是脚本渲染的独立面板)。 */
.recent h2 {
    margin: 0 0 14px;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: -.01em;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

/* "清除记录" = 弱化文字钮(同 .facet-more 的档位: 无底无框), 推到标题行右端 */
.recent .recent-clear {
    margin-left: auto;
    border: none;
    background: none;
    padding: 0 2px;
    color: var(--muted);
    font-size: 12.5px;
    font-family: inherit;
    cursor: pointer;
}

.recent .recent-clear:hover { color: var(--primary); }

.intro h2,
.links h2 {
    margin: 0 0 14px;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: -.01em;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

.intro p {
    margin: 0;
    color: var(--text);
    line-height: 1.75;
}

/* ‼️ 预留规则, 当前不命中(同 .attrs a): detail.jsp 的 <section class="intro"> 里是
   `<p>${fn:escapeXml(resource.intro)}</p>`, 转义过的纯文本, 不会有 <a>。将来简介支持富文本时才生效。 */
.intro a { color: var(--primary); }
.intro a:hover { text-decoration: underline; }

/* 条数 = mute pill, 和 .page-title .total 完全同一套: 尺寸/圆角/字号/字重/字距走上面的 pill 基配方
   (ui-kit.css:82), 这里只挑色。原来这条自己写了一遍 2px 9px 等六个值。 */
.links .cnt {
    background: var(--hover);
    color: var(--muted);
}

/* 窄屏时资源表在卡片内横滚, 不撑破页面(断点里给 .link-table 配 min-width)。
   ‼️ 复核修复(低危): 原注释断言"桌面无溢出, 这里不会出现滚动条" —— 说明列是唯一可伸缩列,
   一旦列内标记全都 nowrap, 表格 min-content 宽度就可能顶破容器, 桌面也会出滚动条。
   下面 .warn 已解除 nowrap 允许折行, 但这里改成不作断言: 桌面**通常**无溢出。
   本轮又堵掉一条: 操作列兜底分支里的裸 URL 原文(见下面 .link-table .ops:has(.warn))。
   已知遗留(未在本轮修): 本 section 内还包着 <h2>资源列表, 横滚时标题会跟着滑出视口 ——
   彻底修需要在 detail.jsp 里给 <table> 外面加一层滚动容器(新增契约类), 属于类名契约变更。 */
.links { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ---------- 资源链接表 ---------- */
/* 逐字复刻 ui-kit.css:89-94 的 .uk-tbl 特征: 表头 12px/大写/字距 .03em/muted 色/
   --surface-2 底; 行线只用更浅的 --border-2; 最后一行去线; hover 整行染 --surface-2。 */
.link-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13.5px;
    font-variant-numeric: tabular-nums;
}

.link-table th {
    text-align: left;
    color: var(--muted);
    font-weight: 600;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: .03em;
    padding: 11px 14px;
    border-bottom: 1px solid var(--border-2);
    background: var(--surface-2);
}

.link-table td {
    padding: 12px 14px;
    border-bottom: 1px solid var(--border-2);
    transition: background-color .12s;   /* ui-kit.css:194 */
}

.link-table tbody tr:last-child td { border-bottom: 0; }
.link-table tbody tr:hover td { background: var(--surface-2); }

/* ‼️ 说明列必须允许在任意字符处断行: 那一列的内容可能是一整条 magnet URI 或超长文件名,
   一串 60+ 字符的不可断 ASCII 会把单元格**从内部**撑破(实测 375px 下 scrollW 372 / clientW 291),
   一路冒泡让整页出现 49px 横滚, 而且**没有任何元素的右边界越过视口** —— 光看 boundingRect 查不出来。
   用 overflow-wrap:anywhere 而不是 word-break:break-all: 后者会把这一格里所有文本(包括中文说明)
   在任意字符处断; anywhere 只在"不断就要溢出"时才断, 且会计入 min-content 尺寸(这点是表格不被撑破的关键)。
   桌面原来靠 .links{overflow-x:auto} 兜住, 而窄屏那条在改卡片布局时已经关掉, 必须有这一道。 */
.link-table .label { overflow-wrap: anywhere; }

/* 列宽: 前三列定宽, 说明列(td.label, 本文件有意不给它写规则)吃掉剩余宽度 */
.link-table .type { width: 88px; color: var(--text); font-weight: 500; }
.link-table .res { width: 96px; color: var(--muted); }

/* nowrap 保留: 操作列正常只有"下载 + 复制链接"两个钮, 不许被挤成两行(它同时把这一列的
   min-content 撑到 ≈148px, 是桌面/移动两档下按钮不堆叠的唯一保证)。 */
.link-table .ops {
    width: 200px;
    white-space: nowrap;
}

/* ‼️ 追加修复(桌面横滚的最后一条路径, 本轮新发现): JSP 侧在本文件写完之后给下载链接加了协议白名单,
   并配了一条兜底分支 —— 协议不在白名单时不渲染成 <a>, 而是把 URL 原文当**裸文本节点**塞进这一格
   (按项目铁律"解析失败也保原文"), 那段文本没有类名可挂。
   上面那条 nowrap 撞上一条不可断的长 URL, 这一列的 min-content 宽度直接顶破容器, 下面 .links 的
   overflow-x:auto 在**桌面**也会出滚动条 —— 正是本文件 .links 处那条"桌面通常无溢出"想避免的情况;
   detail.jsp 那段的注释也已经明确把"给 .ops 补断行"这件事派给 CSS 侧。
   ‼️ 用 :has(.warn) 只钉住兜底分支那一行, 不动正常行 —— 兜底分支里跟着一个 <span class="warn">协议不支持</span>,
   是 .ops 内唯一会出现 .warn 的形态(正常行的 .warn 挂在说明列 td.label, 不在本列), 所以这条既解决了溢出, 又不会让正常行的
   两个钮失去 nowrap 保护。:has() 的渐进增强口径直接沿用 erp: ui-kit.css:140-141 的贴底 flex 就是
   "老浏览器不识别则整段忽略, 布局回到现状"—— 这里回到的现状是靠 .links 横滚兜住, 同样不破版。
   ‼️ 为什么配 overflow-wrap:anywhere 而不是 word-break:break-all —— break-all 会让这一格里**所有**
   文本(包括 .warn pill 的中文提示)在任意字符处断; anywhere 只在"不断就要溢出"时才断, 且会计入
   min-content 尺寸(这一点正是表格不再被撑破的关键, word-break:break-word 不计入所以在这里无效)。
   ‼️ 与 erp 的关系: ui-kit.css 没有对应条目 —— 后台表格是靠 .uk-tbl-scroll(ui-kit.css:94)外挂滚动
   容器兜溢出, 门户的等效物就是 .links 的 overflow-x:auto; 这里补的是"先别溢出"那一层, 不另立语言。
   特异性: :has() 取参数里最高的一项计入, 本条 0-3-0 压得住上面 0-2-0。 */
.link-table .ops:has(.warn) {
    white-space: normal;
    overflow-wrap: anywhere;
}

/* 上一条把整格放开折行后, 两个钮自己还得钉住(否则"复制链接"会被 anywhere 从中间断开)。
   0-3-0 压得住基类 .btn 的 0-1-0, 不需要 !important。 */
.link-table .ops .btn {
    white-space: nowrap;
}

/* 三个行内标记都走 pill 基配方(见文件上部"组件: 状态 pill", ui-kit.css:82), 这里只管定位外边距 +
   各自的语义色。
   ‼️ 复核修复(中危)"pill 碎成 5 套": 原来这条组规则自己写了 padding:1px 7px + border-radius:var(--r-sm)
   —— 是全站唯一用 6px 圆角冒充 pill 的地方, 而 .warn 还额外把字重压到 500, 一行里三个标记的高度、
   圆角、字重全不一样。现在三个都和卡片状态、标题计数共用同一套值。 */
.link-table .grp,
.link-table .pwd,
.link-table .warn {
    margin-left: 8px;
}

/* 只有这两个不许断行: .grp 是压制组名(BluRay-FRDS 这类, 断开就读不出是一个词),
   .pwd 是提取码(断行会让用户抄错)。
   ‼️ .warn 不在这个列表里(复核修复, 低危): 它的文案是整句("需电驴客户端, 有效性未验证", 12px 下约
   170px), 说明列是本表唯一可伸缩列, 一旦这句也 nowrap, 表格 min-content 宽度就会顶破容器,
   桌面也撑出横滚条。让它跟着单元格宽度自然折行, 所以这里不给它 nowrap(基配方也没有 nowrap)。 */
.link-table .grp,
.link-table .pwd {
    white-space: nowrap;
}

.link-table .grp { background: var(--hover); color: var(--muted); }
.link-table .pwd { background: var(--primary-weak); color: var(--primary); }

/* 2026-08-03 新徽标组(pill 基配方已在文件上部并挂, 这里只挑色 + 定位):
   语言标签/整季包 = 中性信息; 存活状态 = 语义色三档(ok/warn/danger, erp 语义色盘现成)。 */
.link-table .ltag,
.link-table .pack,
.link-table .cam,
.link-table .alive-b {
    margin-left: 8px;
    white-space: nowrap;
}

.link-table .ltag { background: var(--hover); color: var(--muted); }
.link-table .pack { background: var(--primary-weak); color: var(--primary); }
/* 枪版标记(2026-08-06): 走 danger 档, 和死链徽标同色 —— 这是本表最强的一记"别下这条"。
   ‼️ 为什么不用 warn(疑似失效那一档): warn 的语义是"可能有问题, 也可能没有", 而枪版是**确定**的
      低质量, 不是概率事件。用户在 ?cam=1 里是主动来看的, 标记必须强到一眼分得清哪几行是枪版,
      弱一档就等于没标 —— 用户拍板原话是"标记一下"。
   ‼️ 与 .alive-b.dead-b 同色不冲突: 死链那条同时还有 tr.dead 的整行降透明 + 删除线,
      两者在同一行里也分得开(而且死链的枪版行本来就该两个标记都出)。 */
.link-table .cam { background: var(--danger-weak); color: var(--danger); }
.link-table .alive-b.ok-b { background: var(--ok-weak); color: var(--ok); }
.link-table .alive-b.sus-b { background: var(--warn-weak); color: var(--warn); }
.link-table .alive-b.dead-b { background: var(--danger-weak); color: var(--danger); }

/* 死链行(2026-08-03): 整行降透明 + 说明文字删除线 —— 排序里它们已沉底(LIST_LINKS),
   这里只是视觉确认"别点我"。按钮不划掉: 复制原文/报失效仍然是合法操作。 */
.link-table tr.dead td { opacity: .55; }
.link-table tr.dead .label { text-decoration: line-through; }

/* 失效反馈钮(2026-08-03): 最次要的动作, 观感与 .btn.copy 同档; hover 才露危险语义色 */
.btn.fail {
    margin-left: 6px;
    border-color: var(--border);
    color: var(--faint);
    background: transparent;
}

.btn.fail:hover { background: var(--danger-weak); border-color: var(--danger); color: var(--danger); }
.btn.fail:disabled { opacity: .6; cursor: default; }

/* 迅雷钮(2026-08-03): 与"下载"同档的描边钮(同一行的两个平级动作) */
.btn.thunder {
    margin-left: 6px;
    border-color: var(--border);
    color: var(--muted);
    background: transparent;
}

.btn.thunder:hover { background: var(--hover); border-color: var(--border-strong); color: var(--text); }
/* warn 语义变体 —— ui-kit.css:84 的 .uk-pill.warn 逐字。圆点由上部 pill 段的
   `.link-table .warn::before` 出(ui-kit.css:83): 这是风险状态, 按 erp 的语义该带点。
   折行时圆点会随 align-items:center 竖直居中在整块上(erp 的 pill 从不折行, 没有这个形态),
   属可接受观感; 圆点自身有 flex:none 所以不会被压成椭圆。 */
.link-table .warn { background: var(--warn-weak); color: var(--warn); }

/* ‼️ 追加(本轮新发现, 同样起因于 JSP 新增的白名单兜底分支): .warn 现在多了第二个挂载点 ——
   兜底分支把它放进了**操作列**, 而且是那一格的第一个元素(后面才是 URL 原文和"复制链接"钮)。
   上面那 8px 左外边距是给"跟在说明文字后面"的原场景写的(说明列 td.label 里的 .grp/.pwd/.warn), 落在一格的首元素上
   就成了一道没来由的缩进, 和同列其它行的按钮左沿对不齐。这里按挂载位置清零, 不动原场景。
   特异性 0-3-0 压得住上面那条 0-2-0; 语义色和 pill 基配方(ui-kit.css:82-84)都照旧继承, 不受影响。 */
.link-table .ops .warn { margin-left: 0; }

/* ---------- 按钮 ---------- */
/* 基类 = ui-kit.css:101 + :192-193 的值; padding/display/border 是 ui-kit 没给、
   原本由 Bootstrap 提供的部分 —— 前台不引 Bootstrap, 按 bs5 默认值补齐。 */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: .375rem .75rem;    /* bs5 .btn 默认值(ui-kit 不声明 padding) */
    line-height: 1.5;
    border: 1px solid transparent;
    border-radius: var(--r);    /* ui-kit.css:101 */
    font-family: inherit;
    font-size: 13.5px;          /* ui-kit.css:101 */
    font-weight: 600;           /* ui-kit.css:101 */
    cursor: pointer;
    transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s, transform .06s;
    /* 默认态 = .btn-outline-primary(ui-kit.css:104): 下载是主动作, 描边不抢版面 */
    background: transparent;
    border-color: var(--primary);
    color: var(--primary);
}

.btn:hover { background: var(--primary); color: #fff; }        /* ui-kit.css:105 */
.btn:active { transform: translateY(.5px); }                    /* ui-kit.css:193 */

/* 在线播放 = 实心主色(唯一强调钮)。原来这里是橙色 #f0a020, 设计系统里没有这个色,
   门户不该自带第二套主色, 所以统一收到 --primary。
   ‼️ 注释订正(2026-08-06): 这里原来写着".btn-primary 当前不命中任何元素", **已经不成立** ——
   404 页与收藏页空态的"回首页"(class="btn btn-primary")、以及收藏页订阅框的"复制"按钮都在用它。
   detail.jsp 的"在线播放"仍然是 class="btn play"(那才是那条注释真正想说的事)。
   下面紧跟的 :not(.btn) 那条注释里记的正是这个类真出过的事故, 两处对照着看。 */
.btn.play,
.btn-primary {
    background: var(--primary);
    border-color: var(--primary);
    color: #fff;
}

.btn.play:hover,
.btn-primary:hover {
    background: var(--primary-hover);
    border-color: var(--primary-hover);
    color: #fff;
}

/* 复制链接 = 次要动作, 降级成 .btn-outline-secondary(ui-kit.css:109-110) */
.btn.copy {
    margin-left: 6px;
    border-color: var(--border);
    color: var(--muted);
    background: transparent;
}

.btn.copy:hover { background: var(--hover); border-color: var(--border-strong); color: var(--text); }

/* "复制全部链接"(2026-08-03, detail.jsp 资源列表标题行里): 次要动作, 观感与 .btn.copy 同档
   (outline-secondary), 尺寸对齐表内按钮那档(ui-kit.css:128 的 12px/.2rem .6rem/500)。
   h2 是 flex 行, margin-left:auto 把它推到右端, 与左边的标题/计数拉开。
   ‼️ 无 JS 或整表没有可复制链接时由脚本藏掉(js/torrent.js), CSS 不用管空态。 */
.links h2 .copy-all {
    margin-left: auto;
    font-size: 12px;            /* ui-kit.css:128 */
    padding: .2rem .6rem;       /* ui-kit.css:128 */
    font-weight: 500;           /* ui-kit.css:128 */
    border-color: var(--border);
    color: var(--muted);
    background: transparent;
}

.links h2 .copy-all:hover { background: var(--hover); border-color: var(--border-strong); color: var(--text); }

/* ‼️ 不能省: 基类 .btn 声明了 display:inline-flex, 作者样式会压过 UA 的 [hidden]{display:none} ——
   脚本在"整表没有可复制链接"时 btn.hidden=true, 没有这条按钮就永远藏不掉(与 .back-top 同一个坑)。 */
.links h2 .copy-all[hidden] { display: none; }

/* 表格内按钮收小一档 —— 同 ui-kit.css:128 只在表格里改 .btn-sm 的做法。
   ‼️ 复核修复(低危)"表内按钮比 erp 大一档且更重": 原来是 font-size:12.5px + padding:5px 11px, 字重
   还沿用基类的 600 —— 注释自称照 ui-kit.css:128, 但那条是
   `.table .btn-sm{font-size:12px;padding:.2rem .6rem;font-weight:500}`, 三个值一个都没对上。
   其中 600→500 和"密度"无关, 是纯字重错位: 表内按钮在 erp 里是**次要**控件, 字重比正文轻。
   三个值现在逐个对齐; 特异性 0-2-0 压得住基类 .btn 的 0-1-0, 不需要 !important。 */
.link-table .btn {
    font-size: 12px;            /* ui-kit.css:128 */
    padding: .2rem .6rem;       /* ui-kit.css:128 */
    font-weight: 500;           /* ui-kit.css:128 */
}

/* 链接截断提示: 和表格拉开一档距离, 语气是"补充说明"所以用 muted; 里面的链接才是主色。 */
.links-more {
    margin: 14px 0 0;
    color: var(--muted);
    font-size: 13px;
    text-align: center;
}

.links-more a { color: var(--primary); margin-left: 6px; }
.links-more a:hover { text-decoration: underline; }

/* 枪版开关行(2026-08-06): 与 .links-more 同一档"补充说明"的观感, 刻意**不**做成按钮 ——
   它是一个次要的、多数人不该点的入口, 做成按钮会把它抬到和"下载"同级。
   ‼️ 不复用 .links-more 类名而是新写一条(值几乎相同): 两者语义不同, 出现条件也不同
      (一个是"截断了", 一个是"藏了枪版"), 将来任一侧要调都不必担心动到另一侧;
      而且同一页上两条可能**同时出现**, 挤在一起时要能分别调 margin。
   ‼️ 上外边距比 .links-more 大一档: 它可能紧跟在 .links-more 之后, 也可能紧跟在
      .empty-state 之后(全是枪版的作品), 两种场景下都要看得出是独立的一段。 */
.cam-more {
    margin: 18px 0 0;
    color: var(--muted);
    font-size: 13px;
    text-align: center;
}

.cam-more a { color: var(--primary); margin-left: 6px; }
.cam-more a:hover { text-decoration: underline; }

/* ---------- 播放页 ---------- */
/* 播放器外框跟卡片同一套圆角/描边; 里面是纯黑视频面, 所以 overflow:hidden 裁圆角。
   max-height 用 vh 是安全的: 本文件没有 zoom:.9, 视口单位不需要反除补偿。 */
.player-wrap {
    background: #000;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-sm);
    overflow: hidden;
    margin-top: 4px;
}

.player-wrap video {
    display: block;
    width: 100%;
    max-height: 72vh;
    max-height: 72dvh;
    background: #000;
    /* ‼️ 2026-08-06 用户报"播放器为什么这么扁"。根因: <video> 在**元数据加载出来之前**没有内在尺寸,
       只声明 width:100% 的话高度会退回 UA 默认(约 150px), 于是撑成一条又宽又矮的黑条 ——
       而本站的播放源来自第三方且**经常整批失效**(实测 mv.shaxyd.com 403 / mv1.zhihuanyan.com 连不上),
       元数据永远加载不出来, 那条黑条就一直在那儿, 看着像播放器坏了。
       给一个 16:9 的占位比例, 加载不出来也保持正常播放器的形状;
       真视频有自己的比例时 object-fit:contain 会在框内留黑边而不是拉伸变形。 */
    aspect-ratio: 16 / 9;
    object-fit: contain;
}

/* ‼️ 复核修复(中危, 同 .card 那条的同一机制): video 填满 .player-wrap 的 padding box,
   而 .player-wrap 有 overflow:hidden, 浏览器画在外侧的 UA 焦点环会被整圈裁掉 —— 键盘用户
   Tab 到播放器看不出焦点在哪。用负偏移把环画进内侧。 */
.player-wrap video:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -3px;
}

/* ‼️ 复核修复(低危): .player-tip 在 play.jsp 里是 <p>(现在有两个挂载点: 能播时的提示、协议不支持时的
   降级提示, 两个都是 <p class="player-tip">), 这里原来只写了 padding, UA 的 1em
   (13px)上下外边距还在 —— 上方实际间距是 13+14=27px 而不是写的 14px, 下方多出的 13px 又叠在
   .site-main 的 padding-bottom:32px 上, 使 play.jsp 到页脚 45px、其余 4 页 32px。清掉外边距,
   间距全部交给 padding 表达。 */
.player-tip {
    margin: 0;
    padding: 14px 0 0;
    color: var(--muted);
    font-size: 13px;
}

.player-tip a { color: var(--primary); }
.player-tip a:hover { text-decoration: underline; }
.player-tip strong { color: var(--text); }   /* JS 失败提示会塞 <strong>, 别是灰的 */

/* ‼️ 2026-08-06 用户定: 源失效时"保留链接, 但在播放页显示该源已失效"。
   原来失败提示只是把同一行灰字加粗, 混在常驻的"可能随时失效"说明里, 用户根本分不出
   "这是通用免责声明"还是"这次真的挂了"。这里给它一个明确的警示块。
   用 --warn 而不是 --danger: 源挂了不是用户操作出错, 下面还有下载链接可用, 不必用红色吓人。 */
.player-tip.dead {
    margin-top: 14px;
    padding: 12px 14px;
    border: 1px solid var(--warn);
    border-radius: var(--r);
    background: var(--warn-weak);
    color: var(--text);
}
.player-tip.dead strong { color: var(--warn); }

/* ‼️ 断行保险(2026-08-01, 与 .link-table .label 同因): 这两处都会输出**采集来的原文**, 里面可能有
   一长串不可断的 ASCII —— 播放页协议不受支持时会把地址原文当纯文本显示(§13.5 铁律: 解析失败也保原文),
   .attrs 里的导演/主演/别名同样是第三方原文。
   一条 60+ 字符不可断串会把容器**从内部**撑破(scrollWidth > clientWidth), 整页因此横滚,
   而且用 boundingRect 一个越界元素都查不到 —— 那正是 /movie/4675.html 那次的症状(见 ROADMAP §43.2)。
   用 anywhere 不用 break-all: 只在"不断就要溢出"时才断, 中文说明不会被任意切开。 */
.player-tip,
.attrs li { overflow-wrap: anywhere; }

/* 空态里的**裸链接**要能被认出来是链接。
   ‼️ 必须写 :not(.btn) —— 2026-08-01 实测踩到: 404 页把出口改成 <a class="btn btn-primary"> 之后,
      这条 0-1-1 的规则压过了 .btn-primary 的 0-1-0(color:#fff), 于是按钮变成**蓝底蓝字**, 整个看不见。
      同类陷阱: 任何"给某容器内所有 a 上色"的规则, 只要容器里可能出现按钮, 就必须把按钮排除掉。 */
.empty-state a:not(.btn) { color: var(--primary); }
.empty-state a:not(.btn):hover { text-decoration: underline; }

/* ---------- 页脚 ---------- */
/* flex:none = 吸底 flex 链的收尾项(见 body 处注释); 原来的 margin-top:40px 去掉了 ——
   吸底靠中间区 flex:1 吃剩余高度, 再加外边距反而会在短页面上多出一条缝。
   配色跟 erp 一致走浅色(白面 + 上边线 + muted 字), 不再用深色块。 */
.site-footer {
    flex: none;
    background: var(--surface);
    border-top: 1px solid var(--border);
    color: var(--muted);
    font-size: 13px;
    text-align: center;
    /* ‼️ 2026-08-06 用户: "footer 占这么大空间"。原来 20px + 三行内容 = 页脚比它承载的信息还高。
       三条入口并成一行、免责降为注脚(见 footer.jsp)后, 上下留白同步收到 14px。 */
    padding: 14px 0;
}

.site-footer p { margin: 0; }
/* ‼️ 原注释说"当前不命中, footer.jsp 里只有一个 <p> 没有 <a>" —— 2026-08-01 起**已经命中**了:
   页脚多了一条语言切换链接(.lang-switch a)。规则本身不用改, 把这条说明更正掉, 免得下一个人
   照旧注释以为它还是死规则。 */
.site-footer a { color: var(--muted); }
.site-footer a:hover { color: var(--primary); }

/* 语言切换: 一条低调的文字链接, 不做成按钮 —— 它是"偶尔用一次"的东西, 抢不过免责声明那行的位置。
   与免责声明拉开一点行距, 让它读起来是独立的一条而不是同一句的续行。 */
.site-footer .lang-switch { margin-top: 8px; }
.site-footer .lang-switch a { text-decoration: underline; text-underline-offset: 2px; }

/* RSS 入口(2026-08-03): 与语言切换同档的弱链接行, 配色由上面的 .site-footer a 统一管 */
/* ---- 页脚单行(2026-08-06, 照 www/news/minify_raw.jsp:331-339 的形态) ----
   那边是: 一整行居中 + 每项 text-nowrap + 项间空格 + 容器 word-wrap 断行。
   这里同构, 按用户要求不放 copyright 与公司名。
   ‼️ 各项之间的间距用 margin 而不是 HTML 里的 &nbsp;: 标签之间没留空白就不会出现
      "换行被当成一个空格"的不可控间距, 间距完全由 CSS 说了算。 */
.site-footer .foot-line {
    word-wrap: break-word;
    line-height: 1.9;                 /* 窄屏折行时行与行不粘在一起 */
}
.site-footer .foot-line .fl-item {
    white-space: nowrap;              /* 链接本身绝不从中间断开 */
    margin: 0 10px;
}
/* 免责声明: 与入口同一行, 但**不**加 nowrap —— 它是整句, 窄屏必须能自己断 */
.site-footer .foot-line .fl-note {
    margin: 0 10px;
    color: var(--faint);
}

/* ---------- 回到顶部(2026-08-03, js/torrent.js 创建) ---------- */
/* 白面圆钮 + 既有 token 阴影; 44px 直接达到触摸目标线, 桌面移动一套尺寸。
   ‼️ [hidden] 那条不能省: 本规则声明了 display:flex, 作者样式会压过 UA 的 [hidden]{display:none},
      不补这一条按钮就永远显示(和 .recent 有意不写 display 是同一个坑的两种解法)。 */
.back-top {
    position: fixed;
    right: 20px;
    bottom: 28px;
    z-index: 15;               /* 顶栏是 20, 悬浮钮别压过吸顶导航 */
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 50%;
    background: var(--surface);
    box-shadow: var(--sh);
    cursor: pointer;
    transition: background-color .15s, border-color .15s;
}

.back-top[hidden] { display: none; }

.back-top:hover { background: var(--hover); border-color: var(--border-strong); }

/* 向上箭头: 与筛选条摘要的箭头同一画法(纯 CSS 边框折角, 不引字体不外链) */
.back-top::before {
    content: '';
    width: 9px;
    height: 9px;
    border-left: 2px solid var(--muted);
    border-top: 2px solid var(--muted);
    transform: rotate(45deg) translate(2px, 2px);
}

.back-top:hover::before { border-color: var(--text); }

/* ============================================================
   2026-08-04 第三批: 体验打磨件
   ============================================================ */

/* 海报淡入: 只有脚本给 <html> 打了 .imgfade 才生效(js/torrent.js) —— 无 JS 时图片照常直出,
   绝不能出现"没有 JS 图片永远透明"的倒挂。已加载完的图脚本会立刻补 .ld, 不闪。 */
.imgfade img.poster {
    opacity: 0;
    transition: opacity .25s ease-out;
}

.imgfade img.poster.ld { opacity: 1; }

/* 面包屑当前页(片名)超长截断: 库里最长片名 51 字, 不截会把面包屑挤成三行 */
.crumb span[aria-current] {
    max-width: 18em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: inline-block;
    vertical-align: bottom;
}

/* 复制成功整行闪一下(js/torrent.js 加 .copied, 1.2s 后移除): 按钮文字变化视线容易错过,
   行底一闪才把"复制的是这一条"钉住。动效偏好 reduce 时被文件头那条全局规则关掉, 无需另写。 */
@keyframes rowcopied {
    0% { background-color: var(--ok-weak); }
    100% { background-color: transparent; }
}

.link-table tr.copied td { animation: rowcopied 1.2s ease-out; }

/* 继续观看(play.jsp): 与 .player-tip 同一行语言, 按钮是主色小钮 */
.resume-tip button {
    margin-left: 8px;
    padding: .2rem .8rem;
    border: 1px solid var(--primary);
    border-radius: var(--r-sm);
    background: var(--primary);
    color: #fff;
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
}

.resume-tip button:hover { background: var(--primary-hover); border-color: var(--primary-hover); }

/* 自动连播开关(2026-08-06, play.jsp): 弱化的行内开关, 挂在播放器下方提示行之后 */
.autonext {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 8px 0 0;
    color: var(--muted);
    font-size: 13px;
    cursor: pointer;
    user-select: none;
}

.autonext input { accent-color: var(--primary); }

/* ‼️ 这条不能省(2026-08-06 复核抓到, 本文件第三次踩同一个坑, 见 .back-top / .copy-all 两处):
   上面声明了 display:inline-flex, **作者样式压过 UA 的 [hidden]{display:none}**(origin 之争,
   与特异性无关) —— 不补这一条, 开关在"没有下一集"的场景(电影/单集/最后一集/无 JS)恒显示,
   点了还什么都不做(脚本在 return 之前根本没给它绑事件)。 */
.autonext[hidden] { display: none; }

/* 播放页选集条里"当前这集": 不可点的实心标记(复用 .ep-chips 结构) */
.ep-nav .ep-chips a.cur,
.ep-nav .ep-chips a.cur:hover {
    background: var(--primary);
    border-color: var(--primary);
    color: #fff;
    cursor: default;
}

/* 搜索即时联想(2026-08-04, js/torrent.js 渲染)。挂在 .search-box 下沿, 走弹层卡片配方。
   ‼️ .search-box 补 position:relative 作定位上下文(不影响其 flex 布局)。 */
.search-box { position: relative; }

.sug-panel {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 30;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r);
    box-shadow: var(--sh-lg);
    overflow: hidden;
}

.sug-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 14px;
    font-size: 13.5px;
    color: var(--text);
}

.sug-item span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sug-item i {
    font-style: normal;
    margin-left: auto;
    flex: none;
    color: var(--faint);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

/* 鼠标悬停与键盘选中(.on)同一态 */
.sug-item:hover,
.sug-item.on {
    background: var(--primary-weak);
    color: var(--primary);
}

/* (这里原来是"手机扫码接力"的 .qr-* 三件套, 2026-08-05 随功能一并删除) */

/* 键盘快捷键面板(按 ? 弹出, js/torrent.js 创建)。遮罩点击即关; 面板走卡片配方。 */
.kbd-mask {
    position: fixed;
    inset: 0;
    z-index: 40;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(16, 20, 28, .45);
}

.kbd-panel {
    min-width: 260px;
    max-width: 90vw;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-lg);
    padding: 18px 20px;
}

.kbd-panel h3 {
    margin: 0 0 12px;
    font-size: 15px;
    font-weight: 700;
}

.kbd-panel .row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 5px 0;
    font-size: 13px;
    color: var(--muted);
}

.kbd-panel kbd {
    flex: none;
    min-width: 2.2em;
    padding: 2px 7px;
    border: 1px solid var(--border-strong);
    border-bottom-width: 2px;
    border-radius: var(--r-sm);
    background: var(--surface-2);
    color: var(--text);
    font-family: var(--font, inherit);
    font-size: 12px;
    text-align: center;
}

/* ============================================================
   移动端 <=640px
   原则: 顶栏换行不换高度写死、卡片列数降一档、详情页海报转竖排、宽表横滚。
   不做后台那套 [data-dense] 密度切换 —— 它只影响表格 padding, 门户用不上。
   ============================================================ */
@media (max-width: 640px) {
    .wrap { padding: 0 12px; }

    /* 顶栏换行: 站名 + 登录态一行, 搜索框整行放到第二行(order:3)。
       min-height 归 0(桌面那 58px 会把换行后的两行内容挤在一行高度里), 高度交给内容 + padding。 */
    /* ‼️ 复核修复(高危)"移动端顶栏贴边": 原来这里是 `padding:10px 0` 简写。header.jsp:25 是
       <div class="wrap header-inner"> —— 同一个元素同时命中本断点开头那条 .wrap{padding:0 12px}
       和本规则, 两条特异性都是 0-1-0 而本规则源序在后, 简写把 left/right 一并写成 0, 站名方块
       和"退出"直接贴死屏幕边缘(桌面正常: 桌面的 .header-inner 压根不声明 padding)。改成纵向
       长手, .wrap 的横向 12px 就能活下来 —— 观感对齐后台 ui-kit.css:261 移动端
       .uk-topbar{padding:0 14px}(横向留白在移动端保留)。
       铁律: 任何和 .wrap 挂在同一个元素上的私有类(还有 detail.jsp 的 <div class="wrap detail">)只能用
       padding-top/right/bottom/left 长手改内边距, 绝不能用 padding 简写。 */
    .header-inner {
        flex-wrap: wrap;
        min-height: 0;
        padding-top: 10px;
        padding-bottom: 10px;
        gap: 10px;
    }

    /* 站名字号 17→16px, 同后台移动端 ui-kit.css:262 的 .uk-topbar .title{font-size:16px}。
       ‼️ 这里原来还有一条 `.brand::before{width:24px;height:24px}` 把品牌方块再缩到 24px, 已删:
       后台移动断点(ui-kit.css:256-273)压根不碰 .uk-brand .logo, 30px 是全尺寸统一值; 再缩一档等于
       在移动端又造出第三套尺寸(桌面 30 / 移动 24), 而 30px 方块配 16px 站名的比例和 erp 的
       30px 配 17px 几乎一致, 换行后的顶栏也放得下。
       并挂的 `.header-inner > .logo` 兼容选择器同上部一起删(header.jsp:27 已是 class="brand")。 */
    .brand { order: 1; font-size: 16px; }

    .user-box { order: 2; }

    /* 整行 = flex-basis 100%, max-width 解除(桌面的 520px 上限在这里会留空) */
    .search-box { order: 3; flex: 1 1 100%; max-width: none; }

    /* ‼️ 2026-08-01 实测补齐触控目标(375x812 真机尺寸下量的):
       窄屏下**所有可点的东西都要够 40px 高** —— 这是本项目"移动端不堆小按钮"的一贯口径,
       也是 Lighthouse"点击目标过小"审计的门槛(文件头为此已放弃 ui-kit 的 zoom:.9)。
       ‼️ 撑的是**触摸盒**, 不是字: 字号/字重/圆角/配色一律沿用桌面的 erp 配方, 一个都不改。
       后台没有这条约束(它只在桌面用), 所以这是门户独有的补充, 不是对 erp 的偏离。 */

    /* 站名: 30 -> 40。它是"回首页"的主入口, 之前是整个顶栏最常被点却最小的一个。 */
    .brand { order: 1; font-size: 16px; min-height: 40px; }

    /* 搜索框: 外壳 41px, 但里面的 input(27) 与 button(31) 没撑开 —— 点在按钮上下各 4px
       其实落在外壳上, 不触发提交。把外壳的**纵向** padding 归零(横向留着, 否则输入文字贴边),
       让 input/button 各自吃满 40px, 外壳连边框 42px, 比原来只高 1px。 */
    .search-box { padding-top: 0; padding-bottom: 0; }
    .search-box input { min-height: 40px; }
    .search-box button { min-height: 40px; padding: 0 14px; }

    /* 登录/退出: 实测只有 27x20px, 是全站最小的可点目标。给纵向内边距撑到 40px,
       横向也给一点, 免得两个字之间没有容错区。 */
    .user-box a {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        padding: 0 6px;
    }

    /* 类型导航: 7 个 chip 在 375px 下会折成 2 行(实测 85px 高), 再把 chip 撑到 40px 就是 ~96px ——
       顶栏已经占了 101px, 内容还没开始就吃掉四分之一屏。
       改成**单行横滑**(移动端内容站的通用做法): 高度从 85px 降到 40px, 同时 chip 达标。
       ‼️ 不隐藏任何一项 —— 横滑能滑到全部 7 个, 最后一个被裁一半正好是"还能滑"的视觉提示。
       -webkit-overflow-scrolling 给 iOS 惯性滚动; scrollbar 在移动端本来就不占位, 顺手藏掉。 */
    .type-nav {
        gap: 6px;
        padding: 12px 0 2px;
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .type-nav::-webkit-scrollbar { display: none; }
    .type-nav a {
        padding: 0 14px;
        font-size: 13px;
        min-height: 40px;
        display: inline-flex;
        align-items: center;
        flex: none;          /* 不许被压扁: 没有它, nowrap 下 chip 会被挤成半个字 */
        white-space: nowrap;
    }

    /* 筛选条: 与 .type-nav 同一套移动端处理 —— 每个维度**单行横滑**, 不折行不缩小 chip。
       ‼️ 为什么不折行: 电影的类型有 16 个候选, 折行能占掉大半屏, 用户还没看到一张海报就要先滚过筛选条。
       ‼️ 维度名改成压在候选值上面一行(grid 从两列变一列): 375px 下留给候选值的宽度本来就紧,
          再被"产地"两个字 + 间距吃掉 40px, 一屏只剩两个半 chip。
       ‼️ chip 高度撑到 40px(触摸目标下限), 但字号/圆角/配色一律不动 —— 撑的是可点盒不是字。 */
    .facets {
        margin: 0 0 14px;
        padding: 2px 10px 8px;
    }
    /* 折叠头: 一整行都是可点区域(44px), 左边是"筛选", 右边是当前选中的值 + 一个箭头。
       ‼️ list-style/marker 两条是去掉浏览器自带的小三角(Chrome 用 ::-webkit-details-marker,
          Firefox/Safari 认 list-style), 三个都写才干净。 */
    .facets > summary {
        display: flex;
        align-items: center;
        gap: 8px;
        min-height: 44px;
        padding: 0 2px;
        cursor: pointer;
        list-style: none;
        font-size: 13.5px;
    }
    .facets > summary::-webkit-details-marker { display: none; }
    .facets > summary::marker { content: ''; }
    .facets > summary .sum-k {
        color: var(--text);
        font-weight: 600;
        flex: none;
    }
    /* 选中值可能很长(产地 · 语种 · 类型 · 年代 四段), 单行截断而不是撑破 */
    .facets > summary .sum-v {
        flex: 1;
        min-width: 0;
        color: var(--muted);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    /* 箭头用 CSS 画(不引图标字体也不外链 SVG), 展开时转 180 度 */
    .facets > summary::after {
        content: '';
        flex: none;
        width: 7px;
        height: 7px;
        margin-right: 4px;
        border-right: 1.5px solid var(--muted);
        border-bottom: 1.5px solid var(--muted);
        transform: rotate(45deg) translate(-2px, -2px);
        transition: transform .15s;
    }
    .facets[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
    /* 折叠时整块只剩摘要行, 下边距收掉一半 */
    .facets:not([open]) { padding-bottom: 2px; }
    .facet-row {
        /* 窄屏回到单列(维度名压在候选值上面一行), "更多"那一列一并消失 —— 那边是横向滚动, 不需要夹取 */
        grid-template-columns: 1fr;
        gap: 4px;
        padding: 8px 0 6px;
    }
    .facet-more { display: none; }
    /* 兜底: 万一脚本在宽屏加了 clamp 之后用户转成竖屏, 别把横滚那一行也夹了 */
    .facet-vals.clamp { max-height: none; overflow: visible; }
    .facet-key { padding: 0; font-size: 12.5px; }
    .facet-vals {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        /* 左右各留一点: 横滑容器贴着卡片内边距时, 第一个 chip 的圆角会像被切掉 */
        padding-bottom: 2px;
    }
    .facet-vals::-webkit-scrollbar { display: none; }
    .facet-vals a {
        min-height: 40px;
        padding: 0 13px;
        flex: none;            /* 同 .type-nav a: 没有它 nowrap 下 chip 会被挤扁 */
        white-space: nowrap;
    }
    .facet-clear { padding: 6px 0 0; }
    /* 清空链接也是可点目标, 在移动端撑到 40px 高(右对齐, 不占额外宽度) */
    .facet-clear a {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
    }

    .page-title { font-size: 18px; margin: 12px 0 14px; }

    .card-list { gap: 12px; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
    .card .meta { padding: 8px 10px 10px; }
    .card .title { font-size: 13px; }

    .pager { gap: 8px; padding: 22px 0 4px; }

    /* ‼️ 这里原来是 `.pager a{padding:7px 12px;font-size:13px}` —— 把桌面已经对齐 ui-kit.css:135 的
       字号又在移动端放大回 13px, 等于同一个控件两套字号。现在移动端**不动**视觉语言(字号/字重/
       圆角/配色一律沿用桌面的 erp 配方), 只把可点区域撑到 40px 高:
       后台是登录后台、只在桌面用(ui-kit.css:22-25 的 zoom 也只作用桌面), 没有触摸目标约束;
       门户要过 Lighthouse 的"点击目标过小"审计(文件头注释里为此专门放弃了 zoom:.9), 所以这一条
       是门户独有的补充, 而不是对 erp 的偏离 —— 撑的是触摸盒不是字。
       min-height 对 inline-flex + align-items:center 生效, 内容仍竖直居中。 */
    .pager a,
    .pager .cur { min-height: 40px; padding-left: .9rem; padding-right: .9rem; }

    /* 省略号本身不是可点目标, 但要和同排 40px 的胶囊**等高**, 否则它的行盒更矮,
       flex 的 align-items:center 会把它摆在视觉上偏下的位置(实测 26px vs 40px, 差 7px)。 */
    .pager .gap {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
    }

    /* ‼️ 窄屏把离当前页 2 格以上的页码隐掉(far 由 JSP 侧算, 见 index.jsp/search.jsp)。
       理由: 手机上每个胶囊要 40px 高 + .9rem 左右内边距, 7 个页码加首末页和上下页会折成三行,
       翻页条比一条资源还高。留"上一页 / 当前页 ±1 / 下一页 / 首末页"够用, 想去远处的页
       用旁边的"去第 N 页" —— 那才是窄屏上真正好使的入口(这也是本项目"移动端不堆小按钮"的一贯口径)。 */
    .pager a.far { display: none; }

    /* ‼️ 2026-08-01 用户实机看过后定的: **窄屏只留数字页码这一排**。
       上一页/下一页/去第N页在手机上一共要多占两行, 加上每个胶囊 40px 高, 分页区比一张卡片还高 ——
       "太拥挤"。数字排里已经带了当前页 ±1(上一页/下一页的等价物)和首页/末页, 够用。
       ‼️ 代价说清楚: 窄屏没法再直达任意一页(比如第 400 页), 只能靠首页/末页和相邻页挪。
          这是用户看过实机后接受的取舍, 不是漏掉 —— 想恢复就把下面这条删掉。
       只用 display:none 不改 DOM: 桌面端与搜索引擎拿到的仍是完整的一套(prev/next 的 rel 关系
       是给爬虫理解序列用的, 不能因为窄屏就从 HTML 里删掉)。 */
    .pager a.prev,
    .pager a.next,
    .pager-jump { display: none; }

    /* 页脚语言切换实测只有 17px 高, 同样撑到 40px(它是页脚唯一的可点目标) */
    .site-footer .lang-switch a {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        padding: 0 8px;
    }

    .detail { padding-top: 14px; }
    /* 面包屑是行内小字导航(WCAG 对句内行内链接有豁免), 不强撑 40px —— 那会让它比 h1 还高。
       但两级之间挨太近容易点错, 给链接一点上下内边距把可点区拉开。 */
    /* 面包屑那两个链接实测只有 27px 高, 是详情页上仅剩的两个不达标触摸目标(2026-08-01 量的)。
       ‼️ 撑的是**可点盒不是字**: 字号/颜色一点不动, 只给 min-height。
       ‼️ 必须脱离行内布局(inline-flex): 行内元素的垂直 padding 与 min-height 都不进布局盒 ——
          原来写成 `padding: 4px 0` 时量出来仍是 27px, 改成 inline-block + padding:7px 也只到 33px
          (12.5px 字的内容盒才 19px, 加 14 不够)。min-height 直接说要多高, 不必跟着字体度量算。
       代价是面包屑那一行从 27px 涨到 41px —— 一行 14px, 换掉全页最后两个不达标目标, 值。 */
    .crumb a {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
    }
    /* 属性里的产地/语种/类别是可点的筛选链接, 移动端同样要够 40px。
       ‼️ 与面包屑同一个做法(inline-flex + min-height), 不用 padding —— 行内元素的垂直 padding
          不进布局盒, 量出来还是 18px(2026-08-01 两处都实测过)。
       代价: 带这三行的属性表高度各涨 22px。属性表本来就是详情页第二重要的区块, 认了。 */
    .attrs .chips a {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
    }
    /* 过滤框在窄屏撑到 40px(触摸目标下限), 命中数换行到下面一行, 不挤输入框 */
    .link-filter { flex-wrap: wrap; gap: 6px; }
    .link-filter input { height: 40px; flex: 1 1 100%; }
    .link-filter .hit { flex: 1 1 100%; }
    /* 分隔符跟着链接一起变成 flex 盒之后会跑到行首上方, 让它自己也居中 */
    .attrs .chips a + a::before { display: inline-flex; align-items: center; }
    .detail .head { flex-direction: column; gap: 16px; }
    .detail .head,
    .intro,
    .links { padding: 16px; }
    .poster-big { width: 150px; }
    .detail h1 { font-size: 20px; }
    .attrs em { width: 48px; }

    /* ‼️ 2026-08-01 改法变更: 原来是"给 min-width:480px 让它在 .links 里横滚"。
       实测 375px 屏下父容器只有 349px —— 用户**每次看资源都得先横滑**, 而这是详情页的主内容;
       更糟的是操作列那两个钮只有 26px 高, 全页最小的可点目标偏偏是主操作。

       现在窄屏把表**拆成卡片**: 表头隐掉(每格自带语义: 类型是 pill、清晰度是灰字、说明是正文),
       每行变成一张带描边的卡, 两个钮各占一半宽、40px 高。横滚从此不需要。
       ‼️ 桌面一个像素都不动 —— 上面那套四列表在宽屏是对的, 这里只在断点内覆盖。
       ‼️ 用 display:block 拆表而不是改 HTML: JSP 那边的 <table> 结构是给桌面与搜索引擎看的,
          语义(表头 + 行列)保留着更好, CSS 只换呈现。 */
    .links { overflow-x: visible; }

    .link-table {
        display: block;
        min-width: 0;
        font-size: 13px;
    }
    .link-table thead { display: none; }
    .link-table tbody { display: block; }

    .link-table tbody tr {
        display: block;
        border: 1px solid var(--border-2);
        border-radius: var(--r);
        padding: 12px;
        margin-bottom: 10px;
    }
    .link-table tbody tr:last-child { margin-bottom: 0; }
    /* 窄屏没有 hover 这回事, 而且卡片自己有描边了, 整行染色反而脏 */
    .link-table tbody tr:hover td { background: transparent; }

    .link-table td {
        display: block;
        width: auto;
        padding: 0;
        border-bottom: 0;
    }

    /* 类型: 桌面是定宽首列, 窄屏当成一枚小标签放在最上面 */
    .link-table .type {
        color: var(--muted);
        font-size: 12px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: .03em;
    }
    /* 说明列是这张卡的正文 */
    .link-table .label { margin-top: 4px; color: var(--text); }
    /* 清晰度为空的行很多, 空的时候别留一道空行 */
    .link-table .res { color: var(--muted); font-size: 12px; }
    .link-table .res:empty { display: none; }

    /* 两个钮各占一半宽、40px 高 —— 主操作必须是最容易点中的那个 */
    .link-table .ops {
        display: flex;
        gap: 8px;
        margin-top: 10px;
        white-space: normal;
    }
    .link-table .ops .btn {
        flex: 1 1 0;
        min-height: 40px;
        font-size: 13px;
    }
    /* 兜底分支(协议不在白名单)那一行: 里面是 pill + 一整条 URL 原文 + 复制钮, 竖着排才读得下来 */
    .link-table .ops:has(.warn) {
        flex-direction: column;
        align-items: stretch;
    }

    .player-wrap { border-radius: var(--r); }
    .player-wrap video { max-height: 56vh; max-height: 56dvh; }

    /* 并挂的裸 .empty 已随上部空态段一起删掉(JSP 侧全仓无 class="empty") */
    .empty-state { padding: 36px 12px; }
    /* 空态按钮同样撑到 40px 触控高(404 页的"回首页"是整页唯一出口) */
    .empty-state .btn { min-height: 40px; padding-left: 1.1rem; padding-right: 1.1rem; }

    /* "显示全部 N 条"是"还有几百条没看到"的唯一出口, 同样撑到 40px */
    .links-more a {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        padding: 0 8px;
    }

    /* ---- 2026-08-03 新增件的窄屏适配(同一条"可点目标 40px / 撑盒不撑字"口径) ---- */
    /* 复制全部链接: 表内按钮已在上面撑过, 标题行里这颗也一样 */
    .links h2 .copy-all { min-height: 40px; }
    /* 最近浏览面板与详情页其它面板同档收窄; 清除钮撑到 40px */
    .recent { padding: 16px; margin-top: 18px; }
    .recent .recent-clear {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
    }
    /* 回到顶部: 往上抬一点避开 iOS 底部手势条; 44px 本来就达标, 尺寸不动 */
    .back-top { right: 14px; bottom: 22px; }
    /* 页脚那几个入口是可点目标, 窄屏撑到 40px 触摸线。
       ‼️ 2026-08-06 页脚并成一行后类名从 .foot-rss 改成 .foot-line .fl-item, 这条跟着改 ——
          漏改的话选择器命不中任何元素, 窄屏触摸目标会**静默**退回 13px 字高。 */
    .site-footer .foot-line .fl-item {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        padding: 0 8px;
        margin: 0 2px;
    }

    /* ---- 2026-08-03 第二批(P0/P1 全量)的窄屏适配 ---- */

    /* iOS Safari 聚焦缩放线: 输入框字号 < 16px 会强制放大且停在缩放态。撑的是字号这一处例外 ——
       它就是这条移动端硬伤的根因, 13px 在 375px 屏上也确实偏小。 */
    .search-box input,
    .link-filter input,
    .pager-jump input[type="number"] {
        font-size: 16px;
    }

    /* 排序外提: h1 下那排 chip 只在窄屏出(桌面用筛选块里的排序行), 40px 触摸目标 */
    .sort-bar {
        display: flex;
        gap: 6px;
        margin: -6px 0 12px;
    }
    .sort-bar a {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        padding: 0 14px;
        border-radius: 20px;
        border: 1px solid var(--border);
        background: var(--surface);
        color: var(--muted);
        font-size: 13px;
    }
    .sort-bar a.on {
        background: var(--primary-weak);
        border-color: var(--primary-weak);
        color: var(--primary);
        font-weight: 600;
    }
    /* 排序行已外提, 筛选块里那行在窄屏藏掉(数据同源, 只是入口去重) */
    .facet-row[data-key="sort"] { display: none; }

    /* 横滑 chip 行的右缘渐隐(2026-08-03): 实测类型行可滑 1500px+ 但边缘无任何提示,
       用户以为就那几个。mask 渐隐是"后面还有"的通用信号(不支持 mask 的内核原样显示, 无害)。 */
    .facet-vals,
    .type-nav {
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
        mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    }

    /* 详情页资源列表前置(2026-08-03): SEO 直落的手机用户唯一目的是拿链接, 实测要滑 1.6 屏。
       CSS order 只动呈现不动 DOM(SEO/读屏顺序不变)。 */
    .wrap.detail { display: flex; flex-direction: column; }
    .wrap.detail > .crumb { order: 0; }
    .wrap.detail > .head { order: 1; }
    .wrap.detail > .links { order: 2; }
    .wrap.detail > .intro { order: 3; }
    .wrap.detail > .related { order: 4; }
    .wrap.detail > .recent { order: 5; }

    /* 直达资源锚点: 窄屏才出(桌面隐藏见主段), 40px 目标 */
    .fav-box .golinks {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        padding: 0 14px;
        border-radius: 20px;
        background: var(--primary-weak);
        color: var(--primary);
        font-size: 13px;
        font-weight: 600;
    }

    /* 复制升主操作(2026-08-03): 手机上点 magnet 大概率无反应(没装接盘 App), 真实动线是
       复制去网盘离线 —— 复制钮换实心主色, 下载钮保持描边次级。只动配色不动布局。 */
    .link-table .ops .btn.copy {
        background: var(--primary);
        border-color: var(--primary);
        color: #fff;
    }
    .link-table .ops .btn.copy:hover { background: var(--primary-hover); border-color: var(--primary-hover); }

    /* 首页分行/频道导航/搜索细筛/选集条的窄屏收窄 */
    .home-row h2 { font-size: 15px; }
    /* 分行的单行裁剪(见桌面段)窄屏同样生效, 不再横滑;
       频道导航改**换行**(2026-08-05 老板口径"要么就换行"): 12 个小 chip 折 2-3 行 ≈ 130px, 可接受 */
    .channel-nav a {
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        white-space: nowrap;
    }
    .search-filters { padding: 2px 10px; }
    .search-filters .sf-row { grid-template-columns: 1fr; gap: 4px; }
    .search-filters .sf-vals {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .search-filters .sf-vals::-webkit-scrollbar { display: none; }
    .search-filters .sf-vals a {
        flex: none;
        display: inline-flex;
        align-items: center;
        min-height: 40px;
        white-space: nowrap;
    }
    /* 失效/迅雷钮在卡片化的操作区里与主钮并排, 同样 40px */
    .link-table .ops .btn.fail,
    .link-table .ops .btn.thunder { min-height: 40px; }
    /* 选集胶囊 40px 触摸目标, 限高照旧滚动 */
    .ep-nav { grid-template-columns: 1fr; gap: 4px; }
    .ep-nav .ep-chips { max-height: 176px; }
    .ep-nav .ep-chips a {
        min-width: 40px;
        min-height: 40px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
    .quick-chip {
        min-height: 40px;
        display: inline-flex;
        align-items: center;
    }

    /* ---- 2026-08-04 第四批的窄屏适配 ---- */
    /* (扫码接力已整链路删除, 2026-08-05 用户拍板; 这里原有它的隐藏规则) */
    /* 联想项撑到触摸目标线 */
    .sug-item { min-height: 44px; }
}

/* ---------- 发现页(2026-08-07, discover.jsp) ---------- */
/* 只加这一页真正新增的几个类。卡片/行/横滑全部复用 .card / .home-row / .row-scroll ——
   发现页在视觉上就该和首页是同一个东西, 另起一套样式只会让两边慢慢漂开。 */
.page-lead {
    margin: -4px 0 18px;
    color: var(--muted);
    font-size: 14px;
    line-height: 1.6;
}

/* 行标题右边那句灰色小字: 解释这一行凭什么存在("评分够好, 却几乎没人点开过")。
   ‼️ 窄屏换行而不是省略 —— 这句话是这一行的全部意义, 截掉就等于没有。 */
.home-row h2 .row-hint {
    margin-left: 10px;
    color: var(--muted);
    font-size: 12px;
    font-weight: 400;
}

@media (max-width: 640px) {
    .home-row h2 .row-hint {
        display: block;
        margin: 2px 0 0;
    }
}

/* "手气不错": 一个按钮 + 一句说明。刻意放在**页面最底下** ——
   随机跳转是"上面几十张都没看中"之后才该有的选项, 放顶上就又变成让用户先赌一把了。 */
.lucky-box {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin: 26px 0 10px;
}

.lucky-box .row-hint {
    color: var(--muted);
    font-size: 12px;
}
