/* ============================================================
   知仓学习社 · 设计令牌与样式
   布局参照：即梦 jimeng.jianying.com 首页（工作台型）
   实测取自参考站的关键参数：
     主内容区 1200px / 主标题 30px 600 居中 / 胶囊切换器圆角 110px
     输入框 1010x158 圆角 24px 渐变底 + blur
     中性深灰底 rgb(18,18,18) 与 rgb(26,26,26)，卡片 rgba(255,255,255,.08)
     文字四级透明度 100% / 69.8% / 60% / 35%
   纪律：全站禁用 em-dash / en-dash
   ============================================================ */

:root {
  /* ---------- 底色（照参考站的中性深灰，不用蓝紫调） ---------- */
  --c-bg:        #121212;                 /* 页面底 = rgb(18,18,18) */
  --c-bg-2:      #1a1a1a;                 /* 次级 = rgb(26,26,26) */
  --c-surface:   rgba(255, 255, 255, .08);/* 卡片 = 参考站的半透明白 */
  --c-surface-2: rgba(255, 255, 255, .12);
  --c-surface-3: rgba(255, 255, 255, .16);
  --c-surface-solid: #232323;
  --c-border:    rgba(255, 255, 255, .10);
  --c-border-2:  rgba(255, 255, 255, .18);

  /* ---------- 文字：四级灰阶（2026-09-26 从「半透明白」改成「实色灰」） ----------
     原来用 rgba(255,255,255,.45/.62/.70) 叠在深色底上，等效亮度虽然够，
     但笔画边缘是与底色混出来的，低 DPI 屏上抗锯齿更脏、观感发虚。
     现在写成等效实色（同样的亮度，笔画更实），四级各自带实测对比度：
       --c-text        #ffffff   纯白，标题与主文字
       --c-text-mid    #b7b7b7   9.14:1   次级文字
       --c-text-2      #9a9a9a   7.45:1   正文常用档（列表说明、注释）
       --c-text-weak   #828282   4.9:1    最弱档：面包屑、页脚、辅助标签
     对比度是在侧栏底色 #171717 上算的，页面底色 #121212 上会略高一点。
     注：#787878 那档在列表行底色 #1c1c1c 上只有 4.24:1，达不到 4.5，
     所以最弱档定在 #828282（实测 4.9:1），不要再往下调。 */
  --c-text:      #ffffff;
  --c-text-mid:  #b7b7b7;
  --c-text-2:    #9a9a9a;
  --c-text-weak: #828282;

  /* ---------- 品牌主色：蓝紫渐变（品牌 Logo / 选中态 / 操作入口 / 主标题） ---------- */
  --c-accent:     #6a5ae0;                       /* 渐变起点：蓝紫（已调深保证白字达标） */
  --c-accent-2:   #2b86c9;                       /* 渐变终点：蓝 */
  --grad-brand:   linear-gradient(96deg, #6248d8 0%, #4a6ede 52%, #2b86c9 100%);
  --c-accent-ink: #0a0a12;
  --c-accent-bg:  rgba(106, 90, 224, .18);
  --c-accent-bd:  rgba(106, 90, 224, .46);
  --c-accent-text:#d2ccff;                       /* 渐变系下的可读文字色 */

  /* ---------- 代码 / 报错块 ---------- */
  --c-code-bg:   #0b0b0b;
  --c-code-ink:  #e8e8e8;
  --c-code-key:  #ffd479;
  --c-code-dim:  #9a9a9a;

  /* ---------- 状态 ---------- */
  --c-success:    #4ade9b;  --c-success-bg: rgba(74, 222, 155, .12);  --c-success-bd: rgba(74, 222, 155, .36);
  --c-warn:       #f8c471;  --c-warn-bg:    rgba(248, 196, 113, .12); --c-warn-bd:    rgba(248, 196, 113, .36);
  --c-danger:     #ff7b72;  --c-danger-bg:  rgba(255, 123, 114, .12); --c-danger-bd:  rgba(255, 123, 114, .36);

  /* ---------- 字体 ---------- */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
               "Segoe UI", "Microsoft YaHei UI", "Microsoft YaHei",
               "PingFang SC", "Hiragino Sans GB", "Noto Sans SC", sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;

  /* ---------- 字号（2026-09-26 重排：每一档数值必须不同） ----------
     原来的阶梯是 .6875/.75/.875/.875rem，两个问题：
       1) --fs-13 与 --fs-14 值完全相同（都是 14px），13 这一档名存实亡；
       2) 11px 档被 20 多处用来排正文（文件树、模型卡说明），
          11px 中文在 100% 缩放的显示器上只有 11 个物理像素高，汉字横画糊在一起。
     现在：11px 档取消（并入 12px），列表正文从 12px 提到 14px。
     参考站阶梯是 30/14/13/12/11，我们把它改成 30/18/14/13/12，下限抬高一档。 */
  --fs-12: .75rem; --fs-13: .8125rem; --fs-14: .875rem;
  --fs-16: 1rem; --fs-18: 1.125rem; --fs-20: 1.25rem; --fs-24: 1.5rem;
  --fs-30: 1.875rem;

  /* ---------- 间距（参考站以 24px 为区块间距基准） ---------- */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
  --sp-6: 24px; --sp-8: 32px; --sp-12: 48px;

  /* ---------- 圆角（参考站：输入框 24px、胶囊 110px、卡片 12px） ---------- */
  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-xl: 24px; --r-pill: 110px;
  --dur-fast: 150ms; --dur-base: 200ms; --dur-slow: 250ms;

  --tap-min: 44px;
  --measure: 72ch;
  --measure-prose: 68ch;

  --sidebar-w: 240px;
  --thumb-h: 210px;         /* 实测：1440 屏缩略图 373x210（约 16:9） */
  --content-pad: 24px;      /* 照实测：右侧留 24px，其余全部给内容 */

  --shadow-1: 0 1px 2px rgba(0, 0, 0, .5);
  --shadow-2: 0 10px 34px rgba(0, 0, 0, .55);
  --glow-hover: 0 0 0 1px rgba(123,108,246,.35), 0 12px 36px rgba(79,180,247,.14);
}

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;   /* 手机横竖屏切换时不要自动放大字号 */
  color-scheme: dark;
  text-rendering: optimizeLegibility;
}

/* ---------- 跨设备清晰度：根字号跟随「像素密度」，版式跟随「视口宽度」 ----------
   ------------------------------------------------------------
   2026-09-26 实测发现的问题：同一份 CSS 在八种设备上，字号恒为 12px，
   但物理高度从 12px（100% 缩放显示器）跨到 36px（iPhone 3x），差三倍。
   原因有两个：
     1) 字号下限太低：12px 中文在 1x 屏上只有 12 个物理像素高，横画糊在一起；
     2) 只有宽度断点，没有像素密度断点，等于放弃了 DPR 这个信息。
   处理办法是两层分开：
     - 底部两条：把字号下限整体抬高（已在 :root 的字号阶梯里做，11px 档取消、
       列表正文提到 14px），并在手机视口再抬一档根字号；
     - 上面两条：按 DPR 微调根字号。注意**只用 dppx，不用 vw** ——
       用 vw 撑根字号会让 1920 宽的桌面取到上限、正文被动变大、首屏条目变少，
       实测过：首屏 11 → 9 条。宽度决定版式，密度决定字号，两件事不要混。 */
html { font-size: 16px; }
@media (min-resolution: 1.25dppx) { html { font-size: 16.5px; } }
@media (min-resolution: 1.5dppx)  { html { font-size: 17px; } }
@media (min-resolution: 2dppx)    { html { font-size: 17.5px; } }
@media (max-width: 640px)         { html { font-size: 17px; } }
@media (max-width: 640px) and (min-resolution: 2dppx) { html { font-size: 17.5px; } }

/* 字体光学尺寸：只有部分浏览器支持，支持时开启（标题自动收紧字距），
   不支持就忽略，不影响任何布局。 */
@supports (font-optical-sizing: auto) { body { font-optical-sizing: auto; } }

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-text);
  font-family: var(--font-sans);
  font-size: var(--fs-14);
  line-height: 1.6;
  overflow-x: hidden;
}

::selection { background: rgba(0, 158, 250, .36); color: #fff; }

:focus-visible {
  outline: 2px solid var(--c-accent);
  outline-offset: 2px;
  border-radius: 4px;
}

* { scrollbar-color: rgba(255,255,255,.22) transparent; scrollbar-width: thin; }
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: rgba(255,255,255,.18); border-radius: 4px; }
*::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.3); }

.skip {
  position: absolute; left: -9999px; top: 0;
  background: #4c3fc4; color: #fff;
  padding: var(--sp-3) var(--sp-4); z-index: 100;
}
.skip:focus { left: 0; }

/* ============================================================
   应用外壳：左侧导航 + 主内容（照参考站的工作台结构）
   ============================================================ */
.shell {
  display: grid;
  /* 照实测：侧栏 240 + 主内容自适应；右栏为浮层，不占宽度 */
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 100vh;
}

/* ---------- 左侧导航 ---------- */
/* 顶部留白口径（2026-09-26 按需求压缩过一次，别再改回 14px/44px）：
   原来「站名行 → 首页」之间是 flex gap 的 24px，加站名行 44px 最小高度与侧栏顶 14px，
   导航文字落在视口 104px 处，顶部显得空。现在拆成三处收紧：
     侧栏 padding-top 14 → 8
     站名行 min-height 44 → 32（品牌行不是主导航项，不需要 44 触控高；图标 26px 仍在）
     站名行与主导航之间 24 → 4（用 .side-nav-fixed 的 margin 抵消，不动整列的 gap：
       「更多板块」「页脚」之间的 24px 是有用的分区间隔，保留） */
.side {
  position: sticky; top: 0; align-self: start;
  height: 100vh; padding: 8px 12px 12px; background: #171717;
  display: flex; flex-direction: column; gap: var(--sp-6);
}
.side-brand {
  display: flex; align-items: center; gap: 10px;
  color: var(--c-text); text-decoration: none;
  font-size: var(--fs-14); font-weight: 600;
  min-height: 32px; padding: 0 12px;
}
/* 站名前的图形标识：圆形头像式。图片由 build.mjs 的 markImg 内联生成
   （96×96 原图，圆形裁切 + 白底，显示成 26px 圆）。
   2026-09-26：先是从「知」字方块换成站点图标，再按需求做成圆形。
   border-radius:50% 是兜底：图片本身已经裁成圆形，这里再加一层，
   以后若换成方形图也不会露出方角。width/height 一起写，避免加载时跳动。 */
