* { -webkit-tap-highlight-color: transparent; box-sizing: border-box; }html, body { margin: 0; padding: 0; }
/* 永久预留滚动条槽位：否则首屏内容由短变长时滚动条才出现，可视宽度收窄 ~15px，
   所有百分比宽度元素（正文列、微预告 video 等）跟着重排 → 轻微上下抖动。
   stable 让有无滚动条时可用宽度一致，宽度恒定即无抖动。 */
/* 页面根画布背景：必须落在 html 上（不能只靠 .app-body）。
   整页跳转/刷新时浏览器先画根画布，若 html 无背景且依赖后加载的 theme.css，
   首帧就是默认白色 → 用户看到「白闪」。此处直接给 html 上底色（变量已在 variables.css
   内联定好默认值），并让 color-scheme 跟随主题（深色下用深色基准画布/滚动条）。 */
/* overflow-anchor:none ⛔ 2026-10-05 加，勿删：sticky 顶栏在 68↔50 之间切高度时，
   文档流高度随之变化，浏览器 scroll anchoring 会「贴心地」补偿 scrollY，把用户
   实际滚到的位置拖偏（实测设定 45 被读成 40），再与顶栏阈值判断耦合成自激振荡
   （用户报「滚到 35 左右高度时菜单栏无限弹跳」）。关掉后滚动位置只由用户输入决定。
   代价：异步内容撑高页面时不再自动保位 —— 本站图片一律带 width/height 或
   aspect-ratio 预留（base.html 的 media_dim_attrs），撑高前已占位，这补偿本就用不上。 */
html { scrollbar-gutter: stable; background-color: var(--color-bg-page); color-scheme: light; overflow-anchor: none; }
html[data-theme="dark"] { color-scheme: dark; }
.app-body {
    margin: 0;
    font-family: var(--font-family);
    background: var(--color-bg-page);
    color: var(--color-text-primary);
    font-size: var(--font-size-base);
    line-height: var(--font-line-height);
    font-weight: var(--font-weight-base);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}h1, h2, h3, h4, h5, h6 {
    color: var(--color-text-title);
    margin: 0 0 12px;
    font-weight: 700;
}h1 { font-size: calc(var(--font-size-title) + 4px); }h2 { font-size: var(--font-size-title); }h3 { font-size: calc(var(--font-size-title) - 2px); }a { color: var(--color-accent); text-decoration: none; transition: color .2s; }a:hover { color: var(--color-accent-hover); }img { max-width: 100%; height: auto; }
/* 加载期抑制 header 过渡：刷新时若浏览器恢复滚动位置，首帧即终态、不播放收窄动画（见 base.html 滚动收窄脚本） */
html.pre-anim .app-header { transition: none; }

/* 收藏更新通知（顶部铃铛） */

/* 透明桥：填住触发器与菜单之间的 8px 间隙，鼠标下移时悬停不丢失，保证能点到菜单项 */

/* 顶部圆形头像按钮（未登录快捷登录入口） */

/* 快捷登录面板 */

.app-shell {
    flex: 1;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-rows: auto auto;
    align-content: start;   /* 阻止第二行(auto 高度)被拉伸填满剩余空间——否则内容不足以填满视口时，页脚会被拉高（如 help 页） */
    min-width: 0;
    width: 100%;
    max-width: 1800px;
    margin: 0 auto;
}.app-main {
    grid-column: 2;
    grid-row: 1;
    flex: 1;
    min-width: 0;
    background: var(--color-bg-page);
}.app-main-inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
    padding: 28px 32px 28px;
    transition: padding .28s ease, gap .28s ease, transform .3s cubic-bezier(0.4, 0, 0.2, 1);
}
/* 左栏宽度变量（兜底 260px；实际响应式分级在 responsive.css 覆盖：
   ≥1661=260 / 1200-1660=240 / ≤991 隐藏=0）。侧栏为浮层(.app-side 固定定位)，
   其占位列 .app-side-col 宽度恒定、折叠时亦不归零（见 side.css），
   故主区宽恒定、内容区(.app-main-inner 含右侧栏)不随折叠缩放或平移。 */
.app-shell { --side-w: 260px; }
/* 左栏折叠态（居中模型）：占位列 .app-side-col 宽恒 = 展开态（见 side.css），故主区宽恒定、
   内容块本就与展开态等宽、零缩放。此处仅用 transform 把「内容块+右侧栏」整体左移半侧栏宽，
   使其在视口内左右对称居中（纯位移、不改宽度 → 折叠/展开绝无「变大缩小」）。
   展开态内容贴 left=260，折叠态左移 side-w/2 → left=130，右间隙同为 side-w/2，居中。 */
