/* ============================================================================
 * 考研周计划 · rpg/rpg.css
 * RPG 层的样式。原则：**只加新类**；少数几处覆盖（桌面分栏比例、抽屉改成
 * 居中对话框、底部多一行）都写在 rpg.css 里，style.css 一个字节没动。
 *
 * ⚠️ 2026-10-11 改：
 *   · 计划块完成确认已移除 → 删掉 .blk.rpg-done 那组样式
 *   · 专注入口改成全局的（桌面在当日安排面板底部粘住；手机是底部独立一行）
 *   · 专注面板用独立浮层 #rpgDlg（不再借用 #sheet）
 *
 * ⚠️ 2026-10-11 第 4 阶段改：
 *   · 桌面分栏从 ≈60:40 改成 70:30（第 4 阶段）→ 阶段 1.1 再收到 **约 80:20**
 *     （--sidew 用 clamp 给右侧留最小可用宽度，同时 --colw 也跟着这个宽度算 ——
 *      否则 7 列会溢出到看不见）
 *   · 专注面板里"暂停 / 结束并保存"居中成一组；"取消本次专注"单独一行、次要样式
 *   · 新增"另一台设备正在专注"的提示条与取消确认清单
 * ==========================================================================*/

/* ================================================================ 设计令牌（阶段 1.2）
   ★ 五个功能界面共用的**唯一一份**尺寸 / 间距 / 圆角 / 品质色。
     要调整观感只改这一段，不在使用处临时写数值。
     命名沿用 rpg-ui-lab/css/tokens.css 的那一族（`--rpg-quality-*` 就是 Lab 里
     定义过的"每个品质三个角色"：主色 / 浅底 / 描边），只是那边派生自 Web Awesome
     令牌，这边落到产品自己的主题变量上。 */
:root {
  --rpg-ok: #2f7d5a;

  /* ---- 字号：五档，相同情境必须用同一个变量 ---- */
  --fs-title: 16px;        /* 窗口 / 功能页面主标题 */
  --fs-section: 13.5px;    /* 区块标题：任务分组、属性分组、商品区域 */
  --fs-body: 13.5px;       /* 正文：任务内容、商品描述、规则正文 */
  --fs-value: 15px;        /* 关键数值与状态：等级、经验、金币、进度、状态标签 */
  --fs-meta: 12.5px;       /* 辅助文字：简短提示、来源、次要元数据 */
  --fs-tag: 11.5px;        /* 徽标 / 部位标签 */

  /* ---- 间距刻度 ---- */
  --sp-1: 4px; --sp-2: 6px; --sp-3: 8px; --sp-4: 12px; --sp-5: 16px;
  --pair-gap: 14px;        /* 二级与三级窗口之间的间距（阶段 2.3） */
  --gap-block: 16px;       /* 区块之间的垂直间距 */
  --gap-card: 12px;        /* 卡片之间 */

  /* ---- 圆角 ---- */
  --rd-s: 8px; --rd-m: 10px; --rd-l: 12px;

  /* ---- 控件 ---- */
  --ctl-h: 34px;           /* 普通按钮高度（触屏也够点） */
  --ctl-h-lg: 48px;        /* 主按钮 */
  /* 卡片网格的最小列宽，列数随可用宽度自动变。
     160 而不是 168：正文区常驻一条滚动条槽（见 .rpg-win-body 的 scrollbar-gutter），
     要给槽留出那 ~15px，商城才稳稳是 4 列 —— 否则槽一出现就从 4 列塌成 3 列。 */
  --card-min: 160px;

  /* ---- 品质色：与 Lab 的 --rpg-quality-* 同名，颜色值只在这里出现一次 ---- */
  --rpg-quality-common: var(--faint);
  --rpg-quality-common-quiet: var(--surface-2);
  --rpg-quality-common-line: var(--hair);
  --rpg-quality-fine: var(--rpg-ok);
  --rpg-quality-fine-quiet: rgba(47, 125, 90, .14);
  --rpg-quality-fine-line: var(--rpg-ok);
  --rpg-quality-rare: var(--accent);
  --rpg-quality-rare-quiet: var(--accent-soft, var(--surface-2));
  --rpg-quality-rare-line: var(--accent-line);
  --rpg-quality-epic: #d98a2b;
  --rpg-quality-epic-quiet: rgba(217, 138, 43, .16);
  --rpg-quality-epic-line: #d98a2b;
}
:root[data-theme="dark"] {
  --rpg-ok: #63c295;
  --rpg-quality-fine-quiet: rgba(99, 194, 149, .18);
  --rpg-quality-epic-quiet: rgba(217, 138, 43, .20);
}

/* 品质 → 三个颜色角色的映射。**只用这一个类名**（`.rpg-q-<key>`）：
   点在商品名前面是品质点，挂在卡片上是那张卡的描边色。
   和 Lab 的 components/rpg-quality.js 一个思路：颜色在令牌里，这里只做名字映射。 */
.rpg-q-common { --rpg-q: var(--rpg-quality-common); --rpg-q-quiet: var(--rpg-quality-common-quiet); --rpg-q-line: var(--rpg-quality-common-line); }
.rpg-q-fine   { --rpg-q: var(--rpg-quality-fine);   --rpg-q-quiet: var(--rpg-quality-fine-quiet);   --rpg-q-line: var(--rpg-quality-fine-line); }
.rpg-q-rare   { --rpg-q: var(--rpg-quality-rare);   --rpg-q-quiet: var(--rpg-quality-rare-quiet);   --rpg-q-line: var(--rpg-quality-rare-line); }
.rpg-q-epic   { --rpg-q: var(--rpg-quality-epic);   --rpg-q-quiet: var(--rpg-quality-epic-quiet);   --rpg-q-line: var(--rpg-quality-epic-line); }
.rpg-q {
  inline-size: 8px; block-size: 8px; border-radius: 999px; flex: 0 0 auto;
  background: var(--rpg-q, var(--faint)); align-self: center;
}

.rpg-xp {
  display: block; width: 34px; height: 4px;
  border-radius: 999px; background: var(--block);
  overflow: hidden;
}
.rpg-xp i { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.rpg-coin::before { content: '◈'; margin-right: 3px; color: var(--faint); }

/* ================================================================ 全局专注入口
   #rpgBottomActions 由 rpg-ui.js 创建（里头是三颗主入口 + 这个「开始专注」），
   并按视口"搬家"：
     桌面 ≥1200px → 放进 .side 底部（粘住）
     手机 <1200px → 作为 body 栅格的一行，压在底栏之上
   按钮本身就是入口，不需要先点任何计划格。 */
/* ⚠️ 必须压在遮罩（.sheetMask，z-index 28）之上：
   窗口开着时遮罩会盖住整页，如果这一排也被盖住，想换个模块就得先关窗口 ——
   第一下点击会被遮罩吃掉（阶段 2.3 实测）。抬到 29 之后可以直接切。 */
#rpgBottomActions { background: var(--surface); position: relative; z-index: 29; }
.rpg-cta {
  width: 100%;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font: inherit; font-size: 15px; font-weight: 650;
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid var(--accent);
  background: var(--accent); color: #fff;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: filter .15s, background .15s;
}
.rpg-cta:hover { filter: brightness(1.06); }
.rpg-cta.running {
  background: var(--surface-2); border-color: var(--accent-line); color: var(--text);
}
.rpg-cta.remote {
  background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent);
}
.rpg-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--now); animation: rpg-pulse 2s infinite;
}
.rpg-dot.paused { background: var(--faint); animation: none; }
@keyframes rpg-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }

/* ================================================================ 专注浮层
   与 app.js 的 #sheet 完全独立：关掉其中一个不影响另一个。 */
.rpg-dlg {
  position: fixed; inset: 0; z-index: 40;
  display: none;
  background: rgba(8, 10, 14, .46);
}
.rpg-dlg.open { display: flex; }
.rpg-dlg-panel {
  position: relative;
  inline-size: 100%;
  max-block-size: 84dvh;
  background: var(--surface); color: var(--text);
  padding: 18px 18px calc(18px + env(safe-area-inset-bottom, 0px));
  border-top-left-radius: var(--r-lg);
  border-top-right-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  /* 阶段 1：和 #sheet 同一条修法 —— 面板本身不滚，只有正文滚，
     这样右上角那个 × 不会跟着内容滚出可视区。 */
  display: flex; flex-direction: column;
  overflow: hidden;
}
#rpgDlgBody { flex: 1 1 auto; min-height: 0; overflow: auto; }
.rpg-dlg-close {
  position: absolute; right: 12px; top: 10px;
  border: none; background: transparent; color: var(--muted);
  font-size: 16px; cursor: pointer; padding: 2px 6px; border-radius: 8px;
}
.rpg-dlg-close:hover { background: var(--surface-2); }
.rpg-dlg h3 { margin: 0 0 8px; font-size: var(--fs-title); font-weight: 650; }

.rpg-note {
  margin: 8px 0 0;
  font-size: var(--fs-meta); line-height: 1.75; color: var(--faint);
}
.rpg-note b { color: var(--text); }

/* 选轨道：按四个考试科目分组，但六条轨道始终全部可见，不折叠 */
.rpg-pick { display: grid; gap: 12px; margin: 14px 0 4px; }
.rpg-pick-grp { display: grid; gap: 6px; }
.rpg-pick-title {
  font-size: var(--fs-meta); font-weight: 650; letter-spacing: .04em; color: var(--faint);
}
.rpg-opt {
  font: inherit; font-size: var(--fs-body); text-align: left;
  padding: 11px 12px; cursor: pointer;
  border-radius: 10px; border: 1px solid var(--hair);
  background: var(--surface-2); color: var(--text);
  transition: border-color .15s, background .15s, color .15s;
}
.rpg-opt:hover { border-color: var(--accent-line); }
.rpg-opt.on {
  border-color: var(--accent); background: var(--accent-soft);
  color: var(--accent); font-weight: 650;
}