.side-mark {
  width: 26px; height: 26px; flex-shrink: 0;
  border-radius: 50%; object-fit: cover; display: block;
}
.side-brand > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.side-nav { display: flex; flex-direction: column; gap: var(--sp-1); }
.side-nav a {
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: var(--tap-min); padding: 0 var(--sp-3);
  border-radius: var(--r-md);
  color: var(--c-text-mid); text-decoration: none;
  font-size: var(--fs-14); font-weight: 500;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.side-nav a:hover { background: var(--c-surface); color: var(--c-text); }
.side-nav a[aria-current="page"] {
  background: var(--c-accent-bg); color: var(--c-accent-text); font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--c-accent-bd);
}
.side-nav .i { display: flex; flex-shrink: 0; opacity: .9; }
.side-nav .grp {
  font-size: var(--fs-12); color: var(--c-text-weak);
  padding: var(--sp-3) var(--sp-3) var(--sp-1);
}

.side-foot { margin-top: auto; font-size: var(--fs-12); color: var(--c-text-weak); }
.side-foot a {
  color: var(--c-text-2); text-decoration: none;
  display: flex; align-items: center; min-height: var(--tap-min);
}
.side-foot a:hover { color: var(--c-text); }

/* ---------- 主内容 ---------- */
.main { min-width: 0; width: 100%; overflow: hidden; padding: 0; }
/* 照实测：内容容器 padding 68px 24px 80px 40px，内容区实宽 1136 */
/* 照实测：内容区实宽 1136（左 40 / 右 64），首屏上留白 68 */
/* 2026-09-26 压缩：上留白 68 → 28。操作栏本身就是 60px 的 sticky 页眉，
   再叠 68px 会在「页眉 → 面包屑」之间留下 92px 空白（实测：面包屑落在视口 141px 处）。
   模型页早就是这么做的（.main-in.is-mpage 用 16px），这里把通用值也收下来，
   两者口径接近，不再出现「模型页紧、其他页松」的不一致。 */
.main-in { max-width: none; width: 100%; min-width: 0; padding: 28px 64px 80px 40px; }

/* 窄屏顶栏（宽屏隐藏） */
.topbar { display: none; }

/* ============================================================
   第一屏：居中标题 + 胶囊切换器 + 大输入框（照参考站）
   ============================================================ */


/* 胶囊切换器（照参考站：半透明白底 / padding 2px / 圆角 110px） */
.seg {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 2px; margin-bottom: var(--sp-6);
  background: var(--c-surface); border-radius: var(--r-pill);
  max-width: 100%; overflow-x: auto; scrollbar-width: none;
}
.seg::-webkit-scrollbar { display: none; }
.seg a {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap-min); padding: 0 var(--sp-4);
  border-radius: var(--r-pill); white-space: nowrap;
  font-size: var(--fs-14); font-weight: 400;
  color: var(--c-text-mid); text-decoration: none;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.seg a:hover { color: var(--c-text); }
.seg a[aria-current="page"] { background: rgba(255,255,255,.14); color: var(--c-text); font-weight: 500; }

/* 大输入框（照参考站：约 1010 宽 / 圆角 24px / 渐变底 + 模糊） */
.wb-input {
  position: relative; width: 100%; max-width: 1136px; margin: 0 auto;
  padding: 1px; border-radius: var(--r-xl);
  background: linear-gradient(180deg, rgba(255,255,255,.16) 0%, rgba(255,255,255,.05) 100%);
  box-shadow: var(--shadow-2);
}
.wb-input-in {
  border-radius: 24px; padding: 18px 20px; min-height: 156px;
  background: linear-gradient(rgba(26,26,26,.92) 0px, rgba(32,32,32,.92) 100%);
  display: flex; flex-direction: column; gap: var(--sp-4);
}
.wb-search { position: relative; }
.wb-search input {
  width: 100%; min-height: 76px;
  padding: 0 4px 0 92px;
  font-size: var(--fs-16); font-family: inherit;
  color: var(--c-text); background: transparent;
  border: 0; outline: none;
}
.wb-search input::placeholder { color: var(--c-text-weak); }
.wb-search .ico {
  position: absolute; left: var(--sp-4); top: 50%; transform: translateY(-50%);
  color: var(--c-text-2); display: flex; pointer-events: none;
}

/* 行内搜索框（页面内的小搜索，区别于首屏的大输入框 .wb-input）
   ------------------------------------------------------------
   2026-09-26 补：`.search` 这个类此前**样式表里根本没有**，节点库与搜索页
   一直在用一个没有样式的 form —— 实测节点库首页的 input 只有 21px 高，
   低于站上 44px 的触控线（audit.cjs 报了 [触控] 节点库首页）。
   这里按 .wb-search 的同一套口径补齐：定位上下文 + 触控高度 + 图标位。
   注意：.sr 浮层靠 top:calc(100% + 10px) 落在输入框下方，
   所以 .search 必须 position: relative，否则浮层会跑到页面左上角。 */
.search {
  position: relative;
  border-radius: var(--r-pill);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  overflow: visible;
}
.search input {
  width: 100%; min-height: var(--tap-min);
  padding: 0 var(--sp-4) 0 48px;
  font-size: var(--fs-16); font-family: inherit;
  color: var(--c-text); background: transparent;
  border: 0; border-radius: var(--r-pill); outline: none;
}
.search input::placeholder { color: var(--c-text-weak); }
.search .ico {
  position: absolute; left: var(--sp-4); top: 50%; transform: translateY(-50%);
  color: var(--c-text-2); display: flex; pointer-events: none;
}
.search input:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 1px; }
.wb-tools { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.wb-chip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--tap-min); padding: 0 var(--sp-4);
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.10);
  color: var(--c-text-2); font-size: var(--fs-12); text-decoration: none;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.wb-chip:hover { background: rgba(255,255,255,.14); color: var(--c-text); border-color: rgba(255,255,255,.2); }
.wb-chip.is-key { color: var(--c-accent-text); border-color: var(--c-accent-bd); background: var(--c-accent-bg); }
.wb-submit {
  margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--tap-min); padding: 0 var(--sp-4);
  border-radius: var(--r-pill); border: 0; cursor: pointer;
  background: var(--grad-brand); color: #fff;
  font-size: var(--fs-13); font-weight: 500; font-family: inherit;
  transition: filter var(--dur-fast), box-shadow var(--dur-fast);
}
.wb-submit:hover { filter: brightness(1.08); box-shadow: var(--glow-hover); }

/* 搜索结果浮层 */
.sr {
  position: absolute; left: 0; right: 0; top: calc(100% + 10px); z-index: 30;
  background: var(--c-surface-solid); border: 1px solid var(--c-border-2);
  border-radius: var(--r-md); box-shadow: var(--shadow-2);
  overflow: hidden; max-height: 56vh; overflow-y: auto; text-align: left;
}
.sr-item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); text-decoration: none; color: inherit;
  border-bottom: 1px solid var(--c-border);
}
.sr-item:last-child { border-bottom: 0; }
.sr-item:hover, .sr-item:focus { background: var(--c-surface-2); }
.sr-c {
  flex-shrink: 0; font-size: var(--fs-12); padding: 1px 8px;
  border-radius: var(--r-pill); background: var(--c-accent-bg);
  color: var(--c-accent); border: 1px solid var(--c-accent-bd);
}
.sr-t { font-size: var(--fs-14); min-width: 0; }
.sr-empty { padding: var(--sp-4); font-size: var(--fs-14); color: var(--c-text-weak); }

/* 通用辅助文字（.muted）：2026-09-26 从 13px 提到 14px。
   它是页面里最常见的「次级正文」（板块介绍、卡片说明、数据来源注解），
   规格上不该比列表正文更小，否则同一屏里出现三种接近的字号，观感发虚。 */
.muted { color: var(--c-text-weak); font-size: var(--fs-14); }

/* ============================================================
   内容区块
   ============================================================ */
.section { padding: var(--sp-8) 0 0; }
.section-head {
  display: flex; align-items: baseline; gap: var(--sp-3);
  margin-bottom: var(--sp-4); flex-wrap: wrap;
}
.section-head h2 { font-size: var(--fs-18); margin: 0; font-weight: 600; }
.section-head .more {
  margin-left: auto; font-size: var(--fs-13); color: var(--c-text-2);
  text-decoration: none; display: inline-flex; align-items: center; min-height: var(--tap-min);
}
.section-head .more:hover { color: var(--c-accent); }

/* 标签筛选行（照参考站：精选 / 广告营销 / 影视作品 ...） */
.chips { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: var(--sp-6); }
.chips a {
  display: inline-flex; align-items: center; min-height: var(--tap-min); padding: 0 var(--sp-4);
  border-radius: var(--r-pill); background: rgba(255,255,255,.06);
  color: var(--c-text-2); font-size: var(--fs-13); text-decoration: none;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.chips a:hover { background: rgba(255,255,255,.12); color: var(--c-text); }
.chips a[aria-current="page"] { background: rgba(255,255,255,.16); color: var(--c-text); }

.grid { display: grid; gap: var(--sp-3); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* 卡片（照参考站：半透明白底 / 圆角 12px） */
.card {
  display: block; text-decoration: none; color: inherit;
  background: #1c1c1c;
  border: 1px solid var(--c-border);
  border-radius: var(--r-md); padding: var(--sp-4);
  transition: border-color var(--dur-fast), transform var(--dur-fast), box-shadow var(--dur-fast), background var(--dur-fast);
}
.card:hover { background: var(--c-surface-2); border-color: var(--c-accent-bd); transform: translateY(-2px); box-shadow: var(--glow-hover); }
.card:active { transform: translateY(0); }
.card h3 { margin: 0 0 var(--sp-1); font-size: var(--fs-14); font-weight: 600; line-height: 1.45; }
.card p { margin: 0; font-size: var(--fs-13); color: var(--c-text-2); line-height: 1.6; }
.card .meta { margin-top: var(--sp-3); display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }

/* 板块入口 */
.entry {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: var(--sp-2);
  padding: var(--sp-6) var(--sp-4); min-height: 140px;
  background: #1c1c1c;
  border: 1px solid var(--c-border);
  border-radius: var(--r-md); text-decoration: none; color: inherit;
  transition: background var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast);
}
.entry:hover { background: var(--c-surface-2); border-color: var(--c-accent-bd); transform: translateY(-2px); box-shadow: var(--glow-hover); }
.entry .ico { color: var(--c-accent); display: flex; }
.entry b { font-size: var(--fs-14); font-weight: 600; }
.entry span { font-size: var(--fs-12); color: var(--c-text-2); line-height: 1.55; }
.entry .count { margin-top: auto; font-size: var(--fs-12); color: var(--c-text-weak); font-variant-numeric: tabular-nums; }

/* 列表行 */
/* ⚠ 类名复用陷阱（2026-09-26 实测踩到，务必看这段）
   `.side` 在本站是**左侧导航栏**的类（见文件上方 .side）：position: sticky、height: 100vh、
   padding、background、flex-direction: column。
   而列表行的右栏也叫 `.side`（见 .row .side），两者撞名。
   只有右栏内容很矮时才看不出问题；一旦右栏内容变高（节点速查的适配模型标签就是），
   height:100vh 会把每一行撑成 900px 高 —— 实测节点库页面因此每行 926px、
   整页 4 万像素、满屏全是空块。
   这里把导航栏的布局属性在 `.row .side` 上全部复位，只保留右栏该有的横排布局。
   文件下方（第 1218 行附近）原本就写了「不能复用 .main / .side」，
   这条警告是真的，新写页面时请给右栏换一个类名（如 .rside）或复用 .row 这一套。 */
.list { display: flex; flex-direction: column; gap: var(--sp-2); }
.row {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--c-border); border-radius: var(--r-md);
  text-decoration: none; color: inherit;
  background: #1c1c1c;
  transition: background var(--dur-fast), border-color var(--dur-fast);
}
.row:hover { background: var(--c-surface-2); border-color: var(--c-border-2); }
/* 行内是链接时，标题颜色要跟正常文字一致。
   不加这条时，<a class="row"><span class="t"> 会被全局链接色（强调紫）接管：
   深色底上只有 3.37:1，达不到 4.5 的对比度门槛（audit.cjs 实测报过）。
   概念页的「相关条目」用它；行整体仍是可点链接，只是文字颜色不变成紫。 */
