/* ══════════════════════════════════════════════════════════════
 * ui-kit.css —— 控件与排版组件（2026-10-17 外部评审驱动）
 * ══════════════════════════════════════════════════════════════
 * 【为什么从 base.css 拆出来】
 *   base.css 的职责是**底座**：令牌、reset、排版、布局骨架。
 *   这一块是**组件**：输入框 / 按钮 / 说明段 / callout / 字体与字号档位 /
 *   窄卡 / 芯片 / 折叠说明 —— 它是「某个页面长什么样」，不是「全站长什么样」。
 *   混在一起的结果是 base.css 一路涨到 700 行（屎山考核的上限就是 700），
 *   而它本来该是最稳定的那份文件。
 *
 * ⚠ 所有页面都必须**在 base.css 之后**引本文件，顺序不能反 ——
 *   这里用了令牌，也故意覆盖 base.css 里少量的默认值。
 * ⚠ 版本串 ?v= 由 tools/bump-version.py 统一改，别手写。
 */

/* ══════════════════════════════════════════════════════════════
 * 控件与排版规整（2026-10-17 外部评审驱动）
 * ══════════════════════════════════════════════════════════════
 * 【为什么整块追加在最后】
 *   评审给的十六进制是**浅色主题**实测值（#8F877B / #9A6208）。
 *   本文件是**双主题**的（暗色 --bg:#0e0d0b，浅色 #f6f3ee），
 *   直接写死会把暗色主题一起弄坏。所以这里全部映射到**主题令牌**，
 *   两套主题自动各自取到对应的色值。
 *
 * 【修的是什么】
 *   本文件此前**一条 input / button 规则都没有** —— 谱师/玩家页的输入框和按钮
 *   全是浏览器默认（边框 #767676、按钮 #EFEFEF），输入框约 20px、按钮约 39px，
 *   不等高、没间距，placeholder 还被截断。这是全站最扎眼的不一致。
 */

:root {
  /* 字阶收口：12–16px 之间原本有五六档，收成 5 级 */
  --fs-1: 14px;   /* 正文 / 说明 */
  --fs-2: 16px;   /* 小标题 */
  --fs-3: 20px;   /* 节标题 */
  --fs-4: 28px;   /* 页标题 */
  --fs-5: 40px;   /* hero */
}

/* ── 表单控件：与按钮同高、同圆角、有明确聚焦态 ── */
input[type="text"],
input[type="search"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="url"],
select,
textarea {
  box-sizing: border-box;
  min-height: 40px;
  padding: 0 12px;
  border: 1px solid var(--line2);
  border-radius: 10px;
  background: var(--card3);
  color: var(--fg);
  font: inherit;
  font-size: var(--fs-1);
  line-height: 38px;         /* 40 - 2×1px 边框，让单行文字垂直居中 */
  width: min(560px, 100%);
  /* ⚠ 不要给 transition all —— 聚焦时整块重绘会有 1px 抖动 */
  transition: border-color .15s, box-shadow .15s;
}
textarea { line-height: 1.7; padding: 10px 12px; min-height: 88px; }
input::placeholder, textarea::placeholder { color: var(--fg4); }

/* 聚焦：2px 描边（评审要求）。用 box-shadow 而不是 outline，
   这样圆角能跟着走、又不会把布局挤动 1px。 */
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 2px var(--brand-line);
}

/* ── 按钮：同一套尺寸，与输入框等高 ── */
button,
.btn {
  box-sizing: border-box;
  min-height: 40px;
  padding: 0 18px;
  border: 1px solid var(--line2);
  border-radius: 10px;
  background: var(--card2);
  color: var(--fg);
  font: inherit;
  font-size: var(--fs-1);
  line-height: 38px;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
button:hover, .btn:hover { background: var(--card3); border-color: var(--brand-line); }
button:disabled { opacity: .5; cursor: not-allowed; }

/* 主操作：实心琥珀 + 深色字（--brand-ink 是为对比度专门定的令牌）。
   ⚠ 评审写的是「白字」，但本站 --brand 是暖亮琥珀，白字对比度不够；
     用 --brand-ink（深暖褐）才是达标的写法。
   ⚠⚠ 选择器必须包含 `.btn.primary` —— 站内两个主操作（首页「开始算定数」、
     下载页「下载 Windows 版」）写的是 `class="btn primary"`（两个类、中间空格），
     不是 `.btn-primary`。第一版只写了 `.btn-primary` 和 `button.primary`，
     于是这两个**最关键的行动点**完全没吃到样式，还是文字链的样子。 */
.btn-primary,
.btn.primary,
button.primary {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-ink);
  font-weight: 600;
}
.btn-primary:hover,
.btn.primary:hover,
button.primary:hover {
  background: var(--brand-hover);
  border-color: var(--brand-hover);
  color: var(--brand-ink);
}

/* ── 说明段：统一口径 ──
   评审指出：卡片外的说明是 15px 近黑，比卡片内的 13–14px 灰更大更黑，
   还紧贴卡片、宽度只有卡片一半。统一成和卡片正文同一档。 */
.note {
  font-size: var(--fs-1);
  color: var(--fg2);
  line-height: 1.7;
  max-width: 72ch;
  margin: 10px 0 0;
}
.note.mono-inline { font-family: var(--font-mono); }

/* ── 警告 callout ──
   评审：最该被看到的「样本量还小，仅供参考」反而最不起眼。
   改成带左侧竖线的块，视觉权重明确高于普通说明。 */