body.sidebar-collapsed .app-main-inner {
    transform: translateX(calc(var(--side-w) / -2));
}
.res-page {
    min-width: 0;
    width: 100%;
    max-width: 1400px;      /* 与单文章页 .doc-container 一致（= responsive.css 桌面值，无冲突） */
    margin: 0 auto;
    padding: 0 0 0;      /* 与 .doc-detail 底部间距一致 */
}
/* documents 资源列表页容器底色（仅本页生效，后台可自定义；不影响首页/标签页） */
body.documents-page .res-page {
    padding: 24px 24px 24px;   /* 底部 24px：分页栏不贴底边框（原为 0 导致分页栏紧贴容器底） */
    background: var(--color-bg-card);   /* 与首页卡片同一底色变量（后台可自定义） */
    border: var(--color-border-width) solid var(--color-border);
    border-radius: var(--radius-card);
    box-shadow: var(--main-shadow);
}
/* 标签筛选页：按首页列表模式单列显示 */

/* 标签筛选页：全部标签以「顶部横向胶囊」展示（复用首页 game-tab 风格） */

/* 标签页顶部间距收窄（其余页面保持默认 28px） */

/* 标签页分页栏：已移入卡片内（与列表同属卡片） */
.app-card-pager {
    display: flex;
    justify-content: center;
    gap: 6px;
    margin-top: 20px;
    flex-wrap: wrap;
}.doc-type-tag, .resource-type {
    display: inline-block;
    background: var(--color-accent);
    color: var(--color-accent-ink);
    font-size: 11px;
    font-weight: 500;
    padding: 3px 10px;
    border-radius: 3px;
}.view-more-link, .doc-more-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--color-accent);
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    margin-top: 12px;
}.view-more-link:hover, .doc-more-link:hover { text-decoration: underline; }.form-label { display: block; font-size: 14px; font-weight: 500; color: var(--color-text-primary); margin-bottom: 8px; }.form-text { font-size: 12px; color: var(--color-text-dim); margin-top: 6px; }.text-center { text-align: center; }.text-muted { color: var(--color-text-secondary); }.mt-2 { margin-top: 8px; }.mt-3 { margin-top: 16px; }.mt-4 { margin-top: 24px; }.mb-2 { margin-bottom: 8px; }.mb-3 { margin-bottom: 16px; }.mb-4 { margin-bottom: 24px; }.d-flex { display: flex !important; }.justify-content-between { justify-content: space-between; }.align-items-center { align-items: center; }.gap-2 { gap: 8px; }.flex-wrap { flex-wrap: wrap; }.w-100 { width: 100%; }[data-theme="dark"] .app-container { width: 100%; max-width: 1600px; margin: 0 auto; }.app-card-pager { display: flex; justify-content: center; gap: 6px; flex-wrap: wrap; align-items: center; }.p-ellipsis { min-width: 24px; text-align: center; color: var(--color-text-dim); }.app-reward-block { display: block; text-align: center; padding: 12px; border-radius: 12px; background: var(--color-accent-gradient); color: var(--color-text-title); font-weight: 500; text-decoration: none; box-shadow: 0 2px 8px color-mix(in srgb, var(--color-accent) 30%, transparent); }.app-bottomnav {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 1400;
    display: none; align-items: stretch; justify-content: space-between; gap: 6px;
    padding: 6px 12px calc(6px + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--color-bg-card) 92%, transparent);
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    border-top: 1px solid var(--color-border);
}.app-bottomnav-item {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; padding: 4px 2px; border-radius: 8px;
    color: var(--color-text-secondary); text-decoration: none;
    font-size: 11px; background: none; border: none; cursor: pointer; transition: all .2s;
}.app-bottomnav-item .ic { font-size: 20px; line-height: 1; }.app-bottomnav-item .lb { font-size: 10px; line-height: 1; }.app-bottomnav-item.active { color: var(--color-accent); background: var(--color-accent-soft); }.app-bottomnav-item:active { transform: scale(.94); }.doc-detail { padding: 0 0 0; }.doc-container { max-width: 1400px; margin: 0 auto; padding: 0; }.doc-head { display: flex; gap: 20px; margin-bottom: 24px; padding: 20px; background: var(--color-bg-card); border: var(--color-border-width) solid var(--color-border); border-radius: var(--radius-card); box-shadow: var(--shadow-sm); }.doc-head-cover { width: 200px; flex-shrink: 0; border-radius: var(--radius-card); overflow: hidden; box-shadow: var(--shadow-sm); align-self: flex-start; }.doc-head-cover img { width: 100%; display: block; }.doc-head-info { flex: 1; min-width: 0; }.doc-title { font-size: 26px; font-weight: 800; color: var(--color-text-title); margin: 0 0 12px; line-height: 1.3; }.doc-title-en { display: block; font-size: 15px; font-weight: 500; color: var(--color-text-secondary); margin-top: 4px; line-height: 1.4; }@keyframes docTagPulse { 0%, 100% { box-shadow: var(--tg-a); } 50% { box-shadow: var(--tg-b); } }.doc-fav-btn { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; padding: 6px 14px; border-radius: 999px; font-size: 12px; font-weight: 700; line-height: 1; cursor: pointer; background: var(--color-bg-tag); color: var(--color-text-secondary); border: 1px solid var(--color-border); transition: all .2s; }.doc-fav-btn .doc-fav-ic { width: 16px; height: 16px; flex-shrink: 0; }.doc-fav-btn .doc-fav-heart { fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; transition: all .2s; }.doc-fav-btn:hover { border-color: var(--color-danger); color: var(--color-danger); }.doc-fav-btn.active { background: color-mix(in srgb, var(--color-danger) 12%, transparent); color: var(--color-danger); border-color: color-mix(in srgb, var(--color-danger) 45%, transparent); box-shadow: 0 0 12px color-mix(in srgb, var(--color-danger) 30%, transparent); }.doc-fav-btn.active .doc-fav-heart { fill: currentColor; stroke: none; }.doc-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 13px; color: var(--color-text-secondary); margin: 20px 0 18px; }.doc-meta-sep { color: var(--color-text-dim); }.doc-meta-item { white-space: nowrap; }.doc-summary { font-size: 14px; color: var(--color-text-secondary); line-height: 1.7; margin: 0; padding: 12px 16px; background: var(--color-bg-page-soft); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; border-left: 3px solid var(--color-accent); }.doc-body { font-size: 15px; line-height: 1.8; color: var(--color-text-primary); margin-top: 20px; padding: 24px 28px; background: var(--color-bg-card); border: var(--color-border-width) solid var(--color-border); border-radius: var(--radius-card); box-shadow: var(--shadow-sm); }.md-rendered h1, .md-rendered h2, .md-rendered h3 { color: var(--color-text-title); margin: 1.2em 0 .6em; line-height: 1.3; }.md-rendered h1 { font-size: 24px; }.md-rendered h2 { font-size: 20px; }.md-rendered h3 { font-size: 17px; }.md-rendered p { margin: 0 0 1em; }.md-rendered img { max-width: 100%; border-radius: 8px; }.md-rendered a { color: var(--color-accent-dark); }.md-rendered ul, .md-rendered ol { padding-left: 1.4em; margin: 0 0 1em; }.md-rendered pre { background: var(--color-bg-page-soft); padding: 14px; border-radius: 8px; overflow: auto; }.md-rendered code { background: var(--color-bg-tag); padding: 2px 6px; border-radius: 4px; font-size: 13px; }.md-rendered blockquote { border-left: 3px solid var(--color-border-strong); padding-left: 14px; color: var(--color-text-secondary); margin: 0 0 1em; }.doc-screenshots { margin-top: 20px; padding: 20px 24px; background: var(--color-bg-card); border: var(--color-border-width) solid var(--color-border); border-radius: var(--radius-card); box-shadow: var(--shadow-sm); }.doc-screenshots-title { font-size: 18px; font-weight: 700; color: var(--color-text-title); margin: 0 0 16px; }.doc-gallery { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }.doc-gallery img { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 10px; cursor: pointer; transition: transform .2s; background: var(--color-bg-page-soft); }.doc-gallery img:hover { transform: scale(1.03); }
/* 截图多是远程直链（Steam CDN / TMDB），国内偶尔拉不回来：加载失败时藏掉裂图图标、保留底色块，
   比一格碎图好看。不用 display:none —— 那样网格会塌掉一格、其余图全部重排跳动。 */