.row.c-link, .row.c-link .t { color: var(--c-text-2); }
.row.c-link:hover, .row.c-link:hover .t { color: var(--c-text); }
.row .main { min-width: 0; flex: 1; }
.row .t { font-size: var(--fs-14); font-weight: 500; line-height: 1.5; }
.row .d { font-size: var(--fs-13); color: var(--c-text-2); margin-top: 2px; }
.row .side {
  display: flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end;
  /* 复位「左侧导航栏」带来的布局属性，见上面的类名复用陷阱 */
  position: static; height: auto; align-self: auto;
  padding: 0; background: none; flex-direction: row;
}

/* 带行尾按钮的列表项（工作流清单：行本身可点进详情，右侧「网盘」单独可点）。
   <a> 不能套 <a>，所以按钮必须与 .row 平级，这里负责把它们排成一行。 */
.list-item { display: flex; align-items: flex-start; gap: var(--sp-2); }
.list-item > .row { flex: 1; min-width: 0; }
.list-item > .wfdl { flex-shrink: 0; align-self: center; white-space: nowrap; }
@media (max-width: 560px) {
  .list-item { flex-wrap: wrap; }
  .list-item > .wfdl { width: 100%; justify-content: center; }
}

/* 徽标 */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-12); line-height: 1.5;
  padding: 2px var(--sp-3); border-radius: var(--r-pill);
  border: 1px solid var(--c-border); background: rgba(255,255,255,.06);
  color: var(--c-text-2); white-space: nowrap; font-variant-numeric: tabular-nums;
}
.badge-accent { background: var(--c-accent-bg); border-color: var(--c-accent-bd); color: var(--c-accent-text); }
.badge-ok { background: var(--c-success-bg); border-color: var(--c-success-bd); color: var(--c-success); }
.badge-warn { background: var(--c-warn-bg); border-color: var(--c-warn-bd); color: var(--c-warn); }
.badge-danger { background: var(--c-danger-bg); border-color: var(--c-danger-bd); color: var(--c-danger); }
.badge-soft { background: rgba(255,255,255,.10); border-color: transparent; }

/* 版本徽标 */
.ver {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-md);
  font-size: var(--fs-13); font-variant-numeric: tabular-nums;
  border: 1px solid var(--c-border); background: var(--c-surface);
  color: var(--c-text-2); flex-wrap: wrap;
}
.ver b { font-weight: 600; color: var(--c-text); }
.ver.fresh { border-color: var(--c-success-bd); background: var(--c-success-bg); }
.ver.stale { border-color: var(--c-warn-bd); background: var(--c-warn-bg); color: #f3d3a0; }
.ver.dead  { border-color: var(--c-danger-bd); background: var(--c-danger-bg); color: #ffb4ad; }
/* 尚未实测核实：中性偏提醒的样式，刻意不用绿色，避免与「已核实」混淆。
   数据补齐后 verBadge() 会自动切回 .ver.fresh，不用手工改样式。 */
.ver.unverified { border-color: var(--c-warn-bd); background: var(--c-warn-bg); color: #f3d3a0; }

/* 报错块 */
.errbox { position: relative; }
.errbox-head {
  display: flex; align-items: center; gap: var(--sp-3);
  background: rgba(255,255,255,.07); color: var(--c-code-ink);
  padding: var(--sp-2) var(--sp-3) var(--sp-2) var(--sp-4);
  border: 1px solid var(--c-border); border-bottom: 0;
  border-radius: var(--r-md) var(--r-md) 0 0;
  font-size: var(--fs-12); font-family: var(--font-mono);
}
.errbox-head .lbl { color: var(--c-code-dim); }
.errbox pre {
  margin: 0; background: var(--c-code-bg); color: var(--c-code-ink);
  padding: var(--sp-4); border: 1px solid var(--c-border); border-top: 0;
  border-radius: 0 0 var(--r-md) var(--r-md);
  font-family: var(--font-mono); font-size: var(--fs-13); line-height: 1.65;
  overflow-x: auto; white-space: pre; tab-size: 2;
}
.errbox pre .k { color: var(--c-code-key); }
.errbox pre .d { color: #94b8d8; }

.copy {
  margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
  background: rgba(255,255,255,.10); color: var(--c-text);
  border: 1px solid var(--c-border-2); border-radius: var(--r-pill);
  padding: 0 var(--sp-3); font-size: var(--fs-12);
  font-family: var(--font-sans); cursor: pointer; min-height: var(--tap-min);
  transition: background var(--dur-fast), border-color var(--dur-fast);
}
.copy:hover { background: rgba(255,255,255,.18); }
.copy[data-done="1"] { background: var(--c-success); border-color: var(--c-success); color: #04241a; font-weight: 600; }

/* 代码块 */
.codeblock { border: 1px solid var(--c-border); border-radius: var(--r-md); overflow: hidden; margin: var(--sp-4) 0; }
.codeblock .errbox-head { border-radius: 0; }
.codeblock pre {
  margin: 0; background: var(--c-code-bg); color: var(--c-code-ink);
  padding: var(--sp-4); font-family: var(--font-mono); font-size: var(--fs-13);
  line-height: 1.65; overflow-x: auto; white-space: pre;
}

/* 表格 */
.table-wrap { overflow-x: auto; border: 1px solid var(--c-border); border-radius: var(--r-md); background: var(--c-surface); }
table.tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-13); }
table.tbl th, table.tbl td {
  padding: var(--sp-3); text-align: left;
  border-bottom: 1px solid var(--c-border); vertical-align: top;
}
table.tbl thead th {
  background: rgba(255,255,255,.07); font-weight: 600; font-size: var(--fs-12);
  color: var(--c-text-2); white-space: nowrap;
}
table.tbl tbody tr:last-child td { border-bottom: 0; }
table.tbl tbody tr:hover { background: rgba(255,255,255,.05); }
.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--fs-13); color: var(--c-text-2); }

@media (max-width: 640px) {
  .table-wrap.as-cards { border: 0; background: transparent; overflow: visible; }
  .as-cards table.tbl, .as-cards thead, .as-cards tbody, .as-cards tr, .as-cards td { display: block; width: 100%; }
  .as-cards thead { display: none; }
  .as-cards tr {
    border: 1px solid var(--c-border); border-radius: var(--r-md);
    margin-bottom: var(--sp-3); padding: var(--sp-2) var(--sp-3); background: var(--c-surface);
  }
  .as-cards td { border: 0; padding: var(--sp-2) 0; }
  .as-cards td::before {
    content: attr(data-th); display: block;
    font-size: var(--fs-12); color: var(--c-text-weak); margin-bottom: 2px;
  }
}

/* 正文 */
.prose { max-width: var(--measure-prose); }
.prose h2 { font-size: var(--fs-18); margin: var(--sp-8) 0 var(--sp-3); font-weight: 600; }
.prose h3 { font-size: var(--fs-14); margin: var(--sp-6) 0 var(--sp-2); font-weight: 600; }
.prose p { margin: 0 0 var(--sp-4); }
.prose ul, .prose ol { margin: 0 0 var(--sp-4); padding-left: 1.4em; }
.prose li { margin-bottom: var(--sp-2); }
.prose code {
  font-family: var(--font-mono); font-size: .92em;
  background: rgba(255,255,255,.10); padding: 1px 6px; border-radius: var(--r-sm);
  color: #cfe6ff;
}
.prose a { color: var(--c-accent); text-underline-offset: 3px; }

.steps { counter-reset: s; list-style: none; padding: 0; margin: 0; }
.steps > li { counter-increment: s; position: relative; padding-left: 42px; margin-bottom: var(--sp-4); }
.steps > li::before {
  content: counter(s); position: absolute; left: 0; top: 1px;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--c-accent-bg); color: var(--c-accent);
  border: 1px solid var(--c-accent-bd);
  display: grid; place-items: center; font-size: var(--fs-12); font-weight: 600;
}
.steps .expect {
  margin-top: var(--sp-2); font-size: var(--fs-13);
  color: var(--c-text-2); border-left: 2px solid var(--c-border-2); padding-left: var(--sp-3);
}

/* 提示块 */
.note {
  border: 1px solid var(--c-border); border-left-width: 3px;
  border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-13); margin: var(--sp-4) 0; background: var(--c-surface);
}
.note b { display: block; margin-bottom: 2px; font-size: var(--fs-13); color: var(--c-text); }
.note.warn { border-left-color: var(--c-warn); background: var(--c-warn-bg); }
.note.danger { border-left-color: var(--c-danger); background: var(--c-danger-bg); }
.note.ok { border-left-color: var(--c-success); background: var(--c-success-bg); }
.note.info { border-left-color: var(--c-accent); background: var(--c-accent-bg); }

/* 目录 */
.toc {
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-6);
  font-size: var(--fs-13);
}
.toc b { display: block; font-size: var(--fs-12); color: var(--c-text-weak); margin-bottom: var(--sp-2); }
.toc ol { margin: 0; padding-left: 1.3em; }
.toc li { margin-bottom: 2px; }
.toc a { color: var(--c-text-2); text-decoration: none; }
.toc a:hover { color: var(--c-accent); text-decoration: underline; }