.callout {
  font-size: var(--fs-1);
  line-height: 1.7;
  color: var(--fg);
  background: var(--brand-soft);
  border-left: 3px solid var(--brand);
  border-radius: 0 8px 8px 0;
  padding: 10px 14px;
  margin: 12px 0;
}
.callout b { color: var(--fg); }

/* 等宽样式只给英文（.exe / 路径 / 字段名）——
   中文套等宽会回退成小号宋体，和周围黑体不一致。 */
.mono-en { font-family: var(--font-mono); font-size: .95em; }

/* ── 字体 / 字号切换（评审 H）──
   ⚠ 只覆盖变量、不改任何具体选择器 —— 全站所有用到 --font-display 的地方
     自动跟着变，不用挨个改。这就是当初把字体抽成令牌的用处。
   ⚠ 字号用 html 的 font-size 百分比来缩放，配合各处的 rem/em 生效；
     写死 px 的地方（少数）不跟随 —— 那些是刻意固定的（比如表格数字）。 */
:root[data-font="sans"] {
  --font-display: var(--font-body);
}
/* 霞鹜文楷：只给标题与数字用。
   ⚠ 文楷只有 Regular 一个字重，而标题的 CSS 写着 font-weight:600 ——
     不关掉合成加粗的话，浏览器会拿 Regular **算法伪造**一遍粗体，
     笔画会糊成一片，楷书那点笔锋全没了。所以这一档显式禁止合成。
   ⚠ 63KB 的子集，按需下载 —— font-display:swap，不选这一档就一辈子不请求。 */
:root[data-font="kai"] {
  --font-display: var(--font-kai);
}
:root[data-font="kai"] h1,
:root[data-font="kai"] h2,
:root[data-font="kai"] h3,
:root[data-font="kai"] .brand,
:root[data-font="kai"] .big { font-synthesis-weight: none; }
:root[data-size="s"] { font-size: 93.75%; }   /* 15px 基准 */
:root[data-size="m"] { font-size: 100%;  }    /* 16px 基准（默认） */
:root[data-size="l"] { font-size: 109.4%; }   /* 17.5px */

/* ── 表单卡收窄并居中（评审 B）──
   查谱师 / 查玩家这两页原先是一张拉满 1100px 的卡里放一个输入框：
   视线要从行首横穿到行尾的按钮，读起来是散的。表单本身只有两个元素，
   收窄到 720px 更像一个"要填的东西"。**结果卡不受此限** —— 表格要宽。 */
.card.narrow { max-width: 720px; margin-left: auto; margin-right: auto; }

/* ── 例子 / 最近查询芯片 ──
   评审：「空着半屏，但因为不知道能填什么，还是不知道怎么开始」。
   给的是可点的具体值，不是"请输入用户名"这种没有信息量的提示。 */
.exrow {
  display: flex; flex-wrap: wrap; gap: 7px; align-items: center;
  margin-top: 13px; font-size: 12px; color: var(--fg3); line-height: 1.5;
}
.exrow .lbl { flex: none; color: var(--fg3); }
/* ⚠ 选择器必须带 .exrow 前缀：`.chip` 这个名字 app.html 里已经在用
   （结果卡之间的切换胶囊），全局限定会把它一起改掉。 */
.exrow .chip {
  font: inherit; font-size: 12px;
  padding: 3px 11px; border-radius: 999px;
  border: 1px solid var(--line2); background: transparent; color: var(--fg2);
  cursor: pointer;
  transition: border-color .12s, color .12s, background .12s;
  max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.exrow .chip:hover { border-color: var(--brand); color: var(--fg); background: var(--brand-soft); }
.exrow .chip:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand-line); }
.exrow .chip .k { color: var(--fg3); margin-right: 5px; }

/* ── 「为什么要两步？」折叠 ──
   原文一整段（三段话）压在输入框上面，把要填的东西推到首屏之外。
   折叠后只留一行标题，想懂的人自己点开 —— 说明从**障碍**变回**补充**。 */
.why { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 10px; }
.why summary { font-size: 12.5px; color: var(--fg3); }
.why summary:hover { color: var(--fg); }
.why .fd { margin-top: 8px; font-size: 12.5px; color: var(--fg2); line-height: 1.75; }
.why .fd b { color: var(--fg); }

/* ── 全局兜底提示（js/guard.js 用）──
 * 存在理由：全站原本只有 app.html 接了 unhandledrejection，
 * 其余页面一个都没接 —— 未捕获的 Promise 拒绝**静默无痕**，
 * 用户看到的是「点了没反应」，而控制台之外无从查起。
 *
 * ⚠ 只用令牌、不写死颜色（双主题都要能读）。
 * ⚠ `pointer-events:none` 是必须的：它浮在右上角，
 *   不该挡住下面的按钮 —— 一个会挡操作的兜底比原来的 bug 更烦。 */
.phm-guard {
  position: fixed;
  top: 12px;
  right: 12px;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: min(380px, calc(100vw - 24px));
  pointer-events: none;
}
.phm-guard-item {
  font-size: 13px;
  line-height: 1.55;
  padding: 9px 13px;
  border-radius: 10px;
  color: var(--fg);
  background: var(--card);
  border: 1px solid var(--err);
  box-shadow: 0 6px 24px rgba(0, 0, 0, .18);
  pointer-events: auto;
}
@media (max-width: 760px) {
  .phm-guard { top: auto; bottom: 12px; left: 12px; right: 12px; max-width: none; }
}
