:root {
  --bg: #0a0c10;
  --bg-2: #11131a;
  --bg-3: #181c27;
  --bg-4: #202636;
  --line: #2a3040;
  --ink: #f0f2f7;
  --ink-2: #b8bfcc;
  --ink-3: #6f7a8e;
  /* 原神金 —— 顶栏控件用。三个色都不是新调的：
       #d3bc8e 是 miao 的描边金（miao.css:158 的 box-shadow）、
       #ffe699 是卡片里「有效词条 / 高分」那层金（miao.css 的 .gold、li.great、武器副属性都在用）、
       #f6ecd2 是卡片右下角评分那层米白。
     ⚠️ 它**不是**档位色：档位色 2026-10-06 重排过（SS 是梅紫 #ef8ce0、SSS 是亮金 #ffe066），
     以前 SS/SSS 确实借过这个金，现在别再拿它当档位色用。
     顶栏要「和下侧搭」，就得从下侧已经在用的色里取 —— 另起一套必然搭不上。
     这里原来放的是 #5b8cff 蓝（--accent），只服务顶栏三处、跟下面一处都不沾，这次一起退场。 */
  --gold: #d3bc8e;
  --gold-lt: #ffe699;
  --cream: #f6ecd2;
  --gold-line: rgba(211, 188, 142, .32);
  --gold-line-hi: rgba(211, 188, 142, .72);
  --ctrl-bg: rgba(22, 26, 36, .82);
  --radius: 14px;
  --radius-sm: 10px;
  --app-width: 520px;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  background: var(--bg);
  /* 600px 画布在窄屏上居中时允许向两侧溢出，别让它顶出横向滚动条 */
  overflow-x: hidden;
  color: var(--ink);
  font-family: "PingFang SC", "Microsoft YaHei", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 14px;
  line-height: 1.5;
  min-height: 100vh;
}

body {
  display: flex;
  flex-direction: column;
}

/* ───────────────────────── 顶栏 ───────────────────────── */

.top {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(10, 12, 16, .92);
  backdrop-filter: blur(12px);
  /* 左右内边距从 .top 挪到里面的 .brand / .query 上：顶栏**背景和底边金线仍然通栏**
     （sticky 背景条只有 520px 宽的话，两侧会露出一条缝，比内容宽更丑），
     限宽的只是内容 —— 内容和下面 .app / .foot 一样收在 --app-width 里居中，
     桌面和手机看到的才是同一条 520px 的内容带。 */
  padding: 10px 0;
  /* 底边那条线由原来的实心灰蓝 border 换成下面的金线；
     sticky + z-index 已经建了包含块，::after 才定得住 */
}
/* 顶栏内容限宽居中：宽度取 --app-width（和 .app 同一个数），左右 padding 也是同一个 14px，
   于是顶栏内容的左右边缘和下面账号头、网格、页脚严格对齐（实测四条都是 l=354 / 宽 492）。 */
.brand, .query {
  width: 100%;
  max-width: var(--app-width);
  margin: 0 auto;
  padding: 0 14px;
}
/* 底边金线：两头淡、中间实。和明细页卡片描边、评级胶囊是同一支金色，
   比一条从左边灌到右边的实线更像游戏里的分隔条。 */
.top::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(90deg,
    transparent, var(--gold-line) 16%, var(--gold-line) 84%, transparent);
}

.brand { display: flex; align-items: center; gap: 9px; margin: 0 auto 10px; }
/* ✦ 那颗方章原来是紫蓝渐变 —— 全站唯一的紫蓝色块，下面全是金/米白/星级底，看着像别处抠来的。
   改成金色浮雕：外渐变 + 内侧顶边高光 + 一圈暖投影，深棕字压在金上（白字在这块金上只有约 1.6:1）。 */
.brand .mark {
  width: 30px; height: 30px; border-radius: 9px;
  background: linear-gradient(150deg, #f7e6bb, #d9bd83 55%, #b6934f);
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; color: #33291a;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .55), 0 2px 10px rgba(211, 188, 142, .28);
}
.brand h1 { margin: 0; font-size: 17px; letter-spacing: 2px; color: var(--cream); }
.brand p { margin: 0; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }

.query {
  display: grid;
  /* 三列：UID（最多 10.5em，可压）｜刷新（紧跟 UID）｜语言（右侧那列里靠右）。
     以前是 minmax(0,1fr) auto auto —— 第一列把剩下的空间全吃掉，刷新按钮被推到
     离 UID 框 857px 远的地方（1200px 视口实测）。现在第一列自己封顶，
     刷新就贴在 UID 框右边缘外 8px，语言靠右端，中间空出来的那一大片才是留白。
     下限写 0 不是 1fr：窄屏上第一列必须压得下去，否则整行会被顶出横向滚动条。 */
  grid-template-columns: minmax(0, 10.5em) auto minmax(0, 1fr);
  gap: 8px;
  align-items: end;
}
/* 查询栏两个布局决策：
   ① 列宽 10.5em ≈ 147px —— 9 位数字连内边距实测要 89px，这是「宽裕但短」的点；
     宽屏上到顶不再拖长，窄屏上轨道照样能压到 115.9px（320px 视口实测）。
   ② 语言下拉推到最右 —— justify-self 一改，grid item 就不再拉伸、按内容宽度收，
     正好贴在顶栏内容带的右边缘上（实测 l=748，与账号头右边缘 846 齐平）。 */
.query .field.locale { justify-self: end; }
.field { display: flex; flex-direction: column; gap: 3px; }
/* 标签改用金调暗版（游戏里属性名那种金色小字）+ 拉开字距，不用灰蓝 --ink-3 ——
   那个灰蓝和顶栏原来那套是一伙的，下面一处都没有。
   line-height 写死 13.5px 不是随手取的：11px 字继承下来的 1.5 倍是 16.5px，
   再加 gap 与定高 36px 的输入框，整个 query 行会比改前高 1.3px ——
   而 .top 是 sticky（**照常占正常流**），这 1.3px 会推着下面全部内容下移，
   像素对拍时整页都脏。13.5 + 2 + 36 = 51.5，正好是改前那一行的高度。 */
.field span { font-size: 11px; line-height: 13.5px; color: rgba(211, 188, 142, .75); letter-spacing: .14em; }
/* 深色玻璃输入控件（顶栏输入框/下拉）共用外观：金描边 + 内阴影 + focus 金晕。
   输入框与下拉统一 36px 定高（原来 input 31 / select 33，同一行底对齐后顶边差 2px；定高 + 垂直居中严丝合缝），垂直 padding 归零全交 height。 */
.field input, .field select {
  padding: 0 12px;
  background: var(--ctrl-bg);
  border: 1px solid var(--gold-line);
  color: var(--cream);
  border-radius: 10px;
  font-size: 13px;
  outline: none;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .45);
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.field input, .field select { height: 36px; width: 100%; }
/* placeholder 是提示不是内容：压到约 3.9:1，够看但不跟真值抢 */
.field input::placeholder { color: rgba(240, 236, 225, .45); }
.field input:hover, .field select:hover { border-color: rgba(211, 188, 142, .5); }
/* focus 走一圈金晕。原来描的是 --accent 蓝边，蓝在这套配色里已经退场了 */
.field input:focus, .field select:focus {
  border-color: var(--gold-line-hi);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .45), 0 0 0 3px rgba(211, 188, 142, .13);
}
.field input:focus, .field select:focus { background: rgba(30, 35, 47, .95); }
/* 原生下拉箭头在深底上是灰的、还紧贴右边缘。换成内联的金色细箭头（data URI，不新引文件），
   并让出 padding-right，免得选中的文字压到箭头上。 */