/* 面包屑 */
/* 面包屑：上间距 24 → 8。它与 .main-in 的上内边距是叠加关系，
   两处都按老值算时，「页眉 → 面包屑」合计 92px。现在合计 36px。 */
.crumb { font-size: var(--fs-13); color: var(--c-text-weak); padding: var(--sp-2) 0 0; }
.crumb a { color: var(--c-text-weak); text-decoration: none; }
.crumb a:hover { color: var(--c-accent); }
.crumb span { margin: 0 var(--sp-2); }

/* 下载卡 */
.dl {
  border: 1px solid var(--c-accent-bd);
  background: #1c1c1c;
  border-radius: var(--r-lg); padding: var(--sp-4); margin: var(--sp-6) 0;
}
.dl h3 { margin: 0 0 var(--sp-2); font-size: var(--fs-14); font-weight: 600; display: flex; align-items: center; gap: var(--sp-2); }
/* 卡片内的次要文字改用 --c-text-2（#9a9a9a），不用 --c-text-weak（#828282）。
   ------------------------------------------------------------
   2026-10-01 修，起因是一次「全量挂载干跑」：
     .dl 卡片有 background:#1c1c1c，而 .muted 是 #828282 —— 在 #1c1c1c 上
     对比度只有 4.43:1，差 0.07 不达 4.5 的 AA 线（audit.cjs 会报）。
     为什么以前没报：包**未挂载**时走的是 .dl.dl-pending 那一支，背景是透明的，
     实际底色是页面底 #121212，同样的 #828282 在它上面是 4.79:1，达标。
     也就是说这条问题只在「链接挂上之后」才出现 —— 正好是上线前那一刻。
     改成 #9a9a9a 后在 #1c1c1c 上是 6.08:1，留足余量；只影响卡片内的次要文字，
     不动 .muted 本身（它在页面底色上是达标的，全站 1138 页都依赖它）。 */