.doc-gallery img.is-failed { visibility: hidden; }.pj-label { font-size: 12px; color: var(--color-text-secondary); }.mb-txt { flex: 1; }

/* ---------- 详情页「留言催更」按钮 + 快捷留言板弹窗（2026-10-07） ---------- */
/* 按钮紧随「收藏」之后（收藏带 margin-left:auto，故两者一起靠右）；形态与 .doc-fav-btn 同款小圆角胶囊 */
.doc-qc-btn { display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; border-radius: 999px; font-size: 12px; font-weight: 700; line-height: 1; cursor: pointer; background: var(--color-bg-tag); color: var(--color-text-secondary); border: 1px solid var(--color-border); transition: all .2s; }
.doc-qc-btn .doc-qc-ic { width: 16px; height: 16px; flex-shrink: 0; }
.doc-qc-btn:hover { border-color: var(--color-accent); color: var(--color-accent); }
/* 弹窗外壳（.doc-qc-modal / -mask / -card / -modal-foot）与标题基础样式
   已于 2026-10-08 并入 modal.css 的 .ui-modal 通用体系（逗号选择器组），
   此处不再重复定义 —— 本文件早于 modal.css 加载，同特异性下写了也会被覆盖。
   本区只保留 modal.css 未覆盖的独有样式。 */
