/* ============================================================================
 * 达拉然资料库 — 移动端样式
 *
 * 选择器全部基于我们自己拼的 DOM 结构(不靠 nth-child、不靠 zh-col-*)。
 * 数据色抄 wowtool、界面色抄参考站。
 * ========================================================================== */

/* ---------- 自托管中文字体(2026-11-02) ----------
 * 源:Windows 自带的 `NotoSansSC-VF.ttf`(OFL 授权,可子集化、可自托管、可商用)。
 * 生成:`python tools/gen-fonts.py` → web/fonts/noto-sans-sc.woff2(约 1.8 MB)
 *   · 字符:GB2312 全集 6,763 字 + 拉丁 + 中日韩标点
 *   · 格式:woff2(可变字体,**一个文件装下 100–900 全部字重**)
 *   · 体积取舍:单档 400 = 987 KB、四档拆静态 ≈ 3.9 MB、可变字体全部字重 1.79 MB
 *     ⇒ 可变字体最优;限制字重轴只省 4%(轮廓共享,gvar 只存增量),不值得做。
 *
 * ⚠️ `font-display: swap` —— 中文 1.8 MB,不能让用户白屏等;先用系统字体渲染,
 *    到了再换。会有一瞬间的字形切换(FOUT),这是唯一可接受的代价。
 * ⚠️ 这个文件巨大,别 inline、别 base64。
 * ⚠️ 换字体版本 = 重跑 gen-fonts.py;要改字符范围也在那个脚本里改。 */
@font-face {
    font-family: "Noto Sans SC";
    src: url("/fonts/noto-sans-sc.woff2") format("woff2");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}


/* ---------- CSS 变量:固定色集中管理 ----------
 * 改这里,所有用到它们的类**自动同步** —— 目前是:
 *   .qN(物品名)+ .qN-alt(筛选选项,配 .facet-opt)
 *   .cN(职业名)+ .cN-alt(筛选选项)
 *   .side-alliance / .side-horde
 *   .namedesc(走独立变量,见下)
 *
 * ⚠️ 同一组颜色**在不同场景用不同的类名**(.qN vs .qN-alt),**不要合并**。
 *    合并 = 把"物品名"和"筛选选项"两个场景绑死,以后想单独调一边就调不了;
 *    各用各的类名但引用同一变量,才能"改一处、两边同步"。
 *    (2026-09-24 一度把 -alt 去掉复用 .qN,已改回。)
 *
 * namedesc 用独立的 --color-namedesc(值同 Q6,但不引用 —— 语义独立)。
 * 界面色(底色/文字/边框/强调)见文件后面「参考站 token」段。
 */
:root {
    /* 品质色 —— 物品名 .qN + 筛选选项 .facet-opt.qN-alt */
    --quality-poor:      #9d9d9d;
    --quality-common:    #fff;
    --quality-uncommon:  #1eff00;
    --quality-rare:      #0070dd;
    --quality-epic:      #a335ee;
    --quality-legendary: #ff8000;
    --quality-artifact:  #e5cc80;
    --quality-heirloom:  #0cf;

    /* 职业色 —— 职业名 .cN + 筛选选项 .facet-opt.cN-alt */
    --class-warrior: #c69b6d;
    --class-paladin: #f48cba;
    --class-hunter:  #aad372;
    --class-rogue:   #fff468;
    --class-priest:  #fff;
    --class-shaman:  #0070dd;
    --class-mage:    #3fc7eb;
    --class-warlock: #8788ee;
    --class-druid:   #ff7c0a;

    /* 阵营色 —— .side-* */
    --faction-alliance: #4A54E8;
    --faction-horde:    #E50D12;

    /* namedesc 后缀 —— 值同 Q6,但不引用 --quality-artifact(独立语义) */
    --color-namedesc: #e5cc80;

    /* 分隔符与两侧文字的间距(2026-09-23)
       —— Vant 最小档是 --van-padding-base(4px),但「/」和「@」两边的
          符号需要更紧才好看,所以单独开一个更小的值 */
    --sep-gap: 1px;
}


/* ============================================================================
 * Vant 变量映射 —— 把 Vant 组件的「长相」接到参考站的 token 上
 *
 * ── 路线(2026-09-28 用户定)──
 *   **留 Vant 组件 + 定制化**;某个组件实在定制不了,才自己重写。
 *   (起因:我自制底部条,漏了 5 处 Vant 的默认行为 —— 最简单的组件都会漏,
 *    所以不复刻功能,只改长相。详见 memory 的 read-vant-source-when-porting)
 *
 * ── 这一层做什么 ──
 *   Vant 每个组件都读一堆 `--van-*` 变量。把**基础的那几十个**指到我们的 token,
 *   全局长相就跟着参考站走了,不用逐个组件写覆盖样式。
 *
 * ── 两个来源(事实依据)──
 *   · Vant 的默认值:`ref/vant/packages/vant/src/style/var.less`
 *     或 `web/vendor/vant.min.css` 的 `:root,:host{}` 段
 *   · 暗色段 `.van-theme-dark{}` **只覆盖 8 个变量**(没有 primary!)——
 *     所以主色必须在这里显式指过去,否则一直是 Vant 的蓝 #1989fa
 *
 * ⚠️ 选择器写 `:root, .van-theme-dark` —— 跟 Vant 的两处同特异性,
 *    靠 **app.css 加载在 vant.min.css 之后** 取胜(见 index.html 的加载顺序注释)。
 * ========================================================================== */
:root,
.van-theme-dark {
    /* ---- 语义色 ---- */
    --van-primary-color:  var(--primary);        /* Vant 默认蓝 → 参考站金黄 */

    /* primary 按钮上的文字 —— Vant 默认是白(--van-white)。
       金黄底配白字对比度不够(实测按钮色 #d2ab37 + 白字),改用参考站的 --primary-fg(深褐)。
       (这个变量影响所有 type="primary" 的按钮:底部条「筛选」、浮层「确定」) */
    --van-button-primary-color: var(--primary-fg);

    /* default 按钮 —— 次要操作,现在落在**条件弹窗的 Vant Dialog「取消」**上
     * (我们已无 type="default" 按钮;状态页那两个「重试」「回首页」2026-09-30 删了)。
     * 配方:参考站 chip 的**选中态** —— 主色边框 + 主色 15% 淡底 + 主色字。
     * ⚠️ 别照参考站的**未选中态**(灰边框)—— 那是给 PC 的 hover 设计的,手机没 hover。
     * 这**不是**主按钮(type="primary" 才是实心主色);描边 + 淡底 = "次要但看得清"。 */
    --van-button-default-border-color: var(--primary);
    --van-button-default-color: var(--primary);
    /* 默认透明(老浏览器不认 color-mix 时的退化);淡底见下方 @supports */
    --van-button-default-background: transparent;
    --van-success-color:  var(--success);
    --van-danger-color:   var(--destructive);
    --van-warning-color:  var(--warning);

    /* ---- 文字(三档 → 我们的两档)----
       参考站只有「主文字 / 次文字」两档,所以 2 和 3 并到一起 */
    --van-text-color:     var(--fg);
    --van-text-color-2:   var(--muted-fg);
    --van-text-color-3:   var(--muted-fg);

    /* ---- 底色(三层 → 我们的两层)---- */
    --van-background:     var(--bg);             /* 页面底 */
    --van-background-2:   var(--card);           /* 卡片 / 弹层底 */
    --van-background-3:   var(--card);           /* 再上一层,我们并到 card */

    /* ---- Cell / CellGroup 底色(2026-09-28)----
       ⚠️ **这里不加任何覆盖** —— 让它们走 Vant 默认。
       Vant 默认:`--van-cell-group-background` 和 `--van-cell-background`
       都指向 `--van-background-2`(= `--card`),所以卡片和行同色,
       行本身"看不见",视觉上等同于透明 —— 这正是 Vant 想要的效果。

       为什么不做覆盖了(走过的弯路):
         第一版把 cell-group 改成 `--muted`(比 --card 亮一档),因为那时**弹层底
         也是 --card** —— 卡片跟弹层撞色,只能靠手工提亮卡片来区分。
         后来把弹层改成页面层(--bg,见下面 .van-popup.filter-popup),
         卡片回到 --card 就自然比弹层亮一档,**这处覆盖就不需要了**。
       详见 docs/filters.md 的「浮层顶部的让位」。 */

    /* ---- 边框 / 按下态 ---- */
    --van-border-color:   var(--border);
    --van-active-color:   var(--accent);

    /* ---- van-field 的 clearable ✕ 颜色(2026-09-28)----
       默认 var(--van-gray-5) #c8c9cc —— 浅主题下能用,暗色下灰扑扑。
       改成 --muted-fg(参考站次级文字色),跟 popup 里的次级文字一致。 */
    --van-field-clear-icon-color: var(--muted-fg);

    /* ---- 圆角 ---- */
    --van-radius-sm:      var(--radius-sm);
    --van-radius-md:      var(--radius-md);
    --van-radius-lg:      var(--radius-lg);
    /* ⚠️ --van-radius-max(999px)不动 —— 那是胶囊形状,不是"更大的圆角" */

    /* ---- 字体 ---- */
    --van-base-font:      var(--font-sans);

    /* ---- 加载中(van-loading)----
       Vant 的 spinner 色默认是 `--van-gray-5`(#c8c9cc —— 为**浅色主题**定的),
       暗色下灰扑扑。2026-09-28 决定:跟旁边的「加载列表…」文字**同色**即可 ——
       加载只是个过渡过程,没必要抢视觉。 */
    --van-loading-spinner-color: var(--muted-fg);

    /* ---- 空状态(van-empty)----
       description 的左右 padding,Vant 默认是 **60px**(为多行长文案预留的缩进)。
       我们的空状态只有一句话(「系统繁忙,请稍后重试」/「没有这个页面」),60px 纯属浪费。
       2026-09-28 用户定的:收成 --sp-4(16px)。 */
    --van-empty-description-padding: 0 var(--sp-4);

    /* ---- 筛选浮层(van-popup)---- 2026-09-28
       · popup 不画自带 ✕(closeable 去掉)—— 顶部直接让给列表页 nav-bar,
         nav-bar 的 ← 在 filterOpen 时变成 ✕(见模板 #left slot)。
       · popup 让出顶部 46px(.van-popup.filter-popup { top: 46px }),让列表页 nav-bar 透出来。
       · 圆角 0 不写变量 —— Vant 的 --van-popup-round-radius 只有传 :round=true 才生效,
         我们没传,Vant 默认也没设 border-radius,自然就是 0。
       · 背景:--van-popup-background 默认 var(--van-background-2),
         上面已映射到 var(--card),不用再写。 */

    /* ⚠️ 间距 / 字号**不映射** —— 逐条比过,值本来就一样:
         --van-font-size-sm/md = 12/14   ==  --fs-xs/sm
         --van-padding-base/xs/sm/md = 4/8/12/16  ==  --sp-1/2/3/4
       改了反而会把 Vant 组件内部的间距带歪。 */
}

/* 上面 `--van-button-default-background` 的**淡底**,浏览器支持 color-mix 才加。
   套路跟 `.tbl .tag` 一致(那里也是"默认只有边框,@supports 里才给底和边框色"),
   老浏览器退化成「金黄边框 + 金黄字、无底」—— 朴素但看得懂,不会变成一坨。 */
@supports (background: color-mix(in oklab, red 15%, transparent)) {
    :root,
    .van-theme-dark {
        --van-button-default-background: color-mix(in oklab, var(--primary) 15%, transparent);
    }

}

/* ---------- 全局(抄 wowtool body 实测配色) ---------- */
/* 布局:app shell —— html/body 撑满视口,body 是竖向 flex,
   中间 #main 是滚动容器,底部筛选条是普通 flex 项(不用 position:fixed)。
   这样按钮不会被视口高度变化带着动(手机浏览器地址栏伸缩 / web-view 缩放)。*/
html {
    background-color: var(--bg);   /* 2026-09-25:原来 --van-background */
    max-width: 100% !important;
    overflow-x: hidden;
    height: 100%;
}
body {
    margin: 0;
    padding: 0;
    height: 100%;
    /* body 必须用 --bg / --fg / --font-sans,别退回 --van-* —— 它是继承链的源头。 */
    background: var(--bg);
    color: var(--fg);
    font-family: var(--font-sans);
    font-size: var(--fs-base);                   /* 16px —— 参考站 body 是 16px */
    line-height: var(--lh-base);                 /* 24px ← 跟字号配对 */
    font-feature-settings: "lnum";
}

/* 2026-09-23 接入 Vue 后:flex 容器从 body 挪到 #app
   —— body 里现在只有 <div id="app">,顶栏/ main / 浮层都由 Vue 渲染在它里面 */
#app {
    height: 100%;
    display: flex;
    flex-direction: column;
}

/* 状态页(出错 / 404 / 加载中)—— 在 main 里**撑满并垂直居中**
 *
 * 为什么需要:main 是 `display:flex; flex-direction:column`,状态页是它唯一的子项。
 * 不撑满的话内容贴顶 —— 原来看着还行是因为 `van-empty` 有个 **160px 的内置图标**在撑高度,
 * 2026-09-28 把图标去掉之后,内容只剩 ~100px,立刻贴到顶栏下面。 */
main > .van-empty {
    flex: 1;                 /* van-empty 自己带 justify-content:center,撑满就居中 */
}
/* ⚠️ `.loading` 跟 `.van-empty` 不一样 —— 它是个**普通 div**(`text-align:center` + padding),
 *    没有垂直居中。所以这里要显式给它 flex 居中(2026-09-28 实测:光 `flex:1` 还是贴顶) */