.field select {
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  padding-right: 32px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' fill='none'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23d3bc8e' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}
/* 展开后的列表由系统画，不写这条在 Windows/Chrome 上就是一片刺眼的白 */
.field select option { background: #1a1f2b; color: #e7e0d0; }

/* 按钮：从「灰蓝平板」换成游戏那套「深色玻璃 + 金描边 + 微浮雕」。三层全是 CSS，不引图：
     ① 上下渐变当玻璃面；② inset 白线当顶边高光 —— 浮雕感全靠它，删了就塌回平板；
     ③ hover 时外扩一圈金晕。字距 .08em 是给中文按钮的：两个字太短，不拉开还是「网页按钮」。
   36px 定高与同一行的输入框/下拉严格等高（原来是 37 vs 31，底对齐后顶边差 6px）。 */
.btn {
  height: 36px;
  padding: 0 16px;
  background: linear-gradient(180deg, rgba(58, 64, 82, .92), rgba(34, 39, 52, .92));
  border: 1px solid var(--gold-line);
  color: #e7e0d0;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .08em;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06), 0 2px 6px rgba(0, 0, 0, .35);
  transition: border-color .16s ease, color .16s ease, box-shadow .16s ease,
              background .16s ease, transform .1s ease;
}
.btn:hover {
  border-color: var(--gold-line-hi);
  color: var(--gold-lt);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 2px 10px rgba(0, 0, 0, .4),
              0 0 12px rgba(211, 188, 142, .18);
}
.btn:active { transform: translateY(1px); }
/* 键盘走到按钮上要看得见；鼠标点不算，所以用 :focus-visible 而不是 :focus */
.btn:focus-visible { outline: 2px solid rgba(211, 188, 142, .55); outline-offset: 2px; }

/* 主按钮（刷新）与返回按钮共用金色实心外观（和卡片「精1」金、评级金同族）；
   字用深棕：白字压在金上只有约 1.6:1，深棕 #3a3020 是 8.3:1，过 AA。尺寸与字体各自声明。 */
.btn.primary, .btn.back {
  background: linear-gradient(180deg, #ffeec2, #e6cd92 52%, #d2b476);
  border-color: #f2e0b4;
  color: #3a3020;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .35);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .65), 0 2px 12px rgba(211, 188, 142, .3);
}
.btn.primary:hover, .btn.back:hover {
  background: linear-gradient(180deg, #fff6d8, #eed9a4 52%, #dcc08a);
  color: #2f2718;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .72), 0 2px 16px rgba(211, 188, 142, .42);
}
.btn:disabled { opacity: .45; cursor: default; transform: none; }
/* 禁用时把 hover 那套金晕压掉（:disabled:hover 的权重压不住 .btn.primary:hover，得单独写） */
.btn:disabled:hover {
  border-color: var(--gold-line); color: #e7e0d0;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06), 0 2px 6px rgba(0, 0, 0, .35);
}
.btn.primary:disabled:hover {
  border-color: #f2e0b4; color: #3a3020;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .65), 0 2px 12px rgba(211, 188, 142, .3);
}

/* 明细页的「← 返回」做成**金色实心**：顶栏在明细页整排收掉后，它是这一屏唯一的退出入口，
   原来那套「纯灰文字、无边框、14px」跟右边灰色的角色名一个分量，扫一眼根本找不到。
   现在和顶栏「刷新」用同一块金 —— 深棕字压在金上 8.3:1（白字只有 1.6:1），过 AA。
   右边原来那个灰色角色名删掉之后，这一行只剩它自己，尺寸顺势提一档：
   34→40px 高、13→15px 字、内边距 15→24px，并给 112px 下限（日文「戻る」只有两个字，
   不设下限会缩成一条细按钮，跟「唯一的退出入口」这个身份不匹配）。 */
.btn.back {
  height: 40px;
  min-width: 112px;
  padding: 0 24px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .08em;
}
.btn.back:hover {
  background: linear-gradient(180deg, #fff6d8, #eed9a4 52%, #dcc08a);
  color: #2f2718;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .72), 0 2px 16px rgba(211, 188, 142, .42);
}
.btn.back:active { transform: translateY(1px); }

/* 顶栏现在只有三个控件（UID + 刷新 + 语言）：360px 视口下 刷新 62.1 + 下拉 98 + 间距 16 = 176px，
   剩下的 156px 给 UID 绰绰有余（9 位连内边距要 89px），320px 也够。
   以前「≤380px 收按钮内边距」的 media query 是为四个控件挤一行准备的，控件减到三个后
   它不再有任何作用，已删（2026-10-06）。 */

/* ───────────────────────── 提示条 ───────────────────────── */

.banner {
  /* 和顶栏/主容器同一条内容带：通栏的话桌面上一句报错会横跨整屏 */
  width: 100%;
  max-width: var(--app-width);
  margin: 8px auto 0;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--ink);
  font-size: 12px;
}
.banner.err { border-color: #e85656; color: #ffb3b3; }
.banner.ok { border-color: #4caf7d; color: #aef0c9; }

/* ───────────────────────── 主容器：手机宽度 ───────────────────────── */

.app {
  flex: 1;
  width: 100%;
  max-width: var(--app-width);
  margin: 0 auto;
  padding: 12px 14px 24px;
}

.view { display: none; }
.view.active { display: block; animation: fadeIn .18s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* 首页没有标题了：原来那行「角色大全」删掉了（2026-10-07），账号头直接顶上。 */

/* ───────────────────────── 首页：账号头 ───────────────────────── */

.acct-header {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px;
  margin-bottom: 14px;
}
.acct-nick { font-size: 17px; font-weight: 700; }
.acct-sig { font-size: 11px; color: var(--ink-3); margin: 4px 0 8px; }
.acct-meta { display: flex; gap: 18px; margin-top: 8px; }
.acct-meta div { display: flex; flex-direction: column; }
.acct-meta b { font-size: 15px; }
.acct-meta span { font-size: 11px; color: var(--ink-3); }

/* ───────────────────────── 首页：筛选条 ─────────────────────────
 *
 * 一行三段：排序（左）｜武器/圣遗物切换（中）｜漏斗筛选（右）。
 * 顺序即频率：排序定第一印象放最左；筛选是末态动作（点完就看结果）沉到最右。
 * 视觉沿用顶栏控件那套（--ctrl-bg 深色玻璃 + --gold-line 金描边），
 * 一个新色都不引 —— 筛选条和顶栏在同一屏上，另起一套必然搭不上。
 * 34px 高：比顶栏控件（36）矮 2px，它是内容区的次级控件，不该和顶栏主角一样高。
 *
 * 筛选是聚合**弹窗**（漏斗图标触发），不再摊三个下拉 —— 三个维度都要多选
 * （同时看火和水），一个大框里一次勾完再确定；选项收起来而不平铺，是给网格省垂直空间。
 * 窄屏（一行放不下时）靠 flex-wrap 折行，中间的视图切换 margin auto 两边分，
 * 折了行它自己那一行也是居中的。
 */
.roster-filter {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  margin-bottom: 12px;
}
/* 视图切换：**一颗循环按钮**（点一下换下一个视图），不是左右分段的 segmented ——
   分段壳天生只画得下两半，加第三个视图就得重排版；循环按钮只报「当前是哪个」。
   位置在筛选条最左，右边两颗（排序/筛选）靠 margin-left:auto 一起顶到右侧。
   框子故意跟右边两颗不一样：**实心金底 + 全圆角胶囊**（右边是深色玻璃 + 方角）——
   右边两颗是「点开弹窗去选」的操作，这一颗是「点一下就换状态」的状态钮，不是一类东西。 */
.rf-switch-btn {
  display: inline-flex; align-items: center;
  height: 30px; padding: 0 14px;
  background: var(--gold);
  border: 1px solid var(--gold);
  border-radius: 999px;
  color: #1a1510;
  font-size: 12px; font-weight: 600; letter-spacing: .04em;
  cursor: pointer;
  transition: background .16s ease, border-color .16s ease;
}
.rf-switch-btn:hover { background: var(--gold-lt); border-color: var(--gold-lt); }
/* 排序那颗：把它和漏斗一起顶到最右（margin-left:auto 吃掉中间剩余空间）。
   两颗是同类的「弹窗触发器」，挨在一起，中间只留筛选条本身的 6px gap */
.rf-sort { margin-left: auto; }
/* 漏斗按钮：图标 + 角标。比别的下拉按钮窄（不摊文案），宽度跟着图标走。
   这里要 position:relative —— 角标是相对它定位的，而漏斗按钮本身不再是 .rf-dd
   （它开的是弹窗，不是挂在按钮下面的小面板） */
.rf-filter { position: relative; margin-left: 0; }
.rf-funnel-btn { padding: 0 9px; }
.rf-funnel-btn svg { width: 14px; height: 14px; flex: 0 0 auto; }
/* 选中数角标：右下角一颗小圆点，金底深字。平时隐藏（visibility 而不是 display，
   免得面板每次重画都改布局） */
.rf-funnel-badge {
  visibility: hidden;
  position: absolute; right: -4px; bottom: -4px;
  min-width: 14px; height: 14px; padding: 0 3px;
  border-radius: 7px;
  background: var(--gold);
  color: #1a1510;
  font-size: 10px; font-weight: 700; line-height: 14px; text-align: center;
}
.rf-funnel-badge.on { visibility: visible; }
/* ── 筛选弹窗 ──
 * 三维度多选挤在 300px 的小面板里：chips 要折行、指针还得瞄准，勾三个元素很难受 ——
 * 改成居中弹窗（最宽 520px），chips 排成网格一次勾完，最后「确定」。
 * 遮罩是纯暗色、不带模糊：筛选前后要能对照着看下面的网格，糊掉就看不出变化了。 */
.rf-mask {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  background: rgba(8, 7, 6, .62);
}
.rf-modal {
  display: flex; flex-direction: column;
  width: min(520px, 100%);
  max-height: min(80vh, 100%);
  background: var(--bg-3);
  border: 1px solid var(--gold-line);
  border-radius: var(--radius);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .6);
}
.rf-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
}
.rf-modal-title { font-size: 14px; font-weight: 600; letter-spacing: .06em; }
.rf-modal-x {
  width: 28px; height: 28px; padding: 0;
  background: none; border: 0; border-radius: 6px;
  color: var(--ink-3); font-size: 18px; line-height: 1; cursor: pointer;
}
.rf-modal-x:hover { color: var(--gold-lt); background: rgba(211, 188, 142, .12); }
/* 内容区自己滚（选项多 / 窄屏不够高时），头和底钉住不动 */
.rf-modal-body { overflow-y: auto; padding: 12px 14px; }
.rf-fgroup + .rf-fgroup { margin-top: 14px; }
.rf-fgroup-title {
  padding: 0 2px 6px;
  color: rgba(240, 236, 225, .45);
  font-size: 11px; letter-spacing: .08em;
}
/* chips 排网格（不是随便折行）：每格 96px 起 —— 元素 7 个两行满、等级 9 档、
   权重 4 项都各自对齐，行与行的列边界是直的，扫视不用跟着折行位置找 */
.rf-fchips { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 6px; }
/* 弹窗里的 chip 比小面板那颗高 8px（34 vs 26）：框大了、指针行程也长，
   26px 在这个尺寸下看着像误触区 */
.rf-chip {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  height: 34px; padding: 0 9px;
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--ink-2);
  font-size: 12px; letter-spacing: .04em;
  cursor: pointer;
  transition: border-color .14s ease, color .14s ease, background .14s ease;
}
.rf-chip:hover { border-color: rgba(211, 188, 142, .5); color: var(--gold-lt); }
.rf-chip.active {
  background: rgba(211, 188, 142, .16);
  border-color: var(--gold-line-hi);
  color: var(--gold-lt);
}
/* 元素那一颗（图标 + 名字）自己也要 flex 居中：img 是行内元素，默认按**基线**对齐 ——
   图标底边压在文字基线上，图标整体就比字的中心低半截（名字越长越明显）。
   chip 外层的 align-items:center 只管得住 chip 这一层，管不住这个 span 内部。
   line-height:1 是配套的：行盒一旦比图标高，flex 居中算的是行盒中心，视觉上又偏了 */
.rf-opt-elem {
  display: inline-flex; align-items: center; gap: 5px;
  line-height: 1;
}
.rf-chip img { width: 18px; height: 18px; object-fit: contain; }
.rf-modal-foot {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  border-top: 1px solid var(--line);
}
.rf-modal-actions { display: flex; gap: 8px; margin-left: auto; }
/* 取消 / 确定：跟筛选条控件同高（34px）。确定是金底深字 —— 它是这一步的主动作，
   不能和「取消」一样轻 */
.rf-btn {
  height: 34px; padding: 0 14px;
  background: var(--ctrl-bg);
  border: 1px solid var(--gold-line);
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  font-size: 12px; letter-spacing: .04em; cursor: pointer;
  transition: border-color .16s ease, background .16s ease, color .16s ease;
}
.rf-btn:hover { border-color: rgba(211, 188, 142, .5); color: var(--gold-lt); }
.rf-btn.primary { background: var(--gold); border-color: var(--gold); color: #1a1510; font-weight: 600; }
.rf-btn.primary:hover { background: var(--gold-lt); border-color: var(--gold-lt); color: #1a1510; }
.rf-fpanel-clear {
  padding: 3px 10px;
  background: none; border: 1px solid var(--line); border-radius: 6px;
  color: var(--ink-2); font-size: 11px; letter-spacing: .04em; cursor: pointer;
}
.rf-fpanel-clear:hover { border-color: rgba(211, 188, 142, .5); color: var(--gold-lt); }
.rf-fpanel-count { color: rgba(240, 236, 225, .45); font-size: 11px; }
/* 排序现在也走弹窗（和筛选同一个 .rf-modal 壳），这些行只是弹窗里的**内容** ——
   不再挂在 .rf-menu 上，宽度跟着弹窗走（520px），行高从 32px 放宽到 38px：
   框大了、指针行程也长了，矮行在小面板里是省空间，在大框里显得局促。 */
.rf-sort-row { display: flex; align-items: center; gap: 8px; height: 38px; padding: 0 4px; }
.rf-sort-row + .rf-sort-row { border-top: 1px solid rgba(255, 255, 255, .05); }
.rf-sort-pos {
  flex: 0 0 auto; width: 18px; height: 18px; line-height: 18px; text-align: center;
  border-radius: 50%; background: rgba(211, 188, 142, .18); color: var(--gold-lt);
  font-size: 11px; font-weight: 600;
}
.rf-sort-name { flex: 1 1 auto; min-width: 0; color: var(--ink-2); font-size: 13px; letter-spacing: .04em; white-space: nowrap; }
/* 小方钮在大框里跟着放大（28 vs 24），24px 在 38px 的行里偏小 */
.rf-sort-mini {
  flex: 0 0 auto; width: 28px; height: 28px; padding: 0;
  background: none; border: 1px solid var(--line); border-radius: 6px;
  color: var(--ink-2); font-size: 12px; line-height: 1; cursor: pointer;
  transition: border-color .14s ease, color .14s ease, background .14s ease;
}
.rf-sort-mini:hover:not(:disabled) { border-color: rgba(211, 188, 142, .5); color: var(--gold-lt); background: rgba(211, 188, 142, .12); }
.rf-sort-mini:disabled { opacity: .3; cursor: default; }
.rf-sort-add { color: var(--gold-lt); border-color: rgba(211, 188, 142, .4); }
.rf-sort-hint { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--line); color: rgba(240, 236, 225, .45); font-size: 11px; line-height: 1.4; }

/* 下拉容器：面板绝对定位挂在它下面，得有个定位参照 */
.rf-dd { position: relative; min-width: 0; }
.rf-dd-btn {
  display: flex; align-items: center; gap: 4px;
  height: 34px; padding: 0 10px;
  background: var(--ctrl-bg);
  border: 1px solid var(--gold-line);
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  font-size: 12px; letter-spacing: .04em;
  cursor: pointer;
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease, color .16s ease;
}
/* 组名和值共用这一个 span：长了省略号截，按钮宽度就不跟着文案乱跳 */
.rf-dd-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 实心三角当方向指示用，9px 会糊成一个小点，11px 才和 12px 的按钮文字配得上 */
.rf-caret { font-size: 11px; line-height: 1; opacity: .7; }
/* 条件排序/没排序时 caret 是空的，留着会白占一个 gap 的右内边距 */
.rf-caret:empty { display: none; }
.rf-dd-btn:hover { border-color: rgba(211, 188, 142, .5); }
/* 展开态 = 金描边 + 金晕；选中态再加淡金底。和顶栏按钮 hover 是同一支金 */
.rf-dd.open .rf-dd-btn {
  border-color: var(--gold-line-hi);
  color: var(--gold-lt);
  box-shadow: 0 0 0 3px rgba(211, 188, 142, .13);
}
.rf-dd-btn.active { border-color: var(--gold-line-hi); background: rgba(211, 188, 142, .16); color: var(--gold-lt); }

/* 面板底用不透明色（--bg-4）：半透明的话下面的角色网格会透上来，选项读不清 */
.rf-menu {
  display: none;
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 20;
  min-width: 100%;
  /* 288px = 9 个选项（等级 MAX…D 共 9 档，最长的那个面板）刚好放满不滚动 */
  max-height: 288px; overflow-y: auto;
  padding: 4px;
  background: var(--bg-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .55);
}
.rf-dd.open .rf-menu { display: block; }
/* 末尾那组（权重 / 排序）改成右对齐：英文的「Elemental Mastery」比按钮本身宽，
   左对齐会一路顶出去被 body 的 overflow-x 裁掉 */
.rf-dd-end .rf-menu { left: auto; right: 0; }
.rf-opt {
  display: flex; align-items: center; gap: 6px;
  width: 100%; height: 30px; padding: 0 10px;
  background: none; border: 0; border-radius: 7px;
  color: var(--ink-2);
  font-size: 12px; letter-spacing: .04em; text-align: left; white-space: nowrap;
  cursor: pointer;
}
.rf-opt:hover { background: rgba(211, 188, 142, .12); color: var(--cream); }
.rf-opt.active { background: rgba(211, 188, 142, .10); color: var(--gold-lt); }
.rf-opt-elem img { width: 18px; height: 18px; object-fit: contain; }

/* ───────────────────────── 首页：角色卡片网格 ─────────────────────────
 *
 * 版式照原魔工具箱「角色展柜」中间那一块：一排五个、不显示角色名、按星级铺底色。
 * 底色不是自己调的渐变，是 miao 的 common/item/bg{4,5}.png —— 也就是游戏里
 * 五星橙 / 四星紫那张底（见 shape.js 的 rarityBg）。
 *
 * 所有尺寸用 cqw（= 卡片宽度的 1%）。同一套版式，桌面一张卡 90px、手机 63px，
 * 字号和内边距都得跟着缩；写死 px 不是桌面太小就是手机溢出。
 * cqw 认最近的容器祖先，所以 .char-card 自己声明 container-type。
 */

.char-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
}

.char-card {
  container-type: inline-size;
  position: relative;
  /* 竖着排两段（画像 + 武器块）。用 flex 而不是 block 是为了让武器块吃掉行内多出来的高度：
     格子里 align-items 默认 stretch，同一行的卡会被拉到「最高的那张」那么高，
     要是卡片是 block，矮的那几张底下就会露一条深色底；flex 让白块自己长上去填满。 */
  display: flex;
  flex-direction: column;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  background: var(--bg-3);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .3);
  transition: transform .12s ease, box-shadow .12s ease;
  font-size: 12px;               /* 万一浏览器不认 cqw，还有个能看的兜底字号 */
}
.char-card:hover { box-shadow: 0 6px 20px rgba(0, 0, 0, .45); }
.char-card:active { transform: scale(.96); }

/*
 * 画像区。比例照参考图量的：一张卡 156×192，其中画像区 156×162（近乎正方）、
 * 底部白块 30。所以 aspect-ratio 取 156/162，白块高度交给内容自己撑。
 */
.cc-top {
  position: relative;
  flex: none;                    /* 高度只由 aspect-ratio 定，不参与上下分配 */
  aspect-ratio: 156 / 162;
  overflow: hidden;
}
.cc-bg {
  position: absolute; inset: 0;
  background-size: cover;
  background-position: center;
}

/*
 * 头像取景。数字是量出来的，不是拍的 —— 参考图里「头顶到下巴」大约占卡片宽度的
 * 六成，按这个把 miao 的 face.webp 对上去。
 *
 * 两个坑，都踩过：
 *   1. **不能 cover**。face.webp 是官方圆形头像切成 256 见方、脸占满整幅，
 *      cover 铺满卡片时头会占到卡片宽度七成以上，比参考图大一圈，像大头贴。
 *      contain 让整张源图进框，头自然落到五成多。
 *   2. **框不能就是可见区**。contain 的缩放取宽高里小的那个，框小图就小。
 *      画像区改成 156:162（≈1.038）后，框高度 92% ≈ 95.5cqw 正好是想要的那个尺寸；
 *      框比卡片宽出来的部分由 .cc-top 裁掉，图也就顺势铺满整个画像区。
 *
 * 源图背景是透明的，所以两侧露出来的是星级底色，不会糊一块白。
 */
.cc-face {
  position: absolute; top: 0; left: -10%;
  width: 120%; height: 92%;
  object-fit: contain;
  object-position: center top;
}

.cc-elem {
  position: absolute; top: 3cqw; left: 3cqw;
  width: 23cqw; height: 23cqw;
  object-fit: contain;
  filter: drop-shadow(0 .5cqw .8cqw rgba(0, 0, 0, .7));
}

/* 右上角角色等级。白字 + 半透明黑底，压在亮橙/亮紫底上都读得出来。
 *
 * top 从 3cqw 挪到 7.8cqw（用户 2026-09-19「等级和左上角属性图标在纵向上对齐一些」）：
 * 这俩都在画像区顶部，但块头差一倍 ——
 *   属性图标 宽高 23cqw，中心在 3 + 23/2 = 14.5cqw
 *   等级胶囊 高 = 字号 11 + 上下内边距 1.2×2 = 13.4cqw，原先 top:3 时中心只有 9.7cqw
 * 顶边对齐了、中心线却差 4.8cqw（4.3px @90px 卡），看着就是「胶囊飘在上面」。
 * 7.8 = 14.5 − 13.4/2，让胶囊中心落在图标中心上。图标图案在框内是居中的，
 * 所以对齐框中心 = 对齐图案中心。
 *
 * 先试过另一条路：把胶囊也撑到 23cqw 高（字号提到 13cqw、内边距 5cqw），
 * 顶底确实都齐了，但胶囊变成一大块半透明黑压在立绘上，Lv.79 也抢眼到跟左下评分同档 ——
 * 等级是配角，不该这么大。所以走「下移对齐」而不是「撑高对齐」。 */
.cc-lv {
  position: absolute; top: 7.8cqw; right: 3cqw;
  padding: 1.2cqw 2.4cqw;
  border-radius: 2cqw;
  background: rgba(0, 0, 0, .5);
  color: #fff; font-size: 11cqw; font-weight: 700; line-height: 1;
}

/*
 * 左下角评分。米白大字压在画像上 —— 但**必须垫一层半透明黑**。
 *
 * 为什么不能省这层（2026-09-19 补）：星级的橙底和紫底都是亮色，奶白的 #f6ecd2
 * 直接写上去，两个都糊成一团，光靠 text-shadow 救不回来（阴影只勾边，不降底噪）。
 * 参考图里敢直接压，是因为它压的是角色原画的深色部位，我们压的是纯色底，不是一回事。
 *
 * 只做**贴着字的一块胶囊**，不做通栏黑带 —— 通栏会和白块上下叠成两层，
 * 又回到「白块跟着黑块」那个老问题。左边距和左上角元素图标对齐（都用 3cqw），
 * 下边距和右下角评级对齐（都用 2cqw），四角看着是一套。
 */
.cc-score {
  position: absolute; left: 3cqw; bottom: 2cqw;
  padding: 1.2cqw 2.4cqw;
  border-radius: 2cqw;
  background: rgba(0, 0, 0, .5);
  font-size: 16cqw; font-weight: 800; line-height: 1;
  color: #f6ecd2;
  text-shadow: 0 .5cqw 1.2cqw rgba(0, 0, 0, .75);
}

/* 右下角评级。color 走 miao.css 的 .mark-*（roster.js 挂上档位类），边框跟着 currentColor 走。
   字号 13cqw（2026-09-19 用户「评分和评级字体相差太多，评级太小了」）：
   评分 16 / 评级 10 是 1.6 倍的落差，两个胶囊高 18.4 vs 14.6，摆在一起像「大字 + 小标签」。
   13 是**胶囊高度追平评分**的那个点：13 + 2×1.2 纵内边距 + 2×1.11 边框 = 17.6，对 18.4。
   为什么不敢再大：最宽的档位是 `MAX`（M 很宽，量出 2.481em），
     可用宽 94cqw（100 − 左右各 3）；评分占 2.752em × 16 = 44.0 + 左右内边距 4.8 = 48.8
     评级占 2.481 × F + 2×(2.2 + 1.11)
     F=13 → 中间只剩 6.3cqw（5.7px）；F=14 → 3.8cqw；F=15 就只剩 1.3cqw 了。 */
.cc-rank {
  position: absolute; right: 3cqw; bottom: 2cqw;
  font-size: 13cqw; font-weight: 800; line-height: 1;
  padding: 1.2cqw 2.2cqw;
  border: 1px solid currentColor;
  border-radius: 2cqw;
  background: rgba(0, 0, 0, .5);
  letter-spacing: .02em;
}

/* 武器块：白底，左右两栏 —— 左边一个图标竖向撑满整块，右边「名字 / 等级·精炼」两行。
   没武器也照样占位，整排高度才整齐。
   注意：这层是白底，不能用 --ink / --ink-3 那套（那是深色主题的浅色字，写上去看不见） */
.cc-weapon {
  display: flex; align-items: stretch; gap: 3cqw;
  padding: 3cqw;
  background: #fff;
  flex: 1;                   /* 同一行里最高那张卡撑出来的余量，由白块吃掉（见 .char-card） */
}
/* 图标那一栏：宽度固定，高度由 align-items:stretch 撑满整块内容区。
   上一版图标被压在「名字那一行」里，只有 20cqw（实测白块 36.6px 时图标才 18.1px，
   底下空 15.8px）。改成一整栏之后图标跟着白块高度走。
   min-height 是「反过来给白块定个下限」用的：中文名字只有一行时，右边两行信息
   合计才 25cqw 高，图标要是没下限就会被压扁。取 34cqw —— 白块正好回到改前的
   40cqw（36.6px），但这 36.6px 全被图标和两行字占满，没有一处空白。
   再往上加白块就要比改前更高了，不划算。
   武器图标素材本身是竖长的（长柄 187×248，单手剑 0.77、大剑 0.93、弓 0.97 的宽高比），
   contain 进这个竖框：长柄/单手剑是高度顶格（它们本来就比框「瘦」），
   大剑/弓则被框宽限制、左右顶格 —— 素材比例如此，不是框小了。 */
.cc-wicon {
  flex: 0 0 auto;
  width: 25cqw;
  min-height: 34cqw;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}
/* 右边信息栏：名字一行 +「等级 · 精炼」一行。
   **名字在剩余空间里垂直居中，等级那行锚死在白块底边**（grid 的 1fr auto 两行）——
   这是「扫视对齐」的关键。同排的白块会被最高的那张卡拉平（flex:1），
   要是等级行跟着名字走（整栏居中），名字一行和两行的卡，等级行会错开：
     实测 en 第一排 4 张两行名的卡在 y=417，一行名的「寒息」在 y=411，差 6px；
     第二排同理（566 vs 572）。
   贴底之后同排一律落在同一条线上，而且跟图标的底边齐平。
   **字号和行高必须落在这一层**，不能只写在里面的 strong 上 ——
   浏览器会给每个块的第一行插一个「隐形字符」(strut)，行盒的最小高度由**这个块**的
   行高决定，跟里面 strong 自己的行高无关。只写 strong 的话这里还继承着卡片
   正文那 16px 的字号，1.15 倍 = 每个行盒 18px：
     实测 2 行名字白块 54.5px、3 行 72.5px（而按字号算应该是 42 和 54）。
   把字号+行高提到这一层，行盒才真是 11cqw × 1.15。 */
.cc-wtext {
  flex: 1; min-width: 0;
  display: grid; grid-template-rows: 1fr auto; gap: 1.4cqw;
  font-size: 11cqw;
  line-height: 1.15;
}
/* 名字在「去掉等级行之后」剩下的空间里居中 —— 不贴顶，留一点呼吸；
   等级行归 grid 的第二行（auto），自动贴底 */
.cc-wtext strong { align-self: center; }
/* 武器名：非中文一行放不下，原来 nowrap + 省略号会把名字切掉（用户 2026-09-19 指出）。
   这段能用多宽，是量出来的，不是拍的：
     列宽 = 100 - 左右内边距(3×2) - 图标(25) - 间距(3) = 66cqw
     每行能放几个字符 = 66 ÷ 11 = 6em
   而实测最长的**单词**是英文的 Gravestone 5.71em、Fragments 5.34em
   （整名最长的 Rainbow Serpent's Rain Bow 是 14.4em，会折行，不是单词超宽）。
   6 > 5.71 还留了约 5% 余量，换行只会发生在空格处，不会把单词从中间劈开 ——
   早先 12.5cqw 字号下这列只有 5.52em，Gravestone 就被断成了「Graveston / e」。
   overflow-wrap: anywhere 是兜底（万一以后来一把单词比整列还宽的武器名，硬断，不让它溢出白块）。

   **这里故意不设折行上限**（用户 2026-09-19：「我不要省略号，要省略号不如不要武器名」）。
   代价要认：英文最长的 Rainbow Serpent's Rain Bow 要 3 行，同排 4 张卡的白块会被一起
   抬到 3 行高（flex:1 拉平，见 .cc-weapon），也就是那一排的短名字卡会多出一点上下留白。
   这个代价只在**含有超长英文名的那一行**出现 —— 中文名实测最长 5 个字，中文页整页不受影响。
   用字号自适应去压到 2 行不可行：canvas 实测那把武器缩到 8cqw 仍需 3 行（要 7.5cqw 才可能），
   比下面那行小字还小，得不偿失。 */
.cc-wtext strong {
  font-weight: 600; color: #2f2f33;   /* 字号/行高继承 .cc-wtext，见上 */
  white-space: normal;
  overflow-wrap: anywhere;
}
/* 等级 · 精炼：跟在名字下面。两端对齐（space-between）把这一栏铺开 ——
   上一版它是横跨整块的一整行、内容却只有左边一小截，看着「聚在左下角」（用户 2026-09-19 指出）。
   现在归到右边这一栏里，两个字段分居左右，栏宽被用满。
   字号 10.5cqw：栏宽 66cqw，「Lv.90」约 26cqw、「精1」约 16cqw，中间还空一截。
   内容少的时候 space-between 会自动退化成左对齐，不用额外处理。 */
.cc-wmeta {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 10.5cqw; line-height: 1.1; color: #7a7a82;
  white-space: nowrap;
  /* 右边单独再缩 5cqw，加起来 8cqw（用户 2026-09-19：先「太靠边了，再留一点点白」→ 再「还要再留白一些」）。
     为什么右边要单独缩：这一项是**右对齐的粗体金色小字**，紧贴容器边时没有任何视觉缓冲。
     左边那 2.7px 之所以不显挤，是因为它有「图标 + 间距」31cqw 顶着，不是同一回事。
     三档截图实测定下来的（文字实际右边缘距卡片右；padding 越大，精炼越往左，右留白越多）：
       3cqw → 5.41px（跟评级徽章的 5.69px 齐平，但金色粗体比徽章里垫了内边距的 SS 重，看着压边）
       5cqw → 7.22px ✔（比那条线多 1.5px，呼吸感出来了，两字段间距仍有 15.8px）
       7cqw → 9.02px（过头：脱离右边那条 5.7px 对齐线太多，「精1」开始跟整卡的右边缘脱钩）
     左边**不能**跟着缩：Lv.90 的左边缘要和上面名字左对齐，缩了就断线。
     底部也不缩：等级行底边跟图标底边齐平，是故意对齐的。 */
  padding-right: 5cqw;
}
.cc-wmeta:empty { display: none; }   /* 没武器时这一块整个不占位（连带 gap 也消掉） */
.cc-wmeta b { font-weight: 600; color: #2f2f33; }
/* 精炼度用金色。白底上 #d3bc8e 太浅，压深一档才看得清 */
.cc-wmeta b.refine { color: #a9853c; }

/* 圣遗物套装块：白底，与武器块同构（flex:1 拉平排高、白底深字）——
   切视图只换下半块内容，整排卡片高度不变。
   没有图标栏（套装只有部位图、没有整套图，硬借一张部位图反而指代不明），
   两行文字垂直居中。 */
.cc-sets {
  display: flex; align-items: center; gap: 3cqw;
  padding: 3cqw;
  background: #fff;
  flex: 1;
}
/* 套装图标那一栏：宽 25cqw、高 34cqw 照抄 .cc-wicon ——
   两种视图的白块必须一样高，切视图时整排卡片不能跳。
   高是**定值**（不是 min-height）：圣遗物图是居中的方图，栏高随内容变会让接缝位置飘。 */
.cc-set-icon {
  position: relative; flex: 0 0 auto;
  width: 25cqw; height: 34cqw;
}
.cc-set-icon img { width: 100%; height: 100%; object-fit: contain; }
/* 2+2：**两朵花左右错开 + 沿两花中点的对角线切开**，各留大半 —— 两朵都看得清。
   演进史（三版都试过、拼图肉眼选的）：
   ① 各切一半硬拼 —— 两套的花在素材里大小/位置不一致，拼出来轮廓对不上，看着是两个半朵；
   ② 一朵完整打底 + 第二套切角楔形 —— 外形是一朵花，但花是圆的、居中放格里，
      楔形罩住的多是花瓣外的留白，切浅了右下认不出、切深了（-30%）又把左上盖没了；
   ③ 定稿这版：两朵花**各往左右挪 14%**，中心错开之后沿中点对角线切，
      每朵留在自己那侧的都是「过半 + 带花心」，不再有谁被盖住。
   ⚠️ clip-path 在元素**本地**坐标系里生效、transform 之后才整体搬走 ——
   第二朵往右挪了 s%，它的切线在本地就得往左补回 s%（斜边顶点取 (100-s)% / -s%），
   不然切线会跟着图一起被挪走、对不上第一朵的边。 */
.cc-set-icon.mix img { position: absolute; inset: 0; }

.cc-set-icon.mix img:last-child {
  transform: translate(10%, 10%);
  clip-path: polygon(80% 10%, 100% 0%, 100% 100%, -20% 100%);
}
/* 一条斜向切线，自然切开两花 */
.cc-set-icon.mix::after {
  content: ''; 
  position: absolute;
  /* 因为图B向右向下各移了10%，两图中心点的中点需要跟着向右向下偏移 5% */
  left: calc(50% + 5%); 
  top: calc(50% + 5%); 
  width: 28cqw; 
  height: 1.5cqw;
  transform: translate(-50%, -50%) rotate(-52.8deg);
  background: linear-gradient(90deg,
    transparent, rgba(169, 133, 60, .95) 20%, rgba(169, 133, 60, .95) 80%, transparent);
  pointer-events: none;
}

.cc-sets-list { display: flex; flex-direction: column; gap: .8cqw; min-width: 0; flex: 1; }
/* 字号 10.5cqw：与武器名同规矩，可折行、不断词（anywhere 兜底）。
   件数**右锚定**（flex 两栏），不写在名字后面 —— 加了图标之后名字那栏只剩 66cqw
   （6 字多），七字名必折行；件数混在折行文本里会粘在断开的半个词后面
   （实测「角斗士的终幕 / 礼×2」），锚到右边则名字怎么折它都在同一列 */
/* 件数**纵向居中**而不是贴第一行：名字被图标挤窄后会折行（七字名必然），
   baseline 对齐让「×2」吊在第一行的基线上、下面空一整行，看着像属于第一行。
   center 让它对着**整块名字**（不管几行）居中，读起来是「这一套几件」 */
.cc-set-row {
  display: flex; align-items: center; gap: 1.2cqw;
  font-size: 10.5cqw; line-height: 1.15; color: #2f2f33;
}
.cc-set-row span { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
/* 件数金色：跟白块里「精1」同一支金，扫一眼就知道哪个数是件数 */
.cc-set-n { flex: 0 0 auto; font-weight: 600; color: #a9853c; }
.cc-sets-empty { font-size: 10.5cqw; color: #9a9aa2; }

/* ───────────────────────── 明细页 ───────────────────────── */

/* 明细页收掉整条顶栏：UID 框/刷新/语言在这里全用不上（切语言回首页做），
   留着既把 600px 画布往下顶，又让「← 返回」这一屏唯一的退出入口显得次要。
   body 上挂 class 而不是给 #top 写 hidden —— 首页/明细页来回切只动一个类名，
   不用在两处各维护一次显隐。 */
body.on-detail .top { display: none; }
/* 顶栏没了，main 顶到屏幕最上沿，12px 有点贴边，多给 4px 呼吸 */
body.on-detail .app { padding-top: 16px; }
/* 明细页卡片最底下已经有一句「数据时间」了，页脚这句不再重复。
   只藏文字、不藏 .foot 盒子：那圈 padding 还留着，明细页底边高度和以前一样，
   来回切页时下面的留白不会跳。JS 该写还写（列表页要用），靠类名决定显不显示。 */
body.on-detail #footmeta { display: none; }

/* 返回栏现在只有一个按钮（角色名已删），gap 跟着去掉 */
.detail-bar {
  display: flex; align-items: center;
  margin-bottom: 12px;
}

/*
 * 明细页放的是 miao 那张 600px 宽的评分画布，比外壳（520px）宽，所以这里
 * 单独放开宽度并让画布居中 —— 用 flex 居中，允许它向两侧对称溢出。
 * 返回栏仍然是外壳宽度，不跟着变宽。
 */
#view-detail.view.active {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}
#view-detail .detail-bar {
  align-self: stretch;
  width: 100%;
  max-width: var(--app-width);
  margin: 0 auto 12px;
}
#view-detail .placeholder { align-self: stretch; }

/* ───────────────────────── 通用状态 ───────────────────────── */

.placeholder {
  background: var(--bg-3);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  padding: 32px 20px;
  text-align: center;
  color: var(--ink-2);
}
.placeholder .dim { color: var(--ink-3); font-size: 12px; }

.loading {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding: 80px 0; color: var(--ink-3);
}
.spin {
  width: 28px; height: 28px; border-radius: 50%;
  /* 转圈也用金 —— --accent 蓝在这里是最后一处（顶栏那两处已改），留着它就还是有个孤立的蓝 */
  border: 3px solid var(--line); border-top-color: var(--gold-lt);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ───────────────────────── 页脚 ─────────────────────────
 *
 * 就一行：这份数据的抓取时间。内核出处、角色数、语言一概不放这儿。
 * body 是 flex column、.app 撑掉剩下的高度，所以它自然贴在页面底部。
 */
.foot {
  width: 100%;
  max-width: var(--app-width);
  margin: 0 auto;
  padding: 4px 14px 32px;
}
.foot > span { font-size: 12px; line-height: 1.6; }
.foot > .dim { color: var(--ink-3); }