.doc-qc-modal-title { margin-bottom: 6px; }
.doc-qc-modal-sub { font-size: 12.5px; color: var(--color-text-secondary); margin: 0 0 14px; line-height: 1.5; }
.doc-qc-modal-doc { color: var(--color-accent-dark); font-weight: 600; }
.doc-qc-textarea { width: 100%; box-sizing: border-box; min-height: 96px; resize: vertical; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--color-border); background: var(--color-bg-page-soft); color: var(--color-text-primary); font-size: 14px; line-height: 1.6; font-family: inherit; outline: none; transition: border-color .2s; }
.doc-qc-textarea:focus { border-color: var(--color-accent); }
.doc-qc-counter { font-size: 12px; color: var(--color-text-dim); }
.doc-qc-actions { display: flex; gap: 10px; }
.doc-qc-cancel { padding: 8px 16px; border-radius: 10px; font-size: 13px; font-weight: 700; cursor: pointer; background: var(--color-bg-page-soft); color: var(--color-text-secondary); border: 1px solid var(--color-border); }
.doc-qc-cancel:hover { color: var(--color-text-primary); }
.doc-qc-send { padding: 8px 18px; border-radius: 10px; font-size: 13px; font-weight: 700; cursor: pointer; background: var(--color-accent-gradient); color: var(--color-accent-ink); border: none; transition: transform .15s; }
.doc-qc-send:hover { transform: translateY(-1px); }
.doc-qc-send:disabled { opacity: .6; cursor: default; transform: none; }
/* 快捷登录弹窗：错误提示行（弹窗外壳复用 .doc-qc-*，表单复用 header.css 的 .quick-login-*） */
.doc-ql-error { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--color-danger); }
body.doc-qc-open { overflow: hidden; }

/* ---------- 资源索引视图（首页 + 资源页共享；原 document/index 内联 <style> 迁出，已去除非法回退色） ---------- */
/* documents 页工具栏同行左侧的面包屑 */
.res-crumb { display:flex; align-items:center; flex-wrap:wrap; gap:6px; font-size:13px; margin:0; flex:1; min-width:0; color:var(--color-text-secondary); }
.res-crumb a { color:var(--color-accent-dark); text-decoration:none; transition:color .15s; }
.res-crumb a:hover { color:var(--color-accent); text-decoration:underline; }
.res-crumb-sep { color:var(--color-text-dim); }
.res-crumb-cur { color:var(--color-text-secondary); font-weight: 500; }

/* 深色模式：实色底元素统一黑色字体（避免浅字在彩色底上看不清）——具体规则已迁移至 home.css / toolbar.css */

/* 视图模式初始态（防刷新闪烁）：由 <head> 内联脚本按 localStorage 给 <html> 设
   doc-view-list / doc-view-grid，首屏绘制前即定好显隐与按钮高亮，避免 JS 在底部
   修改前先闪一下网格；相关显隐规则已迁移至 toolbar.css */

/* ---------- documents 页面响应式样式 ---------- */
/* PC端（≥992px）：列表单列，网格多列，内容区更宽 */

/* 大屏PC端（≥1400px）：内容区最大化 */

/* 平板端（768px-991px）：列表单列，网格两列 */

/* 手机端（<768px）：列表单列，网格自适应 */

/* ---------- 搜索结果提示 ---------- */

/* 搜索结果数 + 清除搜索：独占一行、居中（与加高加宽的搜索框分离换行显示） */

/* 搜索结果页内嵌搜索框（加高加宽、居中显示，可重新输入搜索） */

/* ---------- 空状态优化 ---------- */

/* ---------- 空状态增强：热门搜索和分类 ---------- */

/* ---------- 搜索结果页：热门搜索和分类推荐 ---------- */

/* ========== 搜索结果：帮助中心 FAQ 命中（站内搜索整合） ==========
   仅在 /documents?kw=xxx 且命中 help_faq 时出现，点击跳 /help#faq-{cat}-{id} */
.res-faq-section {
    margin-top: 18px;
    padding: 18px 20px;
    background: var(--color-bg-card);
    border: 1.5px solid var(--color-border);
    border-radius: 12px;
}
.res-faq-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--color-text-title);
    margin-bottom: 12px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.res-faq-title .res-faq-count { font-size: 12px; font-weight: 500; color: var(--color-text-dim); }