main > .loading {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* 状态页**不给按钮** —— 出错 / 404 / 两种空,四个状态页都是「纯文字」,出路交给顶栏。
   (原来靠 .state-action 给「重试」/「回首页」加间距;两个按钮 2026-09-30 删后就没人用了。) */

/* 空状态的图标位 —— 去掉(2026-09-28)
 * 我们的空状态是「纯文字」(跟参考站一致,参考站没有大插画)。
 * 模板里已经传了空的 #image 插槽(Vant 源码里 slots.image 优先,所以不画内置 SVG),
 * 但**外层 div 还在**,`.van-empty__image` 自带高度 → 留一块 160px 空白。
 * 这里用 :empty 精确命中"插槽是空的"那种,不影响将来某页想放真图。 */
.van-empty__image:empty { display: none; }
/* 【临时】占位文字(首页待实现等)—— 13px 不是 Vant 音阶,改 12 */
.state-tmp {
    color: var(--van-text-color-3);
    font-size: var(--van-font-size-sm);          /* 12px */
    line-height: var(--van-line-height-sm);      /* 18px ← 跟字号配对 */
}

/* ===== 2026-09-23 顶栏 / 底部条换成 Vant 组件后的补充 ===== */

/* ⚠️ 顶栏标题颜色**没变** —— 走 NavBar 的 `title` prop,色值就是 --van-nav-bar-title-text-color。
   (老写法是标题里塞个 <a>,得用 .nav-title { color: inherit } 抹下划线;那个 <a> 已删,别再塞回去。) */

/* 顶栏左右两侧的图标 —— **一条自定样式都不需要**(2026-10-04 定稿)。
   模板走 #left / #right 插槽,图标带 Vant 自己的 .van-nav-bar__arrow 类
   (给 margin-right + font-size),文字带 .van-nav-bar__text 类 ——
   间距 / 字号 / 颜色全部由 vant.min.css 管,跟我们"照 Vant 风格"的原则一致。
   ⚠️ 曾短暂用过两条 hack,都已删,别再回来:
     · .filter-nav-icon { font-size }  —— 因为当时插槽图标**没带** .van-nav-bar__arrow,
        才要自己补字号。现在带上了,这条多余。
     · .van-nav-bar.icon-as-cross .van-nav-bar__arrow:before { content: "\e6a7" }
        —— 覆盖 iconfont 码位把 arrow-left 变 ✕。现在直接 :name="cross",不用码位。 */


/* ===== 2026-11-01 小程序 web-view 内(只有 <html class="mp-host"> 才命中) =====
   ⚠️ 更正:`navigationStyle: custom` 对 <web-view> **无效**,原生栏其实一直在,
      上面会显示小程序名(改不了)。这条顶栏只管「页面层」:标题 + 查询。
      返回交给原生的 `‹`,所以这里只处理右侧让开胶囊、以及标题左对齐。
     · --mp-sbh  状态栏高度(小程序传的);用 max() 跟 env() 取大值,
                 env() 拿得到就用系统的,拿不到(部分安卓返回 0)就用传的,不会叠加。
     · --mp-capr 右侧要避让胶囊的宽度 —— 否则右上角「查询」被胶囊压住。
   ⚠️ 浏览器里 html 上永远没有 .mp-host,这两条规则完全不生效,行为跟以前一模一样。 */
/* 顶部留白先交给 Vant 自己的 safe-area-inset-top(它读 env(safe-area-inset-top))。
   小程序那边已经给了 viewport-fit=cover,理论上 env 能拿到状态栏高度。
   ⚠️ 如果真机上 env 拿不到(部分安卓返回 0),再启用下面这条兜底:
   .mp-host .van-nav-bar { padding-top: max(var(--mp-sbh, 0px), env(safe-area-inset-top, 0px)); } */
/* ★ 2026-11-01 小程序内:顶栏做成**页头**,跟后面的表头区分开。
   原生栏(小程序名)撤不掉,上面永远有一行;这一行如果跟页面同底色,就会跟表头糊成一块
   (2026-11-01 用户:「看起来与表头栏合并在一起了」)。
   ⇒ 用 card 底色 + 一条分隔线 = 页头;表头仍是页面底色。三层分得开:
        原生栏(小程序) / 页头(标题+查询) / 表头(列名)
   ⚠️ 浏览器里 .mp-host 不出现,顶栏照旧是 Vant 那条。 */
/* ★ 2026-11-01 三层配色(**用户 2026-11-01 定**):页头亮、表头暗。
   原生栏 #0b0e13(页面底) / 页头 #131820(card) / 表头 #0b0e13(页面底) / 列表 #0b0e13
   ⚠️ 反过来的方案(表头亮、页头暗)试过,用户否掉 —— 别再来回换。
   ⚠️ 浏览器里 .mp-host 不出现,顶栏照旧是 Vant 那条。 */
/* ★ 2026-11-01 三层配色(**用户定的最终版**):
     原生栏 #0b0e13 ┐
     页头   #0b0e13 ┘ 连成一整块顶部(武器 + 查询)
     表头   #131820   唯一的亮底(--card)
     列表   #0b0e13
   ⚠️ 试过反过来的(页头亮、表头暗)和加分隔线的,用户都不要 —— 别再改。
   ⚠️ 浏览器里 .mp-host 不出现,顶栏照旧是 Vant 那条。 */
.mp-host .van-nav-bar {
  background: var(--bg);
}
.mp-host .tbl thead th {
  background: var(--card);
}

/* ⚠️ 2026-11-01 删除:`.mp-host .van-nav-bar__right { padding-right: var(--mp-capr) }`
   —— 那条是**错的**。胶囊长在**原生栏**上,网页内容根本不在它下面(web-view 从原生栏
   下方开始),所以不需要让位;让位的结果是把「🔍查询」往左推了一大截,看着"中间偏右"。 */

/* ★ 2026-11-01 小程序内:标题改成**左对齐**。
   原因:返回交给原生 `‹` 了(见 components.js 的 showBack),顶栏左边空出来;
   标题还居中就显得飘,而且跟上面原生栏那行居中的小程序名叠成两个中心轴。
   左边距 `--sp-2 + --sp-4` = 24px,跟表格第一列 `.tbl td.c-name:first-child` 的
   padding-left **逐像素相同** —— 标题跟内容左对齐,跟小程序导航页的排版也一致。
   ⚠️ 浏览器里 html 上没有 .mp-host,这条不生效,标题照旧居中。 */
.mp-host .van-nav-bar__title {
  margin-left: 0;
  margin-right: auto;
  max-width: none;
  text-align: left;
  padding-left: calc(var(--sp-2) + var(--sp-4));
  /* 2026-11-01 用户定:页面标题用**主题金**,跟「🔍查询」同一个色(--primary #d2ab37),
     也对齐小程序导航页那套金色标题。Vant 默认给的是 --van-text-color(暖白)。 */
  color: var(--primary);
}

/* ⚠️ 例外:筛选浮层开着时,左上角会变成「✕ 取消」——左对齐的标题会**压在它上面**
   (2026-11-01 用户报的)。那种时候把标题退回居中,给左边的按钮让路。
   `has-left` 由模板按 `showBack` 挂上去(见 components.js 的 van-nav-bar)。 */
.mp-host .van-nav-bar.has-left .van-nav-bar__title {
  margin: 0 auto;
  max-width: 60%;
  text-align: center;
  padding-left: 0;
}

/* 【已删 2026-09-28】.nav-status —— 顶栏右上角的状态文字。
   **用户决定顶栏不做状态显示**(连带删了 setStatus / store.status)—— 别再加回来。 */


*, *::before, *::after { box-sizing: border-box; }

a { color: inherit; text-decoration: none; }


/* 【已删 2026-09-23】.topbar / .logo / .status —— 顶栏换成 van-nav-bar 后都不存在了。
   (旧样式值去 git 历史翻,别在这里留快照。) */


/* ---------- 主区域 ---------- */
/* ⚠️ 这组声明**已被下面那个 `main{}`(表格化之后加的)覆盖** —— 滚动早已交给 .tbl-wrap。
   留着是历史;真正生效的那组在下面(搜 `main {` 第二处)。 */
main {
    /* ⚠️ 是 `1 1 0` 不是 `1 1 auto`(2026-09-24 修):
       `auto` 的 flex-basis = 内容高(实测 124135px),会跟底部的
       .action-bar-placeholder 按比例抢空间 —— placeholder 被压成 ~0,
       结果 main 铺到屏幕最底,滚到底时最后一条被 ActionBar 盖住 38px。
       basis 改成 0 之后:main 的基准是 0,placeholder 的 50px 保得住。 */
    flex: 1 1 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    /* 列表离屏幕边缘(2026-09-23:改走 Vant 变量)*/
    padding: var(--van-padding-sm);
}

/* ---------- 筛选浮层:让「内容区」自己滚,popup 不滚(2026-09-24) ----------
 *
 * ⚠️ 这是覆盖 .van-popup 的属性 —— 加 .filter-popup 提特异性
 *    (`.van-popup.filter-popup` = (0,2,0) > `.van-popup` = (0,1,0)),
 *    所以只影响这一个 popup,别的 popup 不受影响。
 *
 * 为什么要 flex column + overflow:hidden:
 *   让滚动只发生在里面那个 <main>(它自己有 `flex:1 1 0` + `overflow-y:auto`)。
 *   这样 `.action-bar-placeholder` 才能作为 main 的兄弟**在流里**顶出 50px ——
 *   它是给 `position:fixed` 的底部条补高度的,popup 自己滚的话它就白加了。
 *
 * ⚠️ ActionBar 的 `placeholder` 还是要开 —— 它是 `position:fixed`,不占流空间,
 *    不开的话内容区会吃满全高,最后 50px 被它盖住(实测遮 50px)。
 *
 * 📌 2026-09-28 更正:上面原来还有一条理由是「✕ 别跟着滚走」(当时 ✕ 在 popup 内,
 *    position:absolute 相对 popup,实测滚到底 top 从 16 变成 -1167)。
 *    现在 ✕ 已搬到列表页 nav-bar(模板 #left 插槽),**那条理由不再适用** ——
 *    但 flex column 本身要留,因为上面那条(placeholder)还在。
 */
.van-popup.filter-popup {
    display: flex;
    flex-direction: column;
    overflow: hidden;

    /* 弹层底 = **页面层**(2026-09-28,方案 A)
       Vant 的默认:`--van-popup-background: var(--van-background-2)` —— 跟
       cell / cell-group / nav-bar 一样都在"面板"那一层(32 个组件都用它)。
       问题是:**我们的弹层本身就是面板**,于是里面再放"面板"就撞色:
         · cell-group(卡片)  → 默认也是 --background-2 → 跟弹层底一模一样
         · tree-select 右栏   → 默认也是 --background-2 → 跟弹层底一模一样
       而且跟 Vant demo 的角色**反了**:Vant demo 里树是放在**页面**上的,
       所以左栏(页面色)融入、右栏(面板色)跳出来;我们是左栏跳出、右栏融入。

       改成页面层之后,弹层里的东西回到 Vant 原本的层级关系:
         弹层(--bg 页面) → 卡片/右栏(--card 面板) → 各自跳出来
         树左栏(--bg 页面) → 融入弹层(同 Vant demo)
       连带好处:cell-group 那处"手工提亮到 --muted"的覆盖**可以撤掉了**。 */
    --van-popup-background: var(--bg);

    /* 让出顶部 —— 列表页 nav-bar 露出来当浮层头。
       ⚠️ 用 calc 加安全区,**别硬编码 46px**(刘海屏 nav-bar 实高 = 46 + inset);
       模板里**别写 inline height**,高度交给 top + `.van-popup--bottom` 的 `bottom: 0`。 */
    top: calc(var(--van-nav-bar-height) + env(safe-area-inset-top, 0px));

    /* 【已否决】别把浮层底提到 --van-background-3 或纯黑 —— 上半部会跟下方空白割裂成两截,
       用户实测「很奇怪」;输入框底提亮也一样,别重复试。 */
}

/* 遮罩也让出同样的高度(2026-09-28)—— popup 传 overlay-class="filter-overlay" 触达这条。
   否则遮罩会盖住列表页 nav-bar,标题和 ← / ✕ 都看不见。
   ⚠️ 同样用 calc,别硬编码 —— 理由见上面那条 top。 */
.van-overlay.filter-overlay {
    top: calc(var(--van-nav-bar-height) + env(safe-area-inset-top, 0px));
}


/* ---------- 筛选浮层内容区:padding-top = 8px(2026-09-28 定) ----------
 * 用户要求「卡片跟导航栏之间留 8px」—— 有意**打破**跟列表页表头对齐的意图,
 * 因为卡片有边框和底色,紧贴导航栏看着挤。
 * ⚠️ 特异性:.filter-popup-body (0,1,0) > main (0,0,1) —— 留着是为了明确顶部值,不依赖 main。 */
.filter-popup-body {
    padding-top: var(--van-padding-xs);     /* 8px —— 卡片离导航栏 */

    /* 浮层里的「细线」色 —— 行间分隔线 + 卡片外框都用 --border。
       ⚠️ 别用 color-mix 混中间值去凑"基准"(列表页表格线一直就是 --border 实写,两处要一样)。 */
    --van-cell-border-color: var(--border);
}

/* 筛选浮层的输入区 —— 多个 field 外面套一层 `<van-cell-group inset>`(Vant 惯例):
 * inset 给圆角/边距、cell::after 画行间线,得到「一张圆角卡片 + 行间细线」,所以这里什么都不加。
 * ⚠️ 行高用 Vant 默认(输入行 44 / tree 48),只压输入行会更不齐;限定 .filter-popup-body。 */

/* ⚠️ 深色主题下"靠底色差分层"是无效的 —— 必须靠边框。
   实测对比度:
     参考站 页面↔卡片  = 1.09:1    我们 popup↔卡片 = 1.06:1   ← 几乎一样,都看不出
     参考站 页面↔边框  = 1.34:1    ← 它的卡片**有 1px border**(实测 class:
                                     `overflow-hidden rounded-lg border bg-card`)
   浅色主题(Vant demo)里 1.04:1 都看得清,是因为人眼在浅色下对亮度差敏感得多;
   深色下同样的数值差几乎不可辨 —— 所以深色的分层靠边框,不靠底色。
   → 给卡片补 1px border(用 --border,跟参考站的 `border-border` 同一个 token)。 */
.filter-popup-body .van-cell-group--inset {
    border: 1px solid var(--border);        /* 跟行间线同色,也都 = 列表页表格线的 --border */
    margin-bottom: var(--van-padding-xs);   /* 跟下面的 tree 拉开 8px(2026-09-28:12 → 8) */
}

/* TreeSelect 也围一样的框(2026-09-28 用户要求)
   输入区(cell-group)已经是一张圆角卡片,tree 光秃秃地挨着不协调。
   用**同一套**:同样的 --border、同样的圆角(--van-radius-lg)、同样的左右 16px 边距
   (直接复用 --van-cell-group-inset-padding,保证跟 cell-group 的 inset 一个值)。
   ⚠️ 必须加 overflow:hidden —— 不加的话两栏的方角会盖住圆角。 */
.filter-popup-body .van-tree-select {
    margin: var(--van-cell-group-inset-padding);   /* 0 16px,跟 cell-group 同一个值 */
    border: 1px solid var(--border);
    border-radius: var(--van-radius-lg);
    overflow: hidden;

    /* 左栏项的**左**内边距:12 → 16,跟上面卡片的 label 对齐(2026-09-28)
       Vant 默认两边不一样:cell 的左右是 --van-padding-md(16),
       tree 左栏项是 `14px var(--van-padding-sm)`(= 14 上下 / 12 左右)。
       两个框都从 16px + 1px 边框起,里面一个 16 一个 12 → **文字差 4px**。
       ⚠️ 只改横向:纵向那 14 撑出 48px 的项高(14 + 行高 20 + 14),别碰。 */
    --van-tree-select-nav-item-padding: 14px var(--van-padding-md);

    /* 左栏项**选中时不加粗**(2026-09-30 用户定)
       Vant 默认 --van-sidebar-selected-font-weight = --van-font-bold(600),
       于是左栏一选中就变粗、右栏却一直是 600 —— 同一屏两种字重规矩。
       统一成 400:选中**只靠底色和左边那条金色竖条**表达,不靠字重。
       ⚠️ 改的是 Vant 变量而不是写 font-weight:覆盖变量不动 Vant 自己的选择器。 */
    --van-sidebar-selected-font-weight: 400;
}


/* ---------- 筛选浮层:TreeSelect 的**右栏**(我们自渲染,走 Vant 的 #content 插槽) ----------
 *
 * 为什么要自己渲染:Vant 默认右栏做不到用户要的两条 ——
 *   ① 选项用**各自的颜色**(品质色 qN / 职业色 cN)
 *      —— 右栏文字是裸文本,TreeselectChild 只有 id/text/disabled,**没有 className**
 *   ② 选中**不变色**,只多一个勾,而且**勾跟选项同色**
 *      —— Vant 的选中色只有全局一条 --van-tree-select-item-active-color
 *
 * ⚠️ 下面的尺寸**抄 Vant 原生项**(.van-tree-select__item / __selected),
 *    保证自渲染项跟原生项长得一样 —— 只换「颜色」部分。
 */
.filter-popup-body .facet-opt {
    position: relative;
    padding: 0 32px 0 var(--van-padding-md);        /* 右边 32px 是给勾留的位置(同原生) */
    /* ⚠️ 这一条**故意不跟 Vant 原生**(2026-09-30 用户定)
       Vant 的 .van-tree-select__item 是 `font-weight: var(--van-font-bold)`(600),
       下面「逐条抄原生」那段本来是照抄的 —— 但整棵树统一成 **400** 了:
         · 左栏选中/未选中都是 400(去掉了 Vant 的选中加粗,见上面那个变量)
         · 右栏也跟着 400,不然同一屏里字重又分两套
       显式写 400 而不是删掉:删掉是"继承默认值",将来父级一变就悄悄跟着变。 */
    font-weight: 400;
    line-height: var(--van-tree-select-item-height);
    user-select: none;
    cursor: pointer;

    /* ⚠️ 这里**故意不写 color** ——
       颜色由选项自己的 class(qN / cN)给,选中前后都不变。
       (对比:Vant 原生会在选中时套一条 --van-tree-select-item-active-color) */
}

/* 筛选选项的「品质色 / 职业色」——
 *
 * ⚠️ `.qN`(物品名)和 `.qN-alt`(筛选选项)**故意分开**,但引用同一组变量 `--quality-*` ——
 *    改一处两边同步;合并 = 以后想单独调一边就调不了(曾把 -alt 去掉复用,是错的,已改回)。
 * 颜色值本身不在这里写 —— 全部走 :root 里那 20 个变量。 */
.filter-popup-body .facet-opt.q0-alt { color: var(--quality-poor); }
.filter-popup-body .facet-opt.q1-alt { color: var(--quality-common); }
.filter-popup-body .facet-opt.q2-alt { color: var(--quality-uncommon); }
.filter-popup-body .facet-opt.q3-alt { color: var(--quality-rare); }
.filter-popup-body .facet-opt.q4-alt { color: var(--quality-epic); }
.filter-popup-body .facet-opt.q5-alt { color: var(--quality-legendary); }
.filter-popup-body .facet-opt.q6-alt { color: var(--quality-artifact); }
.filter-popup-body .facet-opt.q7-alt { color: var(--quality-heirloom); }

.filter-popup-body .facet-opt.c1-alt  { color: var(--class-warrior); }
.filter-popup-body .facet-opt.c2-alt  { color: var(--class-paladin); }
.filter-popup-body .facet-opt.c3-alt  { color: var(--class-hunter); }
.filter-popup-body .facet-opt.c4-alt  { color: var(--class-rogue); }
.filter-popup-body .facet-opt.c5-alt  { color: var(--class-priest); }
.filter-popup-body .facet-opt.c7-alt  { color: var(--class-shaman); }
.filter-popup-body .facet-opt.c8-alt  { color: var(--class-mage); }
.filter-popup-body .facet-opt.c9-alt  { color: var(--class-warlock); }
.filter-popup-body .facet-opt.c11-alt { color: var(--class-druid); }

/* 阵营 —— ⚠️ wowtool 的 <option> **没给 class**(它是 class=""),这两个类名是我们补的
 * (见 core.js 里的 SIDE_CLS)。颜色同源:物品名旁边那个「联盟/部落」用的也是这两个变量。
 *   「联盟」「仅限联盟」→ --faction-alliance
 *   「部落」「仅限部落」→ --faction-horde
 *   「双方」→ 不在这里 —— 官方只有联盟/部落两个值,它没有对应色,走 Vant 默认文字色。 */
.filter-popup-body .facet-opt.side-alliance-alt { color: var(--faction-alliance); }
.filter-popup-body .facet-opt.side-horde-alt    { color: var(--faction-horde); }

/* 反应(NPC 页)—— 友善 / 中立 / 敌对
 * ⚠️ wowtool 的 <option> 自带 q2-alt / q-alt / q10-alt,但那三个类是**品质色槽位**
 *    (只是值恰好同色)。所以 core.js 的 REACT_CLS 按 value 换成下面这三个,
 *    颜色走 `--react-*` —— 跟列表页「反应」列的 `.react-friendly/.react-neutral/.react-hostile`
 *    同一组变量,**不引用 --quality-***。 */
.filter-popup-body .facet-opt.react-friendly-alt { color: var(--react-friendly); }
.filter-popup-body .facet-opt.react-neutral-alt  { color: var(--react-neutral); }
.filter-popup-body .facet-opt.react-hostile-alt  { color: var(--react-hostile); }

/* 勾 —— 位置和大小照抄 Vant 原生的 .van-tree-select__selected */
.filter-popup-body .facet-opt__check {
    position: absolute;
    top: 50%;
    right: var(--van-padding-md);
    margin-top: calc(var(--van-padding-xs) * -1);
    font-size: var(--van-tree-select-item-selected-size);
    /* 主题金(2026-09-30 用户定,**推翻 b3**)
       ⚠️ b3(2026-09-24)原本是 `color: inherit` —— 勾跟选项文字同色,
          也就是跟着**数据色**走(品质色 / 职业色 / 阵营色)。
       改成 --primary 的理由:
         · 数据色有 20 种,等于「选中」这个标记有 20 种长相;
           金的话不管选哪一项,「选中」永远是同一个信号。
         · 左栏选中那条竖条本来就是 --primary(Vant 默认),
           勾也用金色 → 上下两栏的「选中」是同一个颜色语言。
       代价:不再跟该项的文字同色。 */
    color: var(--primary);
}


/* ---------- 筛选浮层:范围对(1 个 van-field + #input slot 塞 2 个 input)----------
 *
 * 结构:1 个 van-field 用 #input slot 塞 2 个原生 <input>(见 web/components.js 模板)。
 *   2026-09-28 重构(原来 2 个 van-field 拼接):5 个 field → 3 个。
 *
 *   <van-field label="物品等级">
 *     <template #input>
 *       <div class="range-input">
 *         <input v-model="f.minLevel" ... />
 *         <span class="range-dash">—</span>
 *         <input v-model="f.maxLevel" ... />
 *       </div>
 *     </template>
 *   </van-field>
 *
 * ⚠️ label-align 走默认 **left**(跟「名称」一致)—— 早前想过 top,后来没采用。
 */
.filter-popup-body .range-input {
    display: flex;
    align-items: center;
    gap: 0;                          /* dash 自带 padding */
    width: 100%;                     /* ⚠️ 不写就退化成"被内容撑爆" → cell 高度变 88 */
    min-width: 0;                    /* flex item 默认 min-width:auto 会按内容撑开 */
}
.filter-popup-body .range-input input {
    flex: 1 1 0;
    min-width: 0;
    text-align: center;
    background: transparent;
    border: 0;
    padding: 0;
    color: var(--van-text-color);
    font-size: var(--van-font-size-md);
    line-height: var(--van-cell-line-height);
    outline: none;
}
.filter-popup-body .range-input input::placeholder {
    color: var(--van-field-placeholder-text-color);
}
/* ✕(还原 clearable,2026-09-28)——
   直接复用 Vant 的 .van-field__clear 类:颜色/字号自动走
   --van-field-clear-icon-color(--muted-fg)/ --van-field-clear-icon-size(18px),
   跟「名称」那个 Vant 原生 ✕ 长得一样。
   ⚠️ 它自带的 margin-right: -8px 是给 Cell 布局用的(往右贴边),
      在 range-input 这个 flex 行里不要 —— 覆盖成 0。 */
.filter-popup-body .range-input .van-field__clear {
    flex: 0 0 auto;
    margin-right: 0;
    padding: 0 var(--van-padding-base);
    cursor: pointer;
}

/* 中间的「—」(跟 cell 高度对齐 → 单行高 24px,= line-height)
   ⚠️ 不再 calc —— cell 高度不再等于"行高 + 上下 padding"(现在是单行)。 */
.filter-popup-body .range-dash {
    flex: 0 0 auto;
    padding: 0 var(--van-padding-base);
    color: var(--muted-fg);
    height: var(--van-cell-line-height);   /* 24px,跟 input 同行 */
    display: flex;
    align-items: center;
}

/* Cell 的 value 区塞了 2 个 input + dash,容易撑破 cell 默认的 flex。
   ⚠️ 这是 Vant field 用了 #input slot 之后才需要的覆盖 —— 默认 field 一个 input,
   value flex:1 不会撑;2 个 input 不写就退回 "被内容撑爆"。 */
.filter-popup-body .van-cell .van-cell__value { flex: 1 1 0; min-width: 0; }

.page-title {
    font-size: var(--van-font-size-lg);          /* 16px */
    line-height: var(--van-line-height-lg);      /* 22px ← 跟字号配对 */
    font-weight: bold;
    /* 上 4(离顶栏)/ 左右 0 / 下 12(离列表) */
    margin: var(--van-padding-base) 0 var(--van-padding-sm);
    color: var(--van-text-color);
}


/* ---------- 品质色(q0-q7)—— wowtool 实测 ---------- */
.q0 { color: var(--quality-poor); }
.q1 { color: var(--quality-common); }
.q2 { color: var(--quality-uncommon); }
.q3 { color: var(--quality-rare); }
.q4 { color: var(--quality-epic); }
.q5 { color: var(--quality-legendary); }
.q6 { color: var(--quality-artifact); }
.q7 { color: var(--quality-heirloom); }


/* ---------- 职业色(c1-c13)—— 官方 ChrClasses.db2(2026-09-17 用户提供) ---------- */
/* 本版本(经典怀旧服)只有这 9 个职业。ID 跳号是原案:6=死亡骑士,10=武僧,本版本没有。
   颜色值逐条对过官方表 ClassColorR/G/B,与 wowtool global.css 也一致。
   1=战士 2=圣骑士 3=猎人 4=潜行者 5=牧师 7=萨满祭司 8=法师 9=术士 11=德鲁伊 */
.c1 { color: var(--class-warrior); }
.c2 { color: var(--class-paladin); }
.c3 { color: var(--class-hunter); }
.c4 { color: var(--class-rogue); }
.c5 { color: var(--class-priest); }
.c7 { color: var(--class-shaman); }
.c8 { color: var(--class-mage); }
.c9 { color: var(--class-warlock); }
.c11 { color: var(--class-druid); }
/* 以下 4 个本版本官方表里没有,注释保留防回归(2026-09-17 用户决策:跟官方一模一样)
.c6  { color: #c41e3a; }   死亡骑士
.c10 { color: #00ff98; }   武僧
.c12 { color: #a330c9; }   恶魔猎手
.c13 { color: #33937f; }   唤魔师
*/


/* ---------- .r1 ~ .r4:wowtool 的通用颜色工具类(2026-10-10 启用) ----------
 *
 * ⚠️ **跟下面那段「种族色」不是一回事,别混。** 种族色那套(r1-r8 按种族取色)2026-09-17
 *    已经**停用**(官方没有种族色表,是我们自己编的)—— 就是紧跟着的下一段,仍在注释里。
 *
 * 这里启用的是 **wowtool 自己的 `.r1-.r4`**(它的 universal.css 里定义的),用途**不是种族**,
 * 而是「**制作难度**」四档色 —— 专业配方的「需要技能」那一列用它(见 .sk-lv):
 *     r1 橙(最优) / r2 黄 / r3 绿 / r4 灰(已过时)
 * 值**逐字照抄 wowtool** —— 这是数据色,不受参考站影响(见 docs/decisions.md)。
 * ⚠️ `.r4` 是 **gray**;下面那段停用的种族色版是 `#605fff`(紫)—— 两个不一样,别拿错。
 * ⚠️ `.r5`~`.r8` **故意不启用**:目前只有 r1-r4 有用途,多定义几个永远没人用的类是负担。
 *    (哪天有第五档再加,那时照 wowtool 的值抄。) */
.r1 { color: #ff8040; }
.r2 { color: #ff0; }
.r3 { color: #40bf40; }
.r4 { color: gray; }


/* ---------- 种族色:官方不存在(2026-09-17 用户查实) ----------
 *
 * 官方表 ChrRaces.db2 没有任何颜色列;UI 源码也搜不到按种族取色的 API;
 * wowtool 的 .r1-.r4 只是通用颜色工具类(和 .qN / .cN 并列),不能证明 r = race。
 * 所以 r1-r8 是我们自己编的,按"跟官方一模一样"停用;种族名走 .meta 默认色 #aaa。
 *
 * 以下为原实现,注释保留防回归:
.r1 { color: #ff8040; }   人类
.r2 { color: #ff0; }      兽人
.r3 { color: #40bf40; }   矮人
.r4 { color: #605fff; }   暗夜精灵
.r5 { color: #c41f3b; }   亡灵
.r6 { color: #804610; }   牛头人
.r7 { color: #ff8040; }   侏儒
.r8 { color: #00ff98; }   巨魔
*/


/* ---------- 错误/404 ---------- */
.error {
    text-align: center;
    padding: 40px 20px;
    color: var(--van-text-color-2);        /* 2026-09-23:Vant 第二档(原 #aaa)*/
}
.error h2 {
    /* 2026-09-23 用户决策:改用 Vant 的强调色(原来是直接写死的 #a335ee,
       那是复用品质色 q4 —— 界面位置不该借用数据色的值) */
    color: var(--van-danger-color);
    margin: 0 0 10px;
}


/* ---------- 加载/空 ---------- */
.loading, .empty {
    text-align: center;
    padding: 40px 20px;
    color: var(--van-text-color-2);        /* 2026-09-23:Vant 第二档(原 #aaa)*/
}


/* ============================================================================
 * 筛选 UI —— 移动端全屏浮层 + 底部固定按钮
 *
 * 设计原则:
 *   - 风格与列表页吻合(12px 基准 / 行高 1.7 / 间距 10px / 弱文字 #666)
 *   - 照搬功能形态(wowtool 5 facet + 动态克隆 filter 行 + 应用/重置)
 *   - 不做动画(用户决策 2026-09-18)
 * ========================================================================== */

/* (2026-09-24) 浮层从 .filter-overlay 老 DOM 实现换成 <van-popup>,这一块
   `.filter-overlay-*` / `.filter-row` / `.filter-chip.*` 等死 CSS 已经删掉
   (见 git diff —— 删了 215 行)。9 个 facet 的实际样式等 ③ van-cell 之后讨论。 */


/* ============================================================================
 * 底部条 —— 容器(2026-09-28 重做)
 *
 * ── 分工 ──
 *   **容器**(这段):只管「固定 + 不遮挡内容」的布局,不含任何交互
 *   **按钮**:用 `van-button`(点击/禁用/loading/焦点全是现成的),
 *             它的颜色圆角跟着上面的「Vant 变量映射」走,不用在这里写样式
 *
 * ── 为什么不用 van-action-bar ──
 *   它的按钮是 van-action-bar-button —— 胶囊 + flex:1 + margin:5px,约束多。
 *   通用 van-button 的 block / plain / round 可塑性好得多。
 *   容器本来就没有逻辑,自己写 8 行比套一个组件更清楚。
 *
 * ── 「不要阻挡内容」怎么实现的 ──
 *   fixed 元素**不占文档流** → 必须配一个**等高的 placeholder** 把内容顶上去。
 *   忘了加的话,滚到底时最后一行被盖住 50px(2026-09-24 踩过)。
 *   ⚠️ placeholder 的高度**必须跟 .action-bar 的算法一致**(两边都算上安全区)。
 * ========================================================================== */
.action-bar-placeholder {
    flex: 0 0 auto;      /* 别被 main 抢走空间(2026-09-24 踩过) */
    height: calc(50px + env(safe-area-inset-bottom, 0px));
}
.action-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 10;
    box-sizing: border-box;
    /* ⚠️ 用 min-height 而不是 height —— 安全区走 padding-bottom,
       固定 height + border-box 会让安全区**吃掉内容区高度** */
    min-height: calc(50px + env(safe-area-inset-bottom, 0px));
    display: flex;
    /* 让按钮**撑满整条**(align-items: stretch + padding: 0,高度跟底条走 = 50px + 安全区)。
       ⚠️ 安全区仍然留成 padding-bottom —— 底条背景铺进安全区,但按钮**不**伸进去
          (否则刘海机的按钮文字会贴着 home 指示条)。 */
    align-items: stretch;
    padding: 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--card);
    /* 分隔线用 inset 阴影 —— 不占高度,不会让 placeholder 算错位 */
    box-shadow: inset 0 1px 0 var(--border);
}

/* 满宽时按钮是**直角** —— 圆角贴到屏幕边缘看起来像被切了。
   ⚠️ 改 `--van-button-radius`(变量)而不是写 `border-radius` ——
      这样只影响底部条里的按钮,不动全局的 --van-radius-md
   ⚠️ 还要 `height: auto` —— Vant 给按钮写死了 `height: var(--van-button-default-height)`(44px),
      不放开的话底条的 `align-items: stretch` **拉不动它**,底下会留缝。
      放开后按钮撑满整条(50px + 安全区),文字仍由 Vant 自己的 flex 居中。 */
.action-bar .van-button {
    --van-button-radius: 0;
    height: auto;
}

/* ---- 按钮文字的字重 ----
 * van-button 的 CSS 里**没写 font-weight** —— 按钮文字继承 body 的 400。
 * 参考站的按钮(chip)是 Tailwind 的 `font-medium` = **500**。
 *
 * ⚠️ **别用 `var(--van-font-bold)`** —— 它是 **600**(Vant 的 "bold" 比 Tailwind 的 "medium" 粗一档),
 *    用上去会比参考站粗。
 * 2026-09-28 用户定:跟 chip 一致 → 500。
 * 适用范围:**所有 van-button**(现在:浮层的「确定」+ tooltip 弹窗的「更多信息」)。状态页 2026-09-30 起没有按钮。 */
.van-button {
    font-weight: 500;
}

/* 2026-09-24:删除了原 .filter-chip.qN-alt 等 8 条规则
   —— 应用场景(筛选 chip)已不存在(浮层换 Vant),留着是死规则。 */


/* ============================================================================
 * 参考站 token(2026-09-25)
 *
 * 风格来源换成参考站「艾泽拉斯金币工坊」—— 见 docs/decisions.md 第九章。
 * 值全部实测自它的 CSS 变量(ref/recipes-spreadsheet/.../raw/05-css-vars.json)。
 *
 * ⚠️ **20 个数据色不受影响** —— 品质 / 职业 / 阵营 / namedesc 在文件顶部那段
 *    :root 里,一个都不动。
 * ========================================================================== */
:root {
    /* ---- 颜色 ---- */
    --bg:          #0b0e13;   /* 页面底 */
    --fg:          #eeebe2;   /* 主文字 */
    --card:        #131820;   /* 卡片底 */
    --muted:       #181e25;   /* 次级底 */
    --muted-fg:    #929caa;   /* 次级文字 */
    --border:      #242a33;   /* 边框 / 分隔线 */
    --primary:     #d2ab37;   /* 品牌金黄 */
    --primary-fg:  #29210a;
    --accent:      #1e252f;   /* hover 底 */
    --accent-fg:   #eae3cd;
    --success:     #36ba5b;
    --warning:     #ce9c27;
    --destructive: #e2554b;
    --info:        #5c8dff;

    /* ---- 备用三色(2026-10-02 抄自参考站,**当前无使用者**)----
       用户定:先抄下来备用;全项目做完还没用到就删掉。
       真要用时先想清楚 —— 是不是该用 --card / --muted / --border 代替。 */
    --popover:     #151b23;   /* 弹窗底(比 --card 略亮) */
    --secondary:   #1d232b;   /* 次级按钮 / 次级底 */
    --input:       #242a33;   /* 输入框边框(与 --border 同值) */

    /* ---- 字号 / 行高(成对)---- */
    --fs-xs:   12px;  --lh-xs:   16px;
    --fs-sm:   14px;  --lh-sm:   20px;
    --fs-base: 16px;  --lh-base: 24px;
    --fs-lg:   18px;  --lh-lg:   28px;

    /* ---- 间距(基准 4px)---- */
    --sp-1:  4px;   --sp-2:  8px;   --sp-3: 12px;
    --sp-4: 16px;   --sp-5: 20px;   --sp-6: 24px;

    /* ---- 圆角 ---- */
    --radius:    8px;   /* 基准 */
    --radius-sm: 4px;
    --radius-md: 6px;
    --radius-lg: 8px;

    /* ---- 字体 ----
       2026-11-02 改:`--font-serif` **删了** —— 全项目 0 处引用,是死变量
         (huashu 规范:“display 不要默认填一个衬线”)。
       `--font-sans` 现在**有真字体**:见本文件顶部的 @font-face,
       文件由 `python tools/gen-fonts.py` 生成(GB2312 全集 6,763 字,可变字体全字重)。

       ⚠️ 一旦 @font-face 声明了同名,浏览器就**不再去系统找、强制下载我们的那份** ——
          这正是要的效果:之前只写名字不托管,iOS 落苹方 / Windows 落雅黑、两张脸。 */
    --font-sans:  "Noto Sans SC", -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
}


/* ============================================================================
 * 表格(2026-09-25)
 *
 * 结构:
 *   <div class="tbl-wrap">        ← 唯一的滚动容器(横 + 纵)
 *     <table class="tbl">
 *       <colgroup>                ← 列宽(table-layout:fixed 靠它)
 *       <thead><tr><th>…         ← sticky top(纵向锁死)
 *       <tbody><tr><td>…         ← .c-icon 是 sticky left(横向锁死)
 *
 * ⚠️ 参考站那个 bug:横向溢出**泄漏到了整个文档**(缺 min-width:0)。
 *    我们的硬约束:**横向滚动只能发生在 .tbl-wrap 里**。
 * ========================================================================== */

/* main 不再自己滚 —— 交给 .tbl-wrap(这样表头的 sticky top 才有意义:
   sticky 是相对**最近的滚动祖先**定位的,父级若不可滚,它就不生效) */
main {
    flex: 1;
    min-height: 0;      /* flex 子项默认 min-height:auto,不加这个收不进去 */
    overflow: hidden;
    padding: 0;
    display: flex;      /* page-title 固定 + .tbl-wrap 弹性 */
    flex-direction: column;
}

.tbl-wrap {
    flex: 1;            /* 占满 main 剩的高度 —— 滚动交给它 */
    min-height: 0;
    overflow: auto;                 /* 横 + 纵都在这层 */
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain; /* 横滑到头不要把整页带跑 */
}

/* 导航首页(2026-10-04)的滚动容器 —— 跟 .tbl-wrap 同结构。
   main 自己是 flex+overflow:hidden(为了 .tbl-wrap 的 sticky 表头生效),
   所以导航页**必须自己**滚。 */
.nav-scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: var(--van-padding-sm);   /* 跟 main 原本的 padding 一个值 */
}

/* 列宽 —— 一处定义,表格总宽和每列宽都用它
   (table-layout:fixed 只在**表格有明确宽度**时才起作用;写 max-content 会让它失效) */
:root {
    --w-icon: 44px;
    /* 名称:2026-09-25 按**实测 80 分位**定的 —— 6775 条里 80% 的名字 ≤ 10 字,
       10 × 14px + padding 16 = 156px,取 160(4 的倍数)。原来 200px 是按最坏情况留的。 */
    --w-name: 160px;
    /* 列宽不能小于「表头文字宽 + 左右 padding(16)」—— 否则文字会溢出到格子外、
       被后画的相邻列盖住,看起来就是"被截"。
       ⚠️ padding **不会被压缩**:列宽不够时被挤的是文字,不是 padding。

       2026-09-25 按**实测文字宽 + 4px 富余**定(用户决策:富余 4):
         物品栏 42+16=58 → 62 · 类型 28+16=44 → 48 · 等级 124+16=140 → 144 · 热门度 42+16=58 → 62
       富余 4 是为了**不同手机的字体宽窄差异**(苹方 / 思源黑体,同一个字差零点几像素)。
       (图标 44 和护甲 48 本来就是余 4,不动;name 和来源由用户指定,不动) */
    --w-slot: 62px;   /* 表头「物品栏」需要 58 */
    --w-type: 62px;   /* 表头「类型」需要 44,2026-09-26 用户改为 62 */
    /* 等级列:表头改用「物品 / 需要等级」(2026-09-25)
       实测渲染宽 111.8px(2026-09-25 用 Playwright getBoundingClientRect 量过),
       余 4 = 116px。原来用「物品等级 / 需要等级」是 139.8 → 144。 */
    --w-lv:   116px;
    --w-arm:  48px;
    /* 来源:两行分别算 80 分位 —— main 7 字 = 98px、sub 4 字 = 56px,取较宽的 98 + 16 = 114px。
       (原来 76px,长描述会换行成好几行,把行高顶到 117px) */
    --w-src:  114px;
    --w-pop:  62px;   /* 表头「热门度」需要 58 */
    /* 武器页新增(2026-09-25)—— DPS / 速度只用于武器页,跟护甲列同宽 */
    --w-dps:   48px;   /* 表头「DPS」需要 30+16 */
    --w-speed: 48px;   /* 表头「速度」需要 30+16 */
    /* 容器页新增(2026-09-26)—— 容量(nslots)只用于容器页,跟护甲列同宽 */
    --w-nslot: 48px;   /* 表头「容量」实测 44+4 */
    /* 配方页新增(2026-09-26)—— 需要技能 */
    --w-skill: 76px;   /* 表头「需要技能」4 字 = 56 + padding 16 + 余 4 */
    /* 技能页(2026-10-04)—— 5 列:图标 / 名称 / 天赋 / 等级 / 类型
       宽度按**表头文字宽 + padding 16 + 余 4**(跟物品页同一套规矩)
       ⚠️ 名称列**没有自己的一条** —— 它跟物品页是同一个列(key `name`),共用 `--w-name`。 */
    --w-talent:  76px;  /* 表头「天赋」44;内容最长是 4 字的「元素战斗」「恶魔学识」= 72 */
    --w-level:   48px;  /* 表头「等级」44;内容是 1~2 位数字 */
    --w-school:  96px;  /* 表头「系」28;内容多为 2 字学派,多学派那 14 条会换行 */
    /* 职业详情页「技能」区块的「分类」(2026-10-21;2026-10-28 前叫「类别」)—— 表头 28 + padding 16 + 余 4 = 48;
       内容最长「**职业技能**」「坐骑技能」「护甲精通」4 字 = 56 + padding 16 + 余 4 = 76。
       (2026-10-21 用户定 7/-5 显示成「职业技能」「坐骑技能」⇒ 从 60 加宽到 76)
       ⚠️ 没有这个 token 时 `var(--w-category)` 无值 ⇒ 整条 calc 失效 ⇒ 整表按比例摊宽。 */
    --w-category: 76px;
    --w-race:    76px;  /* 表头「种族」30;内容最长 4 字「暗夜精灵」= 72(同 --w-talent 那档) */
    --w-class:  104px;  /* 精通页「职业」:表头 30;内容最长 5 个职业(如「战士、圣骑士、猎人、潜行者、萨满」)
                           换行显示(不限高),104 = 4 字 + 顿号两档,再取到 8 的倍数 */
    --w-food:   104px;  /* 猎人宠物页「食物」:表头 28;内容最多 6 项(肉类，鱼，奶酪，面包，真菌，水果)
                           按 4 字 + 中文逗号估,允许换行(不限高) */
    /* 职业详情页「种族」tab 的**双图标**列(2026-10-21)—— 两张 26px 并排 = 52,
       跟 wowtool 同一个尺寸(它的格子是 width:52px)。 */
    --w-raceicon: 52px;

    /* NPC 列表页(2026-10-22)—— 5 列:名称(--w-name)/ 等级 / 地点 / 反应 / 热门度(--w-pop)。
       列宽按"实测最长文字 + padding 16 → 取到 4 的倍数":
         · 等级:表头 28;内容「11-12」≈ 36,第二行小字最长「稀有精英」= 56 → 72。
           ⚠️ **不能复用 --w-level(48)** —— 那格只够 1~2 位数字,放不下小字。
         · 地点:表头 28;地区名最长 8 字(希尔斯布莱德丘陵)= 112,但那是极少数;
           常见最长 6 字 = 84 → 100,更长的**换行**(项目规则:长内容不限高)。
         · 反应:表头 28;内容「A H」≈ 24 → 44。 */
    --w-lvtext: 72px;
    --w-zone:  100px;
    --w-react: 116px;   /* 「联盟 / 部落态度」两格 + 中间斜杠(2026-10-22 用户定改文字) */
    /* 声望(NPC「出售」tab,2026-10-24)—— 表头「声望」28;内容最长「崇敬」≈ 28 → 44。
       ⚠️ **新列必须同时加 token** —— 少一个 `var()` 无值 ⇒ 整个 calc() 作废 ⇒
          表格退回自然宽,弹性列(价格)被挤成 62px。这坑 2026-10-24 当场踩到。 */
    --w-stand: 56px;
    --w-rep:   56px;  /* 阵营页「NPC」块的「声望」值(-125…400,最多 4 字符);表头 28 + padding 16 */
    /* 限量(物品页「商人」区块,2026-10-24)—— 表头「限量」28;内容 `∞` 或数字 → 44~56 */
    --w-stock: 56px;

    /* 任务列表页(2026-10-25)—— 8 列:名称(--w-name)/ 等级(--w-lvtext)/ 需要等级 /
       阵营 / 奖励(弹性)/ 经验 / 金钱 / 分类(--w-zone)。
         · 需要等级:表头 4 字 = 56;内容 1~2 位数字 → **62**(跟 --w-pop 同档)
         · 阵营:表头 2 字 = 28;内容「联盟 / 部落 / 双方」= 28 → **56**
         · 经验:表头 28;内容最长 `1,750` ≈ 40 → **62**
         · 金钱:一格最多三档(金/银/铜各一个图标 + 数字)≈ 60 → **72**
       ⚠️ 新列**必须同时加 token**(见上面 --w-stand 那条:缺一个 var() 整条 calc 作废)。
       ⚠️ 「分类」**复用 `--w-zone`**(100px)—— 内容同样是中文区域名,别新开一个等值的 token。 */
    --w-qreq:   62px;
    --w-qxp:    62px;
    /* 声望(2026-10-26)—— `雷矛卫队 +10` 一行一个。
       ⚠️ 算法要**含单元格内边距**:表格字号 14px、td 左右各 8px(`--sp-2`)
       ⇒ 可用宽 = 本值 − 16。常见最长 `暗矛突袭者 +100` ≈ 5×14 + 4 + 4×8 = 106
       ⇒ 本值 = 106 + 16 = 122 → 取 4 的倍数 = **120**(可用 104,那串 106 会差 2px 折行,
          实测最常见的 `暴风城 +50` / `雷矛卫队 +10` 都只有 80~90,稳稳一行)。
       2026-10-26 第一版写成 104 就是**漏了内边距**(可用只剩 88),5 字名会折成两行。
       ⚠️ 单任务最多 5 个阵营 ⇒ 这一格会**多行**,行高跟着变(正常现象,别设死高度)。
       ⚠️ 极长的职业专精名(`工程学 - 地精工程学专精 +75`,17 字符)**必然折行** —— 接受。 */
    --w-qrep:  120px;
    --w-qmoney: 96px;

    /* NPC「反应」的两种颜色(2026-10-22)—— 值抄 wowtool 的 .q10 / .q2。
       语义是「该阵营对玩家的态度」,跟品质色无关 ⇒ **不引用 --quality-***(虽然 q2 同值),
       跟 namedesc 那条同一个理由。neutral(0)不设 = 用正文色。 */
    --react-hostile:  #ff4040;   /* .q10 */
    /* 图标左上角的库存量(2026-10-24)—— 抄 wowtool 的 .wh-icon-text[data-type=quantity] */
    --icon-qty:       #ffd100;
    --react-friendly: #1eff00;   /* .q2  */
    --react-neutral:  #ffd100;   /* .q(2026-10-22 从原版筛选的 computed color 实测) */

    /* ---- 物品详情页的「相关」表(2026-10-04)----
       「掉率(%)」:按列表页的规矩定的 —— 实测最长文字宽 + padding 16 → 再取到 4 的倍数。
         实测(2026-10-04,跨 5 种字体栈取最宽):8 字符 `10.60436` = 60.84px
         → 60.84 + 16 = 76.84 → 取 4 的倍数 = **80**。
         ⚠️ 没给 `100.00000`(9 字符 = 69.06px,要 92)留余量 —— 它只在掉率正好 100%
            时出现,实测最接近 99.20356%。真出现时会溢出约 2px,那时把这个数改成 92 即可。
       「兑换」那列(原「成本」)**没有 token** —— 2026-10-18 起它是弹性列
         (`COST_COL` 复用材料列,`flex:true`),宽度吃剩余空间。 */
    --w-ratio: 80px;

    /* 专业页 / 物品页配方区块的「需要技能」列(2026-10-10)——
       ⚠️ 跟配方页那个 `--w-skill`(76px)**是两个值**,别混:
         · 配方页:一个数字,右对齐,76px
         · 这里  :**两行** —— 第一行「工程学: 侏儒工程学 (215)」、第二行「285 305 315 325」
       宽度按**最宽的第二行**算。2026-10-10 实测(14px 字号下)文字宽 111.1px
       → + padding 16 + 余 4 = 131.1 → 取 4 的倍数 = 132。
       ⚠️ **原来是 124px**(按 12px 字号算的 103)。14px 下 111.1 > 可用宽 108 ⇒ 会溢出,
          所以改字号**必须**连这条一起改。
       (表头「需要技能」4 字 = 56,不构成约束;第一行最长「工程学: 侏儒工程学 (215)」
        —— 带专精的情况 —— 实测还没超过第二行。)
       ⚠️ key 都是 `skill` ⇒ class 都是 `.c-skill` ⇒ 靠表格上的 `.tbl-recipe` 标记切到这套宽度。 */
    --w-recipe-skill: 132px;
}

.tbl {
    table-layout: fixed;     /* 列宽固定 —— 不随内容变化 */
    border-collapse: separate;
    border-spacing: 0;
    /* 总宽从 inline style 注入(JS 拼 "calc(var(--w-icon) + var(--w-name) + ...)")
       —— 让列配置数据驱动,加一页只改 PAGE_COLS + 这里加 token,不用动 calc */
    font-family: var(--font-sans);
    font-size: var(--fs-sm);      /* 参考站表格是 text-sm = 14px(不是 text-xs 12px)*/
    line-height: var(--lh-sm);    /* 20px ← 跟 14px 配对 */
    color: var(--fg);
    font-feature-settings: "lnum";
}

/* ---- 列宽 ---- */
.tbl .c-icon { width: var(--w-icon); }
.tbl .c-name { width: var(--w-name); }
/* 名称列**是第一列**时(任务 / NPC —— 没有图标列):左边留一条 **16px 标记槽**。
   为什么必须显式写:`.c-name` 的默认是 `padding: 8px 8px 8px 0`(左 0)—— 那个 0 是因为
   **别家的左边距由图标列提供**(`.c-icon { padding: 8px }`)。没有图标列时左边就真是 0。
   ★ 2026-10-25 用户定:槽统一留给**所有行**(不只是有标记的行)——
     名字 / 阵营职业标签 / **表头** 全部从同一条线开始(8 + 16 = 24px);
     标记用**负外边距挂进槽里**,见下面 `.npc-boss / .q-daily` 那条。
   ⚠️ 这里先后写错过:先 4px(比别页窄)、再删掉(回到 0)、再 8px(名字贴槽口)。
      最终值 = `calc(var(--sp-2) + var(--sp-4))`。 */
.tbl td.c-name:first-child, .tbl th.c-name:first-child {
    padding-left: calc(var(--sp-2) + var(--sp-4));
}
.tbl .c-slot { width: var(--w-slot); }
.tbl .c-type { width: var(--w-type); }
.tbl .c-lv   { width: var(--w-lv); }
.tbl .c-arm  { width: var(--w-arm); }
.tbl .c-src  { width: var(--w-src); }
.tbl .c-pop  { width: var(--w-pop); }
.tbl .c-dps   { width: var(--w-dps); }   /* 武器页用 */
.tbl .c-speed { width: var(--w-speed); } /* 武器页用 */
.tbl .c-nslot { width: var(--w-nslot); } /* 容器页 / 箭袋页用 */
.tbl .c-skill { width: var(--w-skill); } /* 配方页用 */
.tbl .c-ratio { width: var(--w-ratio); } /* 物品详情页的「相关」表 */
/* ⚠️ `.c-cost` 没有 width —— 2026-10-18 起它复用材料列(弹性列)。 */
/* 技能页(2026-10-04)—— c-icon / c-name 复用上面那两条 */
.tbl .c-talent { width: var(--w-talent); }
.tbl .c-level  { width: var(--w-level); }
.tbl .c-school { width: var(--w-school); }
.tbl .c-race   { width: var(--w-race); }  /* 种族特长页用 */
.tbl .c-class  { width: var(--w-class); } /* 精通页用 */
.tbl .c-food   { width: var(--w-food); }  /* 猎人宠物页用 */
.tbl .c-raceicon { width: var(--w-raceicon); } /* 职业详情页「种族」tab 的双图标 */
.tbl .c-category { width: var(--w-category); } /* 职业详情页「技能」tab 的「分类」 */
.tbl .c-lvtext { width: var(--w-lvtext); } /* 「等级 + 小字」档(NPC 页 / 副本页共用) */
.tbl .c-zone  { width: var(--w-zone); }  /* NPC 页「地点」 */
.tbl .c-react { width: var(--w-react); } /* NPC 页「反应」 */
.tbl .c-stand { width: var(--w-stand); } /* NPC「出售」tab 的「声望」 */
.tbl .c-rep   { width: var(--w-rep); }   /* 阵营页「NPC」块的「声望」值(数字,右对齐) */
.tbl .c-stock { width: var(--w-stock); } /* 物品页「商人」的「限量」 */
/* 任务列表页(2026-10-25)—— 「奖励」是弹性列(grow),故意**没有**宽度规则 */
.tbl .c-qxp    { width: var(--w-qxp); }
.tbl .c-qrep   { width: var(--w-qrep); }  /* 任务页「声望」(2026-10-26,一行一个阵营) */
.tbl .c-qmoney { width: var(--w-qmoney); } /* 任务页「金钱」(金/银/铜三档图标) */

/* ★ 弹性列(2026-10-20)—— 列对象上声明了 `flex` 才带这个类(见 base.js 的 grow())。
   这里**故意没有宽度规则**:宽度由 components.js 的 updateFlexPx() 量出容器宽、
   减掉固定列之和,以**具体 px** 写到 `<col>` 的 inline style 上。
   原因:Chromium 忽略 `<col>` 上的 calc/百分比/var(只认 px),而 `width:auto`
   会被 table-layout:fixed 按比例摊宽(图标列 44 撑成 59/81)—— 实测清单见 app.js。
   ⚠️ 上面的固定宽规则照旧生效;弹性列靠 inline px 覆盖它们(inline 优先级最高)。 */

/* ★ 「配方表」的作用域覆盖(2026-10-10)—— 专业页 + 物品页那两个配方区块。
   为什么要它:「需要技能」那列的 key 是 `skill`,跟**配方页**那列**同名** ⇒ 同一个 class
   ⇒ 上面 `.c-skill`(宽度 76)和后面数字列规则里那条**右对齐**,两处**只能有一套**。
   而两边内容正好相反 —— 配方页是「一个数字、右对齐」,这里是「两行文本、左对齐」。
   ⇒ 靠表格上的 `.tbl-recipe` 标记切(见 components.js 的 tblIsRecipe / detailTblIsRecipe)。
   ⚠️ 选的是「**不动**已经做好的配方页」那条(A 方案,2026-10-10 用户定)。
   ⚠️ 选择器写成 `.tbl.tbl-recipe`(3 个 class)—— 数字列规则那条是 `.tbl td.c-skill`
      (2 个),多加一层才不靠"谁在后面"决定胜负。 */
.tbl.tbl-recipe .c-skill { width: var(--w-recipe-skill); }
.tbl.tbl-recipe th.c-skill,
.tbl.tbl-recipe td.c-skill { text-align: left; }

/* ---- 表头行:纵向锁死 ----
   ⚠️ 2026-09-25 按参考站的**代码定义**改过一轮(原来照着"印象"写错了):
     参考站 th 的 class: text-foreground h-10 px-2 text-left align-middle font-medium
       · text-foreground  → 色是**主文字色**(不是次级灰)
       · h-10             → height: calc(var(--spacing) * 10) = 40px
       · px-2             → padding-inline 8px(**上下 0**)
       · font-medium      → 字重 500(不是 400)
     下边框在参考站是加在 <tr> 上([&_tr]:border-b),我们加在 th 上效果一样。 */
.tbl thead th {
    position: sticky;
    top: 0;
    z-index: 3;
    /* 46px —— 用户要求「跟导航栏一样高」,所以**引用导航栏的变量**而不是写死数字:
       导航栏变了表头跟着变(参考站本来是 h-10 = 40px,这是有意偏离)。 */
    height: var(--van-nav-bar-height);
    padding: 0 var(--sp-2);             /* 参考站 px-2 —— 上下 0 */
    background: var(--bg);
    border-bottom: 1px solid var(--border);
    color: var(--fg);                   /* 参考站 text-foreground */
    font-weight: 500;                   /* 参考站 font-medium */
    text-align: left;
    vertical-align: middle;
    white-space: nowrap;
}

/* 表头的垂直 padding 统一成 0(2026-09-28 修)
   ⚠️ 下面有两条列规则**本意只想控左右**,但用了简写,把上下也设成了 8px:
        .tbl .c-icon { padding: var(--sp-2); }                            ← 四边 8px
        .tbl .c-name { padding: var(--sp-2) var(--sp-2) var(--sp-2) 0; }   ← 上下也 8px
      (图标列要留白、名称列左 0 —— 那两条的**本意**是对的,别去改它们,否则数据行会跟着变。)
   表头有固定高度 + vertical-align:middle,所以**今天看不出差别**;
   但万一高度改成 auto,这两列会比别的列高出 16px。这里按 `thead` 收窄成 0。
   ⚠️ 选择器必须带 `.tbl thead` —— 只写 `.tbl .c-icon` 的话会连**数据行**一起改掉。 */
.tbl thead .c-icon,
.tbl thead .c-name {
    padding-top: 0;
    padding-bottom: 0;
}

/* ---- 图标列:横向锁死 ---- */
.tbl .c-icon {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--bg);
    padding: var(--sp-2);
}
/* 左上角(表头 × 图标列)—— 两个方向都锁,层级最高 */
.tbl thead .c-icon { z-index: 4; }