.rpg-actions { display: flex; gap: 10px; margin-top: 16px; }
/* 操作组居中：暂停 + 结束并保存是一组，居中放 */
.rpg-actions.center { justify-content: center; flex-wrap: wrap; }
.rpg-actions button {
  flex: 0 0 auto; min-inline-size: 104px;
  font: inherit; font-size: var(--fs-value); font-weight: 600;
  padding: 11px 14px; cursor: pointer;
  border-radius: 11px; border: 1px solid var(--hair);
  background: var(--surface-2); color: var(--text);
}
.rpg-actions button.primary {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.rpg-actions button.rpg-danger {
  background: transparent; border-color: var(--hair); color: var(--muted);
  font-size: var(--fs-meta); font-weight: 600; min-inline-size: 0; padding: 8px 12px;
}
.rpg-actions button.rpg-danger:hover { border-color: var(--now); color: var(--now); }
.rpg-actions button:disabled { opacity: .45; cursor: not-allowed; }

/* 取消确认清单：把代价写清楚，不用大红警告牌，只加一条左侧竖线 */
.rpg-warnlist {
  margin: 10px 0 0; padding: 0 0 0 18px;
  font-size: var(--fs-body); line-height: 1.9; color: var(--muted);
  border-inline-start: 2px solid var(--now);
}
.rpg-warnlist li + li { margin-top: 4px; }
.rpg-warnlist b { color: var(--text); }

/* 另一台设备正在专注 */
.rpg-remote {
  display: grid; gap: 4px;
  margin: 12px 0 2px; padding: 11px 12px;
  border: 1px solid var(--accent-line); border-radius: 11px;
  background: var(--accent-soft);
  font-size: var(--fs-body);
}
.rpg-remote.stale {
  border-color: var(--hair); background: var(--surface-2); border-style: dashed;
}
.rpg-remote b { font-weight: 650; color: var(--text); }
.rpg-remote-sub { font-size: var(--fs-meta); color: var(--muted); font-variant-numeric: tabular-nums; }
.rpg-remote .rpg-actions { margin-top: 8px; }
.rpg-remote .rpg-note { margin: 4px 0 0; }
.rpg-alert { color: var(--accent); }

/* 正在专注：时长是视觉重点，但不加装饰 */
.rpg-run-track {
  margin-top: 6px; text-align: center;
  font-size: var(--fs-value); font-weight: 650;
}
.rpg-big {
  margin: 6px 0 2px; text-align: center;
  font-size: 40px; font-weight: 650; letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
}
.rpg-state { text-align: center; font-size: var(--fs-meta); color: var(--muted); }

/* 结束之后 */
.rpg-result {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px;
  margin-top: 10px; font-size: var(--fs-value);
}
.rpg-result b { font-size: var(--fs-value); }
.rpg-dim { color: var(--faint); font-size: var(--fs-meta); }

/* ================================================================ 角色成长面板
   六条轨道与四个科目合并成分组结构：一级科目、二级轨道，始终展开。 */
.rpg-narrow { max-inline-size: 34rem; }
.rpg-hero { padding-bottom: 12px; border-bottom: 1px solid var(--hair); }
.rpg-hero-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.rpg-lv-big { font-size: 27px; font-weight: 700; letter-spacing: .01em; }
.rpg-hero-xp { font-size: var(--fs-value); color: var(--muted); font-variant-numeric: tabular-nums; }
.rpg-hero .rpg-xp.big { inline-size: 100%; block-size: 7px; margin: 9px 0; }

.rpg-groups { display: grid; gap: var(--sp-5); margin-top: var(--sp-4); }
/* ⚠️ min-inline-size: 0 —— 网格项默认是 min-content，窄窗口（三级 460px）里
   一行科目排不下时会把整条网格轨顶宽，于是窗口内部出现横向滚动条。
   归零后由 .rpg-name 省略号收尾，窗口自己不出横向滚动条。 */
.rpg-grp { display: grid; gap: 2px; min-inline-size: 0; }

.rpg-row {
  display: flex; align-items: center; gap: 10px;
  font-size: var(--fs-body); padding: 5px 0;
}
.rpg-row .rpg-xp { flex: 0 0 auto; inline-size: 118px; block-size: 6px; }
.rpg-name { flex: 1 1 auto; min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rpg-lv {
  flex: 0 0 auto; inline-size: 48px; text-align: right;
  font-size: var(--fs-value); font-weight: 650; font-variant-numeric: tabular-nums;
}
.rpg-val {
  flex: 0 0 auto; inline-size: 104px; text-align: right;
  font-size: var(--fs-meta); color: var(--faint); font-variant-numeric: tabular-nums;
}

/* 一级：考试科目 */
.rpg-row.sub { padding: 6px 0; border-bottom: 1px solid var(--hair); }
.rpg-row.sub .rpg-name { font-size: var(--fs-value); font-weight: 650; }
/* 二级：该科目下的学习轨道（靠缩进与字号分层，不套卡片） */
.rpg-row.trk { padding-inline-start: 16px; font-size: var(--fs-body); }
.rpg-row.trk .rpg-name { color: var(--muted); }
.rpg-row.trk .rpg-lv { color: var(--muted); font-weight: 600; }

/* ================================================================ 成就
   全部列出（未达成的也显示进度与条件），布局沿用角色属性的分组风格，不套卡片。
   ⚠️ 标题用公共的 .rpg-sec-head，这里不再另起一套标题样式。 */
.rpg-ach { padding: 7px 0; border-bottom: 1px solid var(--hair); }
.rpg-ach-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.rpg-ach-name { font-size: var(--fs-value); color: var(--muted); }
.rpg-ach-state { flex: 0 0 auto; font-size: var(--fs-meta); color: var(--faint); font-variant-numeric: tabular-nums; }
.rpg-ach-desc { margin: 2px 0 5px; font-size: var(--fs-meta); color: var(--faint); }
.rpg-ach .rpg-xp { inline-size: 100%; block-size: 5px; }
.rpg-ach.on .rpg-ach-name { color: var(--text); font-weight: 650; }
.rpg-ach.on .rpg-ach-state { color: var(--rpg-ok); }

/* ================================================================ 今日任务 / 本周挑战 / 阶段挑战 / 补记
   每一区都是「区块标题 + 每行两栏（名称 / 进度）+ 一行小字」，说明走公共折叠组件。
   ⚠️ 阶段 1.2 起标题统一用 .rpg-sec-head —— 原来 .rpg-blk-head / .rpg-ach-head /
      .rpg-sub-head 三套写法是同一个东西，已经删掉，只留一份。 */
.rpg-task { padding: 7px 0; border-bottom: 1px solid var(--hair); }
.rpg-task-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.rpg-task-name { font-size: var(--fs-value); color: var(--muted); }
.rpg-task-prog {
  flex: 0 0 auto; font-size: var(--fs-meta); color: var(--faint);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.rpg-task-desc { margin: 2px 0 0; font-size: var(--fs-meta); color: var(--faint); line-height: 1.65; }
.rpg-task-rw { color: var(--muted); }
.rpg-task.on .rpg-task-name { color: var(--text); font-weight: 650; }
.rpg-task.on .rpg-task-prog { color: var(--rpg-ok); font-weight: 650; }
.rpg-task-weak { margin-top: 6px; }
.rpg-alert { color: var(--now); }

/* ================================================================ 归潮 · 场景条
   只做"安静的一眼"：一条盐脊、一条路、几个走过的刻度，和一个站在当前位置的小人。
   颜色全部走现有令牌，所以默认/Shoelace、浅色/深色都自动跟着变。 */
.rpg-scene {
  position: relative; height: 84px; margin: 10px 0 12px;
  border-radius: 12px; overflow: hidden;
  border: 1px solid var(--hair); background: var(--surface-2);
}
.sc-svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.sc-far { fill: var(--block); opacity: .55; }
.sc-near { fill: var(--block); opacity: .85; }
/* 路：贴在下三分之一，刻度就是节点 */
.sc-route {
  position: absolute; left: 10px; right: 10px; bottom: 20px; height: 2px;
  background: var(--hair); border-radius: 2px;
}
.sc-tick {
  position: absolute; top: -3px; width: 2px; height: 8px; margin-left: -1px;
  background: var(--hair); border-radius: 2px;
}
.sc-tick.on { background: var(--muted); height: 10px; top: -4px; }
.sc-you {
  position: absolute; bottom: -3px; width: 8px; height: 12px; margin-left: -4px;
  border-radius: 4px 4px 3px 3px; background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft, var(--block));
}
/* ⚠️ 营地标记用的是 sc-campmark，**不能**叫 sc-camp ——
   场景状态类也叫 sc-camp（加在 .rpg-scene 上），同名会把 84px 的高度压成 0（W2 实测踩到过）。 */
.sc-campmark { position: absolute; bottom: 20px; width: 0; height: 0; }
.sc-tent, .sc-fire { position: absolute; bottom: 0; display: none; }
.sc-tent {
  left: -20px; width: 0; height: 0; border-left: 7px solid transparent;
  border-right: 7px solid transparent; border-bottom: 10px solid var(--muted); opacity: .7;
}
.sc-fire {
  left: 2px; width: 6px; height: 8px; border-radius: 50% 50% 45% 45%;
  background: var(--now); opacity: .75;
}
.rpg-scene.sc-camping .sc-tent, .rpg-scene.sc-camp .sc-tent { display: block; }
.rpg-scene.sc-camping .sc-fire, .rpg-scene.sc-camp .sc-fire { display: block; }
.rpg-scene.sc-walking .sc-you { animation: sc-bob 1.5s ease-in-out infinite; }
.rpg-scene.sc-resting .sc-you { opacity: .55; }
.rpg-scene.sc-camping .sc-fire, .rpg-scene.sc-camp .sc-fire { animation: sc-flicker 2.4s ease-in-out infinite; }
.sc-cap {
  position: absolute; left: 10px; bottom: 4px; font-size: var(--fs-tag); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
@keyframes sc-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-2px); } }
@keyframes sc-flicker { 0%, 100% { opacity: .55; } 50% { opacity: .9; } }
/* 系统开了"减少动态效果"就全部停掉 */
@media (prefers-reduced-motion: reduce) {
  /* ⚠️ 这里必须把**所有**循环动画列全 —— 漏掉一个就等于没实现这条偏好。
     收尾回归时发现 `.rpg-dot`（专注面板里闪的那个点）原本漏在这条规则外面。 */
  .rpg-dot,
  .rpg-scene.sc-walking .sc-you, .rpg-scene.sc-camping .sc-fire, .rpg-scene.sc-camp .sc-fire {
    animation: none;
  }
}

/* ================================================================ 归潮 · 状态行与日志
   与成长面板其它区块同一套读法：标题 + 小字，不套卡片、不加装饰。 */