.res-faq-list { display: flex; flex-direction: column; gap: 8px; }
.res-faq-item {
    display: block;
    padding: 10px 14px;
    border-radius: 10px;
    background: var(--color-bg-page-soft);
    border: 1px solid var(--color-border);
    text-decoration: none;
    transition: all .18s ease;
}
.res-faq-item:hover {
    background: var(--color-accent-soft);
    border-color: var(--color-accent);
    transform: translateX(2px);
}
.res-faq-q {
    display: block;
    font-size: 14px;
    font-weight: 500;
    color: var(--color-text-primary);
    margin-bottom: 3px;
}
.res-faq-item:hover .res-faq-q { color: var(--color-accent-dark); }
.res-faq-a {
    display: block;
    font-size: 12px;
    color: var(--color-text-dim);
    line-height: 1.6;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ========== NEW 徽章：闪电主题动画（弱化版） ==========
   new-bolt-pulse  → 电光呼吸（低强度辉光，3s 慢循环）
   （流光动画 badge-sweep 已移至 tags.css —— 徽章专用，方向为从左到右） */
@keyframes new-bolt-pulse {
    0%, 100% {
        box-shadow: 0 0 3px color-mix(in srgb, var(--color-accent) 35%, transparent);
        filter: brightness(1);
    }
    50% {
        box-shadow: 0 0 6px color-mix(in srgb, var(--color-accent) 50%, transparent), 0 0 12px color-mix(in srgb, var(--color-accent) 25%, transparent);
        filter: brightness(1.06);
    }
}

/* ========== 覆盖：documents 页网格模式桌面端固定一行4个 ========== */

/* 深色模式：分页栏选中项（金色背景）统一深色字体（后台变量 --color-bg-footer，深浅模式均为深色；兜底黑色） */
/* ============================================================
   documents 资源卡/列表 meta 信息行
   - 分类标签放时间前；新增：版本号 / 扩展内容 / 容量 / 标题语言
   - 全部使用后台 CSS 变量，不写死颜色
   ============================================================ */
/* 网格卡片：meta 信息行（分类 + 语言/版本/扩展/容量） */

/* 列表模式：语言 / 版本 / 扩展 / 容量（分类 res-list-cat 已有样式） */

/* documents 页跟随单文章页容器宽度（≤576px 加内边距） */

/* ===== 通用工具类（电站配色变量规范）：转移模板内联样式而来，全部依赖后台 CSS 变量 ===== */

.hidden { display: none !important; }

#preview-bar { position: fixed; top: 0; left: 0; right: 0; z-index: 99999; background: linear-gradient(90deg, var(--color-accent), var(--color-accent-dark)); color: var(--color-accent-ink); font-size: 13px; font-weight: 500; padding: 8px 16px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,.2); }
body.has-preview-bar { padding-top: 36px; }

/* ===== 顶部导航选中项与左侧菜单统一：浅色=黑色、深色=金色 ===== */
/* 深色变体规则已迁移至 header.css */

/* ===== 顶部菜单栏滚动收窄：向下滚动后 header 高度 68px → 50px ===== */

/* 电源状态徽章 .power-state-badge 已抽到 badge.css（前台 + 后台共享，
   后台不加载本文件、此前徽章无样式）；样式与变量桥接单一来源见该文件。 */

/* 首页分页栏行：分页居中，查看更多绝对定位到右侧同行 */
.app-card-pager-row { display: flex; align-items: center; justify-content: center; position: relative; margin-top: 20px; }
.app-card-pager-row .app-card-pager { margin-top: 0; }

/* ---------- 文章正文视频（Steam 抓取的 HLS 预告片） ----------
   <video> 未显式设置尺寸时，浏览器默认按 300×150 渲染，抓取的视频会显得很小。
   此处让它撑满正文宽度，高度按视频原始比例自适应（不变形、无黑边）。 */
.doc-body video,
#article-content video,
video[data-hls] {
    /* 历史遗留：旧抓取内容曾自带 style="max-width:100%;..."，当时需 !important 覆盖。
       现已由脚本批量清洗 documents.content（备份表 documents_content_bak_20260916），
       且 common.php 新生成的内容不再写内联样式，故去掉 !important，保持样式纯净。
       点击播放后，由 detail.html 的 bindAutoFit() 用普通内联样式覆盖为视频真实比例（仅 play 之后）。 */
    display: block;
    width: 100%;
    max-width: 430px;              /* 未播放时的占位框上限 430px（窄屏自动缩小，不溢出） */
    aspect-ratio: 16 / 9;          /* 占位比例：Steam 预告片多为 16:9；
                                     poster 加载后由 detail.html 按 poster 真实比例精调，杜绝黑边 */
    height: auto;
    margin: 12px auto;             /* 居中 + 上下留白 */
    background: #000;              /* 与显示框比例不一致时的留边底色 */
    object-fit: contain;           /* 保持原始比例，绝不拉伸变形 */
    border-radius: var(--radius-card);
}

/* 抓取生成的视频容器（common.php 输出 <div class="doc-video-wrap"> 包裹 <video data-hls>）
   容器只负责居中与上下间距；视频尺寸由上方 .doc-body video 规则统一控制。 */
.doc-video-wrap {
    text-align: center;
    margin: 1.2em 0;
    position: relative;   /* 供 .doc-video-play 绝对定位到画面中心 */
}

/* 点播占位按钮：未播放时盖在封面上，点了才起播。
   ⚠️ 为什么必须自己画一个、不能直接用原生 controls：
      hls.js 一 attachMedia 就把 MediaSource 挂上了，video 立刻进入「加载中」状态，
      原生控件会显示 loading 转圈；而本项目为了不预取 56.9MB 分片，配了 autoStartLoad:false，
      数据不会真的来 → 那个圈会**一直转**，看着像卡死（其实点一下就能播）。
      所以未播放时先摘掉原生控件（v.controls=false），用这个按钮代替；起播后再交还原生控件。
   三角用 currentColor（= --color-accent-ink），随主题自动反色，禁写死颜色。 */
.doc-video-play {
    position: absolute;
    /* 左下角（贴**视频画面**的左下，不是整篇正文的左下）：
       未播放时 video 宽度上限 430px 且在 .doc-video-wrap 内居中（见上方 .doc-body video 规则），
       故画面左边缘 = 50% - 215px，再往里缩 14px；窄屏画面满宽时用 max() 兜底到 14px，不会溢出。
       ⚠️ 215px 是 430/2，改上面 .doc-body video 的 max-width 时必须同步改这里。
       ⚠️ 只在**未播放**时存在（点击即移除），所以不必考虑播放后被 bindAutoFit 放大的宽度。 */
    left: max(14px, calc(50% - 201px));
    bottom: 26px;                  /* video 自带 margin:12px auto → 画面底边再往上 14px */
    top: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 58px;
    height: 58px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--color-accent);
    color: var(--color-accent-ink);
    box-shadow: 0 4px 14px color-mix(in srgb, var(--color-text-primary) 30%, transparent);
    cursor: pointer;
    font: inherit;
    transition: transform .18s ease, filter .18s ease;
}
.doc-video-play::before {
    content: "";
    display: block;
    margin-left: 4px;          /* 三角形的视觉重心偏左，右移一点才居中 */
    border-style: solid;
    border-width: 9px 0 9px 15px;
    border-color: transparent transparent transparent currentColor;
}
.doc-video-play:hover {
    transform: scale(1.06);
    filter: brightness(1.06);
}
.doc-video-play:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 3px;
}