/* ---- 数据行 ---- */
.tbl tbody tr {
    cursor: pointer;
}
.tbl tbody td {
    padding: var(--sp-2);       /* 参考站 p-2 = 8px(四周)*/
    border-bottom: 1px solid var(--border);
    vertical-align: middle;     /* 参考站 align-middle —— 垂直对齐「居中」 */
    /* 参考站行上是 transition-colors —— 让 hover 是**渐变的**而不是硬切。
       时长/缓动取它 --default-transition-* 的值。 */
    transition: background-color .15s cubic-bezier(.4, 0, .2, 1);
    /* 背景**不设** —— 只有 sticky 的图标列需要(见 .tbl .c-icon),其余透出页面底色 */
}
/* 尊重「减少动态效果」的系统设置 */
@media (prefers-reduced-motion: reduce) {
    .tbl tbody td { transition: none; }
}

/* 行 hover(参考站 hover:bg-muted/50)
   ⚠️ 必须门控 —— 触摸设备上 hover 会"粘住"。
   混到 --bg 上而不是用 transparent:图标列是 sticky,**半透明背景会漏出下层内容**。 */
@media (hover: hover) and (pointer: fine) {
    .tbl tbody tr:hover td {
        background: color-mix(in oklab, var(--muted) 50%, var(--bg));
    }
}
.tbl tbody tr:active td { background: var(--accent); }