.dl .muted { color: var(--c-text-2); }
.dl .files { font-size: var(--fs-13); color: var(--c-text-2); margin: 0 0 var(--sp-4); padding-left: 1.2em; }
.dl .files li { margin-bottom: 2px; }
.btns { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: var(--tap-min); padding: 0 var(--sp-4);
  border-radius: var(--r-pill); font-size: var(--fs-13); font-family: inherit;
  text-decoration: none; cursor: pointer;
  border: 1px solid var(--c-border-2); background: rgba(255,255,255,.08); color: var(--c-text);
  transition: background var(--dur-fast), border-color var(--dur-fast);
}
.btn:hover { background: rgba(255,255,255,.15); }
.btn-primary { background: var(--grad-brand); border-color: transparent; color: #fff; font-weight: 500; }
.btn-primary:hover { filter: brightness(1.08); background: var(--grad-brand); box-shadow: var(--glow-hover); }
.btn-sm { min-height: var(--tap-min); padding: 0 var(--sp-3); font-size: var(--fs-13); }

/* 示例数据标注（预览版专用） */
.sample {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-12); padding: 1px 7px; border-radius: var(--r-pill);
  background: rgba(196, 154, 255, .16); color: #d6b8ff;
  border: 1px solid rgba(196, 154, 255, .38); white-space: nowrap;
}
.sample-bar {
  background: rgba(139, 123, 247, .16);
  border-bottom: 1px solid rgba(139, 123, 247, .30);
  color: #cfc4ff; font-size: var(--fs-12);
  padding: var(--sp-2) var(--sp-4); text-align: center;
}
.sample-bar b { color: #e2dbff; }

/* 页脚 */
.foot {
  margin-top: var(--sp-12); padding-top: var(--sp-6);
  border-top: 1px solid var(--c-border);
  font-size: var(--fs-12); color: var(--c-text-weak);
}
.foot .cols { display: flex; gap: var(--sp-8); flex-wrap: wrap; margin-bottom: var(--sp-4); }
.foot .col b { display: block; color: var(--c-text-2); font-size: var(--fs-12); margin-bottom: var(--sp-2); }
.foot a { color: var(--c-text-2); text-decoration: none; display: flex; align-items: center; min-height: var(--tap-min); }
.foot a:hover { color: var(--c-accent); }
.foot .legal { line-height: 1.8; }
.foot .legal b { color: var(--c-text-2); }

.slogan-card { display: flex; flex-direction: column; }
.slogan-text { font-size: var(--fs-16); line-height: 1.5; font-weight: 600; }

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

@media (max-width: 1180px) {
  :root { --sidebar-w: 200px; }

  .main { padding-right: var(--sp-4); }
  .side { padding-left: var(--sp-4); }
}

@media (max-width: 900px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 820px) {
  /* 窄屏：侧边导航收起为顶栏一行 */
  .shell { grid-template-columns: minmax(0, 1fr); }
  .side { display: none; }
  .topbar {
    display: block; position: sticky; top: 0; z-index: 20;
    background: rgba(18,18,18,.86);
    backdrop-filter: saturate(1.5) blur(14px); -webkit-backdrop-filter: saturate(1.5) blur(14px);
    border-bottom: 1px solid var(--c-border);
  }
  .topbar-in {
    max-width: none; width: 100%;
    padding: var(--sp-2) var(--sp-4); display: flex; align-items: center; gap: var(--sp-3);
  }
  /* 窄屏顶栏的品牌位恢复 44px 触控高：桌面侧栏那份可以压到 32px（品牌只是回首页的
     次要入口，主导航另有「首页」），但顶栏在手机上是要用手指点的，不能低于 44px。
     （2026-09-26 压缩侧栏留白时曾把两处一起压到 32px，audit.cjs 的触控检查当场抓到。） */
  .topbar .side-brand { flex-shrink: 0; min-height: var(--tap-min); }
  .topnav { display: flex; gap: var(--sp-1); margin-left: auto; overflow-x: auto; scrollbar-width: none; }
  .topnav::-webkit-scrollbar { display: none; }
  .topnav a {
    display: inline-flex; align-items: center; min-height: var(--tap-min);
    padding: 0 var(--sp-3); border-radius: var(--r-md);
    color: var(--c-text-mid); text-decoration: none; font-size: var(--fs-14); white-space: nowrap;
  }
  .topnav a[aria-current="page"] { color: var(--c-text); background: var(--c-surface-2); }
  .main { padding: 0 var(--sp-4) var(--sp-8); }
}

@media (max-width: 640px) {
  .wb-input-in { padding: var(--sp-3); gap: var(--sp-3); }
  .wb-search input { min-height: 52px; font-size: var(--fs-14); padding-left: 42px; }
  .search input { min-height: 52px; font-size: var(--fs-14); padding-left: 42px; }
  .wb-submit { margin-left: 0; width: 100%; justify-content: center; }
  .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .row { flex-wrap: wrap; }
  .row .side { width: 100%; justify-content: flex-start; }
  .btns .btn { flex: 1 1 auto; }
  .seg a { min-height: var(--tap-min); }
}

/* ============================================================
   文字扫光（照参考站：2s linear 一次扫过）
   做法：渐变文字 + 遮罩扫过，比 conic-gradient 更稳、不掉帧
   ============================================================ */
.sweep {
  position: relative;
  background: var(--grad-brand);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: var(--c-accent);
  width: fit-content; max-width: 100%;
}
@media print {
  .side, .topbar, .foot, .skip, .sample-bar, .wb-tools, .wb-submit { display: none; }
  body { background: #fff; color: #111; }
  .shell { grid-template-columns: 1fr; }
  .card, .dl, .note { break-inside: avoid; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  .card:hover, .entry:hover { transform: none; }
  .sweep::after { display: none; }
}

/* ============================================================
   顶部全局操作栏（全站第二层导航骨架）
   ============================================================ */
.actbar {
  position: sticky; top: 0; z-index: 15;
  background: rgba(18, 18, 18, .62);
  backdrop-filter: saturate(1.6) blur(20px); -webkit-backdrop-filter: saturate(1.6) blur(20px);
  border-bottom: 1px solid var(--c-border);
  margin: 0 0 var(--sp-3) 0;
  padding: 0 var(--sp-6);
}
.actbar-in {
  max-width: none; width: 100%;
  display: flex; align-items: center; gap: var(--sp-3); min-height: 60px;
}
.actbar .path {
  font-size: var(--fs-13); color: var(--c-text-2);
  display: flex; align-items: center; gap: var(--sp-2); min-width: 0;
}
.actbar .path b { color: var(--c-text); font-weight: 600; }
.actbar .path .sep { color: var(--c-text-weak); }
.actbar-actions { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }
.iconbtn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: var(--tap-min); min-width: var(--tap-min); padding: 0 var(--sp-3);
  border-radius: var(--r-pill); border: 1px solid var(--c-border);
  background: rgba(255,255,255,.06); color: var(--c-text-2);
  font-size: var(--fs-13); text-decoration: none; cursor: pointer; font-family: inherit;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.iconbtn:hover { background: rgba(255,255,255,.13); color: var(--c-text); border-color: var(--c-border-2); }
.iconbtn.is-primary {
  background: var(--grad-brand); border-color: transparent; color: #fff; font-weight: 500;
}
.iconbtn.is-primary:hover { filter: brightness(1.08); box-shadow: var(--glow-hover); }

/* 首屏居中标题（照实测：h1 在输入框上方居中） */
/* 照实测：标题栏 flex gap 24px，高 102px，h1 30px/600/38px */
.hero-title {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding: 0 0 28px; min-height: 102px; text-align: center;
}
.hero-title h1 {
  font-size: 44px; line-height: 56px; font-weight: 600;
  margin: 0 0 var(--sp-2); color: var(--c-text); letter-spacing: -.01em;
}
.hero-slogan {
  margin: 0; font-size: 18px; line-height: 28px;
  color: var(--c-text-2); letter-spacing: .04em;
}
.hero-title .en {
  font-family: var(--font-mono); font-size: var(--fs-12);
  letter-spacing: .2em; color: var(--c-text-weak); text-transform: uppercase;
}
/* ============================================================
   首屏 Banner：通栏大幅焦点位
   ============================================================ */
.banner {
  position: relative;
  border-radius: var(--r-lg);
  padding: 28px 32px;
  background: #1a1a1a;                 /* 实测即梦底色 rgb(26,26,26)，不用彩色 */
  border: 1px solid rgba(255,255,255,.08);
  margin-bottom: var(--sp-4);
  display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap;
}
.banner .tag {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-12); padding: 3px var(--sp-3); border-radius: var(--r-pill);
  background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.12);
  color: var(--c-text-2); white-space: nowrap;
}
.banner h2 {
  font-size: var(--fs-18); line-height: 1.5; font-weight: 600;
  margin: 0; color: var(--c-text); letter-spacing: 0;
  background: none; -webkit-text-fill-color: currentColor;
}
.banner p {
  margin: 0; font-size: var(--fs-13); line-height: 1.6;
  color: var(--c-text-weak); flex: 1 1 260px; min-width: 0;
}.banner .btns { position: relative; z-index: 2; }

/* ============================================================
   双层分类标签导航
   ============================================================ */
.tagstack { display: flex; flex-direction: column; gap: var(--sp-3); margin-bottom: var(--sp-6); }
.tagrow { display: flex; gap: var(--sp-2); flex-wrap: wrap; align-items: center; }
.tagrow .lbl {
  font-size: var(--fs-12); color: var(--c-text-weak);
  margin-right: var(--sp-2); flex-shrink: 0;
}
.tagrow a {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--tap-min); padding: 0 var(--sp-4);
  border-radius: var(--r-pill); text-decoration: none;
  font-size: var(--fs-13); color: var(--c-text-2);
  background: rgba(255,255,255,.05); border: 1px solid transparent;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.tagrow a:hover { background: rgba(255,255,255,.11); color: var(--c-text); }
.tagrow a[aria-current="page"] {
  background: var(--c-accent-bg); border-color: var(--c-accent-bd);
  color: var(--c-accent-text); font-weight: 500;
}
.tagrow.is-mode a {
  background: rgba(255,255,255,.08);
  border-color: rgba(255,255,255,.10);
}
.tagrow.is-mode a[aria-current="page"] {
  background: var(--grad-brand); border-color: transparent; color: #fff; font-weight: 500;
}

/* ============================================================
   灵感内容区：网格瀑布流
   ============================================================ */
/* ============================================================
   首页「最近更新」卡片：纯文字版式（2026-09-26 改）
   ------------------------------------------------------------
   改之前是「16:9 缩略图 + 固定信息栏」的方框块：卡片高度写死
   （--thumb-h + 88px = 278/292px），配图用的是 4 张模糊示例图循环。
   实测发现两件事：图片不是真实内容（只是占位素材），
   而固定高度让纯文字卡片留下大片空白。
   现在改成：没有缩略图，卡片高度由内容决定（grid-auto-rows: auto），
   三列网格，每张卡 = 分类行 + 标题（最多两行）+ 说明行。
   保留 .thumb / .thumb-cat / .thumb-tag / .play 的样式定义不删：
   它们描述的是「有图卡片」的形态，将来要加真实配图可以直接复用。
   ============================================================ */
/* 照实测自适应：宽度够就 4 列（卡片 398），不够就 3 列（卡片 373） */
.masonry {
  display: grid; gap: 12px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-auto-rows: auto;          /* 高度跟内容走，不再锁死方框 */
  align-items: stretch;
}
.masonry > * { min-width: 0; }
.masonry > * { margin: 0; }

.work {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: 6px;
  padding: var(--sp-4);
}
/* 分类行：文字版式里分类改为独立一行（原来是叠在缩略图上的角标） */
.work .cat-line {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-12); color: var(--c-text-2); letter-spacing: .02em;
}
.work h3 {
  margin: 0; font-size: var(--fs-14); font-weight: 600; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* 卡片上那一行「板块 · 一句话」：字号用 12px 档，但颜色提到 --c-text-2。
   用 --c-text-weak（#828282）时实测 4.43:1，差 0.07 达不到 4.5（audit.cjs 报过）。 */
.work .by { font-size: var(--fs-12); color: var(--c-text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.work .tags { margin-top: var(--sp-3); display: flex; gap: 6px; flex-wrap: wrap; }

/* 播放角标：留在分类行里，尺寸不动（视频类工作流用） */
.work .play {
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
  background: var(--c-surface-2); border: 1px solid var(--c-border-2);
  display: grid; place-items: center; color: var(--c-text-2);
}

/* ---------- 以下是「有图卡片」的样式，纯文字版式用不到，保留备用 ---------- */
/* 实测参考站缩略图比例 = 1.78（16:9），高度按行高锁定 */
/* 实测即梦：缩略图是真实画面铺满整块，界面元素叠在画面上 */
.work .thumb {
  position: relative; width: 100%; flex: 1 1 auto; min-height: 0;
  display: block; overflow: hidden;
  background: #232323;
  border-bottom: 1px solid var(--c-border);
  padding: 0;
}
.work .thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* 分类角标：叠在缩略图左上角 */
.thumb-cat {
  position: absolute; left: 8px; top: 8px; z-index: 2;
  font-size: var(--fs-12); line-height: 1.5; font-weight: 500;
  padding: 2px 8px; border-radius: var(--r-pill);
  background: rgba(0,0,0,.62); color: #fff;
  border: 1px solid rgba(255,255,255,.20);
  backdrop-filter: blur(6px);
}
/* 示例素材角标：区分占位内容用，替换真实素材后可删 */
.thumb-tag {
  position: absolute; left: 8px; bottom: 8px; z-index: 2;
  font-size: var(--fs-12); line-height: 1.5;
  padding: 1px 7px; border-radius: var(--r-pill);
  background: rgba(0,0,0,.62); color: #dcdcdc;
  border: 1px solid rgba(255,255,255,.16);
  backdrop-filter: blur(6px);
}
/* 照实测：信息栏高 88px（缩略图 210 + 88 = 298） */
.work .body {
  flex: 0 0 88px; height: 88px; padding: 12px 14px;
  display: flex; flex-direction: column; justify-content: center; gap: 3px;
  overflow: hidden;
}
.work.has-thumb .thumb + .body { flex: 0 0 auto; }

/* 运营活动卡 / 合作卡：保留自身品牌配色，做深色适配 */
.promo {
  border-radius: var(--r-md); padding: var(--sp-4);
  border: 1px solid rgba(255,255,255,.14);
  background: #1c1c1c;
}
.promo .kicker { font-size: var(--fs-12); color: #ffb86b; margin-bottom: var(--sp-2); }
.promo h3 { margin: 0 0 var(--sp-2); font-size: var(--fs-16); font-weight: 650; }
.promo p { margin: 0 0 var(--sp-4); font-size: var(--fs-13); color: var(--c-text-2); }

.coop {
  border-radius: var(--r-md); padding: var(--sp-4);
  border: 1px solid rgba(255,255,255,.12);
  background: #1c1c1c;
}
.coop .kicker { font-size: var(--fs-12); color: #6fc3ff; margin-bottom: var(--sp-2); }
.coop h3 { margin: 0 0 var(--sp-2); font-size: var(--fs-16); font-weight: 650; }
.coop p { margin: 0 0 var(--sp-4); font-size: var(--fs-13); color: var(--c-text-2); }

/* ============================================================
   响应式补充
   ============================================================ */
@media (max-width: 1180px) {
  .actbar { margin-right: calc(var(--sp-4) * -1); padding: 0 var(--sp-4); }
}
@media (max-width: 900px) {
  .masonry { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 820px) {
  .actbar { order: -1; margin: 0 calc(var(--sp-4) * -1) var(--sp-4); padding: 0 var(--sp-4); }
  .banner { padding: var(--sp-8) var(--sp-4); min-height: 0; }
  .banner h2 { font-size: 1.625rem; }
}
@media (max-width: 640px) {
  .masonry { grid-template-columns: minmax(0, 1fr); }
  .actbar-in { min-height: 52px; }
  .actbar .path { display: none; }
  .actbar-actions { margin-left: 0; width: 100%; }
  .actbar-actions .iconbtn { flex: 1 1 auto; }
  .tagrow .lbl { width: 100%; margin-bottom: 2px; }
}
/* ============================================================
   网格与卡片的响应式（放在文件末尾，确保覆盖前面的基础规则）
   2026-09-26 改版后只保留「几列」这一个变量：
   卡片高度交给内容（grid-auto-rows: auto），不再按屏宽写死高度。
   原来那套数值（4 列 398x292 / 3 列 373x278 / 缩略图 224/210）是配图版式的实测值，
   随缩略图一起下线；要恢复有图版式时，把高度写回 .work 或 .has-thumb 即可。
   ============================================================ */
@media (min-width: 1685px) {
  .masonry { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 1684px) {
  .masonry { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 1180px) {
  /* 1024 左右 3 列会把卡片压到 230px 以下，这里有意义的是 2 列 */
  .masonry { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .masonry { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .masonry { grid-template-columns: minmax(0, 1fr); }
}
/* ============================================================
   侧边栏三段式（照参考站：上固定 / 中滚动 / 下固定）
   加板块时不需要改这里，只改 nav.config.mjs
   ============================================================ */
.side { overflow: hidden; }
/* 站名行与主导航之间只留 4px：整列的 gap 是 24px（分区间隔要保留），
   这里用负 margin 抵消掉 20px，效果=「品牌 → 首页」4px，其余间隔不变。 */
.side-nav-fixed { flex-shrink: 0; margin-top: -20px; }
.side-scroll {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  padding-right: 4px; margin-right: -4px;
  scrollbar-width: thin;
}
.side-scroll::-webkit-scrollbar { width: 6px; }
.side-scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,.14); border-radius: 3px; }
.side-foot { flex-shrink: 0; margin-top: var(--sp-3); padding-top: var(--sp-3);
  border-top: 1px solid var(--c-border); }
.side-meta { font-size: var(--fs-12); color: var(--c-text-weak); padding: 4px 12px 0; }

/* 导航右侧小徽标（新 / 筹备） */
.nb {
  margin-left: auto; font-size: var(--fs-12); line-height: 1.4;
  padding: 1px 6px; border-radius: var(--r-pill);
  background: var(--c-accent-bg); color: var(--c-accent-text);
  border: 1px solid var(--c-accent-bd); flex-shrink: 0;
}
.nb.soon { background: rgba(255,255,255,.07); color: var(--c-text-weak); border-color: var(--c-border); }

/* ============================================================
   板块空态（板块已建、内容待填时的页面）
   ============================================================ */
.empty {
  border: 1px dashed var(--c-border-2); border-radius: var(--r-md);
  padding: 48px 32px; text-align: center; background: #191919;
}
.empty .ico { color: var(--c-text-weak); display: flex; justify-content: center; margin-bottom: var(--sp-3); }
.empty h2 { font-size: var(--fs-18); font-weight: 600; margin: 0 0 var(--sp-2); }
.empty p { color: var(--c-text-weak); font-size: var(--fs-13); margin: 0 auto var(--sp-4); max-width: 46ch; }
.empty .links { display: flex; gap: var(--sp-2); justify-content: center; flex-wrap: wrap; }
.empty .soon-note {
  margin-top: var(--sp-4); font-size: var(--fs-12); color: var(--c-text-weak);
  border-top: 1px solid var(--c-border); padding-top: var(--sp-3);
}
/* ============================================================
   右侧悬浮快捷栏 · 已于 2026-09-25 按需求方要求删除
   ------------------------------------------------------------
   原实现是 .rail（position:fixed; right:12px; top:68px; width:148px，
   半透明 rgba(26,26,26,.72) + backdrop-filter 毛玻璃），
   挂在全站每一页上，z-index 12。

   删除理由（实测，不是审美）：
     1) 它是悬浮层，不挤占内容宽度 —— 内容区本来就占满 1200px，
        所以它一直盖在内容右缘上。
     2) 1440px 下与 main 内 103 个元素水平重叠，其中 95 个被盖 96px，
        包括 .crumb / h1 / .tbl 表格 / .table-wrap。
     3) 背景是 0.72 不透明度，所以被盖的那一条不是"看不到"，
        而是文字蒙了一层，读起来发糊。
     4) 它那 7 个入口（搜索 / 概念 / 模型档案 / 技能包 / 变现方向 /
        关于与说明 / 站内搜索）左侧栏与页脚全都有，删除不丢入口。
     5) 1180px 以下本来就已经 display:none，影响面只在宽屏。

   一并删掉的规则：.rail / .rail-sec / .rail-sec > .lbl / .rail a /
   .rail a:hover / .rail a[aria-current] / .rail .i / .rail-meta
   以及 @media (max-width:1180px) 那条隐藏规则。
   注意：a[aria-current="page"] 的通用样式在左侧栏另有定义，不要动。
   ============================================================ */


/* ============================================================
   首屏节奏（照实测：标题 106 → 输入框 244 → 最近上新 494 → 内容 806）
   ============================================================ */
.section-head { margin-bottom: 16px; }
.section-head h2 { font-size: var(--fs-16); }
.tagstack { margin-bottom: 24px; }
/* ============================================================
   移动端：首屏字号与搜索栏收敛（放大后的对应处理）
   ============================================================ */
@media (max-width: 900px) {
  .hero-title h1 { font-size: 34px; line-height: 44px; }
  .hero-slogan { font-size: 16px; line-height: 24px; }
}
@media (max-width: 640px) {
  .hero-title h1 { font-size: 27px; line-height: 36px; letter-spacing: 0; }
  .hero-slogan { font-size: 15px; line-height: 24px; }
  .hero-title { padding: 0 0 20px; gap: 10px; }
}
@media (max-width: 400px) {
  .hero-title h1 { font-size: 24px; line-height: 32px; }
}
/* ============================================================
   内容分类筛选（筛同一批卡片，不跳转）
   ============================================================ */
.feed-filter { margin-bottom: 16px; }
.feed-filter button {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--tap-min); padding: 0 var(--sp-4);
  border-radius: var(--r-pill); cursor: pointer; font-family: inherit;
  font-size: var(--fs-13); color: var(--c-text-2);
  background: rgba(255,255,255,.06); border: 1px solid transparent;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.feed-filter button:hover { background: rgba(255,255,255,.12); color: var(--c-text); }
.feed-filter button.is-on {
  background: rgba(255,255,255,.16); border-color: var(--c-border-2);
  color: var(--c-text); font-weight: 500;
}
.feed-filter .n {
  font-size: var(--fs-12); color: var(--c-text-weak);
  font-variant-numeric: tabular-nums;
}
.feed-filter button.is-on .n { color: var(--c-text-2); }

/* 被筛掉的卡片 */
.work.is-hidden { display: none; }
.feed-empty { margin-top: 16px; }

/* 运营与合作：网格之外的通栏两列 */
.ops-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-top: 16px; }
@media (max-width: 900px) { .ops-row { grid-template-columns: minmax(0, 1fr); } }
/* ============================================================
   网盘挂载口
   live   态：正常下载卡
   pending 态：占位，不产生任何链接
   ============================================================ */
.dl-pending {
  border-style: dashed;
  border-color: var(--c-border-2);
  background: #191919;
}
.dl-pending h3 { color: var(--c-text-2); }
.pending-row { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-2); }
.pending-badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-12); padding: 2px 10px; border-radius: var(--r-pill);
  background: var(--c-warn-bg); color: var(--c-warn); border: 1px solid var(--c-warn-bd);
  white-space: nowrap;
}
.pending-hint { font-size: var(--fs-13); color: var(--c-text-weak); }

/* 技能包条目 */
.pack-item {
  border: 1px solid var(--c-border); border-radius: var(--r-md);
  background: #1c1c1c; padding: 16px;
}
.pack-head { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: 6px; flex-wrap: wrap; }
.pack-head b { font-size: var(--fs-16); font-weight: 600; }
.pack-item > p { margin: 0 0 12px; font-size: var(--fs-13); }
.pack-item .dl { margin: 0; }
/* ============================================================
   内容规划区块（占位清单：说清还缺什么、每条要什么素材）
   ============================================================ */
.plan-bar {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-3);
  background: #1c1c1c; border: 1px solid var(--c-border); border-radius: var(--r-md);
  font-size: var(--fs-13); color: var(--c-text-2);
}
.plan-bar b { color: var(--c-text); font-variant-numeric: tabular-nums; }
.plan-sep { color: var(--c-text-weak); }
.plan-rest { margin-left: auto; color: var(--c-warn); font-size: var(--fs-12); }

.plan-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.plan-item {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: 10px var(--sp-4);
  border: 1px solid var(--c-border); border-radius: var(--r-md);
  background: #1a1a1a;
}
.plan-item.is-done { opacity: .62; }
.plan-no {
  flex-shrink: 0; font-family: var(--font-mono); font-size: var(--fs-12);
  color: var(--c-text-weak); font-variant-numeric: tabular-nums; padding-top: 2px;
}
.plan-main { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
.plan-t { font-size: var(--fs-14); font-weight: 500; }
.plan-need { font-size: var(--fs-12); color: var(--c-text-weak); }
.plan-state {
  flex-shrink: 0; font-size: var(--fs-12); padding: 1px 8px; border-radius: var(--r-pill);
  background: var(--c-warn-bg); color: var(--c-warn); border: 1px solid var(--c-warn-bd);
}
.plan-item.is-done .plan-state {
  background: var(--c-success-bg); color: var(--c-success); border-color: var(--c-success-bd);
}

/* 执行清单页：板块分组 */
.plan-group { margin-bottom: 40px; }
.plan-group-head {
  display: flex; align-items: baseline; gap: var(--sp-3);
  margin-bottom: var(--sp-3); padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--c-border);
}
.plan-group-head h2 { margin: 0; font-size: var(--fs-18); font-weight: 600; }
.plan-group-head a { font-size: var(--fs-13); color: var(--c-text-2); text-decoration: none; }
.plan-group-head a:hover { color: var(--c-accent-2); }
.plan-group-head .cnt { margin-left: auto; font-size: var(--fs-12); color: var(--c-text-weak); }

@media (max-width: 640px) {
  .plan-item { flex-wrap: wrap; }
  .plan-state { margin-left: auto; }
}
/* ==========================================================================
   模型档案 · Comfy-Org 的 16 个 ComfyUI 模型
   --------------------------------------------------------------------------
   站点定位（2026-09-25 需求方确认）：本页只放模型与模型介绍。
   所以这里没有任何外链、上游 chip、来源平台字样 —— 改版时相关样式已删除，
   不要照旧版样式回填（旧版有 .mscope-out / .mscope-up / .mscope-ups）。

   分区依据来自对 16 个模型的实际统计：
     declared（声明来源数）分布是 9 个 >1、7 个 =1、0 个 =0，
     所以实际只有两段；分段由 model-scope.data.mjs 动态产出，空段不会渲染。
     段内按下载量排。卡片与压缩行两种密度由数据决定（行布局是保留能力）。
   复用既有令牌，不新增色相。
   ========================================================================== */

/* ---------- 数据概览条 ---------- */
.mscope-stats {
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-6);
  margin: var(--sp-6) 0;
  font-size: var(--fs-12); color: var(--c-text-2);
}
.mscope-stats b { color: var(--c-text); font-weight: 600; font-size: var(--fs-13); }
/* 告警态：当前 16 个模型没有需要标黄的口径（无来源声明数为 0），
   保留该类名供数据变化时使用；不要因为「没人用」而删掉它。 */
.mscope-stats .is-warn b { color: var(--c-warn); }
/* 弱化文本：参数量、下载量这类次要数字。
   2026-10-01 从 --c-text-weak（#828282）提到 --c-text-2：模型档案涨到 91 条后
   出现了压缩行段，这些数字第一次渲染在 .row 底色上，实测 4.43:1、差 0.07 不达标
   （与第 921 行 .work .by 同一个原因，同一个修法）。 */
.mscope-dim { color: var(--c-text-2); }

/* ---------- 检索行 ---------- */
.mscope-tools {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3);
  margin-bottom: var(--sp-6);
}
.mscope-search {
  flex: 1 1 300px; min-width: 200px;
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: var(--tap-min); padding: 0 var(--sp-4);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-xl);
  color: var(--c-text-weak);
  transition: border-color var(--dur-fast) ease;
}
.mscope-search:focus-within { border-color: var(--c-accent-bd); color: var(--c-text-2); }
.mscope-search input {
  flex: 1; min-width: 0;
  /* 触控验收要求可交互元素自身高度 >= 44px；容器带 1px 边框，
     所以输入框必须自己撑到 44，不能靠 height:100% 跟着容器走（那样只有 42）。 */
  min-height: var(--tap-min);
  background: none; border: 0; outline: none;
  color: var(--c-text); font: inherit; font-size: var(--fs-13);
}
.mscope-search input::placeholder { color: var(--c-text-weak); }