/* ---------- 文章正文动态插图（Steam 微预告 microtrailer） ----------
   common.php 的 steam_build_content_markdown() 会在「# 关于」开篇导语后插入
   <div class="doc-microtrailer-wrap"><video autoplay loop muted playsinline preload="metadata">…</video></div>。
   微预告是 7~8 秒的无声短循环（Steam 商店页鼠标悬停播放的那段），源头只有 MP4/WEBM，**没有 HLS**，
   因此不走 detail.html 的 hls.js 分支，纯靠浏览器原生解码。
   ⚠️ 2026-09-30 曾误判把它改成点播（当时把 HLS 宣传片的 56.9MB 算到了它头上），结果「动态插图」不动了。
      实测它只是**单个完整文件**：webm 1.49MB / mp4 2.1MB，下完一次后循环播放走缓存、不再产生新请求
      → 已恢复 autoplay+loop，且不带 controls（装饰性插图，控制条会破坏版式）。
      真正的流量大头是 `## 视频` 的 HLS 宣传片，那个才保持点播（见 detail.html 的 autoStartLoad:false）。
   与 .doc-body video（点播型、430px 占位、黑底 contain）不同，这里按正文宽度展示、
   无黑边也不设硬框（源尺寸差异大，最终比例由 detail.html 按 videoWidth/Height 校正）。

   ⚠️ aspect-ratio 不能写 auto：auto 意味着「等元数据到位才知道高宽」，
      首帧该 video 高度为 0，元数据到达后瞬间撑到 ~390px（实测发生在 FCP 之后 83ms），
      正文被顶下去 = 刷新可见的第三段闪动。故先用 16/9 预留（Steam 微预告实际比例，
      实测 693×390），真实比例由 JS 纠偏。

   ⚠️ 选择器必须带 #article-content：
   上方「正文视频」规则用的是 `.doc-body video, #article-content video, video[data-hls]`，
   其中 #article-content video 是 (1,0,1) 的 ID 级权重，远高于本组 (0,1,1) 的类级权重，
   只写 .doc-microtrailer-wrap video 会被它按「max-width:430px + aspect-ratio:16/9 + 黑底」
   压住 —— 微预告被迫缩成 430px 小框、出现黑边。这里用 #article-content 把权重抬到同级、
   靠源码顺序（本段在后）胜出。 */