/* ---- 数字列 ----
   写成 th.c-x / td.c-x 是为了盖过 `.tbl thead th { text-align:left }`
   —— 两者特异性都是 (0,2,1),靠**写在后面**赢

   2026-09-25 拆成三组:**等宽**所有数字列都留,但**对齐**按列不同。 */
.tbl th.c-lv, .tbl td.c-lv,
.tbl th.c-arm, .tbl td.c-arm,
.tbl th.c-dps, .tbl td.c-dps,
.tbl th.c-speed, .tbl td.c-speed,
.tbl th.c-nslot, .tbl td.c-nslot,
.tbl th.c-skill, .tbl td.c-skill,
.tbl th.c-pop, .tbl td.c-pop,
.tbl th.c-level, .tbl td.c-level,
.tbl th.c-lvtext, .tbl td.c-lvtext,
.tbl th.c-rep, .tbl td.c-rep,
.tbl th.c-ratio, .tbl td.c-ratio,
.tbl th.c-qxp, .tbl td.c-qxp,
.tbl th.c-qmoney, .tbl td.c-qmoney {
    font-variant-numeric: tabular-nums;    /* 等宽数字 */
}
/* 右对齐 —— 护甲 / DPS / 速度 / 容量 / 需要技能 / 热门度 / 等级(技能页)/ 掉率 */
.tbl th.c-arm, .tbl td.c-arm,
.tbl th.c-dps, .tbl td.c-dps,
.tbl th.c-speed, .tbl td.c-speed,
.tbl th.c-nslot, .tbl td.c-nslot,
.tbl th.c-skill, .tbl td.c-skill,
.tbl th.c-pop, .tbl td.c-pop,
.tbl th.c-level, .tbl td.c-level,
.tbl th.c-lvtext, .tbl td.c-lvtext,
.tbl th.c-ratio, .tbl td.c-ratio,
.tbl th.c-qxp, .tbl td.c-qxp,
.tbl th.c-qmoney, .tbl td.c-qmoney {
    text-align: right;
}
/* 居中 —— **只有「物品等级 / 需要等级」这一列**(用户 2026-09-25 指定):
   它是成对的值,右对齐会整体偏到右边、跟表头对不齐。**其他数字列不动。** */