.mscope-sort { display: flex; gap: var(--sp-1); }
.mscope-sortbtn {
  min-height: var(--tap-min); padding: 0 var(--sp-3);
  font: inherit; font-size: var(--fs-12);
  color: var(--c-text-2); background: transparent;
  border: 1px solid var(--c-border); border-radius: var(--r-sm);
  cursor: pointer;
  transition: color var(--dur-fast) ease, background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.mscope-sortbtn:hover { color: var(--c-text); background: var(--c-surface); }
.mscope-sortbtn.is-on { color: var(--c-text); background: var(--c-surface-2); border-color: var(--c-border-2); }

.mscope-count { font-size: var(--fs-12); color: var(--c-text-weak); font-family: var(--font-mono); }

.mscope-none {
  padding: var(--sp-8) var(--sp-6); text-align: center;
  color: var(--c-text-weak); font-size: var(--fs-13);
}

/* ---------- 三段分区 ---------- */
.mscope-seg + .mscope-seg { margin-top: var(--sp-12); }
.mscope-seg-head {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--c-border);
}
.mscope-seg-head h2 { margin: 0; font-size: var(--fs-18); font-weight: 600; }
.mscope-seg--plain .mscope-seg-head h2 { font-size: var(--fs-16); }
.mscope-seg-n { font-size: var(--fs-12); color: var(--c-text-weak); font-family: var(--font-mono); }
/* 每段的下载量占比：整页最反直觉的事实，能不能被看见就看这一块放得多重 */
.mscope-seg-share {
  font-size: var(--fs-12); color: var(--c-text-2);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  padding: 2px var(--sp-2);
  border: 1px solid var(--c-border); border-radius: var(--r-sm);
}