.rpg-jrow { display: flex; align-items: baseline; gap: 8px; padding: 3px 0; font-size: var(--fs-body); }
.rpg-jlabel { flex: 0 0 auto; color: var(--faint); }
.rpg-jval { flex: 1 1 auto; color: var(--text); min-inline-size: 0; }
.rpg-jsub { color: var(--faint); margin-left: 6px; font-size: var(--fs-meta); }
.rpg-jsec {
  margin: 14px 0 4px; padding-top: 10px; border-top: 1px solid var(--hair);
  font-size: var(--fs-section); font-weight: 650; color: var(--muted);
}
.rpg-jsec-n { float: right; font-weight: 500; color: var(--faint); }
.rpg-jline { font-size: var(--fs-body); color: var(--muted); line-height: 1.7; }
.rpg-jdim { color: var(--faint); }
.rpg-jamb { margin-top: 3px; font-size: var(--fs-meta); color: var(--faint); font-style: italic; line-height: 1.7; }
.rpg-jitem { padding: 7px 0; border-bottom: 1px solid var(--hair); }
.rpg-jitem-top { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.rpg-jtitle { font-size: var(--fs-value); color: var(--text); font-weight: 600; }
.rpg-jtag {
  font-size: var(--fs-tag); font-style: normal; color: var(--muted);
  border: 1px solid var(--hair); border-radius: 999px; padding: 0 6px;
}
.rpg-jtag.prev { color: var(--faint); border-style: dashed; }
.rpg-jmile { margin-left: auto; font-size: var(--fs-tag); color: var(--faint); font-variant-numeric: tabular-nums; }
.rpg-jtext { margin-top: 3px; font-size: var(--fs-body); color: var(--muted); line-height: 1.75; white-space: pre-wrap; }
.rpg-jnote { margin-top: 3px; font-size: var(--fs-meta); color: var(--faint); line-height: 1.7; }
.rpg-jitem.lock { opacity: .72; }
.rpg-jitem.lock .rpg-jtext { color: var(--faint); }
.rpg-jneed { margin-top: 4px; font-size: var(--fs-meta); color: var(--now); }
.rpg-jarc { margin-top: 8px; }
.rpg-jarc > summary {
  cursor: pointer; font-size: var(--fs-meta); color: var(--muted); font-weight: 650;
  padding: 5px 0; list-style: revert;
}
.rpg-jarc-p { color: var(--faint); font-weight: 500; font-variant-numeric: tabular-nums; }

/* ================================================================ 布局调整（仅必需处）
   一、桌面：周计划网格 : 当日安排面板 ≈ **80 : 20**（阶段 1.1 从 70:30 收窄）
        · 右侧用 clamp() 保住"最小可用宽度"：窄到极致也不低于 296px
          （三颗入口 + 开始专注还排得下），超宽屏（>约 2190px）封顶 460px ——
          再宽它也读不满，不如把空间还给网格。
        · `--colw` 必须跟着 --sidew 一起算：原来是写死的 (100vw - 轴 - 320px)/7，
          而右侧实际占到 20% 时比 320px 宽得多，7 列就会横向溢出、看不见周日那几列。
          这就是"左栏网格太窄"的真正原因：不是网格小，是算出来的列宽比可用空间还大。
        · ⚠️ 这里必须写 **21vw**，不能写 21%：
          预定义属性里的百分比是"用在哪算在哪"。--sidew 用在 grid-template-columns 上时，
          21% 是相对 body 算的（没错）；但 --colw 里也嵌了同一个 clamp()，而 --colw 是用在
          .col 的 width 上的 —— 那个 21% 就变成相对 .col 的包含块（.cols，宽度又由列宽决定）
          去算，成了循环依赖，浏览器只能退到 clamp 的下限，于是 7 列总宽又比可用空间大、
          照样横溢（当年 30% 那版实测 1400px 下溢出 110px）。
          换成 vw 之后数值是确定的，7 列正好铺满，不再有横向溢出。
        · 断点仍是 1200px，手机 / 平板那一套完全不动。 */
@media (min-width: 1200px) {
  :root {
    /* 阶段 1.1：右侧从 ≈70:30 收到 **约 80:20**（按 21vw 算），
       下限 296px 是"三颗入口 + 开始专注"还能排得下的最小宽度，
       上限 460px 免得超宽屏把网格又挤窄。 */
    --sidew: clamp(296px, 21vw, 460px);
    --axisw: 68px;
    --colw: calc((100vw - var(--axisw) - var(--sidew)) / 7);
    /* 二级（角色成长）与三级窗口的宽度。三级开着时两个窗口并排居中，
       所以宽度不能吃掉整个视口：各 40vw，1200px 下也还有富余。 */
    --rpg-sheetw: min(560px, 40vw);
  }
  body { grid-template-columns: minmax(0, 1fr) var(--sidew); }
  /* 让 7 列**正好铺满**可视宽度。
     --colw 是按 100vw 算的，而 .scroller 自己有一条竖直滚动条（Windows 上约 8~10px），
     所以严格算出来的 7 列会比可视区宽 10px —— 差一点点就出现"最后一天要横着拖一下"。
     这里给列加弹性 + 最小宽度 0，多出来的那几像素由 flex 吸收，列宽仍然接近 --colw。
     ⚠️ 只对桌面生效：手机/平板上那套"7 列里只显示 4 列、横向拖动看别的天"必须保持原样。 */
  .stage { min-width: 0; }              /* 桌面不做横向滚动：让 7 列去适配可视宽度 */
  .cols { min-width: 0; }
  .col, .dayhead { flex: 1 1 var(--colw); min-width: 0; }
  .side { display: flex; flex-direction: column; padding: 16px 16px 0; }
  /* 右侧面板底部那一组（三颗主入口 + 开始专注）粘在面板底部：
     面板内部滚动时它们始终可见、随手可点。 */
  #rpgBottomActions {
    position: sticky; inset-block-end: 0;
    margin-block-start: auto;
    /* 阶段 2.3.1：四周留呼吸位；阶段 2.4：把这一块做成一个**有完整边界的操作区** ——
       整块用现有圆角令牌 `--rd-l` 收边，按钮本身一点没动（尺寸/排列/间距/事件都不变）。
       层级仍是 z-index: 29（在遮罩之上），只改外观。 */
    padding: 12px var(--sp-3) 14px;
    border: 1px solid var(--hair);
    border-radius: var(--rd-l);
    background: var(--surface);
    display: flex; flex-direction: column; gap: 9px;
  }
  /* 计划项详情 / 设置 / AI 这些抽屉，桌面端改成居中对话框 */
  .sheet {
    left: 50%; right: auto; bottom: auto; top: 50%;
    inline-size: var(--rpg-sheetw, min(560px, 92vw));
    max-block-size: 82vh;
    transform: translate(-50%, -46%);
    opacity: 0; pointer-events: none;
    border: 1px solid var(--hair);
    border-radius: var(--r-lg);
    padding: 0;
    /* 原来靠 `0 0 0 100vmax rgba(...)` 假装遮罩，但那层阴影拦不住点击；
       现在换成真实的 #sheetMask（style.css），这里只留窗口自己的投影。 */
    box-shadow: var(--shadow-lg);
    transition: transform .2s ease, opacity .2s ease;
  }
  .sheet.open { transform: translate(-50%, -50%); opacity: 1; pointer-events: auto; }
  #sheetBody { padding: 20px 22px 22px; }
  /* 按钮按内容自然排列，不再拉伸到整窗宽 */
  .sheet .actions button { flex: 0 0 auto; min-inline-size: 104px; }
  /* 专注面板：桌面居中，限制宽高 */
  .rpg-dlg { align-items: center; justify-content: center; }
  .rpg-dlg-panel {
    inline-size: min(420px, 92vw);
    max-block-size: 78vh;
    border: 1px solid var(--hair);
    border-radius: var(--r-lg);
    padding: 20px 22px 22px;
  }
}