.doc-microtrailer-wrap {
    text-align: center;
    margin: 1.2em 0 1.6em;
}

.doc-body .doc-microtrailer-wrap video,
#article-content .doc-microtrailer-wrap video {
    display: block;
    width: 100%;
    /* 自适应窗口：窄屏随列宽收缩，宽屏封顶放大，居中 */
    max-width: clamp(340px, 90%, 760px);
    /* 16/9 预留位：避免元数据到位前高度为 0（见上方注释）。
       真实比例若非 16/9，由 detail.html 的 bindMicrotrailer 在 loadedmetadata 时改写。 */
    aspect-ratio: 16 / 9;
    height: auto;
    margin: 0 auto;
    border-radius: var(--radius-card);
    background: transparent;
    object-fit: contain;
}

/* ============================================================
   文档正文：TMDB 集合影片卡片（后台粘贴 collection 链接写入正文）
   结构与 TMDB 集合页一致：竖版海报 + 片名 + 上映日期 + 简介，**不含排序控件**；
   封面由后端写死为远程 image.tmdb.org（不落盘）。
   ⚠️ 必须带 .doc-body / #article-content 前缀：.md-rendered 给 h3/p/ul 定过样式，
      不带前缀压不住（同理见 .doc-microtrailer-wrap）；颜色一律走主题变量，禁硬编码。
   ============================================================ */
.doc-body .doc-collection,
#article-content .doc-collection {
    margin: 1.2em 0 1.6em;
}
.doc-body .doc-collection-title,
#article-content .doc-collection-title {
    font-size: 17px;
    font-weight: 700;
    color: var(--color-text-title);
    margin: 0 0 .7em;
}
.doc-body .doc-collection-list,
#article-content .doc-collection-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.doc-body .doc-collection-item,
#article-content .doc-collection-item {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 12px;
    background: var(--color-bg-card-2);
    border: var(--color-border-width) solid var(--color-border);
    border-radius: var(--radius-card);
}
.doc-body .doc-collection-item + .doc-collection-item,
#article-content .doc-collection-item + .doc-collection-item {
    margin-top: 10px;
}
.doc-body .doc-collection-poster,
#article-content .doc-collection-poster {
    flex: 0 0 94px;
    width: 94px;
    line-height: 0;                 /* 消掉 img 行内基线空隙 */
}
.doc-body .doc-collection-poster img,
#article-content .doc-collection-poster img {
    width: 94px;
    height: 141px;
    object-fit: cover;
    border-radius: var(--radius-sm);
}
.doc-body .doc-collection-body,
#article-content .doc-collection-body {
    flex: 1 1 auto;
    min-width: 0;
}
.doc-body .doc-collection-name,
#article-content .doc-collection-name {
    font-size: 15px;
    font-weight: 500;
    color: var(--color-text-title);
    line-height: 1.4;
    /* 合集条目的游戏名常是长英文串/无空格长名，不加这两行会被 min-content 撑破
       .doc-collection-body 的 min-width:0 → 整页在窄屏出现横向滚动（实测 500px 视口被撑到 707px）。 */
    overflow-wrap: anywhere;
    word-break: break-word;
}
.doc-body .doc-collection-date,
#article-content .doc-collection-date {
    font-size: 13px;
    color: var(--color-text-secondary);
    margin-top: 2px;
}
.doc-body .doc-collection-overview,
#article-content .doc-collection-overview {
    font-size: 13px;
    line-height: 1.65;
    color: var(--color-text-body, var(--color-text-secondary));
    margin: .5em 0 0;
    overflow-wrap: anywhere;
    word-break: break-word;
}
/* 合集条目的窄屏收紧（原 max-width:575px，2026-10-03 归入 5 档断点的手机档）。
   已迁至 responsive.css ⑯ 段统一维护，此处不再写断点。 */

/* ============================================================
   文档正文：TMDB 剧集季卡片（后台粘贴 /tv/{id}/seasons 链接写入正文）
   与上面 .doc-collection-* 同构（海报 + 名称 + 元信息 + 简介），差异只有两点：
     ① 元信息行是「评分 · 首播日期 · 共 N 集」三合一（合集只有上映日期）；
     ② 类名独立成套（.doc-seasons-*）——**刻意不与 .doc-collection-* 合并**：
        两者锚点不同（COLLECTION_HEAD / SEASONS_HEAD），同一篇文章可能同时存在，
        合并会让「先粘季列表再粘集合」互相影响样式或被 upsert 顶掉。
   前缀与颜色纪律同上（.doc-body / #article-content + 主题变量，禁硬编码）。
   ============================================================ */