/* ---------- 卡片（前两段） ---------- */
.mscope-grid { margin-top: 0; }
.mscope-pack { display: flex; flex-direction: column; gap: var(--sp-3); }
.mscope-metrics {
  display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4);
  font-size: var(--fs-12); color: var(--c-text-2);
  font-variant-numeric: tabular-nums;
}
.mscope-tags { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.mscope-tags .badge b { font-weight: 700; }

/* ---------- 压缩行（第三段） ----------
   行内元素用 mscope-r-* 唯一类名，不能复用 .main / .side / .t / .d：
   本站全局已有 .side（侧边栏 sticky + height:100vh）和 .main（width:100%），
   复用通用名会让一行被撑成 1000px 高。这是实测踩过的坑。 */
.mscope-r-main { min-width: 0; flex: 1; }
.mscope-r-t { font-size: var(--fs-14); font-weight: 500; line-height: 1.5; overflow-wrap: anywhere; }
.mscope-r-side {
  display: flex; align-items: center; gap: var(--sp-2);
  flex-wrap: wrap; justify-content: flex-end; flex-shrink: 0;
}
.mscope-rows .mscope-row { align-items: center; }
.mscope-row .mscope-dim { font-size: var(--fs-12); }

.mscope-note {
  margin: var(--sp-8) 0 0;
  font-size: var(--fs-13); line-height: 1.7; color: var(--c-text-weak);
}

/* ---------- 窄屏 ---------- */
@media (max-width: 720px) {
  .mscope-grid { grid-template-columns: minmax(0, 1fr); }
  .mscope-seg + .mscope-seg { margin-top: var(--sp-8); }
  .mscope-rows .mscope-row { align-items: flex-start; }
  .mscope-rows .mscope-row .mscope-r-side { flex-shrink: 1; justify-content: flex-start; }
}
@media (max-width: 480px) {
  .mscope-stats { gap: var(--sp-1) var(--sp-4); }
  .mscope-tools { gap: var(--sp-2); }
  .mscope-sortbtn { padding: 0 var(--sp-2); font-size: var(--fs-12); }
}

/* 动效降级：本模块没有循环动画，只需保证过渡在关闭动效时不拖沓 */
@media (prefers-reduced-motion: reduce) {
  .mscope-search, .mscope-sortbtn { transition: none; }
}

/* 隐藏规则：.card 是 display:flex，hidden 属性默认会被盖掉，所以要显式声明 */
.mscope-pack[hidden], .mscope-row[hidden], .mscope-seg[hidden], .mscope-none[hidden] { display: none !important; }

/* ==========================================================================
   模型单独页 + 文件夹页
   --------------------------------------------------------------------------
   主要排版风险是长路径：实测最长单条路径 85 字符
   （Wan_2.1_ComfyUI_repackaged 的 example workflows 那组文件名）。
   等宽不折行在 320px 视口是 85 * ~7px ≈ 600px，必然横向溢出，
   所以 .mfile-name 必须能任意断行（overflow-wrap:anywhere），
   且整行用 grid 两列：名字占满剩余，体积靠右且不许被压。
   ========================================================================== */

/* ---------- 介绍段 ----------
   2026-09-25 需求方两轮反馈后的最终形态：
     1) 「介绍这一块需要上升点，现在中间留白太多」
        → 收掉标题上方留白（见下面的 .main-in.is-mpage 三条）
     2) 「关键数据这一块放到介绍下面」
        → 不再并排两栏，改成上下排；.mhead 两栏容器已删
   这段的 max-width 给 78ch：单栏铺满会拉成 1376px 长行，
   中文一行塞太多字，扫描时容易串行。
   关键数据表不设限宽，它会自然铺满内容区。 */
.mintro {
  margin: 0; max-width: 78ch;
  font-size: var(--fs-14); line-height: 1.85; color: var(--c-text-2);
}

/* ---------- 介绍 + 下载入口并排 ----------
   需求方 2026-09-25：「这部分的右边放下载链接，下载页单独一页」。
   所以介绍左边、下载入口卡片右边；真正的内容在单独一页上。
   窄屏收成单栏（卡片挪到介绍下面），否则 239px 宽里两栏都没法看。 */
.mintro-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--sp-4) var(--sp-6);
  align-items: start;
}
@media (max-width: 720px) {
  .mintro-row { grid-template-columns: minmax(0, 1fr); gap: var(--sp-3); }
}

/* ---------- 模型页的下载入口卡片 ----------
   结构：一个主链接（进下载页）+ 一个整仓下载动作。
   两者必须分开：主链接铺满卡片（整卡可点），整仓按钮 z-index 压在上面独立可点。
   踩过的坑：早先把整张卡片做成单个 <a>，整仓按钮无处安放。 */
.mdl {
  position: relative; display: block;
  min-width: 0; max-width: 300px;
  padding: var(--sp-3) var(--sp-4);
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  transition: border-color var(--dur-fast), background var(--dur-fast);
}
.mdl:hover { border-color: var(--c-accent-bd); background: var(--c-surface-2); }
.mdl-main { display: block; color: inherit; text-decoration: none; }
.mdl-main::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.mdl-t { display: block; font-size: var(--fs-14); font-weight: 600; color: var(--c-text); }
.mdl-n {
  display: block; margin-top: 4px;
  font-size: var(--fs-12); color: var(--c-text-2);
  font-variant-numeric: tabular-nums;
}
.mdl-s {
  display: inline-block; margin-top: var(--sp-2);
  padding: 1px 6px; border-radius: var(--r-sm);
  font-size: var(--fs-12);
  color: var(--c-text-weak); border: 1px solid var(--c-border);
}
.mdl-s.is-pending { color: var(--c-warn); border-color: var(--c-warn); }
.mdl-go { display: inline-block; margin-top: var(--sp-2); font-size: var(--fs-12); color: var(--c-accent-text); }
.mdl-act {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: var(--sp-2);
  flex-wrap: wrap; margin-top: var(--sp-3);
}
.mdl:focus-within { outline: 2px solid var(--c-accent-text); outline-offset: 2px; }
@media (max-width: 720px) {
  .mdl { max-width: none; }
}

/* ---------- 模型页 / 文件夹页：收掉标题上方的大段留白 ----------
   需求方 2026-09-25 反馈「介绍这部分上面留白太多了」。
   实测（1440 视口，models/wan-2-2-comfyui-repackaged.html）：
     .actbar 底部 61  →  .crumb 顶部 141      空 80px（.main-in padding-top 68 + actbar margin 12）
     .crumb  底部 187  →  h1 顶部 238         空 51px（.crumb padding-top 24 + .section padding-top 32 + h1 margin）
   也就是从操作栏底到标题文字共约 177px 的纯空白。
   .main-in 那 68px 是全站骨架的量（82 页共用），不能直接改全局，
   所以用页面级钩子 .is-mpage 只压这两类页面。
   实测压完：actbar 底部 → h1 文字 约 109px（原来 177px），少 68px。 */
/* 注意：extraClass 是加在 .main-in 自己身上的（build.mjs 的 head()），
   所以必须用同元素复合选择器 .main-in.is-mpage。
   写成后代选择器 .is-mpage .main-in 不会匹配 —— 实测踩过：
   规则在 CSSOM 里、也不报错，就是静默不生效，只靠看 CSS 看不出来。 */
.main-in.is-mpage { padding-top: 16px; }
.main-in.is-mpage .crumb { padding-top: var(--sp-2); }
.main-in.is-mpage .section { padding-top: var(--sp-5); }

/* ---------- 头部两栏：介绍 + 关键数据 ----------
   2026-09-25 已废弃并删除：需求方要求「关键数据这一块放到介绍下面」，
   改成上下排后不再需要 grid 容器。
   保留这段说明是为了防止有人照着旧截图把它加回来。 */

/* ---------- 文件树 ---------- */
.mtree { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--c-border); }
.mfile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--sp-2) var(--sp-4);
  /* 缩进用一个变量控制，每深一级 16px；缩进不占 padding 而用 margin，
     这样窄屏下 3 层缩进也不至于把名字挤到无法阅读 */
  padding: var(--sp-2) 0 var(--sp-2) calc(var(--d, 0) * 16px);
  border-bottom: 1px solid var(--c-border);
}
.mfile-name {
  font-family: var(--font-mono); font-size: var(--fs-12);
  color: var(--c-text); line-height: 1.6;
  /* 关键：长文件名必须能在任意位置断行，否则 320px 视口横向溢出 */
  overflow-wrap: anywhere; word-break: break-word;
}
.mfile-size {
  font-family: var(--font-mono); font-size: var(--fs-12);
  color: var(--c-text-weak); font-variant-numeric: tabular-nums;
  white-space: nowrap; display: inline-flex; align-items: center; gap: var(--sp-2);
}
.mfile-lfs {
  font-size: var(--fs-12); color: var(--c-text-weak);
  border: 1px solid var(--c-border); border-radius: var(--r-sm);
  padding: 0 4px; line-height: 1.5;
}

/* ---------- 文件夹分组行 ---------- */
.mfolders { margin-top: var(--sp-2); }
.mrow-main { min-width: 0; flex: 1; }
.mrow-t { display: block; font-family: var(--font-mono); font-size: var(--fs-14); overflow-wrap: anywhere; }
/* 条目说明行：2026-09-26 从 12px（--fs-12）提到 14px（--fs-14）。
   这一行是列表条目的第二行正文（报错索引 112 条每条都有一行），
   12px 中文在 100% 缩放的显示器上只有 12 个物理像素高，正是「看着糊」的来源。
   与 .muted、.row .d 同为「次级正文」，三处统一用 14px，
   13px 这一档留给更短的辅助文字（表格单元格、状态说明）。 */