.tbl th.c-lv, .tbl td.c-lv {
    text-align: center;
}

/* ---- 名称列:最多 3 行 ---- */
.tbl .c-name { padding: var(--sp-2) var(--sp-2) var(--sp-2) 0; }   /* 左 0:图标列已有 padding */
/* 物品名字重 —— 参考站是 font-medium(500),我们之前没设,继承成 400 了(比它细一档)。
   注意:参考站用 truncate(单行截断),我们是**换行**(最多 3 行)—— 那是需求不同,故意的。 */
.tbl .c-name .name { font-weight: 500; }
.tbl .c-name .nm-line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-1);
}
/* 名称列里**相邻两组之间**才加 2px —— 组数会变(标签会提到名字上面),
   不能假定"第 1 行是名字"。 */
.tbl .c-name .nm-line + .nm-line { margin-top: 2px; }
/* 标记 + 名字绑成**一组**(2026-10-25)—— .nm-line 是 flex-wrap:wrap,
   不绑的话名字一长,标记自己留在上一行(实测日常任务那 150 行就是这样)。
   `min-width:0` 让里面的名字仍然能正常折行。 */
.tbl .c-name .nm-lead {
    display: inline-flex;
    align-items: flex-start;   /* 名字折行时标记跟**第一行**对齐(别垂直居中到两行中间) */
    gap: var(--sp-1);
    min-width: 0;
}
/* rank(技能名后面的「等级 3」「召唤」那种灰字)—— 跟名字在**同一个 `.nm-line` 里**
   (靠上面那个 gap 拉开),字体 / 字号 / 行距跟名字**完全一样**,只差颜色。
   用户 2026-10-04 定:空格分隔,**不加任何分隔符号**。
   ⚠️ 2026-10-10 起这条属于 `.c-name` —— 技能家族的名称列**就是**物品页那一列了
   (原来叫 `sname`,是一整块重复的 CSS;两列的 key / 宽度 / 结构从第一天起就一样)。 */
.tbl .c-name .sp-rank { color: var(--muted-fg); }
/* 名字下面的副标题(2026-10-22 加,NPC 的 `<商人>` 这种)—— 灰小字,
   跟 wowtool 的 `<div class="small">` 同一个视觉档(12px)。 */
.tbl .c-name .nm-sub { font-size: 12px; color: var(--muted-fg); }

/* NPC 图标列里的 **Boss 骷髅**(2026-10-22)—— 只有 `boss: 1` 的行有(211/6547)。
   源图是 12×16 的 gif(原版把它当文本行内小标记,`padding-left: 23`);
   我们把它放进**跟别家一样的 28px 图标位置**,所以要放大:
     · 按 **28 高**等比缩放 = 21×28(ratio 0.75,同原图比例)
     · `image-rendering: pixelated` —— 像素图放大要锐利,别用默认的双线性(会糊)
   ⚠️ 做成格子里面的 span,**不是 td 背景图**:行 hover 时 `tr:hover td` 会换背景,
      背景图做的图标会消失。
   ⚠️ 资源用**完整绝对 URL**(规则 2):写 `/images/...` 会打到我们服务器。 */
.tbl .c-name .npc-boss {
    display: inline-block;      /* 名字前面(2026-10-25)—— 不再独占图标列 */
    flex: none;
    /* ★ 挂进左边那条 16px 槽:负的槽宽 + 正常的 --sp-1 间距 ⇒ 名字仍在 24px */
    margin-left: calc(-1 * var(--sp-4));
    margin-top: 2px;        /* 行高 20 − 16,取一半 ⇒ 跟第一行文字对齐 */
    /* **原始尺寸 12×16**,不放大(2026-10-22 用户定:放大后像素糊,看不清)——
       图本身是低分辨率 gif,强行拉到 28 高没法看。
       ⚠️ 间距**不在这里加 margin** —— .nm-lead 的 gap 就是 4px,跟材料列「图标→名字」一致。 */
    width: 12px;
    height: 16px;
    background: url("https://wowtool.tips/images/icons/boss.gif") center / 12px 16px no-repeat;
}

/* 日常任务标记(2026-10-25)—— 名字前面,234/10246 行有。
   ★ 用**图标**不用文字:wowhead 的 tiny 图标集里有 quest_start_daily.gif(实测 200)。 */
.tbl .c-name .q-daily {
    flex: none;
    margin-left: calc(-1 * var(--sp-4));   /* 同上:挂进槽里 */
    margin-top: 4px;                       /* 行高 20 − 12,取一半 */
    width: 12px;
    height: 12px;
    display: block;
}

.tbl .c-icon .npc-boss {
    display: block;
    /* **原始尺寸 12×16**,不放大(2026-10-22 用户定:放大后像素糊,看不清)——
       图本身是低分辨率 gif,强行拉到 28 高没法看。居中在图标格里即可。 */
    width: 12px;
    height: 16px;
    margin: 0 auto;
    background: url("https://wowtool.tips/images/icons/boss.gif") center / 12px 16px no-repeat;
}

/* ---- 「等级 + 小字」列的第二行(NPC 页 2026-10-22;副本页 2026-10-28 起共用)---- */
/* 小字内容:NPC = 精英 / 稀有 / 稀有精英 / Boss;副本 = 团队副本 —— 跟 wowtool 的 .small 同档 */
.tbl .c-lvtext .small { font-size: 12px; color: var(--muted-fg); }
/* 态度列 —— 两格文字(友善 / 中立 / 敌对),中间一个斜杠;缺数据那格是 `-`。
   ★ 2026-10-22 用户定:**斜杠和 `-` 都用正文色、字面空格** —— 跟物品页
   「物品 / 需要等级」那格的写法完全一致(那边是 `<span> / </span>` + `<span>-</span>`,
   没有任何额外样式)。所以这两样**不要**加 color / margin。 */
.tbl .c-react .react-friendly { color: var(--react-friendly); }
.tbl .c-react .react-hostile  { color: var(--react-hostile); }
.tbl .c-react .react-neutral  { color: var(--react-neutral); }


/* ---- 来源列:两行 ----
   ★ 2026-10-10:副行加 **`margin-top: 2px`** —— 全站「两个信息之间 = 2px」统一到这一条。
   这一条原来**没有**(两行都是裸 `display:block`、0 间距),是 2026-09-24 写死的,
   当时「需要技能」那列还不存在;2026-10-10 加那列时按名称列的规矩给了 2px,
   回头一比才发现来源列漏了这条 ⇒ 同一个"两行"在两处是 0 和 2。
   ⚠️ **只加在"两组之间",不加在"一组自己换行"上** ——
      名字太长 / main 太长时那几行仍然是 0(靠 `line-height:20px` 紧挨着),这是有意的。
   ⚠️ 跟 wowtool 的取值**不一样也别跟**:它的副行用 `.small2{font-size:12px;padding-top:3px}`、
      正行用 `.small{font-size:12px}` 无 padding ⇒ 它是 **3px / 0px**,正好跟我们反过来。
      那两套 class 的副产物不是设计意图;照抄会让「需要技能」两行贴死。 */
.tbl .c-src .sr-main,
.tbl .c-src .sr-sub { display: block; }
.tbl .c-src .sr-sub {
    margin-top: 2px;                 /* 跟 .c-name 的 `.nm-line + .nm-line` 同一个值 */
    color: var(--muted-fg);
}

/* ---- 图标方框(一份配方,三处共用)----
   三个地方都是「一个 28px 的方框」:① 行首的图标 `.c-icon img`
   ② 行内可点图标 `.cell-ico img` ③ 没图时的占位方块 `.icon-ph`。
   ★ 2026-10-07 合成一条选择器列表:原来**三个块各写一份同样的六条声明**
     (`cell-ico img` 那块的注释自己都写着「跟行图标同一套配方」)——
     改 28→32 漏一处,同一张表里行首图标和材料图标尺寸就不一样;
     漏改 `.icon-ph` 更糟:没图的行会**矮一截、行高跳**。
   ⚠️ 三者必须**逐条相同**,要改一起改;各自的尺寸差异请用别的方式做,别在这儿分叉。
   ⚠️ **新加一个作用域(如任务正文的 `.db`)时,把选择器加进这个列表**,别另写一份槽 ——
      2026-10-26 正文就是这么翻的:自造了个 `.db-thumb`,顺手写了 `overflow:hidden`,
      结果压在右下角的数量角标 `.ico-cnt` 被裁掉。**槽和角标是一套**:槽要 `position:relative`
      且**不许裁切**。 */
/* 行内链接(2026-10-17,精通页职业列)—— 文字保持普通列的字号/行距,
   颜色由职业色 `.cN` 给(这里**不设 color**,否则会盖掉 `.c1`~`.c11`)。 */
.tbl .cell-link { text-decoration: none; cursor: pointer; }

.tbl .c-icon img,
.tbl .cell-ico img,
.tbl .cell-ico .icon-ph,
.db .cell-ico img,
.db .cell-ico .icon-ph,
.db .ico-thumb img {
    display: block;
    width: 28px;
    height: 28px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
}

/* 种族行的**双图标**(2026-10-21,职业详情页「种族」tab)——
   两张 26px 并排、**无间隙**(格子宽 52 = 26×2,跟 wowtool 一致)。
   ⚠️ 别加 margin —— 会把格子撑到 52 以上,名字列被挤。 */
.tbl .c-raceicon img {
    display: inline-block;
    vertical-align: middle;
    width: 26px;
    height: 26px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
}