/* 正文分隔线（hr）：Markdown 的 '---' 渲染产物。2026-10-05 季模式「### 介绍」后
   固定跟一条，用来把简介与下面的季卡片视觉隔开。此前全站**没有任何 hr 样式**，
   浏览器默认样式是「1px 立体灰线 + 上下大间距」，深色主题下会显脏且留白过重。
   边距取 1.4em/1.4em：与 .doc-seasons 的 1.2em/1.6em 视觉重量相当，不抢卡片标题。 */
.doc-body hr,
#article-content hr {
    border: 0;
    border-top: 1px solid var(--color-border);
    margin: 1.4em 0;
}
.doc-body .doc-seasons,
#article-content .doc-seasons {
    margin: 1.2em 0 1.6em;
}
.doc-body .doc-seasons-title,
#article-content .doc-seasons-title {
    font-size: 17px;
    font-weight: 700;
    color: var(--color-text-title);
    margin: 0 0 .7em;
}
.doc-body .doc-seasons-list,
#article-content .doc-seasons-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.doc-body .doc-seasons-item,
#article-content .doc-seasons-item {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 12px;
    background: var(--color-bg-card-2);
    border: var(--color-border-width) solid var(--color-border);
    border-radius: var(--radius-card);
}
.doc-body .doc-seasons-item + .doc-seasons-item,
#article-content .doc-seasons-item + .doc-seasons-item {
    margin-top: 10px;
}
.doc-body .doc-seasons-poster,
#article-content .doc-seasons-poster {
    flex: 0 0 94px;
    width: 94px;
    line-height: 0;                 /* 消掉 img 行内基线空隙 */
}
.doc-body .doc-seasons-poster img,
#article-content .doc-seasons-poster img {
    width: 94px;
    height: 141px;
    object-fit: cover;
    border-radius: var(--radius-sm);
}
.doc-body .doc-seasons-body,
#article-content .doc-seasons-body {
    flex: 1 1 auto;
    min-width: 0;                    /* 缺它长简介会把整页撑出横向滚动 */
}
.doc-body .doc-seasons-name,
#article-content .doc-seasons-name {
    font-size: 15px;
    font-weight: 500;
    color: var(--color-text-title);
    line-height: 1.4;
    overflow-wrap: anywhere;
    word-break: break-word;
}
/* 元信息行（评分 · 首播日期 · 共 N 集）：与上方名称拉开一点距离，靠次级字色弱化 */
.doc-body .doc-seasons-meta,
#article-content .doc-seasons-meta {
    font-size: 13px;
    color: var(--color-text-secondary);
    margin-top: 3px;
}
.doc-body .doc-seasons-overview,
#article-content .doc-seasons-overview {
    font-size: 13px;
    line-height: 1.65;
    color: var(--color-text-body, var(--color-text-secondary));
    margin: .5em 0 0;
    overflow-wrap: anywhere;
    word-break: break-word;
}
/* 季条目的窄屏收紧已并入 responsive.css ⑯ 段（与 .doc-collection-* 同一档一起处理）。 */

/* 详情页分类已改为标签行内的 .doc-info-tag.tag-cat（见 tags.css），
   原 .doc-meta-cat 渐变胶囊 chip 及其入场动画已于 2026-10-01 废弃移除。 */

/* ============================================================
   退出登录（POST 表单承载，见 base.html / mbnav.html）
   ------------------------------------------------------------
   登出由 GET 改 POST + CSRF 后，提交控件只能是 <button>。需抹掉浏览器对
   button 的 UA 默认（Arial 字体 / 灰底 / 边框 / 居中 / 默认行高），否则外观
   与同级 <a> 明显不同。

   ⚠️ 选择器必须包在 :where() 里（特异性归 0）：这样只覆盖「既有类没声明」的属性
   （font-family/line-height/背景/边框/光标/对齐），而 padding/font-size/color/display
   等仍由 .user-dropdown-item / .app-drawer-link / .mb-side-item 决定；
   若写成 button.X（特异性 0,1,1）会反过来压掉这些类自己的 color/font-size。
   ⚠️ .logout-form 用 display:contents：表单盒子不参与布局，按钮与改动前的 <a>
   一样直接作为父容器的子项（下拉 / 抽屉 / 侧栏的 flex 布局不受影响）。 */
.logout-form {
    display: contents;
}
:where(button.user-dropdown-item, button.app-drawer-link, button.mb-side-item) {
    appearance: none;
    font-family: inherit;
    font-weight: inherit;
    line-height: inherit;
    text-align: left;
    background: none;
    border: 0;
    cursor: pointer;
}