/* 二、手机：底部多一行操作区，压在成长条之上；并让出安全区 */
@media (max-width: 1199px) {
  body { grid-template-rows: auto minmax(0, 1fr) auto auto; }
  /* 窄屏：底部那一组（三入口 + 开始专注）整体占一行，压在底栏之上 */
  #rpgBottomActions {
    grid-row: 3;
    /* 窄屏同样收成一个圆角操作区（左右留一点边，别贴屏边）；底部不加外边距，
       免得把 `--rpg-bottombars` 的高度量歪（抽屉要正好停在它上面）。 */
    padding: 8px 10px 10px;
    margin-inline: 8px;
    border: 1px solid var(--hair);
    border-radius: var(--rd-l);
    background: var(--surface);
  }
  .bottombar {
    grid-row: 4;
    padding-bottom: calc(5px + env(safe-area-inset-bottom, 0px));
  }
  /* 计划 / 成长 / 设置这些抽屉停在「专注入口 + 底栏」之上。
     抽屉是贴底固定定位的，不收起来就会把底部那个专注入口整个盖住 ——
     实测现象是"点那个位置什么都不会发生"，用户会以为按钮坏了。
     高度由 rpg-ui.js 实测后写进 --rpg-bottombars（改了字号/内边距也不会失准）。 */
  .sheet {
    bottom: var(--rpg-bottombars, 0px);
    max-height: min(72dvh, calc(100dvh - var(--rpg-bottombars, 0px) - 8px));
  }
  /* ⚠️ 收起时也得把上面的 bottom 一起补进 transform。
     style.css 里收起态写的是 `transform: translateY(103%)` —— 那是按 `bottom: 0` 算的：
     位移只有"自身高度 +3%"，抽屉被抬高 100px 之后，这 100px 就露在屏幕里了。
     实测（390×844，--rpg-bottombars=100px）：收起态的抽屉顶边停在 y=762，
     屏幕最下面 82px 一直露着面板内容，正好压住底部那一组入口（#rpgBottomActions），
     点那个位置没反应 —— 手机上就打不开面板了。
     补上 bottom 之后，收起态重新完整退到屏幕外（--rpg-bottombars 为 0 时行为与原来一致）。 */
  .sheet:not(.open) {
    transform: translateY(calc(103% + var(--rpg-bottombars, 0px)));
  }
  /* 窄屏不再显示那一行等级/金币摘要 —— 竖向空间有限，信息在「角色属性」里 */
  .rpg-side-stat { display: none; }
  /* 悬浮球上移，避免压住底部那一组 */
  .fab { bottom: 126px; }
  .rpg-dlg { align-items: flex-end; }
}

/* 三、很窄的屏幕：把成长行的固定列收窄，先保住文字 */
@media (max-width: 480px) {
  .rpg-row .rpg-xp { inline-size: 64px; }
  .rpg-lv { inline-size: 42px; }
  /* 时长从 "0h" 改成"20 分钟 / 1 小时 20 分"之后更长，这里多让一点宽度 */
  .rpg-val { inline-size: 96px; font-size: var(--fs-tag); }
  .rpg-row.sub .rpg-name { font-size: var(--fs-value); }
}
/* ================================================================== 五个二级功能入口
   #rpgNav 里五颗**同级**按钮：角色属性 / 任务 / 归潮 / 商城 / 装备。
   它们和「开始专注」一起待在右侧面板底部（#rpgBottomActions）。
   排布用 6 列网格：第一行三颗各占 2 列，第二行两颗居中各占 2 列 ——
   不缩进、不嵌套，谁也看不出主次。设置不在这里，仍在整页底栏。 */