/* 职业列里的**职业图标**(2026-10-21,`classIcon:true` 的列)——
   跟文字同一行,17px(比行首图标小一档);点了跟着文字一起跳职业页。 */
.tbl .cls-ico {
    display: inline-block;
    vertical-align: middle;
    width: 17px;
    height: 17px;
    margin-right: 3px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
}

/* ---- 标签(pill)—— 抄参考站的配方 ----
   参考站原文(实测):
     inline-flex items-center whitespace-nowrap rounded-sm px-1.5 py-0.5
     text-xs font-medium bg-primary/15 text-primary border border-primary/30
   → 背景 = 该色 15% / 边框 = 该色 30% / 文字 = 该色 100%

   我们改用 **currentColor** —— 一条规则覆盖全部 20 个数据色
   (职业标签走 .cN、阵营标签走 .side-*,颜色自动跟随)。

   参考站是**渐进增强**(color-mix 那条写在后面,老浏览器忽略 → 退回纯色背景)。
   我们改成 @supports 包住:不支持就退回"只有边框",不会比现在更丑。*/
/* ★ 2026-10-27:同一个标签也用在**任务正文的「系列」**里(`.db`),
   所以选择器扩到两处 —— 别在 .db 里再抄一份。 */
.tbl .tag,
.db .tag {
    display: inline-flex;
    align-items: center;
    padding: 2px 6px;           /* 参考站的 py-0.5 px-1.5 */
    border: 1px solid currentColor;
    border-radius: var(--radius-sm);
    font-size: var(--fs-xs);
    line-height: var(--lh-xs);
    font-weight: 500;           /* 参考站的 font-medium */
    white-space: nowrap;
}
@supports (background: color-mix(in oklab, red 15%, transparent)) {
    .tbl .tag,
    .db .tag {
        background: color-mix(in oklab, currentColor 15%, transparent);
        border-color: color-mix(in oklab, currentColor 30%, transparent);
    }
}

/* ---- 表格里的阵营色 ----
   原规则是 `.item-row .side-alliance`(带前缀),表格里匹配不上,补一份。
   品质色 .qN / 职业色 .cN 是**裸类名**,表格里自动生效,不用补。 */
.tbl .side-alliance, .db .side-alliance { color: var(--faction-alliance); }
.tbl .side-horde,    .db .side-horde    { color: var(--faction-horde); }

/* ---- 名字后缀 / 赛季标签 ----
   两条决策:
     · **去掉 italic** —— 中文没有斜体传统,浏览器会机械倾斜让笔画变形
     · 颜色走参考站的 token,不再依赖 Vant 变量 */
.tbl .namedesc {
    color: var(--color-namedesc);   /* 数据色,不动 */
    white-space: nowrap;
}


/* ==========================================================================
   筛选浮层 · 更多筛选条件(动态条件 · filters)—— 2026-09-29 接 3+4
   详见 docs/filters.md 6.8:
   · 两栏(左分组 + 右条件 · 跟现有 facet 那块同源)
   · 弹窗居中,按「可选项个数」分 chip / picker / field
   · 「匹配:AND / OR」放在「更多筛选条件」标题行右侧
   ========================================================================== */

/* 标题行 —— 文字 + 紧跟其后的两个 chip(2026-09-30 用户定)
   ⚠️ 原来是 `justify-content: space-between`,把 chip 甩到最右边;
      现在改成默认(靠左)排列 + 一个 gap —— 两个 chip **跟在文字后面**。 */
.more-filters-title {
    display: flex;
    /* ⚠️ flex-start,不是 center(2026-09-30 用户定,看过三版对比图后选的)。
       chip 回到参考站原版 34px 后,这一行有 34 高;用 center 的话标题会飘在整行的
       正中,上下各留 5px 空白。flex-start 让标题**站在顶线**上,chip 从同一条顶线往下挂。
       ⚠️ 副作用(实测):标题的**文字墨迹顶**这时比 chip 里的文字墨迹顶高 **6.5px** ——
          对的是**盒子顶**,不是**文字顶**。要"文字顶对齐"得用 center(差 1.5px)。
          这是用户明确选的"盒子顶对齐"。 */
    align-items: flex-start;
    gap: var(--van-padding-sm);           /* 文字 ↔ chip 组 之间 */
    margin: var(--van-padding-md) var(--van-padding-md) var(--van-padding-xs);
    font-size: var(--van-font-size-md);
    font-weight: 500;
    color: var(--fg);
}
.more-filters-title .match-chip {
    display: flex;
    gap: var(--van-padding-xs);
}
/* 「AND / OR」两个 chip —— **不是按钮,是 chip**(2026-09-30 用户定)
 *
 * ⚠️ 短暂试过换成 <van-button>(想要按压态 / disabled / 表单语义),撤回了:
 *    cherry-pick 那几个能力要反过来覆盖 van-button 的 44px 高、6px 圆角、
 *    全站金色描边 —— 得不偿失,chip 也不需要按钮语义(不提交表单、不 loading)。
 *
 * 长相 = **参考站的「开关 chip」配方**(2026-09-30 用户从参考站截图里认出来的)。
 * 出处:参考站「攻略指南」那一排(亡灵骑士 / 战士 / 牧师 / 法师 …),选中态在「亡灵骑士」上。
 *
 *   未选中: inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm
 *           transition-colors border-border text-muted-foreground
 *           hover:border-primary/40 hover:text-foreground
 *   选中:   ……同上…… border-primary bg-primary/15 font-medium text-primary
 *
 * ⚠️⚠️ **别跟 `.tbl .tag`(B 家族徽章)搞混** —— 两套配方不一样:
 *
 *           | 徽章(.tbl .tag)| 开关(本规则)
 *        圆角 | 4px            | **6px**
 *        padding | 2 / 6px      | **6 / 12px**
 *        字号 | 12px           | **14px**
 *        选中边框 | 该色 30%   | **该色 100% 实心**
 *        字重 | 500 恒定       | **400 → 500(选中才粗)**
 *
 *   徽章(高利润 / 亏损 / S 级)是**静态标签**,没有"未选中";开关才是成对的。
 *   2026-09-30 我先按徽章改过一轮,是抄错了对象。
 */
/* 「拓展搜索」chip 的容器 —— 只做一件事:跟**名称那一行的 input 左对齐**
   (缩进 label 列那 6.2em,用户 2026-10-05 定)。
   ⚠️ 这一行的 van-field **故意不写 label** —— 它修饰的是上面那个名称搜索,
      写个 label 反而像"另一个并列字段"。
   ⚠️ 缩进量 = **label 列宽 + label 右边距**,两个都用 Vant 自己的变量(带默认值兜底),
      别只写 6.2em —— 那样会**差 12px**(2026-10-05 实测:label 左 33、input 左 131.8,
      差 98.8px = 6.2em 的 86.8 + 12px 的右边距)。 */
.filter-chip {
    margin-left: calc(var(--van-field-label-width, 6.2em)
                    + var(--van-field-label-margin-right, 12px));
}

.more-filters-title .match-chip span,
.cond-chip span,                        /* cond 弹窗里的 chip 也用这一套(2026-09-30 用户定) */
.filter-chip span {                     /* 筛选浮层里的「拓展搜索」chip(2026-10-05 加) */
    display: inline-flex;
    align-items: center;
    /* 尺寸 = **参考站原版**(2026-09-30 改回来)。
       ⚠️ 中间压小过一轮(2/8 padding + 12px = 22px),理由是"塞在 24px 的文字行旁边
          会被撑高、看着太大"。**那个前提后来没了** —— 用户定下"一行 + 盒子顶对齐
          (flex-start)",标题行本来就是 34 高,chip 不再撑高任何东西。
          而且量过参考站:它那排 34px 的 chip 也是 `gap-2`、也是能换行的独立块。
       ⚠️ 6px 是 Tailwind 的 `py-1.5`,**不在我们的 4px 间距刻度上**(--sp-* 没有 6),
          照抄参考站就得用这个值。改它 = 改 chip 高度(6+6+20+2 = 34)。 */
    padding: 6px 12px;                 /* 参考站 px-3 py-1.5 */
    border: 1px solid var(--border);   /* 未选中:灰边 + 灰字 + 透明底 */
    border-radius: var(--radius-md);   /* 6px(不是 chip 徽章的 4px) */
    font-size: var(--fs-sm);           /* 14px —— 参考站的 text-sm */
    line-height: var(--lh-sm);         /* 20px —— text-sm 自带的 20,正好对上 */
    font-weight: 400;                  /* 未选中不加粗 */
    white-space: nowrap;
    color: var(--muted-fg);
    cursor: pointer;
    user-select: none;
}
/* ⚠️ 文字墨迹比框中心**低约 1px** —— **已知,故意不修**(2026-09-30 定)。
 *    根因是字体(Noto Sans SC)的垂直度量,CSS 的居中都是"基于盒子"的,管不到墨迹。
 *    决定性依据:**参考站同款 chip 同样偏 0.38~0.84px,而且它全站 0 处光学微调** ——
 *    我们跟它一致。详见 docs/filters.md「⚠️ chip 里的文字墨迹偏下」那一节。
 *    ⚠️ 别用 `padding: 1px 8px 3px` 之类的"修正" —— 那是偏离参考站。 */

/* 选中 —— 边框是**实心主色**(不是 30% 半透明),字主色,字重提一档 */
.more-filters-title .match-chip span.on,
.cond-chip span.on,
.filter-chip span.on {
    border-color: var(--primary);
    color: var(--primary);
    font-weight: 500;                  /* 参考站的 font-medium */
}
/* 淡底:只有底是 15% 半透明,浏览器支持 color-mix 才加
   (不支持就退回"实心金边 + 金字",不会比现在更丑) */
@supports (background: color-mix(in oklab, red 15%, transparent)) {
    .more-filters-title .match-chip span.on,
    .cond-chip span.on,
    .filter-chip span.on {
        background: color-mix(in oklab, currentColor 15%, transparent);
    }
}

/* 第二个 TreeSelect(跟第一个同款,只是 data 不同)—— 外框复用 .filter-popup-body .van-tree-select,
   这个类本身不需要任何声明(2026-10-02 删掉了那个空规则) */

/* 右栏项(facet-opt 的动态条件版) —— 跟 .facet-opt 走一致
   · 多两行:第 1 行名字,第 2 行值 + ✕
   · 满分锁时:cond-opt--locked class */
.filter-popup-body .cond-opt {
    display: flex;
    flex-direction: column;
    gap: 2px;
    /* 右边 32px 是给 ✕ 留的位置(同 `.filter-popup-body .facet-opt` 给勾留的)
       —— ✕ 是 absolute 的,不占流,不给右边距的话长值会钻到它底下。 */
    padding: var(--van-padding-sm) 32px var(--van-padding-sm) var(--van-padding-md);
    /* ✕ 是绝对定位的,以**整行**为参照 */
    position: relative;
    font-size: var(--van-font-size-md);
    /* 跟 .facet-opt 一致取 400,显式写出以防被当成漏写(2026-09-30 用户定) */
    font-weight: 400;
    line-height: var(--van-cell-line-height);
    color: var(--van-text-color);
    cursor: pointer;
    /* ⚠️ 同 .facet-opt:漏写 user-select:none 会让长按选中文字、弹出「复制/全选」——按钮不该变成选字 */
    user-select: none;
}
.filter-popup-body .cond-opt:active { background: var(--muted); }
.filter-popup-body .cond-opt--locked {
    color: var(--muted-fg);
    cursor: not-allowed;
    pointer-events: none;
}
.filter-popup-body .cond-opt__name {
    word-break: break-all;        /* 长名允许在词内换行(filters.md 6.8) */
}
.filter-popup-body .cond-opt__value {
    display: flex;
    align-items: center;
    gap: var(--van-padding-xs);
    /* 12 → 14(--fs-sm),跟名称同字号(2026-09-30 用户定) */
    font-size: var(--fs-sm);
    /* 这里原有一行 `font-weight: 400`,是为了压住 .cond-opt 的 600。
       .cond-opt 现在就是 400 了(2026-09-30),这行变得多余 —— 删掉,
       让它自然继承。要单独调再写。 */
    color: var(--muted-fg);
    word-break: break-all;
}
/* ✕ 清空 —— 对着**整条选项**(所以是 .cond-opt 的直接子元素,不在 __value 里);位置/居中照抄
   .facet-opt__check(absolute + top:50% + margin-top:-半图标高),颜色走 --muted-fg;改图标字号两处一起改。 */
.filter-popup-body .cond-opt__clear {
    position: absolute;
    top: 50%;
    right: var(--van-padding-md);
    margin-top: calc(var(--van-padding-xs) * -1);
    font-size: var(--van-tree-select-item-selected-size);
    color: var(--muted-fg);
    cursor: pointer;
}
.filter-popup-body .cond-opt__clear:hover { color: var(--fg); }

/* ══════════════════════════════════════════════════════════════════════════
 * cond 弹窗 —— van-dialog(2026-09-30 换)
 *
 * ① Vant 白送、别在这里重写的:
 *      页脚 48px 贴边 / 顶部分隔线 / 中间竖线
 *      底色 #131820、圆角 16px、遮罩 .7、top 45%
 *      —— 底色和「确定」色**自动**就是我们的值,因为文件顶部早就把
 *         --van-background-2 / --van-primary-color 接到了自己的 token
 *         (--van-dialog-background → var(--van-background-2) = --card
 *          --van-dialog-confirm-button-text-color → var(--van-primary-color))
 *
 * ② 必须覆盖的几条,理由逐条写在行末:
 * ══════════════════════════════════════════════════════════════════════════ */
.van-dialog {
    /* 宽度:85%(跟全站浮层一致)。Dialog 默认是**固定** 320px,没 max-width */
    --van-dialog-width: 85%;
    /* 标题:收回我们的尺度。Dialog 默认 16px / 600 / 上边距 26px ——
       那是给一段纯文字 message 排的排场,我们装的是 chip + 输入框 */
    --van-dialog-font-size: var(--van-font-size-md);
    --van-dialog-header-font-weight: 500;
    --van-dialog-header-padding-top: var(--van-padding-md);
    max-width: 360px;
}
/* ④ 标题:**左对齐**(2026-09-30 用户定,不跟 Dialog 的居中)。
 *    左右内边距必须自己补 —— Dialog 的 header 是通栏的,不给左右 padding,
 *    光改 text-align 会让标题贴在弹窗左边缘,跟下面的 chip 行错开 16px。
 *    下内边距 12px = **标题底 → 内容顶的间隔**
 *    (跟 .page-title 的下边距同一个 token,是全站"标题 → 内容"的既有值;
 *     Dialog 的 0 间距只对纯文字 message 成立,对 default slot 不成立)。 */
.van-dialog__header {
    text-align: left;
    padding-left: var(--van-padding-md);
    padding-right: var(--van-padding-md);
    padding-bottom: var(--van-padding-sm);      /* 12px */
}
/* ① Dialog 只清了页脚按钮的 border 和 border-radius,**没清 background**,
      于是吸到 .van-button 的 --van-button-default-background(金色 15% tint),
      页脚会变成一条黄带子 */
.van-dialog__cancel,
.van-dialog__confirm { background: transparent; }
/* ② Dialog 不给取消设色 → 它继承 --van-button-default-color = 我们的金,
      会跟「确定」同色、没有对比 */
.van-dialog__cancel { color: var(--fg); }
/* ③ Dialog 的 padding 只作用于纯文字 message(.van-dialog__message),
      我们走 default slot,拿不到 → 自己补左右边距(下边距由各块的
      margin-bottom 提供,别再叠一层) */
.van-dialog__content { padding: 0 var(--van-padding-md); }

/* chip 行 —— 可选项 ≤5(number / 小 choice) */
.cond-chip {
    display: flex;
    flex-wrap: wrap;
    gap: var(--van-padding-xs);
    margin-bottom: var(--van-padding-md);
}
/* chip 自己的长相**不在这里** —— 跟 AND / OR 共用同一套配方(参考站的「开关 chip」),
   规则在 `.more-filters-title .match-chip span` 那一段的**同一个选择器组**里。
   2026-09-30 用户定:两处必须一样,所以写成一个选择器列表,防止两边漂移。
   (那轮「压到 22px」的实验**已经回退了**,现在是参考站原版 34px —— 见上方 .more-filters-title 那段。) */

/* field 行 —— 第二项是输入框时(num 数字 / text 文本);比较符是第一项的 chip,这行只剩一个铺满的输入框 */
.cond-field {
    display: flex;
    align-items: center;
    /* 上下各 10px = **抄筛选面板里「名称」那一格**(van-field cell:10 + 24 + 10 = 44 高)。
       ⚠️ 输入框本身是"裸输入"(无边框/无底色/无内边距),不给上下留白的话整行只有
          24px —— 在弹窗里就是标题下面**一行裸字**,看不出能输入。2026-09-30 用户定。
       ⚠️ **左右不加** —— 弹窗内容区已经有 16px 左右内边距,再加会跟标题错开。 */
    padding: 10px 0;
    margin-bottom: var(--van-padding-md);
}
/* 输入框 —— 跟筛选面板里「名称」那个输入框**一样**(裸输入,高 24):
 * 无边框 / 无圆角 / 无内边距 / 透明底,14px / 24px / 400 / --fg。
 * ⚠️ 弹窗里没有左侧 label 提示,补了两样:① 行上下各 10px(见 .cond-field)
 *    ② 兜底占位符「请输入……」(见 components.js 的 condPlaceholder)。2026-09-30 用户定。 */