.mrow-d { display: block; font-size: var(--fs-14); color: var(--c-text-2); margin-top: 2px; }
.mrow-side { flex-shrink: 0; }

/* ---------- 放置位置 ---------- */
.mplace { list-style: none; margin: var(--sp-2) 0 0; padding: 0; }
.mplace-item {
  font-family: var(--font-mono); font-size: var(--fs-12);
  line-height: 1.8; color: var(--c-text-2);
  padding-left: calc(var(--d, 0) * 16px);
  overflow-wrap: anywhere;
}
.mplace-item.is-dir { color: var(--c-text); font-weight: 600; }

/* ---------- 量化写法 ---------- */
.mvariants { list-style: none; margin: var(--sp-2) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.mvariants li {
  display: inline-flex; align-items: baseline; gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-3);
  background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--r-sm);
  font-size: var(--fs-12);
}
.mvariants-n { color: var(--c-text-weak); font-family: var(--font-mono); font-size: var(--fs-12); }

.mnote { margin: var(--sp-4) 0 0; font-size: var(--fs-12); color: var(--c-text-weak); }

/* ---------- 下载页：按「文件放置位置」的目录树组织 ----------
   需求方 2026-09-25：「下载页按照这个样子放」，给的是仓库说明里那棵
   ComfyUI/models/... 树。所以这一块的主体是树，不是扁平清单。

   排版约束与做法：
     - 树线字符「│   ├── 」占**独立的 grid 列**（auto 宽），不能和名字同格：
       同格会把名字列压到 179px（实测 1096px 的行），长文件名整段不显示。
     - 名字列用 minmax(0,1fr) + overflow-wrap:anywhere：
       最长文件名 85 字符，320px 视口下必须能折行，否则溢出。
     - 窄屏时动作列换到第二行，否则名字被压成两三个字一行。 */
.mdl-tree { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--c-border); }
.mdl-t-file {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: baseline;
  gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--c-border);
}
/* 目录行只有三段：树线 / 图标 + 名字 */
.mdl-t-dir {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr);
  align-items: baseline;
  gap: var(--sp-2);
  padding: var(--sp-3) 0 var(--sp-1);
  border-bottom: 0;
}
.mdl-t-bar {
  font-family: var(--font-mono); font-size: var(--fs-12);
  color: var(--c-text-weak); white-space: pre;
}
.mdl-t-folder { line-height: 1; }
.mdl-t-name {
  font-family: var(--font-mono); font-size: var(--fs-12);
  color: var(--c-text); overflow-wrap: anywhere; word-break: break-word;
}
.mdl-t-dir .mdl-t-name { font-weight: 600; }
.mdl-t-size {
  font-family: var(--font-mono); font-size: var(--fs-12);
  color: var(--c-text-weak); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mdl-t-act { display: inline-flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; }
.mdl-t-note { font-size: var(--fs-12); color: var(--c-text-weak); }
@media (max-width: 720px) {
  .mdl-t-file { grid-template-columns: auto minmax(0, 1fr) auto; }
  .mdl-t-act { grid-column: 1 / -1; justify-content: flex-start; }
}

/* ---------- 下载页：文件夹入口行 + 文件行 ----------
   需求方 2026-09-25：「下载页只有文件夹显示 … 点开之后是所属的单独文件，
   这种文件夹可以整个文件夹下载，点开后也可单独下载」。

   两个动作必须互不遮挡：
     点行本身 → 进该文件夹的下载页（看文件、逐个下载）
     点右侧「下载」→ 整个文件夹打包下载
   做法与模型卡片同一套：主链接的 ::after 铺满整行（整行可点），
   下载按钮 z-index 更高压在上面（自己可点），且禁用它的 ::after
   以免再叠一层遮罩把主链接抢走。 */
.mfolders-list { display: flex; flex-direction: column; gap: var(--sp-2); }
.mfolder {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  background: #1c1c1c;
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  transition: background var(--dur-fast), border-color var(--dur-fast);
}
.mfolder:hover { background: var(--c-surface-2); border-color: var(--c-border-2); }
.mfolder-main {
  min-width: 0; display: block;
  color: inherit; text-decoration: none;
}
.mfolder-main::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.mfolder:focus-within { outline: 2px solid var(--c-accent-text); outline-offset: 2px; }
.mfolder-name {
  display: block; font-family: var(--font-mono); font-size: var(--fs-14);
  font-weight: 600; overflow-wrap: anywhere;
}
.mfolder-meta { display: block; margin-top: 2px; font-size: var(--fs-12); color: var(--c-text-2); }
.mfolder-act { position: relative; z-index: 1; display: inline-flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; }
/* 文件行：三列，名字 / 体积 / 下载位 */
.mfile-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  background: #1c1c1c;
}
.mfile-row-name {
  font-family: var(--font-mono); font-size: var(--fs-12);
  color: var(--c-text); overflow-wrap: anywhere; word-break: break-word;
}
.mfile-row-size {
  font-family: var(--font-mono); font-size: var(--fs-12);
  color: var(--c-text-weak); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mfile-row-act { display: inline-flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; }
/* 文件夹下载页顶部那条：整包按钮 + 状态说明 */
.mfolder-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3);
  margin-top: var(--sp-4); padding: var(--sp-3) var(--sp-4);
  background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--r-md);
}
@media (max-width: 720px) {
  .mfile-row { grid-template-columns: minmax(0, 1fr) auto; }
  .mfile-row-act { grid-column: 1 / -1; justify-content: flex-start; }
  .mfolder { grid-template-columns: minmax(0, 1fr); }
  .mfolder-act { justify-content: flex-start; }
}

/* ---------- 下载页：未列入目录树的文件（说明文件、或说明未更新的新文件） ----------
   用仓库完整路径显示，三列：路径 / 体积 / 动作。 */
.mfile--dl { grid-template-columns: minmax(0, 1fr) auto auto; }
.mfile-act { display: inline-flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; }
.mfile-code {
  font-family: var(--font-mono); font-size: var(--fs-12);
  color: var(--c-text-weak);
}
/* 注意：这里不要重新定义 .btn-sm。
   站点已有一条 .btn-sm { min-height: var(--tap-min) }（44px 触控标准），
   在这里覆盖成更小会把它压下去 —— 实测踩过一次，
   audit.cjs 的触控验收量的是元素自身盒子，会因此不达标。 */
@media (max-width: 720px) {
  .mfile--dl { grid-template-columns: minmax(0, 1fr) auto; }
  .mfile-act { grid-column: 1 / -1; justify-content: flex-start; }
}

/* ---------- 内容页的链接式卡片（模型名现在可点，是站内落点） ----------
   需求方 2026-09-25：整张卡片都要能点，不是只有标题。
   做法用「全卡遮罩」而不是把一个 <a> 包住整张卡片：
   包住会破坏 .card 自身的 flex 布局，还要为 .card 的内部选择器再套一层。
   这里让链接的 ::after 铺满卡片（inset:0），整卡即点击区。
   条件：.card 与 .row 都是 display:block/flex 且没有 position，
   所以这里显式给 position:relative 建立定位上下文。
   好处：卡片里若以后加别的链接，它们 z-index 更高仍然可点，不会被遮罩吞掉。 */
.mscope-pack, .mscope-row { position: relative; }
.mscope-pack h3 a, .mscope-r-t a { color: inherit; text-decoration: none; }
.mscope-pack h3 a::after, .mscope-r-t a::after { content: ''; position: absolute; inset: 0; }
.mscope-pack h3 a:hover, .mscope-r-t a:hover,
.mscope-pack h3 a:focus-visible, .mscope-r-t a:focus-visible { color: var(--c-accent-text); }
/* 键盘 Tab 到链接时，焦点环要覆盖整张卡片，否则看不出焦点在哪 */
.mscope-pack h3 a:focus-visible, .mscope-r-t a:focus-visible { outline: none; }
.mscope-pack:focus-within, .mscope-row:focus-within { outline: 2px solid var(--c-accent-text); outline-offset: 2px; }

/* ---------- 标题后的下载按钮 ----------
   需求方 2026-09-25：「下载按钮放到 Wan_2.2_ComfyUI_Repackaged 这种标题后面」。
   两个位置都有：模型页的 h1、索引卡片的 h3。

   卡片上要特别注意：上面那条 .mscope-pack h3 a::after 会让 h3 里**每个**
   链接都铺满整卡。如果下载链接也吃到这条，两个遮罩会重叠，
   后出现的下载链接会抢走整卡点击，模型页链接直接失效。
   所以这里必须：
     1) 用 [class] 提升特异性，覆盖掉 ::after 的 inset:0 并置为 auto；
     2) 给下载链接 position:relative + z-index:1，让它自己可点、
        同时压在整卡遮罩之上，点击不会被模型页遮罩截走。 */
.mh1 {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--sp-3) var(--sp-4);
}
.mh1-dl, .mscope-pack h3 a.mcard-dl {
  position: relative; z-index: 1;
  display: inline-flex; align-items: center; gap: 6px;
  /* 必须 >= 44px：本站触控红线是 --tap-min，
     audit.cjs 量的是元素自身盒子，靠伪元素放大点击区不算数。
     原来写 36px/32px，是我按视觉大小定的，不达标。 */
  min-height: var(--tap-min); padding: 0 var(--sp-3);
  font-size: var(--fs-13); font-weight: 400;
  color: var(--c-text); text-decoration: none;
  background: var(--c-surface-2);
  border: 1px solid var(--c-border-2); border-radius: var(--r-sm);
  transition: border-color var(--dur-fast), background var(--dur-fast), color var(--dur-fast);
}
.mh1-dl:hover, .mscope-pack h3 a.mcard-dl:hover {
  color: var(--c-accent-text); border-color: var(--c-accent-bd); background: var(--c-surface);
}
.mscope-pack h3 a.mcard-dl::after { content: none; inset: auto; }
.mcard-h { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); }
/* 标题链接必须在 flex 行里拉伸占满剩余宽度。
   背景：h3 原来是 display:block，标题链接天然撑满整行（约 239px），
   audit.cjs 的触控验收因此达标。改成 flex 放下载按钮后，
   链接缩成内容宽（Krea-2 只有 42px），触控验收直接报 6 项不达标 —— 实测踩过。
   注意 audit 量的是 <a> 自己的盒子，::after 铺满整卡不算数，
   所以只能靠 flex 拉伸把盒子做大，不能靠遮罩糊过去。 */
.mcard-h > a:not(.mcard-dl) {
  flex: 1 1 auto;
  display: flex; align-items: center;
  min-height: var(--tap-min);
  min-width: 0;
}
.mscope-pack h3 a.mcard-dl { padding: 0 var(--sp-2); font-size: var(--fs-12); }