.rpg-nav { display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--sp-3); }
.rpg-navbtn {
  grid-column: span 2;
  min-inline-size: 0; min-block-size: var(--ctl-h);
  font: inherit; font-size: var(--fs-meta); font-weight: 600;
  padding: var(--sp-2) var(--sp-1); border-radius: var(--rd-m); cursor: pointer;
  border: 1px solid var(--hair); background: var(--surface-2); color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: border-color .15s, background .15s, color .15s;
}
/* 六个入口正好两行各三个（每颗 span 2 / 共 6 列），不需要再手工摆第二行 */
.rpg-navbtn:hover { border-color: var(--accent-line); }
.rpg-navbtn:active { background: var(--block); }
.rpg-side-stat {
  font-size: var(--fs-meta); color: var(--faint); font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rpg-side-stat b { color: var(--text); font-weight: 650; }

/* 阶段 2.2：AI 入口进了上面那一排之后，右下角固定悬浮球退休。
   它原来正压在「归潮」按钮上（桌面端实测挡住点击）。只隐藏、不删：元素与它的
   点击处理器都还在，新入口就是去点它。 */
.rpg-fab-retired { display: none !important; }

/* ====================================================== 窗口层（阶段 2.3 / 2.3.1）
   二级 #rpgSub 与三级 #rpgSub3 是**两个并列的元素**，一起放进 #rpgWin：
     桌面：整组在**左侧主区域**里居中并排，三级出现在二级右侧。
     窄屏：改成单窗口 —— 三级盖在上面，关掉它二级原样露出来（二级从未被销毁）。
   这里只管"摆在哪"；里面长什么样仍然走下面那些公共组件与令牌。
   ⚠️ 阶段 2.3.1：三级那一格**始终占位**（只是看不见），所以开/关三级都不会
      改变组的宽度 —— 二级的水平位置因此与"三级开不开"无关（原来会横移 237px）。 */
.rpg-win {
  position: fixed; inset: 0; z-index: 31;
  display: flex; align-items: center; justify-content: center;
  gap: var(--pair-gap); padding: var(--sp-5);
  pointer-events: none;
}
.rpg-sub, .rpg-sub3 {
  position: relative;
  display: flex; flex-direction: column; flex: 0 0 auto;
  max-block-size: min(82vh, calc(100dvh - 2 * var(--sp-5)));
  background: var(--surface); color: var(--text);
  border: 1px solid var(--hair); border-radius: var(--r-lg);
  overflow: hidden; box-shadow: var(--shadow-lg);
  pointer-events: auto;
  /* ⚠️ 阶段 2.3.1：关着的时候只是**看不见**，仍然占位 ——
     这样"三级开不开"完全不改变布局宽度，二级的水平位置就不会跳。
     （以前用 display:none 控制开合，三级一出现就把整组挤得重新居中，
       实测二级会横移 237px。） */
  visibility: hidden;
}
.rpg-sub  { inline-size: min(560px, 100%); }
/* 商城 / 装备是卡片网格，窗口放宽一点才排得下更多列（桌面端尽量用足横向空间） */
.rpg-sub.rpg-wide { inline-size: min(760px, 100%); }
.rpg-sub3 { inline-size: min(460px, 100%); }
.rpg-sub.open, .rpg-sub3.open { visibility: visible; animation: rpgWinIn .16s ease; }
.rpg-sub:not(.open), .rpg-sub3:not(.open) { pointer-events: none; }
/* 三级槽位只在"当前二级确实有三级"时才占位；商城 / 装备没有三级，不预留空白 */
.rpg-win:not(.rpg-win-pair) .rpg-sub3 { display: none; }
@keyframes rpgWinIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* 桌面端（阶段 2.3.1）：把右侧那一条（`--sidew`，放着"开始专注 + 六个入口"）整个留出来。
   ① 窗口不会再压住入口区（改之前 1400px 下三级右边界 1217 会盖到入口面板 1104 上）；
   ② 三级可用宽度从左侧区域算出来，窄一点的桌面自动收窄，不会溢出。
   ③ 二级宽度固定，三级宽度只跟视口有关 → 两者都跟"三级开不开"无关。 */
@media (min-width: 1200px) {
  .rpg-win { padding-inline-end: calc(var(--sidew) + var(--sp-3)); }
  .rpg-sub3 {
    inline-size: min(460px, calc(100% - 560px - var(--pair-gap) - var(--sp-3)));
    min-inline-size: 300px;
  }
  .rpg-sub.rpg-wide { inline-size: min(760px, calc(100% - var(--sp-3))); }
}
/* ⚠️ 窗口头这三个类名不能叫 .rpg-sub-head —— 那个名字早就被「当日目标」那行占了
   （.rpg-sub-head 在任务区里表示虚线分隔），同名会把虚线画到窗口顶上。 */
.rpg-win-head {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  padding: 12px 12px 10px 18px; border-bottom: 1px solid var(--hair);
}
.rpg-win-title { flex: 1 1 auto; min-inline-size: 0; font-size: var(--fs-title); font-weight: 650; }
.rpg-win-close {
  flex: 0 0 auto; border: none; background: transparent; color: var(--muted);
  font-size: 17px; cursor: pointer; padding: 2px 6px; border-radius: 8px;
}
.rpg-win-close:hover { background: var(--surface-2); }
/* scrollbar-gutter: 常驻给滚动条留出槽位（阶段 1.2.1）。
   原来滚动条是"要才出现"的，一出现就吃掉 ~15px 正文宽度 —— 效果是展开说明后
   卡片网格当场重排（商城实测 4 列 → 3 列、卡宽 172 → 228px）。
   常驻槽位之后，滚动条来去都不改变内容宽度。 */
.rpg-win-body {
  flex: 1 1 auto; min-height: 0; overflow: auto;
  padding: 14px 18px 22px; scrollbar-gutter: stable;
}

/* ================================================================== 公共组件（阶段 1.2）
   五个功能界面**共用**这一组。结构全部由 rpg-ui.js 里的
     fold() / secHead() / statChip() / itemCard()    生成，
   所以同一件事在任何窗口里长得一样、改一处就全变。字号与间距只走上面的令牌。 */

/* —— ① 说明入口 + 说明浮窗（阶段 2.2）——
   默认只是一个轻量的「ⓘ + 文字」按钮，不占版面；点它在当前窗口**上方**弹浮窗。
   原来用的是 <details>：在正文里往下撑开，会把窗口顶高、把下面的内容推走。 */
.rpg-help-wrap { display: inline-block; margin: var(--sp-3) 0 0; }
.rpg-help {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-block-size: 32px;                      /* 够点，但不抢版面 */
  padding: var(--sp-1) var(--sp-3);
  font: inherit; font-size: var(--fs-meta); font-weight: 600; color: var(--muted);
  background: transparent; border: 1px solid var(--hair); border-radius: var(--rd-s);
  cursor: pointer; transition: border-color .15s, color .15s;
}
.rpg-help:hover { border-color: var(--accent-line); color: var(--text); }
.rpg-help:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rpg-fold-i {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  inline-size: 16px; block-size: 16px; border-radius: 50%;
  border: 1px solid currentColor; font-size: 10.5px; font-weight: 400; line-height: 1;
}
.rpg-help-what { min-inline-size: 0; }

/* 浮窗：独立的一层，不挂在任何窗口内部 ——
   所以关掉它不会动到底下窗口的滚动位置、展开状态和内容。 */
.rpg-help-pop {
  position: fixed; inset: 0; z-index: 60; display: none;
  align-items: center; justify-content: center; padding: var(--sp-5);
  background: rgba(8, 10, 14, .44);
}
.rpg-help-pop.open { display: flex; }
.rpg-help-panel {
  inline-size: min(520px, 100%); max-block-size: min(72vh, 560px);
  display: flex; flex-direction: column;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--hair); border-radius: var(--rd-l);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .35);
}
.rpg-help-head {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--hair); color: var(--muted);
}
.rpg-help-title { font-size: var(--fs-value); font-weight: 650; color: var(--text); }
.rpg-help-close {
  margin-inline-start: auto; font: inherit; font-size: var(--fs-value);
  inline-size: 32px; block-size: 32px; line-height: 1; cursor: pointer;
  border: 1px solid var(--hair); border-radius: var(--rd-s);
  background: transparent; color: var(--muted);
}
.rpg-help-close:hover { color: var(--text); border-color: var(--accent-line); }
.rpg-help-body {
  padding: var(--sp-4); overflow: auto;
  font-size: var(--fs-body); line-height: 1.85; color: var(--muted);
}
.rpg-help-body b { color: var(--text); }
.rpg-help-body p { margin: 0 0 var(--sp-3); font-size: inherit; color: inherit; }
.rpg-help-body p:last-child { margin-bottom: 0; }

/* —— ①b 二级总览里的「进入详细」入口（阶段 2.3）——
   三个二级窗口共用这一个组件：整行可点、左边标题、右边箭头。 */