.cond-field input {
    flex: 1 1 0;
    min-width: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    color: var(--fg);
    font-size: var(--van-font-size-md);
    line-height: var(--van-cell-line-height);
    font-weight: 400;
    font-family: inherit;
    outline: none;
    text-align: left;
}
/* wowtool 把数字框设为 textAlign=center(str 只有 small 的才居中)
   照抄:is-center = num 或 (str 且 small) */
.cond-field input.is-center { text-align: center; }
/* ⚠️ 原来的 `:focus { border-color: var(--primary) }` 已删 —— 输入框没有边框了 */
.cond-field input::placeholder { color: var(--muted-fg); }

/* picker 占满行 */
.cond-picker {
    margin-bottom: var(--van-padding-md);
    /* 2026-09-30 用户定去掉 `padding: 8px 0`:① 加了它间距跟别的形态不齐(标题→控件 20 / 控件→footer 24);
       ② mask 最外圈最暗,这 8px 未压暗的底色紧挨着显亮带。选项字号同轮拉平到 14px(见下方变量)。 */
    --van-picker-option-font-size: var(--van-font-size-md);
}

/* 选中行(2026-09-30 用户定,方案 V2)—— 跟 chip 的 `.on` 同一套语言:
   金底 15% + 金字 500 + 上下各一条金线。
   ⚠️ Vant **默认完全不做选中样式** —— 选中项和未选中项的**文字色一模一样**
      (都是 --van-text-color),只靠 `.van-picker__mask` 在选中行留的那个"洞"
      (背景 alpha 0,周围 0.1~0.58)来暗示,用户原话是"特别看不清"。 */
.cond-picker .van-picker__frame {
    left: 0;                                /* Vant 默认左右各缩 16,铺满整宽更像"一行" */
    right: 0;
    border-top: 1px solid var(--primary);
    border-bottom: 1px solid var(--primary);
}
/* 淡底:跟 chip 的 .on 一样,只在浏览器支持 color-mix 时加
   (不支持就退回"金线 + 金字",不会比现在更难看) */
@supports (background: color-mix(in oklab, red 15%, transparent)) {
    .cond-picker .van-picker__frame {
        background: color-mix(in oklab, var(--primary) 15%, transparent);
    }
}
/* ⚠️ 选中项的**文字故意不加任何样式** —— 不要"补"成金色 / 加粗。
   (2026-09-30 用户定,方案 A)
   理由:Vant 的 `--selected` 类**只在滚轮停下之后**才提交一次,滑行途中完全不更新。
        实测:甩一下 → **1454ms 里没有任何一项是金色的** → 停住那一瞬才"啪"地跳一下,
        用户原话"变色过程很慢,体验不好"。
        (把 `swipe-duration` 从默认 1000 调小只能降到 ~600ms,地板就那儿了,治不干净。)
   而 `.van-picker__frame` 是**静态**的 —— 东西滑进框里就是选中,
   它天生跟着滚轮"实时"走。所以变色是**额外、且最慢**的一层提示,去掉就没延迟感了。
   → 选中的唯一提示 = 金框(15% 金底 + 上下 1px 金线,见上)。
   实际效果:选中项和未选中项的文字色**完全一样**(都是 --van-text-color),本来就是 Vant 的默认。 */

/* 弹窗底部两个按钮交给 van-dialog 的 show-cancel-button 渲染(分隔线 / 等分 / 中间竖线都是 Vant 的 hairline) */

/* ══════════════════════════════════════════════════════════════════════════
   物品 tooltip 弹窗(2026-10-03)
   ★ 全项目**唯一**一处"内容长相照搬 wowtool"的地方。

   tooltip 自己带完整长相:深蓝底 + 边框来自 web/tooltip.css 的
   `.wowhead-tooltip td { background:url(https://wowtool.tips/images/wow/tooltip.png) }`。
   所以**外壳要尽量空** —— popup 自己的底色 / 圆角 / 内边距全部去掉,
   只留一个 320px 宽的口子,让那块盒子自己画自己。

   为什么用 Popup 不用 Dialog:见 components.js 里那段模板注释。

   宽度 320 是**我们定的**,不是照抄来的 —— ⚠️ 别写成"wowtool 的固定宽",**wowtool 的宽
   是它 JS 量出来的**(`ref/wowtool/js/wh-tooltips.js` 的 `ne()`:取两张内容表**自然宽**
   的最大值 +20,再按上限 clamp),所以**每件物品宽窄不同、大多小于 320**。
   我们固定 320 是**有意偏离**:列宽稳定,点开时盒子不跳。
   窄屏用 max-width 兜一下 —— 里面的表格都是百分比宽,会自己换行。
   ══════════════════════════════════════════════════════════════════════════ */
.tip-popup {
    background: transparent;
    border-radius: 0;
    padding: 0;
    overflow: visible;
}
/* 一块 tooltip + **它自己的**按钮(2026-10-27)。
   · 组内(tooltip ↔ 它自己的按钮)= **16px** —— 跟全站「tooltip → 更多信息」同一个数
     (用户 2026-10-27 定:**这个间距全站相同**)。
   · 组间(弹窗里多块之间)= 外层 `.tip-popup-box` 的 16px。
     **只有地图那种"带按钮的组"**再加 8 ⇒ 24,为的是看得出 tooltip 和按钮是配对的
     (`.tip-group--paired`)。法术两块 / 详情页两块仍然是 16(用户同日定:2、12 都是 16)。 */
.tip-group {
    display: flex;
    flex-direction: column;
    gap: var(--van-padding-md);
}
.tip-group--paired + .tip-group--paired {
    margin-top: var(--sp-2);
}
.tip-popup-box {
    display: flex;
    flex-direction: column;
    gap: var(--van-padding-md);
    width: 320px;
    max-width: calc(100vw - 40px);
    /* ★ 2026-10-27 **可滚动** —— 触发场景:任务「相关地点」的标记合并了多个对象,
       一个弹窗里要摞好几块 tooltip(用户定:「支持滚动就ok」)。
       单块 tooltip 一般 300px 上下,加这两行不改变它的长相;
       真超出屏幕时改成**框内滚动**,而不是顶出可视区点不到关闭。
       `dvh` 是给手机地址栏伸缩用的;不支持的浏览器退回上面的 `vh`。 */
    max-height: calc(100vh - 40px);
    max-height: calc(100dvh - 40px);
    overflow-y: auto;
    overscroll-behavior: contain;
}
/* 加载中 / 出错 —— 这两种情况**没有** tooltip 那块底,得自己有一块,
   否则文字直接浮在列表上面看不清 */
.tip-popup-hint {
    margin: 0;
    padding: var(--van-padding-lg) var(--van-padding-md);
    border-radius: var(--radius-md);
    background: var(--bg);
    /* 字号 / 颜色:跟列表页 .loading 里的 van-loading 共用 Vant 变量。
       行高**不写** —— 列表页 loading 的行高也是继承来的(无声明 → 24px,
       跟 body 的 --lh-base 同值),tooltip 不写就是 24px,一致。
       ⚠️ 真名是 `--van-loading-text-font-size`(vendor 出现 2 次);没
       `--van-loading-font-size` / `--van-loading-line-height` 这两个 —— grep 过。
       颜色用 Vant 变量而不是项目 --fg / --muted-fg 是为了**永远对齐列表页**
       —— Vant 升级或主题切换时一起动,不会被各写一份的硬编码拉开。 */
    font-size: var(--van-loading-text-font-size);
    color: var(--van-loading-text-color);
    text-align: center;
}
/* 失败那档(「没有查询到数据」)—— 行高跟列表页
   `.van-empty__description` 对齐(20px),而不是 loading 那档的 24px。
   列表页两档本来就不同:van-loading 的文字 24px(继承)、van-empty 的 20px
   (Vant 显式给的)。实测两处都是 20px / 14px / #929caa。
   ⚠️ 字号 / 颜色不用重写 —— 上面的 .tip-popup-hint 已经跟这两处同源。 */
.tip-popup-hint--empty {
    line-height: var(--van-empty-description-line-height);
}

.tbl .season-tag { color: var(--muted-fg); }

/* ==========================================================================
   详情页(2026-10-04 物品 / 2026-10-05 泛化到所有实体)
   设计见 docs/item-page.md 第九节、docs/spell-page.md

   结构:顶栏(标题 = 实体名)→ tab 条(固定)→ 内容区(唯一滚动的地方)

   ★ **任何时刻只有一层滚动条**:
       · 基础信息 → .detail-tip-box 自己纵向滚
       · 相关区块 → .tbl-wrap 横 + 纵都在这层(表头吸顶 / 首列吸左,跟列表页同一套)
     内容区(van-tabs__content)自己**不滚**(overflow:hidden)—— 否则会跟上面两层
     叠成"套两层滚动条",手机上手指很容易滚错那一层。
   ========================================================================== */
.detail-tabs {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.detail-tabs .van-tabs__wrap { flex: none; }
.detail-tabs .van-tabs__content { flex: 1; min-height: 0; overflow: hidden; }
.detail-tabs .van-tab__panel { height: 100%; display: flex; flex-direction: column; }

/* 基础信息 —— 物品信息那块。跟列表页弹窗是**同一个盒子**(JS 里的 TipBox),
   只是宽度不固定 320(这里交给容器)。 */
.detail-tabs .detail-tip-box {
    flex: 1;
    min-height: 0;
    overflow: auto;
    padding: var(--sp-3) var(--sp-4);
    -webkit-overflow-scrolling: touch;
}

/* 「基础信息」里由**页面静态 HTML** 拼出来的内容(2026-10-18 宠物 / 2026-10-19 种族)——
   它不是 wowhead tooltip 结构,而是页面 `.text` 里的 h1(+ 宠物还有一句描述)。
   塞进 TipBox 后按 tooltip 正文的字号排;名称行比正文重一档。
   种族页只有名字;宠物页有名字 + 描述。
   ⚠️ 2026-10-19 用户定:**不要「小知识」块**。 */
.detail-tip-box .detail-about-name {
    margin: 0 0 var(--sp-1);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 600;
}
.detail-tip-box .detail-about-desc { line-height: 1.6; }
/* ⚠️ **宽度必须跟列表页弹窗一致(320)** —— 2026-10-04 用户定。
   起因:TipBox 只复用「边框怎么闭合」(框架表 + 三个角格子),**宽度不在组件里**,
   而在外面那层容器上 —— 弹窗是 .tip-popup-box(width:320),这里原来是"撑满容器"
   → 390 屏下 358px,**同一件物品在弹窗和详情页里宽窄不一样**,一眼看得出来。
   (原版那块是它 JS **按内容量**出来的:风剑 320、柳木腰带 116 —— 我们固定 320 是
   跟弹窗同一套的有意偏离,见 .tip-popup-box 那条注释。)
   ⚠️ 别改成 width:100% —— 那就退回 358 了。 */
/* **固定 320,居中**(2026-10-04 用户定)。
   · 宽度**写死 320** —— 跟列表页弹窗一致(.tip-popup-box 也是 320)。
   · **居中交给浏览器**:左右 margin 写 `auto`,它按**当前容器宽**算剩余空间再平分。
     ⚠️ 这里**没有任何跟屏幕宽有关的数** —— 390 屏是 (390-32-320)/2 = 19px,
        360 屏是 4px,600 屏是 124px,全是它自己算的,换屏不用改代码。
     (别理解成"给 390 留 19px" —— 那正是硬编码,换个宽度就错。)
   · `max-width:100%` 兜底:屏幕比 320+padding 还窄时(小屏横竖切换、
     分屏)收到容器宽,不横向溢出;那时左右各 0,也就是"撑满"。
   ⚠️ 试过 `fit-content`(跟着内容宽)—— 那是**原版**的行为(柳木腰带 116),
      但**不是我们要的**,别改回去。 */
.detail-tabs .detail-tip-box .wowhead-tooltip {
    width: 320px;
    max-width: 100%;
    margin-left: auto;
    margin-right: auto;
}
/* ★ **两块之间的间距**(2026-10-05 加法术时发现的缺口)。
   以前详情页的「基础信息」**恒为一块**(物品只有 tooltip),所以没有这条也看不出来。
   法术是**两块**(法术信息 + 魔法增益),不加就是两块贴在一起 —— 边框叠边框。
   举值跟列表页 tooltip 弹窗**同一档**(`.tip-popup-box` 的 gap 就是 var(--van-padding-md))
   —— 同一件东西在两处的样子必须一致(2026-10-04 用户定过同一条,那次是宽度 320)。 */
.detail-tabs .detail-tip-box .wowhead-tooltip + .wowhead-tooltip {
    margin-top: var(--van-padding-md);
}

/* 相关区块 —— 一张表。横滚 + 纵滚都在 .tbl-wrap 这一层 */
.detail-tabs .tbl-wrap { flex: 1; min-height: 0; }

/* ---- tab 条的长相 ----
   抄参考站的「开关 chip」那一排(出处:参考站「攻略指南」页,选中态在「亡灵骑士」上)。
   本项目的同款配方:.match-chip / .cond-chip(2026-09-30 抄的)。

   ⚠️ Vant 默认是"底部一条下划线"—— **参考站是整块变色,所以那条线必须干掉**:
      · .van-tabs__line 隐藏
      · .van-tabs__nav--line 的 padding-bottom:15px(给下划线留的位置)要归零
      · .van-tabs--line .van-tabs__wrap 的固定高度 44px 要放开(我们的 chip 更高) */
.detail-tabs.van-tabs--line .van-tabs__wrap { height: auto; }
.detail-tabs .van-tabs__nav {
    background: transparent;
}
.detail-tabs .van-tabs__nav--line {
    box-sizing: border-box;
    padding: var(--sp-2) var(--sp-3);
    gap: var(--sp-2);
}
.detail-tabs .van-tabs__nav--line.van-tabs__nav--shrink,
.detail-tabs .van-tabs__nav--line.van-tabs__nav--complete {
    padding-left: var(--sp-3);
    padding-right: var(--sp-3);
}
.detail-tabs .van-tabs__nav--complete {    /* 标签多到放不下 → 横滑那档 */
    -webkit-overflow-scrolling: touch;
}
.detail-tabs .van-tabs__line { display: none; }

.detail-tabs .van-tab {
    flex: none;                       /* 宽度跟着内容走(shrink),不强行等分 ——
                                         等分会把「掉落于（200）」这类长标签省略掉 */
    padding: 6px 12px;                /* 参考站的 px-3 py-1.5 */
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    color: var(--muted-fg);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    white-space: nowrap;
}
.detail-tabs .van-tab--active {
    color: var(--primary);
    border-color: var(--primary);
    background: color-mix(in oklab, var(--primary) 15%, transparent);
    font-weight: 500;
}
/* 还不让点的那些(非 item 模板的区块 —— 列要等对应的列表页做完再复用)
   ⚠️ **不能靠 Vant 原生的禁用色**:那是 `.van-tab--disabled{color:var(--van-tab-disabled-text-color)}`,
      而 `--van-tab-disabled-text-color` → `--van-text-color-3` → **我们映射的 `--muted-fg`**,
      **正好等于未选中 chip 的字色** → 走下来禁用和正常**长得一样**,看不出来。
      改用参考站自己的写法:`disabled:opacity-50`(它的 tab 就是这么标的)。 */
.detail-tabs .van-tab--disabled {
    opacity: .5;
    cursor: not-allowed;
}

/* ---- ★ 行内**可点**图标(2026-10-07 坐骑页的材料列 —— 全项目第一条"行内可点")----
   一格摆若干个小图标,**每个单独可点**(点它弹那个东西的 tooltip,不是这一行的)。
   契约 = class `.cell-ico` + 元素自己的 `data-id` / `data-href`,点击委托按它认
   (core.js 的 document click 监听)。加新的行内可点内容照这个形状写,通用代码不用改。
   尺寸 = **跟行图标一样 28px**(跟 .c-icon img 同尺寸,取自 --w-icon 里的 28)。
   ⚠️ 比行内小图标(1em)大是有意的:这列**要能点**,太小的图标点不准。
   (物品详情页的「兑换」列 2026-10-18 起也走这里 —— 原来它那种 1em 小图标已删。) */
/* 图标怎么排 —— 小史:
   · 2026-10-10:图标之间靠 `margin-right + margin-bottom` 排(当时一条记录只有一个图标)。
   · **2026-10-18:加物品名了** ⇒ 一条记录变成「图标 + 名字」,用户要求**每条单独一行**
     ⇒ `.cell-ico` 改成 `display:flex`(整条是 flex 容器),条目之间靠 `margin-bottom` 分行,
     图标和名字之间用 `gap`。
   ⚠️ 仍然**不能**给 `.c-reagents` 那个 **td** 上加 `display:flex` ——
      td 的 display 一改就不再是 table-cell,表格布局会塌。flex 只能下放到条目这一层。 */
.tbl .cell-ico,
.db .cell-ico {
    display: flex;                     /* ★ 2026-10-18:每条(图标+名字)独占一行 */
    align-items: center;
    gap: var(--sp-1);
    cursor: pointer;
    margin: 0 0 var(--sp-1) 0;
}

/* 任务「奖励」列(2026-10-25)—— 图标**横排**,不沿用材料列那种「每条一行」。
   原版奖励格就是一排 `iconsmall`(inline-block);材料列"每条换行"是 2026-10-18 对**材料**的决定,
   两件事别混。⚠️ 只把**条目**从 flex 改成 inline-flex —— td 的 display 仍然不动
   (td 一改就不是 table-cell,表格布局会塌,见下面那条警告)。 */
.tbl .c-qrew .cell-ico {
    display: flex;              /* 一行一个(2026-10-25 用户定) */
    margin: 0 0 var(--sp-1) 0;
}

/* 「多选一」的分组框(2026-10-25 用户定:用**视觉分组**,不抄原版那句长文字)。
   框内 = 这几件里选一件;框外 = 必得。标签固定两个字,不占一整行。 */
/* 货币在**奖励**列的最后一行(2026-10-25 用户定),一行一个。
   ★ 2026-10-26:同一个元件也用在**任务正文的「奖励」段**(`.db`),
     所以选择器扩到两处 —— 别在 .db 里再抄一份(那就是重复样式)。 */
.tbl .c-qrew .rew-cur,
.db .rew-cur { display: block; margin-top: 2px; }

.tbl .c-qrew .rew-choice,
.db .rew-choice {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: var(--sp-1);
    padding: var(--sp-1) var(--sp-2);
    border: 1px dashed var(--border);
    border-radius: var(--radius-sm);
}
.tbl .c-qrew .rew-choice-tag,
.db .rew-choice-tag {
    display: block;              /* 在框外、方框上面(2026-10-25 用户定) */
    color: var(--muted-fg);
    font-size: var(--fs-xs);
    line-height: 1.2;
    margin-top: var(--sp-1);
}

/* 图标 + 角标的定位盒(2026-10-18 从 cell-ico 拆出来)——
   角标要压在**图标**右下角,不能压到名字那头(cell-ico 现在是整行的 flex 容器)。 */
/* 图标 + 角标的定位壳 —— **材料列和行图标列共用**(2026-10-18 扩到行图标)。
   · 材料列(`.cell-ico` 里):flex 容器里的一个条目,`flex:none` 防止被长名字挤压;
   · 行图标列(`.c-icon` 里):td 的直接子元素 → 指定 `display:block`,否则 inline 壳
     会把 28px 图标挂在一条 0 高的行盒上,垂直位置会偏。 */
.tbl .ico-thumb,
.db .ico-thumb {
    position: relative;
    line-height: 0;
    flex: none;                        /* 图标不许被长名字挤压 */
}
.tbl .c-icon > .ico-thumb { display: block; }

/* 物品名 `.ico-name`(2026-10-18 用户定)—— **故意不写任何 CSS 规则**:
   不设字号 / 行高 / 颜色,让它们跟普通列完全一致(字号继承 td 的 14px,
   颜色由品质类 `.q<quality>` 给;没有品质时 q-1 无规则 ⇒ 继承正文色)。
   ⚠️ **别加** `.ico-name { color: inherit }` 之类的规则 —— 选择器优先级会盖掉 `.q3` 品质色。 */

/* 材料图标上的**数量角标**(2026-10-10 加 —— **通用规则**,坐骑页 / 专业页共用同一个 kind)。
   只有数量 > 1 才渲染(core.js 的行函数给 count=null);照 wowtool:它也是 >1 才出角标。
   实测这个不能省 —— 7984 个材料项里 5941 个数量 > 1。
   形状照 wowhead 惯例:压在图标**右下角**、小字 + 黑色描边(压在亮色图标上也读得出)。 */
.tbl .ico-cnt,
.db .ico-cnt {
    position: absolute;
    right: -2px;
    bottom: -2px;
    line-height: 1;
    font-size: 10px;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 0 2px #000, 0 0 2px #000, 0 0 2px #000;
    pointer-events: none;              /* ★ 别挡住图标的点击 —— 它自己不可点 */
}

/* 图标**左上角**的库存量 (N)(2026-10-24,只在 NPC「出售」tab 出现)。
   照 wowtool 的 `.wh-icon-text[data-type=quantity]`:金色、圆括号、左上角
   —— 跟右下角那个白色数量角标(`.ico-cnt`)**两种东西**,别合并。 */
.tbl .ico-qty {
    position: absolute;
    left: 0;
    top: 0;
    line-height: 1;
    font-size: var(--fs-xs);          /* 12px —— wowtool 图标中号是 13px,站内取最近的档 */
    font-weight: 700;
    color: var(--icon-qty);
    text-shadow: 0 0 2px #000, 0 0 2px #000;   /* 压在亮色图标上也读得出 */
    pointer-events: none;
}

/* ---- 金币价格(kind:"icons" 里的金币条目,2026-10-24)----
   出现在 NPC 详情页「出售」tab(和物品页「兑换」)的「价格」列:商人用金币标价时,
   那一格是「数字 + 币种小图」,没有物品名、也不可点。
   小图直接复用 `web/img/icons/money-*.gif`(tooltip.css 里给金团块用的就是这三张)——
   ⚠️ **不能直接套 `.moneygold`**:那套是给深色 tooltip 写的(`color:#fff`),
      放到浅色表格里数字会看不见 ⇒ 这里只借图,颜色继承正文。 */
.tbl .coin,
.db .coin {
    display: inline-block;
    padding-right: var(--sp-4);        /* 给右边的小图留位(小图 15px,留 16) */
    background: no-repeat right center;
    font-variant-numeric: tabular-nums;
}
.tbl .coin + .coin,
.db .coin + .coin { margin-left: var(--sp-1); }
/* ⚠️ 这三张图走 **wowtool 的绝对 URL**(硬规则 2),本地不再留副本。
   2026-11-02 用户定 `web/img/` 整个删除 —— 浏览器按 URL 去重 + 缓存共享,
   同一张图跨页面只下一次,本地化省不到带宽。跟 tooltip.css 里那几条同源同处理。 */
.tbl .coin-gold,
.db .coin-gold { background-image: url("https://wowtool.tips/images/icons/money-gold.gif"); }
.tbl .coin-silver,
.db .coin-silver { background-image: url("https://wowtool.tips/images/icons/money-silver.gif"); }
.tbl .coin-copper,
.db .coin-copper { background-image: url("https://wowtool.tips/images/icons/money-copper.gif"); }

/* ---- 「需要技能」那一格(kind:"skillreq",2026-10-10)—— 专业页 + 物品页两个配方区块 ----
   两行:第一行「炼金术 (50)」,第二行「285 305 315 325」(每个数字带 .r1~.r4 色)。
   形状照 wowtool 的 id:"skill" 列:两行都是 small,第二行加粗。
   ⚠️ **字号是表格默认的 14px**(2026-10-10 用户定)—— 这里原来写的是 `--fs-xs`(12px),
      是照抄 wowtool 的 `.small`;但它成了**全表唯一一列不是 14px 的**,跟来源列
      (同为两行,`.sr-main`/`.sr-sub` 都是 14px)对不上。**表里所有字都是 14px**。
      连带后果:列宽得跟着 `--w-recipe-skill` 一起放大(12px 的 124px 装不下 14px 的内容)。 */
.tbl .c-skill .sk-no { font-weight: 700; }        /* 第一行的 learnedat 数字(加粗) */
.tbl .c-skill .sk-lv {
    margin-top: 2px;                              /* 跟名称列「相邻两组之间」同一个 2px */
    font-weight: 700;
}
/* 数字之间留一个"空格"的距离 —— 用**相邻兄弟**选择器:第一个前面不加
   (照 wowtool 的写法:只有已经输出过至少一个才补空格)。
   被 v-if 挡掉的 0 不渲染,所以相邻的就是真正看得见的那几个。 */
.tbl .c-skill .sk-lv span + span { margin-left: 4px; }
/* 图标方框的尺寸/边/圆角/底色 —— 统一在上面的 `.c-icon img, .cell-ico img, .icon-ph` 那条,
   这里不再重复(2026-10-07 合并)。 */

/* 导航首页(2026-10-04):四个板块平铺 —— 每个板块一个标题 + 一组 van-cell-group。
   板块标题和板块间距 van-cell 不管,这里补。**组本身不用管**(inset 自带圆角/边距)。 */
.nav-board + .nav-board { margin-top: var(--sp-4); }
.nav-board-title {
    /* 左边对齐 van-cell-group inset 的内容区(它的内边距就是 --van-padding-md)。
       字号/字重照参考站的板块标题。 */
    padding: var(--sp-2) calc(var(--sp-3) + var(--van-padding-md)) var(--sp-1);
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--muted-fg);
}
/* 不可点的那 19 项:模板给的是 is-link=false → **不画右箭头**,这就是标记。
   (Vant 的 cell 没有 disabled prop,所以没有"灰化"这一说 —— 别去找那个类。)*/

/* ==========================================================================
   任务详情页「任务」tab 的正文(2026-10-26)
   --------------------------------------------------------------------------
   数据由 `entities/quest.js` 的 `parseQuestBody` 解析,组件是 `QuestBody` / `QuestMap`。
   用户 2026-10-26 定:**自己用数据渲染,不搬原版 HTML**(原版是 PC 排版)。
   四块:目标块 / 奖励 / 收获 / 系列 + 相关地点地图。
   ========================================================================== */

/* 内容区滚动 —— 跟 .detail-tip-box 同一套(内容区自己不滚,这一层滚) */
.db-wrap {
    flex: 1;
    min-height: 0;
    overflow: auto;
    padding: var(--sp-3) var(--sp-4) var(--sp-6);
    -webkit-overflow-scrolling: touch;
}

.db { display: flex; flex-direction: column; gap: var(--sp-2); }
.db-say { margin: 0; color: var(--muted-fg); font-size: var(--fs-sm); line-height: 1.75; }
.db-h { margin: var(--sp-5) 0 var(--sp-1); font-size: var(--fs-base); font-weight: 600; }
/* 第一个段名贴着顶(否则 tab 条下面会多出 20px 空) */
.db > .db-h:first-child { margin-top: 0; }

/* 固定表(2026-10-28,阵营「基础信息」的声望 8 档)——
   ★ **故意不用 `.tbl`**:那是列表样式(行可点 / 弹性列 / 吸顶表头 / 横向滚动),
     长得一样会让用户以为这些行能点。这是**只读表**,4 列定宽、不滚动、不吸顶。
   ★ 数字列右对齐(原版 `.grid` 也是 text-align:right),「名称」列左对齐。
   ★ 颜色/字号全走设计 token,别写死。 */
.db-table {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--font-sans);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: var(--fg);
    font-feature-settings: "lnum";
}
.db-table th {
    color: var(--muted-fg);
    font-weight: 400;
    text-align: left;
    padding: var(--sp-1) var(--sp-2);
    border-bottom: 1px solid var(--border);
}
.db-table td { padding: var(--sp-1) var(--sp-2); border-bottom: 1px solid var(--border); }
/* 「名称」是第 2 列,左对齐;其余三列(级别 / 最低 / 数量)右对齐 */
.db-table th:not(:nth-child(2)),
.db-table td:not(:nth-child(2)) { text-align: right; }
.db-table tr:last-child td { border-bottom: 0; }

/* 目标块 / 奖励 —— 一行一个:图标 + 名字(可点)+ 数量 */
.db-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.db-list li { display: flex; align-items: center; gap: var(--sp-2); }
.db-name { font-size: var(--fs-sm); }
.db-qty { font-style: normal; color: var(--muted-fg); font-size: var(--fs-xs); }

/* 奖励段里的「物品那一坨」—— 必得 / 选一框 / 货币,竖着排。
   ⚠️ **选一框和货币的规则不在这一节** —— 它们跟列表页「奖励」列共用,
      选择器在上面 `.rew-choice` / `.rew-cur` 那几条里(2026-10-26 扩到 .db)。 */
.db-rew { display: flex; flex-direction: column; gap: var(--sp-2); }

/* 经验 / 声望 / 奖金 —— 一行一个,左边小字标签,右边值。
   用 <dl> 而不是表格:两列对齐靠 grid,不用管宽度。 */
.db-stats {
    margin: 0;
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: baseline;
    gap: var(--sp-1) var(--sp-3);
    font-size: var(--fs-sm);
}
.db-rew + .db-stats { margin-top: var(--sp-3); }
.db-stats dt { color: var(--muted-fg); }
.db-stats dd { margin: 0; }

/* 奖金:一排「数字 + 币种小图」 */
.db-money { display: flex; gap: var(--sp-2); }
/* 系列 —— 编号**显式画出来**(原版的「1.」「2.」)。不用 <ol> 自动编号:
   全局 reset 把列表符号去掉了,而且原版的编号是**右对齐 + 点号**的一列。 */
.db-series { margin: 0; padding: 0; list-style: none; font-size: var(--fs-sm); line-height: 1.9; }
.db-series li { display: flex; gap: var(--sp-1); }
/* 序号 —— 跟原版 `.series th` 对齐:字号跟正文一致、**右对齐**、
   序号到文字的**视觉间距 ≈ 10px**(原版是 `padding-right: 10px`)。
   ⚠️ `min-width` 是给**两位数**留位的(1.3em ≈ 18px,「10.」约 17px 放得下);
       别调大到 1.5em —— 那会让单数位行多出 7px,看着像隔了一条缝(2026-10-27 用户反馈)。 */
.db-no {
    color: var(--muted-fg);
    font-variant-numeric: tabular-nums;
    text-align: right;
    min-width: 1.3em;
}
/* 一环里可能有多个任务(联盟版 / 部落版 / 多个 id)—— 竖着排,编号只出现一次 */
.db-series-items { display: flex; flex-direction: column; gap: var(--sp-1); }
.db-series-item { display: flex; align-items: center; gap: var(--sp-1); flex-wrap: wrap; }
/* 当前项 —— **主题色**,不加粗(2026-10-27 用户定:加粗效果不好)。
   ⚠️ 别改回 `<b>`:系列的链接本来就跟正文同色,靠"当前项是唯一带色的"来区分。 */
.db-cur { color: var(--primary); }

/* ---- 相关地点 ----------------------------------------------------------
   整块照原版:一句话(地区名可点切图)+ 地图 + 标记。
   ⚠️ 标记的长相在 `web/map.css`(生成器从原版 CSS 抽的),别写在这里。 */
.qmap-box { display: flex; flex-direction: column; gap: var(--sp-2); }
.db-map-say { margin: 0; font-size: var(--fs-sm); line-height: 1.9; color: var(--muted-fg); }
/* 地区名 —— 跟系列同一条规矩:**只有当前地图**用主题色(2026-10-27 用户定)。
   非当前的用正文色:比周围那圈 muted 的文字亮一档,一眼看得出"这些能点";
   主题色留给当前那张图。 */
.db-zone { color: var(--fg); cursor: pointer; }
/* ⚠️ 必须写成 `.db-zone.db-cur`(特异性 0,2,0)——
   光靠通用的 `.db-cur` 会被上面那条 `.db-zone` 盖掉(特异性相同、且它写在后面)。 */
.db-zone.db-cur { color: var(--primary); }
/* 地区名后面的坐标点数(道具页,2026-10-28)——
   **全角「（」自带左留白**,直接跟在名字后面会看起来空了一截(用户当天:
   「名称后面有数字,但是他们中间的间隔好像有点大」)。往左收回 0.3em,视觉上贴着名字。
   ⚠️ 别改成半角括号:原版是全角,收回留白只是补字形的内边距,字符不变。 */
.db-zone-n { margin-left: -0.3em; }
/* 地区名前面的小标记:! / ? / !?(原版是 tiny 的 gif,这里同源) */
.db-zone[data-mark="start"],
.db-zone[data-mark="end"],
.db-zone[data-mark="startend"] {
    padding-left: 16px;
    background-repeat: no-repeat;
    background-position: 0 50%;
    background-size: 11px 11px;
}
.db-zone[data-mark="start"]    { background-image: url("https://wowtool.tips/images/wow/icons/tiny/quest_start.gif"); }
.db-zone[data-mark="end"]      { background-image: url("https://wowtool.tips/images/wow/icons/tiny/quest_end.gif"); }
.db-zone[data-mark="startend"] { background-image: url("https://wowtool.tips/images/wow/icons/tiny/quest_startend.gif"); }

/* 标记的点击区(2026-10-27)—— 原版那个 `<a>` 只有 11×11(鼠标够用,**手指不够**)。
   用**透明伪元素**把可点面积撑到 23×23:伪元素不画任何东西,
   所以图标的尺寸 / 位置 / 层级一点没变(别改成放大 `a` 本身 —— 那会把图标也放大)。 */
.qmap .pin a { cursor: pointer; }
.qmap .pin a::after { content: ""; position: absolute; inset: -6px; }

/* 地图本体 —— **只用 normal 一档**(488×325);宽 = 屏宽 − 16、上限 488、大屏不放大。
   `.qmap-bleed` 负责"比正文多出 8px"(正文左右各有 16px 内边距)。 */
/* 让地图比正文宽出 8px(正文左右各有 16px 内边距)⇒ 屏宽 − 16,用户 2026-10-26 定 */
.qmap-bleed { margin-inline: calc(var(--sp-2) * -1); }
.qmap {
    position: relative;
    width: 100%;
    max-width: 488px;
    margin: 0 auto;
    line-height: 0;
    border-radius: 6px;
    overflow: hidden;
}
.qmap img { width: 100%; height: auto; display: block; }