.rpg-entries { display: grid; gap: var(--sp-2); margin-top: var(--sp-4); }
.rpg-entry {
  display: flex; align-items: baseline; gap: var(--sp-3);
  inline-size: 100%; min-block-size: 44px; padding: var(--sp-2) var(--sp-4);
  font: inherit; text-align: left; cursor: pointer;
  border: 1px solid var(--hair); border-radius: var(--rd-m);
  background: var(--surface-2); color: var(--text);
  transition: border-color .15s, background .15s;
}
.rpg-entry:hover { border-color: var(--accent-line); }
.rpg-entry:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rpg-entry-t { flex: 0 0 auto; font-size: var(--fs-value); font-weight: 650; }
.rpg-entry-d {
  flex: 1 1 auto; min-inline-size: 0; font-size: var(--fs-meta); color: var(--faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 这一项此刻的状态值（阶段 2.3.1）：二级只给这一句摘要，详情留给三级 */
.rpg-entry-v {
  flex: 0 0 auto; margin-inline-start: var(--sp-3);
  font-size: var(--fs-meta); font-weight: 650; color: var(--text);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.rpg-entry-i {
  flex: 0 0 auto; margin-inline-start: var(--sp-2); font-style: normal; font-weight: 700;
  color: var(--accent); opacity: .85;
}

/* —— ② 区块标题（任务分组 / 属性分组 / 商品区域都用它）—— */
.rpg-sec-head {
  margin: var(--gap-block) 0 var(--sp-2); padding-top: var(--sp-4);
  border-top: 1px solid var(--hair);
  display: flex; align-items: center; gap: var(--sp-3);
  font-size: var(--fs-section); font-weight: 700; color: var(--text);
}
.rpg-sec-head:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.rpg-sec-n {
  margin-left: auto; font-size: var(--fs-meta); font-weight: 500;
  color: var(--faint); font-variant-numeric: tabular-nums;
}

/* —— ③ 信息块：关键数值横向排（不再一项一行）—— */
.rpg-chips { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-4); }
.rpg-chipbox {
  display: flex; flex-direction: column; gap: 1px; min-inline-size: 0;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--hair); border-radius: var(--rd-m);
  background: var(--surface-2);
}
.rpg-chipbox-k { font-size: var(--fs-tag); color: var(--faint); white-space: nowrap; }
.rpg-chipbox-v {
  font-size: var(--fs-value); font-weight: 650; color: var(--text);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.rpg-chipbox-v small { font-size: var(--fs-meta); font-weight: 500; color: var(--muted); }

/* 角色属性的三个统计块（阶段 2.2）：等宽三列 + 整组居中 + 块内内容居中。
   等宽 = 三块视觉尺寸一致；margin-inline:auto = **整组**居中（不是只让块内文字居中）。 */
.rpg-stats {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-3); margin-top: var(--sp-4);
  max-inline-size: 420px; margin-inline: auto;
}
.rpg-stats .rpg-chipbox { align-items: center; text-align: center; padding-inline: var(--sp-2); }
.rpg-stats .rpg-chipbox-k { display: inline-flex; align-items: center; justify-content: center; }
/* 窄屏：整组铺满可用宽度（仍是等宽三列），不横向溢出 */
@media (max-width: 420px) { .rpg-stats { max-inline-size: none; } }

/* 可点击的信息块（阶段 2.1）：整块就是入口，箭头 › 是那个"图形符号"。
   点击面积 = 整块（与旁边信息块一样大），悬停/聚焦有明确反馈，键盘也能 Tab 到。 */
.rpg-chipbox-btn {
  font: inherit; text-align: left; cursor: pointer; color: inherit;
  min-block-size: 44px;                      /* 触屏最小点击高度 */
}
.rpg-chipbox-btn:hover { border-color: var(--accent-line); background: var(--surface-1, var(--surface-2)); }
.rpg-chipbox-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rpg-chipbox-i {
  font-style: normal; margin-left: 3px; color: var(--accent);
  font-weight: 700; opacity: .85;
}

/* —— ③b 当日目标（与"今日专注"分开说：它是目标，不是上限）—— */
.rpg-goal {
  margin-top: var(--sp-4); padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--hair); border-radius: var(--rd-m); background: var(--surface-2);
}
.rpg-goal-top { display: flex; align-items: baseline; gap: var(--sp-3); margin-bottom: 6px; }
.rpg-goal-k { font-size: var(--fs-tag); color: var(--faint); }
.rpg-goal-v {
  margin-left: auto; font-size: var(--fs-value); font-weight: 650;
  color: var(--text); font-variant-numeric: tabular-nums;
}
.rpg-goal-v small { font-size: var(--fs-meta); font-weight: 500; color: var(--muted); }
.rpg-goal-note { margin-top: 6px; font-size: var(--fs-meta); color: var(--faint); line-height: 1.6; }

/* —— ③c 明细行 / 日期块（三个统计块的详情屏共用）—— */
.rpg-led {
  display: flex; align-items: baseline; gap: var(--sp-3);
  padding: 5px 0; border-bottom: 1px solid var(--hair);
  font-size: var(--fs-body);
}
.rpg-led:last-child { border-bottom: none; }
.rpg-led-d {
  flex: 0 0 auto; min-inline-size: 68px; font-size: var(--fs-meta);
  color: var(--faint); font-variant-numeric: tabular-nums;
}
.rpg-led-k { min-inline-size: 0; color: var(--muted); }
.rpg-led-tag {
  font-style: normal; margin-left: 6px; padding: 1px 6px;
  border: 1px solid var(--hair); border-radius: var(--rd-s);
  font-size: var(--fs-tag); color: var(--faint); white-space: nowrap;
}
/* 可点击的明细行（一条冒险日志 = 一行，点开看详情） */
.rpg-led-btn {
  inline-size: 100%; font: inherit; text-align: left; cursor: pointer;
  border: 1px solid transparent; border-radius: var(--rd-s); padding-inline: 6px;
  background: transparent; color: inherit;
}
.rpg-led-btn:hover { border-color: var(--accent-line); background: var(--surface-2); }
.rpg-led-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* 专注期间那一段临时叙事：明确标注"进行中"，与已保存的日志区分开 */
.rpg-live-node { border-left: 2px solid var(--accent-line); }
.rpg-led-v {
  margin-left: auto; flex: 0 0 auto; font-weight: 650;
  color: var(--text); font-variant-numeric: tabular-nums;
}
.rpg-led.in .rpg-led-v { color: var(--rpg-ok); }
.rpg-led.out .rpg-led-v { color: var(--accent); }
.rpg-days { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-2); }
.rpg-day {
  position: relative; padding: 3px 8px; border-radius: var(--rd-s);
  border: 1px solid var(--hair); background: var(--surface-2);
  font-size: var(--fs-meta); color: var(--muted); font-variant-numeric: tabular-nums;
}
.rpg-day.shield { border-color: var(--accent-line); color: var(--text); }
.rpg-day-n { font-style: normal; margin-left: 4px; font-size: var(--fs-tag); color: var(--accent); }

/* —— ④ 卡片网格（商城商品 / 装备位 / 可换上的装备）——
   列数随可用宽度自动变：卡片最小 --card-min，宽了就多排几列。 */
.rpg-cards {
  display: grid; gap: var(--gap-card);
  grid-template-columns: repeat(auto-fill, minmax(var(--card-min), 1fr));
  margin-top: var(--sp-4);
}
.rpg-card {
  display: flex; flex-direction: column; gap: var(--sp-3);
  min-inline-size: 0; padding: var(--sp-4);
  border: 1px solid var(--rpg-q-line, var(--hair)); border-radius: var(--rd-l);
  background: var(--surface-2);
}
.rpg-card.on { border-color: var(--rpg-q-line, var(--accent-line)); }
.rpg-card-top { display: flex; align-items: center; gap: var(--sp-2); }
.rpg-card-name {
  flex: 1 1 auto; min-inline-size: 0;
  font-size: var(--fs-value); font-weight: 650; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rpg-card-tag {
  flex: 0 0 auto; font-size: var(--fs-tag); color: var(--faint);
  border: 1px solid var(--hair); border-radius: var(--rd-s); padding: 0 var(--sp-2);
}
.rpg-card-eff {
  flex: 1 1 auto; font-size: var(--fs-meta); line-height: 1.65; color: var(--muted);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.rpg-card-foot { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
/* 一句话氛围说明（阶段 2.5）—— 只是文字，不参与任何计算 */
.rpg-card-desc {
  margin-top: 2px; font-size: var(--fs-tag); line-height: 1.5; color: var(--faint);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.rpg-card-note { flex: 1 1 auto; min-inline-size: 0; font-size: var(--fs-meta); color: var(--faint); }
.rpg-card-state { font-size: var(--fs-meta); font-weight: 600; color: var(--rpg-ok); }
.rpg-card-bad { font-size: var(--fs-meta); color: var(--now); }

/* —— ⑤ 按钮（窗口内的小按钮统一外形；商城/装备/任务/归潮都用）—— */
.rpg-mini {
  font: inherit; font-size: var(--fs-meta); font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center;
  min-block-size: var(--ctl-h); padding: 0 var(--sp-4);
  border-radius: var(--rd-m); border: 1px solid var(--hair);
  background: var(--surface); color: var(--text); cursor: pointer;
  transition: border-color .15s, background .15s;
}
.rpg-mini:hover { border-color: var(--accent-line); }
.rpg-mini.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.rpg-mini:disabled { opacity: .5; cursor: not-allowed; }
.rpg-card-foot .rpg-mini { margin-left: auto; }
/* 按钮行：窗口里的「取消 / 保存」「再录一次 / 返回」都用它 */
.rpg-acts { display: flex; gap: var(--sp-3); flex-wrap: wrap; margin-top: var(--sp-4); }
.rpg-acts .rpg-mini { flex: 1 1 auto; }
/* 专注明细的日期切换（2026-10-15）：只换显示，不改任何记录。
   样式沿用 .rpg-mini / .rpg-led-tag，这里只负责把它们排成一行。 */
.rpg-daynav {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  margin-top: var(--sp-3);
}
.rpg-daynav .rpg-mini { flex: 0 0 auto; min-inline-size: 44px; }
.rpg-daynav-d { font-size: var(--fs-body); color: var(--text); white-space: nowrap; }
/* 结果 / 提示框：原来这几屏借用 .sheet .cost，但功能窗口不在 #sheet 里，等于没样式 ——
   这里给一个同语义的通用盒子（阶段 1.2 统一） */
.rpg-box {
  padding: var(--sp-4); border-radius: var(--rd-m);
  background: var(--surface-2); border: 1px solid transparent;
  font-size: var(--fs-body); line-height: 1.75; color: var(--muted);
}
.rpg-box b { color: var(--text); }
.rpg-box + .rpg-box, .rpg-box + .rpg-acts, .rpg-help-wrap + .rpg-box { margin-top: var(--sp-3); }
.rpg-box.warn { border-color: #d98a2b; color: #c07a1e; background: rgba(217, 138, 43, .10); }
.rpg-box.stop { border-color: var(--now); color: var(--now); background: rgba(224, 43, 78, .10); }
.rpg-box.warn b, .rpg-box.stop b { color: inherit; }
/* 功能窗口里的表单：这几个屏不在 #sheet 里，借用不了 style.css 的 `.sheet .form` 那套，
   所以在 RPG 层给一份同样的语义（.rpg-form / .rpg-field2），而不是去改 style.css。 */
.rpg-form { display: flex; flex-direction: column; gap: var(--gap-block); }
.rpg-form label {
  display: flex; flex-direction: column; gap: var(--sp-1);
  font-size: var(--fs-meta); color: var(--muted);
}
/* ⚠️ number / time 也要一起写进来：补记的「实际学习时长」是 input[type=number]，
   漏了它这个框就完全没有样式（浏览器原生白底），跟旁边几个框明显不是一套。 */
.rpg-form input[type="text"], .rpg-form input[type="date"], .rpg-form input[type="time"],
.rpg-form input[type="number"], .rpg-form select {
  font: inherit; font-size: var(--fs-value); color: var(--text);
  background: var(--surface-2); border: 1.5px solid var(--accent-line);
  border-radius: var(--rd-m); padding: 9px 11px; width: 100%;
  font-variant-numeric: tabular-nums;
}
.rpg-form input:focus, .rpg-form select:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
/* 数字框自带的上下小箭头：应用里其它输入框都没有这种装饰，
   统一去掉（直接敲数字更省事，手机上本来也没有）。 */
.rpg-form input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.rpg-form input[type="number"]::-webkit-outer-spin-button,
.rpg-form input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none; appearance: none; margin: 0;
}
.rpg-field2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
@media (max-width: 480px) { .rpg-field2 { grid-template-columns: 1fr; } }

@media (max-width: 1199px) {
  /* 窄屏：不做并排（两个完整窗口压不下），改成**单窗口** ——
     二级与三级都是贴着底栏的抽屉，同一时刻只露一层。
     ⚠️ 二级只是被藏起来，没有销毁：关掉三级它就原样回来，滚动与展开状态都还在。 */
  .rpg-win {
    flex-direction: column; justify-content: flex-end; align-items: stretch;
    gap: 0; padding: 0;
  }
  .rpg-sub, .rpg-sub3, .rpg-sub.rpg-wide {
    inline-size: auto; flex: 0 0 auto;
    max-block-size: min(72dvh, calc(100dvh - var(--rpg-bottombars, 0px) - 8px));
    margin-block-end: var(--rpg-bottombars, 0px);
    border: none; border-top: 1px solid var(--hair);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
  }
  /* 窄屏是**单窗口**：三级关着时不许占位（不然它会把二级整个顶上去） */
  .rpg-sub3:not(.open) { display: none; }
  html.rpg-pair3 .rpg-sub { display: none; }
  html.rpg-sub-open #sheet { display: none; }
  /* 窄屏上六个入口紧凑一点（宽度本来就只有 390 上下），网格仍是两行各三颗 */
  .rpg-nav { gap: var(--sp-2); }
  .rpg-navbtn { padding: var(--sp-2) var(--sp-1); }
}

/* ================================================================== 小分组标题与部位标签
   商城 / 装备 / 滴答面板共用（卡片本身在「公共组件」那一段）。 */
.rpg-sec {
  margin: var(--gap-block) 0 var(--sp-2); font-size: var(--fs-section); font-weight: 650;
  letter-spacing: .04em; color: var(--faint);
}
.rpg-sec .rpg-sec-n { letter-spacing: 0; }
.rpg-eqtag {
  flex: 0 0 auto; min-inline-size: 36px; font-size: var(--fs-tag); color: var(--faint);
  border: 1px solid var(--hair); border-radius: var(--rd-s); padding: 0 var(--sp-2); text-align: center;
}
/* 滴答设置面板：一条轨道一行（标签 + 任务下拉）。窄屏也要放得下，不许横向溢出 */
.dtMapRow {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 0; border-bottom: 1px solid var(--hair);
}
.dtMapRow .rpg-eqtag { min-inline-size: 96px; text-align: left; }
.dtMapRow select {
  flex: 1 1 auto; min-inline-size: 0;
  font: inherit; font-size: var(--fs-meta); padding: 6px 8px;
  border-radius: var(--rd-m); border: 1px solid var(--hair);
  background: var(--surface-2); color: var(--text);
}
@media (max-width: 480px) {
  /* 窄屏：卡片只放一列，按钮给足触控宽度 */
  .rpg-cards { grid-template-columns: 1fr; }
  .rpg-card-foot .rpg-mini { flex: 1 1 auto; }
  .dtMapRow { flex-wrap: wrap; }
  .dtMapRow .rpg-eqtag { min-inline-size: 0; }
  .dtMapRow select { flex: 1 1 100%; }
}
